From: Markus Koetter Date: Fri, 10 Dec 2010 19:30:09 +0000 (+0100) Subject: Add extv3 X509 field support to --x509-username-field X-Git-Tag: v2.3-alpha1~272 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3fa86d237721ca113fa020b7e888a1e10374a560;p=thirdparty%2Fopenvpn.git Add extv3 X509 field support to --x509-username-field This allows using other X509 certificate fields for the certificate authentication. To use altSubjectName, use --x509-username-field ext:altSubjectName This feature requires OpenVPN to be built with --enable-x509-alt-username This patch is slightly modified, to honour --enable-x509-alt-username compile time configuration. Two #ifdef's are added. Signed-off-by: Markus Koetter Signed-off-by: David Sommerseth Acked-by: David Sommerseth Signed-off-by: David Sommerseth --- diff --git a/options.c b/options.c index f4eeaee23..4c28a8f7b 100644 --- a/options.c +++ b/options.c @@ -5907,7 +5907,8 @@ add_option (struct options *options, { char *s = p[1]; VERIFY_PERMISSION (OPT_P_GENERAL); - while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */ + if( strncmp ("ext:",s,4) != 0 ) + while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */ options->x509_username_field = p[1]; } #endif /* ENABLE_X509ALTUSERNAME */ diff --git a/ssl.c b/ssl.c index ed1071481..7b2291c6b 100644 --- a/ssl.c +++ b/ssl.c @@ -520,6 +520,61 @@ extract_x509_field_ssl (X509_NAME *x509, const char *field_name, char *out, int } } +#ifdef ENABLE_X509ALTUSERNAME +static +bool extract_x509_extension(X509 *cert, char *fieldname, char *out, int size) +{ + bool retval = false; + X509_EXTENSION *pExt; + char *buf = 0; + int length = 0; + GENERAL_NAMES *extensions; + int nid = OBJ_txt2nid(fieldname); + + extensions = (GENERAL_NAMES *)X509_get_ext_d2i(cert, nid, NULL, NULL); + if ( extensions ) + { + int numalts; + int i; + /* get amount of alternatives, + * RFC2459 claims there MUST be at least + * one, but we don't depend on it... + */ + + numalts = sk_GENERAL_NAME_num(extensions); + + /* loop through all alternatives */ + for (i=0; itype) + { + case GEN_EMAIL: + ASN1_STRING_to_UTF8((unsigned char**)&buf, name->d.ia5); + if ( strlen (buf) != name->d.ia5->length ) + { + msg (D_TLS_ERRORS, "ASN1 ERROR: string contained terminating zero"); + OPENSSL_free (buf); + } else { + strncpynt(out, buf, size); + OPENSSL_free(buf); + retval = true; + } + break; + default: + msg (D_TLS_ERRORS, "ASN1 ERROR: can not handle field type %i", + name->type); + break; + } + } + sk_GENERAL_NAME_free (extensions); + } + return retval; +} +#endif + /* * Save X509 fields to environment, using the naming convention: * @@ -805,6 +860,20 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx) string_replace_leading (subject, '-', '_'); /* extract the username (default is CN) */ +#ifdef ENABLE_X509ALTUSERNAME + if (strncmp("ext:",x509_username_field,4) == 0) + { + if (!extract_x509_extension (ctx->current_cert, x509_username_field+4, common_name, sizeof(common_name))) + { + msg (D_TLS_ERRORS, "VERIFY ERROR: could not extract %s extension from X509 subject string ('%s') " + "-- note that the username length is limited to %d characters", + x509_username_field+4, + subject, + TLS_USERNAME_LEN); + goto err; + } + } else +#endif if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), x509_username_field, common_name, sizeof(common_name))) { if (!ctx->error_depth)