You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/06/27 23:36:59 UTC
svn commit: r1606252 - in /subversion/branches/svn-auth-x509/subversion:
libsvn_subr/x509.h libsvn_subr/x509parse.c tests/libsvn_subr/x509-test.c
Author: breser
Date: Fri Jun 27 21:36:58 2014
New Revision: 1606252
URL: http://svn.apache.org/r1606252
Log:
On svn-auth-x509 branch, Support GeneralizedTime format for validity dates.
* subversion/tests/libsvn_subr/x509-test.c
(cert_tests): Add a cert with a GeneralizedTime format date.
* subversion/libsvn_subr/x509.h
(ASN1_GENERALIZED_TIME): New macro.
(x509_utc_to_apr_time): Remove function.
(x509_get_date): New function, that supports retrieving one date
in UTCTime or GeneralizedTime and converts it to an apr_time_t. While
doing this get rid of the static buffer and memset/memcpy. Use the
more specific apr_time_exp_gmt_get() in preference to the ambigously
named apr_time_exp_get().
(x509_get_dates): Use x509_get_date(), reorder arguments to our norm of
output arguments coming first, take a scratch_pool argument.
(svn_x509_parse_cert): Update x509_get_dates() calls to the new signature.
Modified:
subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h
subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c
subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h?rev=1606252&r1=1606251&r2=1606252&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h Fri Jun 27 21:36:58 2014
@@ -58,6 +58,7 @@
#define ASN1_T61_STRING 0x14
#define ASN1_IA5_STRING 0x16
#define ASN1_UTC_TIME 0x17
+#define ASN1_GENERALIZED_TIME 0x18
#define ASN1_UNIVERSAL_STRING 0x1C
#define ASN1_BMP_STRING 0x1E
#define ASN1_PRIMITIVE 0x00
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c?rev=1606252&r1=1606251&r2=1606252&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c Fri Jun 27 21:36:58 2014
@@ -343,19 +343,68 @@ x509_get_name(const unsigned char **p, c
return svn_error_trace(x509_get_name(p, end2, cur->next, result_pool));
}
-/* Convert from X.509 UTCTime to apr_time_t.
- * X.509 UTCTime is defined in RFC 5280 § 4.1.2.5.1 */
+/* Retrieve the date from the X.509 cert data between *P and END in either
+ * UTCTime or GeneralizedTime format (as defined in RFC 5280 § 4.1.2.5.1 and
+ * 4.1.2.5.2 respectively) and place the result in WHEN using SCRATCH_POOL
+ * for temporary allocations. */
static svn_error_t *
-x509_utc_to_apr_time(apr_time_t *time, const char *date)
+x509_get_date(apr_time_t *when,
+ const unsigned char **p,
+ const unsigned char *end,
+ apr_pool_t *scratch_pool)
{
- apr_time_exp_t xt = { 0 };
+ svn_error_t *err;
apr_status_t ret;
+ int len, tag;
+ char *date;
+ apr_time_exp_t xt = { 0 };
char tz;
- if (sscanf(date, "%2d%2d%2d%2d%2d%2d%c",
- &xt.tm_year, &xt.tm_mon, &xt.tm_mday,
- &xt.tm_hour, &xt.tm_min, &xt.tm_sec, &tz) < 6)
- return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, NULL, NULL);
+ tag = **p;
+ err = asn1_get_tag(p, end, &len, ASN1_UTC_TIME);
+ if (err && err->apr_err == SVN_ERR_ASN1_UNEXPECTED_TAG)
+ {
+ svn_error_clear(err);
+ tag = **p;
+ err = asn1_get_tag(p, end, &len, ASN1_GENERALIZED_TIME);
+ }
+ if (err)
+ return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, err, NULL);
+
+ date = apr_pstrndup(scratch_pool, (const char *) *p, len);
+ switch (tag)
+ {
+ case ASN1_UTC_TIME:
+ if (sscanf(date, "%2d%2d%2d%2d%2d%2d%c",
+ &xt.tm_year, &xt.tm_mon, &xt.tm_mday,
+ &xt.tm_hour, &xt.tm_min, &xt.tm_sec, &tz) < 6)
+ return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, NULL, NULL);
+
+ /* UTCTime only provides a 2 digit year. X.509 specifies that years
+ * greater than or equal to 50 must be interpreted as 19YY and years
+ * less than 50 be interpreted as 20YY. This format is not used for
+ * years greater than 2049. apr_time_exp_t wants years as the number
+ * of years since 1900, so don't convert to 4 digits here. */
+ xt.tm_year += 100 * (xt.tm_year < 50);
+ break;
+
+ case ASN1_GENERALIZED_TIME:
+ if (sscanf(date, "%4d%2d%2d%2d%2d%2d%c",
+ &xt.tm_year, &xt.tm_mon, &xt.tm_mday,
+ &xt.tm_hour, &xt.tm_min, &xt.tm_sec, &tz) < 6)
+ return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, NULL, NULL);
+
+ /* GeneralizedTime has the full 4 digit year. But apr_time_exp_t
+ * wants years as the number of years since 1900. */
+ xt.tm_year -= 1900;
+ break;
+
+ default:
+ /* shouldn't ever get here because we should error out above in the
+ * asn1_get_tag() bits but doesn't hurt to be extra paranoid. */
+ return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, NULL, NULL);
+ break;
+ }
/* check that the timezone is GMT
* ASN.1 allows for the timezone to be specified but X.509 says it must
@@ -364,20 +413,15 @@ x509_utc_to_apr_time(apr_time_t *time, c
if (tz != 'Z')
return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, NULL, NULL);
- /* UTCTime only provides a 2 digit year. X.509 specifies that years
- * greater than or equal to 50 must be interpreted as 19YY and years less
- * than 50 be interpreted as 20YY. This format is not used for years
- * greater than 2049. apr_time_exp_t wants years as the number of years
- * since 1900, so don't convert to 4 digits here. */
- xt.tm_year += 100 * (xt.tm_year < 50);
-
/* apr_time_exp_t expects months to be zero indexed, 0=Jan, 11=Dec. */
xt.tm_mon -= 1;
- ret = apr_time_exp_get(time, &xt);
+ ret = apr_time_exp_gmt_get(when, &xt);
if (ret)
return svn_error_wrap_apr(ret, NULL);
+ *p += len;
+
return SVN_NO_ERROR;
}
@@ -391,12 +435,14 @@ x509_utc_to_apr_time(apr_time_t *time, c
* generalTime GeneralizedTime }
*/
static svn_error_t *
-x509_get_dates(const unsigned char **p,
- const unsigned char *end, apr_time_t * from, apr_time_t * to)
+x509_get_dates(apr_time_t *from,
+ apr_time_t *to,
+ const unsigned char **p,
+ const unsigned char *end,
+ apr_pool_t *scratch_pool)
{
svn_error_t *err;
int len;
- char date[64];
err = asn1_get_tag(p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
if (err)
@@ -404,28 +450,9 @@ x509_get_dates(const unsigned char **p,
end = *p + len;
- /*
- * TODO: also handle GeneralizedTime
- */
- err = asn1_get_tag(p, end, &len, ASN1_UTC_TIME);
- if (err)
- return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, err, NULL);
-
- memset(date, 0, sizeof(date));
- memcpy(date, *p, (len < (int)sizeof(date) - 1) ?
- len : (int)sizeof(date) - 1);
- SVN_ERR(x509_utc_to_apr_time(from, date));
- *p += len;
-
- err = asn1_get_tag(p, end, &len, ASN1_UTC_TIME);
- if (err)
- return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, err, NULL);
+ SVN_ERR(x509_get_date(from, p, end, scratch_pool));
- memset(date, 0, sizeof(date));
- memcpy(date, *p, (len < (int)sizeof(date) - 1) ?
- len : (int)sizeof(date) - 1);
- SVN_ERR(x509_utc_to_apr_time(to, date));
- *p += len;
+ SVN_ERR(x509_get_date(to, p, end, scratch_pool));
if (*p != end)
{
@@ -684,7 +711,8 @@ svn_x509_parse_cert(apr_hash_t **certinf
* notAfter Time }
*
*/
- SVN_ERR(x509_get_dates(&p, end, &crt->valid_from, &crt->valid_to));
+ SVN_ERR(x509_get_dates(&crt->valid_from, &crt->valid_to, &p, end,
+ scratch_pool));
/*
* subject Name
Modified: subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c?rev=1606252&r1=1606251&r2=1606252&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c (original)
+++ subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c Fri Jun 27 21:36:58 2014
@@ -76,6 +76,34 @@ static struct x509_test cert_tests[] = {
"C=US, O=Thawte, Inc., CN=Thawte SSL CA",
"2014-04-11T00:00:00.000000Z",
"2016-04-07T23:59:59.000000Z" },
+ /* the expiration is after 2049 so the expiration is in the
+ * generalized format, while the start date is still in the UTC
+ * format. Note this is actually a CA cert but that really doesn't
+ * matter here. */
+ { "timestamp-after-2049",
+ "MIIDtzCCAp+gAwIBAgIJAJKX85dqh3RvMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV"
+ "BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX"
+ "aWRnaXRzIFB0eSBMdGQwIBcNMTQwNjI3MTczMTUxWhgPMjExNDA2MDMxNzMxNTFa"
+ "MEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJ"
+ "bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw"
+ "ggEKAoIBAQDaa4gwNBB6vgWrlOIEMdzvD06zmmiocEt6UnTHtmAcfrBuDnKrBwEh"
+ "f5JxneL16XIuKwK6n/4omBtem/PPjjpOLM9PMQuoO0cpQ0UGFnfpmko6PSQoqRHl"
+ "qTbDGv4usn7qdZV+FKz/B9CMonRSzWHMz5YPmqfob6BqaaJY/qJEzHJA24bm4jPH"
+ "IsaVCInEGpqAUpejwBzNujfbLibBNrVX7K846zk+tnsNR90kP5h3IRP3SdWVywKC"
+ "AMN2izzhmaDhuPzaTBobovr+ySJShmX6gdB5PpWkm6rcBl6RJ+tM0ZBSJjQvkYp4"
+ "seV+rcXFgpJP/aQL3vhDON32tjWh3A2JAgMBAAGjgacwgaQwHQYDVR0OBBYEFF+N"
+ "7TyDI8THpAbx1pfzFFtl5z4iMHUGA1UdIwRuMGyAFF+N7TyDI8THpAbx1pfzFFtl"
+ "5z4ioUmkRzBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8G"
+ "A1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkggkAkpfzl2qHdG8wDAYDVR0T"
+ "BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAo4t9fYe2I+XIQn8i/KI9UFEE9fue"
+ "w6rQMnf9yyd8nwL+IcV84hvyNrq0+7SptUBMq3rsEf5UIBIBI4Oa614mJ/Kt976O"
+ "S7Sa1IPH7j+zb/jqH/xGskEVi25dZz7psFCmi7Hm9dnVz9YKa2yLW6R2KZcTVxCx"
+ "SSdDRlD7SonsYeq2fGrAo7Y9xfZsiJ2ZbJ18kHs2coMWuhgSrN9jrML6mb5B+k22"
+ "/rgsCJgFsBDPBYR3ju0Ahqg7v6kwg9O2PJzyb4ljsw8oI0sCwHTZW5I5FMq2D9g6"
+ "hj80N2fhS9QWoLyeKoMTNB2Do6VaNrLrCJiscZWrsnM1f+XBqV8hMuHX8A==",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2014-06-27T17:31:51.000000Z",
+ "2114-06-03T17:31:51.000000Z" },
{ NULL }
};