Common Name only
I am developing the mTLS infrastructure in my organization and some tasks require services to be able to connect via ssh for remote execution of commands. Since I already (will) have TLS certificates for communicating services over HTTPS, etc., I thought it would be wise to use them for ssh instead of supporting a parallel infrastructure of regular ssh keys. So I found your wonderful project
But during the experiments on the test installation, I encountered the problem that pkixssh expects a full set of fields like O, OU, CN, etc. in the DN field of the certificate, while in my certificates there is only an identifier in the bare form, i.e. only the contents of the CN field, such as "service.example.com" (in easy-rsa for this there is the value of the variable EASYRSA_DN or the option --dn-mode is called "cn_only" as opposed to "org").
When checking such a certificate, pkixssh rejects the connection with the output of the message "x509key_str2X509NAME: cannot parse ..." because it does not find a single equal sign in DN.
After studying the source code, I made a small change to the code section for extracting fields from DN. The new logic is as follows: if the equal sign is not found and no fields have been found yet, then assume that this is a certificate of type "cn_only" and the entire DN is the value of the CN field.
I tried to make a merge request to your repository, but it looks like you've closed this possibility, so I give the patch code in this issue.
Patch code
diff --git a/ssh-x509.c b/ssh-x509.c
index 633c0d0..3ff9d54 100644
--- a/ssh-x509.c
+++ b/ssh-x509.c
@@ -441,6 +441,7 @@ x509key_str2X509NAME(const char* _str, X509_NAME *_name) {
char *str = NULL;
char *p, *q, *token;
int has_more = 0;
+ int was_more = 0;
str = xmalloc(strlen(_str) + 1); /*fatal on error*/
strcpy(str, _str);
@@ -473,25 +474,30 @@ x509key_str2X509NAME(const char* _str, X509_NAME *_name) {
token = p + strlen(p);
}
q = strchr(p, '=');
- if (!q) {
- error_f("cannot parse '%.200s' ...", p);
- ret = 0;
- break;
+ if (q) {
+ {
+ char *s = q;
+ for(--s; ISSPACE(*s) && (s > p); s--)
+ {/*skip trailing space*/}
+ *++s = 0;
+ }
+ nid = OBJ_txt2nid(p);
+ p = q + 1;
+ } else {
+ if (was_more) {
+ error_f("cannot parse '%.200s' ...", p);
+ ret = 0;
+ break;
+ }
+ debug3_f("Assume DN contains CN only");
+ nid = OBJ_txt2nid("CN");
}
- {
- char *s = q;
- for(--s; ISSPACE(*s) && (s > p); s--)
- {/*skip trailing space*/}
- *++s = 0;
- }
- nid = OBJ_txt2nid(p);
if (nid == NID_undef) {
error_f("cannot get nid from string '%.200s'", p);
ret = 0;
break;
}
- p = q + 1;
if (!*p) {
error_f("no data");
ret = 0;
@@ -511,6 +517,7 @@ x509key_str2X509NAME(const char* _str, X509_NAME *_name) {
p = token;
if (has_more) p++;
+ was_more = 1;
}
free(str);