Fossil SCM
Display SSL certificate validity timestamps in ISO8601 format
Commit
d847300f3b59fa136536f6d48a8472dfbacfc84d783dba5354530713d44d3d56
Parent
a517c30c794adb8…
1 file changed
+44
-4
+44
-4
| --- src/http_ssl.c | ||
| +++ src/http_ssl.c | ||
| @@ -89,10 +89,50 @@ | ||
| 89 | 89 | "authentication. Specify the pathname to a file containing the PEM " |
| 90 | 90 | "encoded certificate and private key with the --ssl-identity option " |
| 91 | 91 | "or the ssl-identity setting."); |
| 92 | 92 | return 0; /* no cert available */ |
| 93 | 93 | } |
| 94 | + | |
| 95 | +/* | |
| 96 | +** Convert an OpenSSL ASN1_TIME to an ISO8601 timestamp. | |
| 97 | +** | |
| 98 | +** Per RFC 5280, ASN1 timestamps in X.509 certificates must | |
| 99 | +** be in UTC (Zulu timezone) with no fractional seconds. | |
| 100 | +** | |
| 101 | +** If showUtc==1, add " UTC" at the end of the returned string. This is | |
| 102 | +** not ISO8601-compliant, but makes the displayed value more user-friendly. | |
| 103 | +*/ | |
| 104 | +static const char *ssl_asn1time_to_iso8601(const ASN1_TIME *asn1_time, | |
| 105 | + int showUtc){ | |
| 106 | + assert( showUtc==0 || showUtc==1 ); | |
| 107 | + if( !ASN1_TIME_check(asn1_time) ){ | |
| 108 | + return mprintf("Bad time value"); | |
| 109 | + }else{ | |
| 110 | + char res[20]; | |
| 111 | + char *pr = res; | |
| 112 | + char *pt = (char *)asn1_time->data; | |
| 113 | + /* 0123456789 1234 | |
| 114 | + ** UTCTime: YYMMDDHHMMSSZ (YY >= 50 ? 19YY : 20YY) | |
| 115 | + ** GeneralizedTime: YYYYMMDDHHMMSSZ */ | |
| 116 | + if( asn1_time->length < 15 ){ | |
| 117 | + /* UTCTime, fill out century digits */ | |
| 118 | + *pr++ = pt[0]>='5' ? '1' : '2'; | |
| 119 | + *pr++ = pt[0]>='5' ? '9' : '0'; | |
| 120 | + }else{ | |
| 121 | + /* GeneralizedTime, copy century digits and advance source */ | |
| 122 | + *pr++ = pt[0]; *pr++ = pt[1]; | |
| 123 | + pt += 2; | |
| 124 | + } | |
| 125 | + *pr++ = pt[0]; *pr++ = pt[1]; *pr++ = '-'; | |
| 126 | + *pr++ = pt[2]; *pr++ = pt[3]; *pr++ = '-'; | |
| 127 | + *pr++ = pt[4]; *pr++ = pt[5]; *pr++ = ' '; | |
| 128 | + *pr++ = pt[6]; *pr++ = pt[7]; *pr++ = ':'; | |
| 129 | + *pr++ = pt[8]; *pr++ = pt[9]; *pr++ = ':'; | |
| 130 | + *pr++ = pt[10]; *pr++ = pt[11]; *pr = '\0'; | |
| 131 | + return mprintf("%s%s", res, (showUtc ? " UTC" : "")); | |
| 132 | + } | |
| 133 | +} | |
| 94 | 134 | |
| 95 | 135 | /* |
| 96 | 136 | ** Call this routine once before any other use of the SSL interface. |
| 97 | 137 | ** This routine does initial configuration of the SSL module. |
| 98 | 138 | */ |
| @@ -382,14 +422,14 @@ | ||
| 382 | 422 | mem = BIO_new(BIO_s_mem()); |
| 383 | 423 | BIO_puts(mem, " subject: "); |
| 384 | 424 | X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0, XN_FLAG_ONELINE); |
| 385 | 425 | BIO_puts(mem, "\n issuer: "); |
| 386 | 426 | X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE); |
| 387 | - BIO_puts(mem, "\n notBefore: "); | |
| 388 | - ASN1_TIME_print(mem, X509_get_notBefore(cert)); | |
| 389 | - BIO_puts(mem, "\n notAfter: "); | |
| 390 | - ASN1_TIME_print(mem, X509_get_notAfter(cert)); | |
| 427 | + BIO_printf(mem, "\n notBefore: %s", | |
| 428 | + ssl_asn1time_to_iso8601(X509_get_notBefore(cert), 1)); | |
| 429 | + BIO_printf(mem, "\n notAfter: %s", | |
| 430 | + ssl_asn1time_to_iso8601(X509_get_notAfter(cert), 1)); | |
| 391 | 431 | BIO_printf(mem, "\n sha256: %s", zHash); |
| 392 | 432 | desclen = BIO_get_mem_data(mem, &desc); |
| 393 | 433 | |
| 394 | 434 | prompt = mprintf("Unable to verify SSL cert from %s\n%.*s\n" |
| 395 | 435 | "accept this cert and continue (y/N/fingerprint)? ", |
| 396 | 436 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -89,10 +89,50 @@ | |
| 89 | "authentication. Specify the pathname to a file containing the PEM " |
| 90 | "encoded certificate and private key with the --ssl-identity option " |
| 91 | "or the ssl-identity setting."); |
| 92 | return 0; /* no cert available */ |
| 93 | } |
| 94 | |
| 95 | /* |
| 96 | ** Call this routine once before any other use of the SSL interface. |
| 97 | ** This routine does initial configuration of the SSL module. |
| 98 | */ |
| @@ -382,14 +422,14 @@ | |
| 382 | mem = BIO_new(BIO_s_mem()); |
| 383 | BIO_puts(mem, " subject: "); |
| 384 | X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0, XN_FLAG_ONELINE); |
| 385 | BIO_puts(mem, "\n issuer: "); |
| 386 | X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE); |
| 387 | BIO_puts(mem, "\n notBefore: "); |
| 388 | ASN1_TIME_print(mem, X509_get_notBefore(cert)); |
| 389 | BIO_puts(mem, "\n notAfter: "); |
| 390 | ASN1_TIME_print(mem, X509_get_notAfter(cert)); |
| 391 | BIO_printf(mem, "\n sha256: %s", zHash); |
| 392 | desclen = BIO_get_mem_data(mem, &desc); |
| 393 | |
| 394 | prompt = mprintf("Unable to verify SSL cert from %s\n%.*s\n" |
| 395 | "accept this cert and continue (y/N/fingerprint)? ", |
| 396 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -89,10 +89,50 @@ | |
| 89 | "authentication. Specify the pathname to a file containing the PEM " |
| 90 | "encoded certificate and private key with the --ssl-identity option " |
| 91 | "or the ssl-identity setting."); |
| 92 | return 0; /* no cert available */ |
| 93 | } |
| 94 | |
| 95 | /* |
| 96 | ** Convert an OpenSSL ASN1_TIME to an ISO8601 timestamp. |
| 97 | ** |
| 98 | ** Per RFC 5280, ASN1 timestamps in X.509 certificates must |
| 99 | ** be in UTC (Zulu timezone) with no fractional seconds. |
| 100 | ** |
| 101 | ** If showUtc==1, add " UTC" at the end of the returned string. This is |
| 102 | ** not ISO8601-compliant, but makes the displayed value more user-friendly. |
| 103 | */ |
| 104 | static const char *ssl_asn1time_to_iso8601(const ASN1_TIME *asn1_time, |
| 105 | int showUtc){ |
| 106 | assert( showUtc==0 || showUtc==1 ); |
| 107 | if( !ASN1_TIME_check(asn1_time) ){ |
| 108 | return mprintf("Bad time value"); |
| 109 | }else{ |
| 110 | char res[20]; |
| 111 | char *pr = res; |
| 112 | char *pt = (char *)asn1_time->data; |
| 113 | /* 0123456789 1234 |
| 114 | ** UTCTime: YYMMDDHHMMSSZ (YY >= 50 ? 19YY : 20YY) |
| 115 | ** GeneralizedTime: YYYYMMDDHHMMSSZ */ |
| 116 | if( asn1_time->length < 15 ){ |
| 117 | /* UTCTime, fill out century digits */ |
| 118 | *pr++ = pt[0]>='5' ? '1' : '2'; |
| 119 | *pr++ = pt[0]>='5' ? '9' : '0'; |
| 120 | }else{ |
| 121 | /* GeneralizedTime, copy century digits and advance source */ |
| 122 | *pr++ = pt[0]; *pr++ = pt[1]; |
| 123 | pt += 2; |
| 124 | } |
| 125 | *pr++ = pt[0]; *pr++ = pt[1]; *pr++ = '-'; |
| 126 | *pr++ = pt[2]; *pr++ = pt[3]; *pr++ = '-'; |
| 127 | *pr++ = pt[4]; *pr++ = pt[5]; *pr++ = ' '; |
| 128 | *pr++ = pt[6]; *pr++ = pt[7]; *pr++ = ':'; |
| 129 | *pr++ = pt[8]; *pr++ = pt[9]; *pr++ = ':'; |
| 130 | *pr++ = pt[10]; *pr++ = pt[11]; *pr = '\0'; |
| 131 | return mprintf("%s%s", res, (showUtc ? " UTC" : "")); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | /* |
| 136 | ** Call this routine once before any other use of the SSL interface. |
| 137 | ** This routine does initial configuration of the SSL module. |
| 138 | */ |
| @@ -382,14 +422,14 @@ | |
| 422 | mem = BIO_new(BIO_s_mem()); |
| 423 | BIO_puts(mem, " subject: "); |
| 424 | X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0, XN_FLAG_ONELINE); |
| 425 | BIO_puts(mem, "\n issuer: "); |
| 426 | X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE); |
| 427 | BIO_printf(mem, "\n notBefore: %s", |
| 428 | ssl_asn1time_to_iso8601(X509_get_notBefore(cert), 1)); |
| 429 | BIO_printf(mem, "\n notAfter: %s", |
| 430 | ssl_asn1time_to_iso8601(X509_get_notAfter(cert), 1)); |
| 431 | BIO_printf(mem, "\n sha256: %s", zHash); |
| 432 | desclen = BIO_get_mem_data(mem, &desc); |
| 433 | |
| 434 | prompt = mprintf("Unable to verify SSL cert from %s\n%.*s\n" |
| 435 | "accept this cert and continue (y/N/fingerprint)? ", |
| 436 |