static int todigit(variant_char c) { if (ossl_isdigit(c)) return c - '0'; else if (ossl_isxdigit(c)) return ossl_tolower(c) - 'a' + 10; /* return largest base value to make caller terminate the loop */ return 16; }
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) { char *v; int gmt = 0, l; struct tm stm; if (!asn1_time_to_tm(&stm, tm)) { /* asn1_time_to_tm will check the time type */ goto err; } l = tm->length; v = (char *)tm->data; if (v[l - 1] == 'Z') gmt = 1; if (tm->type == V_ASN1_GENERALIZEDTIME) { char *f = NULL; int f_len = 0; /* * Try to parse fractional seconds. '14' is the place of * 'fraction point' in a GeneralizedTime string. */ if (tm->length > 15 && v[14] == '.') { f = &v[14]; f_len = 1; while (14 + f_len < l && ossl_isdigit(f[f_len])) ++f_len; } return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s", _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour, stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900, (gmt ? " GMT" : "")) > 0; } else { return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour, stm.tm_min, stm.tm_sec, stm.tm_year + 1900, (gmt ? " GMT" : "")) > 0; } err: BIO_write(bp, "Bad time value", 14); return 0; }
static int type_str(unsigned long value, void *arg) { unsigned long types = *((unsigned long *)arg); const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value); if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native) || native == ' ')) types &= ~B_ASN1_NUMERICSTRING; if ((types & B_ASN1_PRINTABLESTRING) && !ossl_isasn1print(native)) types &= ~B_ASN1_PRINTABLESTRING; if ((types & B_ASN1_IA5STRING) && !ossl_isascii(native)) types &= ~B_ASN1_IA5STRING; if ((types & B_ASN1_T61STRING) && (value > 0xff)) types &= ~B_ASN1_T61STRING; if ((types & B_ASN1_BMPSTRING) && (value > 0xffff)) types &= ~B_ASN1_BMPSTRING; if (!types) return -1; *((unsigned long *)arg) = types; return 1; }
static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name) { const char *p = NULL; /* If there are no search criteria, all names are accepted */ if (ctx->_.dir.search_name[0] == '\0') return 1; /* If the expected type isn't supported, no name is accepted */ if (ctx->expected_type != 0 && ctx->expected_type != OSSL_STORE_INFO_CERT && ctx->expected_type != OSSL_STORE_INFO_CRL) return 0; /* * First, check the basename */ if (strncasecmp(name, ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name) - 1) != 0 || name[sizeof(ctx->_.dir.search_name) - 1] != '.') return 0; p = &name[sizeof(ctx->_.dir.search_name)]; /* * Then, if the expected type is a CRL, check that the extension starts * with 'r' */ if (*p == 'r') { p++; if (ctx->expected_type != 0 && ctx->expected_type != OSSL_STORE_INFO_CRL) return 0; } else if (ctx->expected_type == OSSL_STORE_INFO_CRL) { return 0; } /* * Last, check that the rest of the extension is a decimal number, at * least one digit long. */ if (!ossl_isdigit(*p)) return 0; while (ossl_isdigit(*p)) p++; # ifdef __VMS /* * One extra step here, check for a possible generation number. */ if (*p == ';') for (p++; *p != '\0'; p++) if (!ossl_isdigit(*p)) break; # endif /* * If we've reached the end of the string at this point, we've successfully * found a fitting file name. */ return *p == '\0'; }
int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) { static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 }; static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; char *a; int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md; struct tm tmp; /* * ASN1_STRING_FLAG_X509_TIME is used to enforce RFC 5280 * time string format, in which: * * 1. "seconds" is a 'MUST' * 2. "Zulu" timezone is a 'MUST' * 3. "+|-" is not allowed to indicate a time zone */ if (d->type == V_ASN1_UTCTIME) { if (d->flags & ASN1_STRING_FLAG_X509_TIME) { min_l = 13; strict = 1; } } else if (d->type == V_ASN1_GENERALIZEDTIME) { end = 7; btz = 6; if (d->flags & ASN1_STRING_FLAG_X509_TIME) { min_l = 15; strict = 1; } else { min_l = 13; } } else { return 0; } l = d->length; a = (char *)d->data; o = 0; memset(&tmp, 0, sizeof(tmp)); /* * GENERALIZEDTIME is similar to UTCTIME except the year is represented * as YYYY. This stuff treats everything as a two digit field so make * first two fields 00 to 99 */ if (l < min_l) goto err; for (i = 0; i < end; i++) { if (!strict && (i == btz) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { i++; break; } if (!ossl_isdigit(a[o])) goto err; n = a[o] - '0'; /* incomplete 2-digital number */ if (++o == l) goto err; if (!ossl_isdigit(a[o])) goto err; n = (n * 10) + a[o] - '0'; /* no more bytes to read, but we haven't seen time-zone yet */ if (++o == l) goto err; i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i; if ((n < min[i2]) || (n > max[i2])) goto err; switch (i2) { case 0: /* UTC will never be here */ tmp.tm_year = n * 100 - 1900; break; case 1: if (d->type == V_ASN1_UTCTIME) tmp.tm_year = n < 50 ? n + 100 : n; else tmp.tm_year += n; break; case 2: tmp.tm_mon = n - 1; break; case 3: /* check if tm_mday is valid in tm_mon */ if (tmp.tm_mon == 1) { /* it's February */ md = mdays[1] + leap_year(tmp.tm_year + 1900); } else { md = mdays[tmp.tm_mon]; } if (n > md) goto err; tmp.tm_mday = n; determine_days(&tmp); break; case 4: tmp.tm_hour = n; break; case 5: tmp.tm_min = n; break; case 6: tmp.tm_sec = n; break; } } /* * Optional fractional seconds: decimal point followed by one or more * digits. */ if (d->type == V_ASN1_GENERALIZEDTIME && a[o] == '.') { if (strict) /* RFC 5280 forbids fractional seconds */ goto err; if (++o == l) goto err; i = o; while ((o < l) && ossl_isdigit(a[o])) o++; /* Must have at least one digit after decimal point */ if (i == o) goto err; /* no more bytes to read, but we haven't seen time-zone yet */ if (o == l) goto err; } /* * 'o' will never point to '\0' at this point, the only chance * 'o' can point to '\0' is either the subsequent if or the first * else if is true. */ if (a[o] == 'Z') { o++; } else if (!strict && ((a[o] == '+') || (a[o] == '-'))) { int offsign = a[o] == '-' ? 1 : -1; int offset = 0; o++; /* * if not equal, no need to do subsequent checks * since the following for-loop will add 'o' by 4 * and the final return statement will check if 'l' * and 'o' are equal. */ if (o + 4 != l) goto err; for (i = end; i < end + 2; i++) { if (!ossl_isdigit(a[o])) goto err; n = a[o] - '0'; o++; if (!ossl_isdigit(a[o])) goto err; n = (n * 10) + a[o] - '0'; i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i; if ((n < min[i2]) || (n > max[i2])) goto err; /* if tm is NULL, no need to adjust */ if (tm != NULL) { if (i == end) offset = n * 3600; else if (i == end + 1) offset += n * 60; } o++; } if (offset && !OPENSSL_gmtime_adj(&tmp, 0, offset * offsign)) goto err; } else { /* not Z, or not +/- in non-strict mode */ goto err; } if (o == l) { /* success, check if tm should be filled */ if (tm != NULL) *tm = tmp; return 1; } err: return 0; }
static int _dopr(char **sbuffer, char **buffer, size_t *maxlen, size_t *retlen, int *truncated, const char *format, va_list args) { char ch; int64_t value; LDOUBLE fvalue; char *strvalue; int min; int max; int state; int flags; int cflags; size_t currlen; state = DP_S_DEFAULT; flags = currlen = cflags = min = 0; max = -1; ch = *format++; while (state != DP_S_DONE) { if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) state = DP_S_DONE; switch (state) { case DP_S_DEFAULT: if (ch == '%') state = DP_S_FLAGS; else if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) return 0; ch = *format++; break; case DP_S_FLAGS: switch (ch) { case '-': flags |= DP_F_MINUS; ch = *format++; break; case '+': flags |= DP_F_PLUS; ch = *format++; break; case ' ': flags |= DP_F_SPACE; ch = *format++; break; case '#': flags |= DP_F_NUM; ch = *format++; break; case '0': flags |= DP_F_ZERO; ch = *format++; break; default: state = DP_S_MIN; break; } break; case DP_S_MIN: if (ossl_isdigit(ch)) { min = 10 * min + char_to_int(ch); ch = *format++; } else if (ch == '*') { min = va_arg(args, int); ch = *format++; state = DP_S_DOT; } else state = DP_S_DOT; break; case DP_S_DOT: if (ch == '.') { state = DP_S_MAX; ch = *format++; } else state = DP_S_MOD; break; case DP_S_MAX: if (ossl_isdigit(ch)) { if (max < 0) max = 0; max = 10 * max + char_to_int(ch); ch = *format++; } else if (ch == '*') { max = va_arg(args, int); ch = *format++; state = DP_S_MOD; } else