In verify_callback, read X509 Subject Name without truncation.
In verify_callback, rather than silently truncating Common Name at
64 bytes, throw an error if Common Name is larger than 64 bytes.
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3084 e7ae566f-a301-0410-adde-c780ea21d3b5
| ... | ... |
@@ -347,8 +347,11 @@ tmp_rsa_cb (SSL * s, int is_export, int keylength) |
| 347 | 347 |
* /C=US/ST=CO/L=Denver/O=ORG/CN=First-CN/CN=Test-CA/Email=jim@yonan.net |
| 348 | 348 |
* |
| 349 | 349 |
* The common name is 'Test-CA' |
| 350 |
+ * |
|
| 351 |
+ * Return true on success, false on error (insufficient buffer size in 'out' |
|
| 352 |
+ * to contain result is grounds for error). |
|
| 350 | 353 |
*/ |
| 351 |
-static void |
|
| 354 |
+static bool |
|
| 352 | 355 |
extract_x509_field_ssl (X509_NAME *x509, const char *field_name, char *out, int size) |
| 353 | 356 |
{
|
| 354 | 357 |
int lastpos = -1; |
| ... | ... |
@@ -367,21 +370,26 @@ extract_x509_field_ssl (X509_NAME *x509, const char *field_name, char *out, int |
| 367 | 367 |
|
| 368 | 368 |
/* Nothing found */ |
| 369 | 369 |
if (lastpos == -1) |
| 370 |
- return; |
|
| 370 |
+ return false; |
|
| 371 | 371 |
|
| 372 | 372 |
x509ne = X509_NAME_get_entry(x509, lastpos); |
| 373 | 373 |
if (!x509ne) |
| 374 |
- return; |
|
| 374 |
+ return false; |
|
| 375 | 375 |
|
| 376 | 376 |
asn1 = X509_NAME_ENTRY_get_data(x509ne); |
| 377 | 377 |
if (!asn1) |
| 378 |
- return; |
|
| 378 |
+ return false; |
|
| 379 | 379 |
tmp = ASN1_STRING_to_UTF8(&buf, asn1); |
| 380 | 380 |
if (tmp <= 0) |
| 381 |
- return; |
|
| 381 |
+ return false; |
|
| 382 | 382 |
|
| 383 | 383 |
strncpynt(out, (char *)buf, size); |
| 384 |
- OPENSSL_free(buf); |
|
| 384 |
+ |
|
| 385 |
+ {
|
|
| 386 |
+ const bool ret = (strlen ((char *)buf) < size); |
|
| 387 |
+ OPENSSL_free (buf); |
|
| 388 |
+ return ret; |
|
| 389 |
+ } |
|
| 385 | 390 |
} |
| 386 | 391 |
|
| 387 | 392 |
static void |
| ... | ... |
@@ -529,7 +537,7 @@ print_nsCertType (int type) |
| 529 | 529 |
static int |
| 530 | 530 |
verify_callback (int preverify_ok, X509_STORE_CTX * ctx) |
| 531 | 531 |
{
|
| 532 |
- char subject[256]; |
|
| 532 |
+ char *subject = NULL; |
|
| 533 | 533 |
char envname[64]; |
| 534 | 534 |
char common_name[TLS_CN_LEN]; |
| 535 | 535 |
SSL *ssl; |
| ... | ... |
@@ -548,22 +556,28 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx) |
| 548 | 548 |
session->verified = false; |
| 549 | 549 |
|
| 550 | 550 |
/* get the X509 name */ |
| 551 |
- X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), subject, |
|
| 552 |
- sizeof (subject)); |
|
| 553 |
- subject[sizeof (subject) - 1] = '\0'; |
|
| 551 |
+ subject = X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), NULL, 0); |
|
| 552 |
+ if (!subject) |
|
| 553 |
+ {
|
|
| 554 |
+ msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, could not extract X509 subject string from certificate", ctx->error_depth); |
|
| 555 |
+ goto err; |
|
| 556 |
+ } |
|
| 554 | 557 |
|
| 555 | 558 |
/* enforce character class restrictions in X509 name */ |
| 556 | 559 |
string_mod (subject, X509_NAME_CHAR_CLASS, 0, '_'); |
| 557 | 560 |
string_replace_leading (subject, '-', '_'); |
| 558 | 561 |
|
| 559 |
- msg (M_INFO, "X509: '%s'", subject); // JYFIXME |
|
| 560 |
- |
|
| 561 | 562 |
/* extract the common name */ |
| 562 |
-#ifdef USE_OLD_EXTRACT_X509_FIELD |
|
| 563 |
- extract_x509_field (subject, "CN", common_name, TLS_CN_LEN); |
|
| 564 |
-#else |
|
| 565 |
- extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), "CN", common_name, TLS_CN_LEN); |
|
| 566 |
-#endif |
|
| 563 |
+ if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), "CN", common_name, TLS_CN_LEN)) |
|
| 564 |
+ {
|
|
| 565 |
+ if (!ctx->error_depth) |
|
| 566 |
+ {
|
|
| 567 |
+ msg (D_TLS_ERRORS, "VERIFY ERROR: could not extract Common Name from X509 subject string ('%s') -- note that the Common Name length is limited to %d characters",
|
|
| 568 |
+ subject, |
|
| 569 |
+ TLS_CN_LEN); |
|
| 570 |
+ goto err; |
|
| 571 |
+ } |
|
| 572 |
+ } |
|
| 567 | 573 |
|
| 568 | 574 |
string_mod (common_name, COMMON_NAME_CHAR_CLASS, 0, '_'); |
| 569 | 575 |
|
| ... | ... |
@@ -786,10 +800,12 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx) |
| 786 | 786 |
msg (D_HANDSHAKE, "VERIFY OK: depth=%d, %s", ctx->error_depth, subject); |
| 787 | 787 |
|
| 788 | 788 |
session->verified = true; |
| 789 |
+ free (subject); |
|
| 789 | 790 |
return 1; /* Accept connection */ |
| 790 | 791 |
|
| 791 | 792 |
err: |
| 792 | 793 |
ERR_clear_error (); |
| 794 |
+ free (subject); |
|
| 793 | 795 |
return 0; /* Reject connection */ |
| 794 | 796 |
} |
| 795 | 797 |
|
| ... | ... |
@@ -3291,7 +3307,14 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi |
| 3291 | 3291 |
s1 = verify_user_pass_plugin (session, up, raw_username); |
| 3292 | 3292 |
if (session->opt->auth_user_pass_verify_script) |
| 3293 | 3293 |
s2 = verify_user_pass_script (session, up); |
| 3294 |
- |
|
| 3294 |
+ |
|
| 3295 |
+ /* check sizing of username if it will become our common name */ |
|
| 3296 |
+ if (session->opt->username_as_common_name && strlen (up->username) >= TLS_CN_LEN) |
|
| 3297 |
+ {
|
|
| 3298 |
+ msg (D_TLS_ERRORS, "TLS Auth Error: --username-as-common name specified and username is longer than the maximum permitted Common Name length of %d characters", TLS_CN_LEN); |
|
| 3299 |
+ s1 = OPENVPN_PLUGIN_FUNC_ERROR; |
|
| 3300 |
+ } |
|
| 3301 |
+ |
|
| 3295 | 3302 |
/* auth succeeded? */ |
| 3296 | 3303 |
if ((s1 == OPENVPN_PLUGIN_FUNC_SUCCESS |
| 3297 | 3304 |
#ifdef PLUGIN_DEF_AUTH |
| ... | ... |
@@ -4783,25 +4806,6 @@ done: |
| 4783 | 4783 |
return BSTR (&out); |
| 4784 | 4784 |
} |
| 4785 | 4785 |
|
| 4786 |
-#ifdef EXTRACT_X509_FIELD_TEST |
|
| 4787 |
- |
|
| 4788 |
-void |
|
| 4789 |
-extract_x509_field_test (void) |
|
| 4790 |
-{
|
|
| 4791 |
- char line[8]; |
|
| 4792 |
- char field[4]; |
|
| 4793 |
- static const char field_name[] = "CN"; |
|
| 4794 |
- |
|
| 4795 |
- while (fgets (line, sizeof (line), stdin)) |
|
| 4796 |
- {
|
|
| 4797 |
- chomp (line); |
|
| 4798 |
- extract_x509_field (line, field_name, field, sizeof (field)); |
|
| 4799 |
- printf ("CN: '%s'\n", field);
|
|
| 4800 |
- } |
|
| 4801 |
-} |
|
| 4802 |
- |
|
| 4803 |
-#endif |
|
| 4804 |
- |
|
| 4805 | 4786 |
#else |
| 4806 | 4787 |
static void dummy(void) {}
|
| 4807 | 4788 |
#endif /* USE_CRYPTO && USE_SSL*/ |