Please send this patch as an attachment to [email protected].  This will
track it as a ticket.

-Kyle H

On Tue, Mar 3, 2009 at 2:37 PM, Oliver Martin <[email protected]> wrote:
> Hello,
>
> this patch adds support for GeneralizedTime for startdate/enddate in
> openssl ca. I submitted an earlier version to openssl-users a bit more
> than a week ago [1] but got no reaction there, so I'll try again here.
> Any chance of getting something like this accepted? I guess not too
> many people need certificates beyond 2049 (or before 1950) right now,
> but having the capability surely can't hurt.
>
> Also, previously it accepted non-GMT times and values without seconds,
> both of which are not allowed by RFC 5280 (and previous ones). This is
> fixed too.
>
> Regards,
> Oliver
>
> [1] http://marc.info/?l=openssl-users&m=123532280026134&w=2
>
>
> --- openssl-SNAP-20090303.orig/apps/ca.c        2009-03-03 19:04:00.000000000 
> +0100
> +++ openssl-SNAP-20090303/apps/ca.c     2009-03-03 23:04:24.000000000 +0100
> @@ -227,6 +227,9 @@
>  static int get_certificate_status(const char *ser_status, CA_DB *db);
>  static int do_updatedb(CA_DB *db);
>  static int check_time_format(const char *str);
> +static int check_time_valid_rfc(const char *str, int numcnt);
> +static int check_utctime(const char *str);
> +static int check_generalizedtime(const char *str);
>  char *make_revocation_str(int rev_type, char *rev_arg);
>  int make_revoked(X509_REVOKED *rev, const char *str);
>  int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
> @@ -1109,9 +1112,10 @@
>                        if (startdate == NULL)
>                                ERR_clear_error();
>                        }
> -               if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
> +               if (startdate && !((ASN1_UTCTIME_set_string(NULL, startdate) 
> && check_utctime(startdate))
> +                               || (ASN1_GENERALIZEDTIME_set_string(NULL, 
> startdate) && check_generalizedtime(startdate))))
>                        {
> -                       BIO_printf(bio_err,"start date is invalid, it should 
> be YYMMDDHHMMSSZ\n");
> +                       BIO_printf(bio_err,"start date is invalid, it should 
> be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
>                        goto err;
>                        }
>                if (startdate == NULL) startdate="today";
> @@ -1123,9 +1127,10 @@
>                        if (enddate == NULL)
>                                ERR_clear_error();
>                        }
> -               if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
> +               if (enddate && !((ASN1_UTCTIME_set_string(NULL, enddate) && 
> check_utctime(enddate))
> +                               || (ASN1_GENERALIZEDTIME_set_string(NULL, 
> startdate) && check_generalizedtime(enddate))))
>                        {
> -                       BIO_printf(bio_err,"end date is invalid, it should be 
> YYMMDDHHMMSSZ\n");
> +                       BIO_printf(bio_err,"end date is invalid, it should be 
> YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
>                        goto err;
>                        }
>
> @@ -1689,6 +1694,7 @@
>        STRING *irow=NULL;
>        STRING *rrow=NULL;
>        char buf[25];
> +       int year;
>
>        tmptm=ASN1_UTCTIME_new();
>        if (tmptm == NULL)
> @@ -2007,11 +2013,39 @@
>
>        if (strcmp(startdate,"today") == 0)
>                X509_gmtime_adj(X509_get_notBefore(ret),0);
> -       else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
> +       else
> +               {
> +               if 
> (!ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate))
> +                       {
> +                       if (sscanf(startdate, "%4u", &year) != 1)
> +                               goto err;
> +                       if (year >= 1950 && year <= 2049)
> +                               {
> +                               memmove(startdate, startdate + 2, 
> strlen(startdate) - 1);
> +                               
> ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
> +                               }
> +                       else
> +                               
> ASN1_GENERALIZEDTIME_set_string(X509_get_notBefore(ret),startdate);
> +                       }
> +               }
>
>        if (enddate == NULL)
>                X509_time_adj_ex(X509_get_notAfter(ret),days, 0, NULL);
> -       else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
> +       else
> +               {
> +               if (!ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate))
> +                       {
> +                       if (sscanf(enddate, "%4u", &year) != 1)
> +                               goto err;
> +                       if (year >= 1950 && year <= 2049)
> +                               {
> +                               memmove(enddate, enddate + 2, strlen(enddate) 
> - 1);
> +                               
> ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
> +                               }
> +                       else
> +                               
> ASN1_GENERALIZEDTIME_set_string(X509_get_notAfter(ret),enddate);
> +                       }
> +               }
>
>        if (!X509_set_subject_name(ret,subject)) goto err;
>
> @@ -2107,7 +2141,7 @@
>                }
>
>        BIO_printf(bio_err,"Certificate is to be certified until ");
> -       ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
> +       ASN1_TIME_print(bio_err,X509_get_notAfter(ret));
>        if (days) BIO_printf(bio_err," (%ld days)",days);
>        BIO_printf(bio_err, "\n");
>
> @@ -2398,11 +2432,15 @@
>  static int check_time_format(const char *str)
>        {
>        ASN1_UTCTIME tm;
> +       ASN1_GENERALIZEDTIME gtm;
>
>        tm.data=(unsigned char *)str;
>        tm.length=strlen(str);
>        tm.type=V_ASN1_UTCTIME;
> -       return(ASN1_UTCTIME_check(&tm));
> +       gtm.data=(unsigned char *)str;
> +       gtm.length=strlen(str);
> +       gtm.type=V_ASN1_GENERALIZEDTIME;
> +       return(ASN1_UTCTIME_check(&tm) || ASN1_GENERALIZEDTIME_check(&gtm));
>        }
>
>  static int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
> @@ -3005,3 +3043,32 @@
>
>        return ret;
>        }
> +
> +/* As per RFC 5280, both UTCTime and GeneralizedTime must include seconds 
> and be
> + * specified in GMT; additionally, the latter must not include fractional 
> seconds.
> + */
> +static int check_time_valid_rfc(const char *str, int numcnt)
> +       {
> +       int i;
> +
> +       if (strlen(str) != numcnt + 1)
> +               return 0;
> +       if (str[numcnt] != 'Z')
> +               return 0;
> +       for (i = 0; i < numcnt; i++)
> +               {
> +                       if (str[i] < '0' || str[i] > '9')
> +                               return 0;
> +               }
> +       return 1;
> +       }
> +
> +static int check_utctime(const char *str)
> +       {
> +               return check_time_valid_rfc(str, 12);
> +       }
> +
> +static int check_generalizedtime(const char *str)
> +       {
> +               return check_time_valid_rfc(str, 14);
> +       }
>

Reply via email to