X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fapps.c;h=c5a3bb27e476b4ca8b23760c2cf93e52ed954cba;hp=5dccea70d2be6d43492578fe5db565da71c05d2b;hb=e933f91f50108a43c0198cdc63ecdfdbc77b4d0d;hpb=245d2ee3d00eb72a13bc4f60a46aaaeba127056f diff --git a/apps/apps.c b/apps/apps.c index 5dccea70d2..c5a3bb27e4 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -109,7 +109,7 @@ * */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) #define _POSIX_C_SOURCE 2 /* On VMS, you need to define this to get the declaration of fileno(). The value 2 is to make sure no function defined @@ -118,7 +118,7 @@ #include #include #include -#if !defined(OPENSSL_SYSNAME_WIN32) && !defined(NETWARE_CLIB) +#if !defined(OPENSSL_SYSNAME_WIN32) && !defined(OPENSSL_SYSNAME_WINCE) && !defined(NETWARE_CLIB) #include #endif #include @@ -257,6 +257,8 @@ int args_from_file(char *file, int *argc, char **argv[]) int str2fmt(char *s) { + if (s == NULL) + return FORMAT_UNDEF; if ((*s == 'D') || (*s == 'd')) return(FORMAT_ASN1); else if ((*s == 'T') || (*s == 't')) @@ -273,6 +275,8 @@ int str2fmt(char *s) return(FORMAT_PKCS12); else if ((*s == 'E') || (*s == 'e')) return(FORMAT_ENGINE); + else if ((*s == 'H') || (*s == 'h')) + return FORMAT_HTTP; else if ((*s == 'P') || (*s == 'p')) { if (s[1] == 'V' || s[1] == 'v') @@ -377,13 +381,12 @@ void program_name(char *in, char *out, int size) int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[]) { - int num,len,i; + int num,i; char *p; *argc=0; *argv=NULL; - len=strlen(buf); i=0; if (arg->count == 0) { @@ -782,12 +785,80 @@ static int load_pkcs12(BIO *err, BIO *in, const char *desc, return ret; } +int load_cert_crl_http(const char *url, BIO *err, + X509 **pcert, X509_CRL **pcrl) + { + char *host = NULL, *port = NULL, *path = NULL; + BIO *bio = NULL; + OCSP_REQ_CTX *rctx = NULL; + int use_ssl, rv = 0; + if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl)) + goto err; + if (use_ssl) + { + if (err) + BIO_puts(err, "https not supported\n"); + goto err; + } + bio = BIO_new_connect(host); + if (!bio || !BIO_set_conn_port(bio, port)) + goto err; + rctx = OCSP_REQ_CTX_new(bio, 1024); + if (!rctx) + goto err; + if (!OCSP_REQ_CTX_http(rctx, "GET", path)) + goto err; + if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host)) + goto err; + if (pcert) + { + do + { + rv = X509_http_nbio(rctx, pcert); + } + while (rv == -1); + } + else + { + do + { + rv = X509_CRL_http_nbio(rctx, pcrl); + } while (rv == -1); + } + + err: + if (host) + OPENSSL_free(host); + if (path) + OPENSSL_free(path); + if (port) + OPENSSL_free(port); + if (bio) + BIO_free_all(bio); + if (rctx) + OCSP_REQ_CTX_free(rctx); + if (rv != 1) + { + if (bio && err) + BIO_printf(bio_err, "Error loading %s from %s\n", + pcert ? "certificate" : "CRL", url); + ERR_print_errors(bio_err); + } + return rv; + } + X509 *load_cert(BIO *err, const char *file, int format, const char *pass, ENGINE *e, const char *cert_descrip) { X509 *x=NULL; BIO *cert; + if (format == FORMAT_HTTP) + { + load_cert_crl_http(file, err, &x, NULL); + return x; + } + if ((cert=BIO_new(BIO_s_file())) == NULL) { ERR_print_errors(err); @@ -797,7 +868,9 @@ X509 *load_cert(BIO *err, const char *file, int format, if (file == NULL) { #ifdef _IONBF +# ifndef OPENSSL_NO_SETVBUF_IONBF setvbuf(stdin, NULL, _IONBF, 0); +# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ #endif BIO_set_fp(cert,stdin,BIO_NOCLOSE); } @@ -856,6 +929,55 @@ end: return(x); } +X509_CRL *load_crl(const char *infile, int format) + { + X509_CRL *x=NULL; + BIO *in=NULL; + + if (format == FORMAT_HTTP) + { + load_cert_crl_http(infile, bio_err, NULL, &x); + return x; + } + + in=BIO_new(BIO_s_file()); + if (in == NULL) + { + ERR_print_errors(bio_err); + goto end; + } + + if (infile == NULL) + BIO_set_fp(in,stdin,BIO_NOCLOSE); + else + { + if (BIO_read_filename(in,infile) <= 0) + { + perror(infile); + goto end; + } + } + if (format == FORMAT_ASN1) + x=d2i_X509_CRL_bio(in,NULL); + else if (format == FORMAT_PEM) + x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL); + else { + BIO_printf(bio_err,"bad input format specified for input crl\n"); + goto end; + } + if (x == NULL) + { + BIO_printf(bio_err,"unable to load CRL\n"); + ERR_print_errors(bio_err); + goto end; + } + +end: + BIO_free(in); + return(x); + } + + EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *key_descrip) { @@ -875,10 +997,17 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, if (format == FORMAT_ENGINE) { if (!e) - BIO_printf(bio_err,"no engine specified\n"); + BIO_printf(err,"no engine specified\n"); else + { pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data); + if (!pkey) + { + BIO_printf(err,"cannot load %s from engine\n",key_descrip); + ERR_print_errors(err); + } + } goto end; } #endif @@ -891,7 +1020,9 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, if (file == NULL && maybe_stdin) { #ifdef _IONBF +# ifndef OPENSSL_NO_SETVBUF_IONBF setvbuf(stdin, NULL, _IONBF, 0); +# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ #endif BIO_set_fp(key,stdin,BIO_NOCLOSE); } @@ -923,7 +1054,7 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, &pkey, NULL, NULL)) goto end; } -#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) else if (format == FORMAT_MSBLOB) pkey = b2i_PrivateKey_bio(key); else if (format == FORMAT_PVK) @@ -937,8 +1068,11 @@ EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, } end: if (key != NULL) BIO_free(key); - if (pkey == NULL) + if (pkey == NULL) + { BIO_printf(err,"unable to load %s\n", key_descrip); + ERR_print_errors(err); + } return(pkey); } @@ -977,7 +1111,9 @@ EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, if (file == NULL && maybe_stdin) { #ifdef _IONBF +# ifndef OPENSSL_NO_SETVBUF_IONBF setvbuf(stdin, NULL, _IONBF, 0); +# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ #endif BIO_set_fp(key,stdin,BIO_NOCLOSE); } @@ -1198,7 +1334,8 @@ STACK_OF(X509) *load_certs(BIO *err, const char *file, int format, const char *pass, ENGINE *e, const char *desc) { STACK_OF(X509) *certs; - load_certs_crls(err, file, format, pass, e, desc, &certs, NULL); + if (!load_certs_crls(err, file, format, pass, e, desc, &certs, NULL)) + return NULL; return certs; } @@ -1206,7 +1343,8 @@ STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format, const char *pass, ENGINE *e, const char *desc) { STACK_OF(X509_CRL) *crls; - load_certs_crls(err, file, format, pass, e, desc, NULL, &crls); + if (!load_certs_crls(err, file, format, pass, e, desc, NULL, &crls)) + return NULL; return crls; } @@ -2113,7 +2251,7 @@ X509_NAME *parse_name(char *subject, long chtype, int multirdn) X509_NAME *n = NULL; int nid; - if (!buf || !ne_types || !ne_values) + if (!buf || !ne_types || !ne_values || !mval) { BIO_printf(bio_err, "malloc error\n"); goto error; @@ -2217,6 +2355,7 @@ X509_NAME *parse_name(char *subject, long chtype, int multirdn) OPENSSL_free(ne_values); OPENSSL_free(ne_types); OPENSSL_free(buf); + OPENSSL_free(mval); return n; error: @@ -2225,6 +2364,8 @@ error: OPENSSL_free(ne_values); if (ne_types) OPENSSL_free(ne_types); + if (mval) + OPENSSL_free(mval); if (buf) OPENSSL_free(buf); return NULL; @@ -2239,6 +2380,10 @@ int args_verify(char ***pargs, int *pargc, int purpose = 0, depth = -1; char **oldargs = *pargs; char *arg = **pargs, *argn = (*pargs)[1]; + const X509_VERIFY_PARAM *vpm = NULL; + time_t at_time = 0; + const unsigned char *hostname = NULL, *email = NULL; + char *ipasc = NULL; if (!strcmp(arg, "-policy")) { if (!argn) @@ -2276,6 +2421,21 @@ int args_verify(char ***pargs, int *pargc, } (*pargs)++; } + else if (strcmp(arg,"-verify_name") == 0) + { + if (!argn) + *badarg = 1; + else + { + vpm = X509_VERIFY_PARAM_lookup(argn); + if(!vpm) + { + BIO_printf(err, "unrecognized verify name\n"); + *badarg = 1; + } + } + (*pargs)++; + } else if (strcmp(arg,"-verify_depth") == 0) { if (!argn) @@ -2291,6 +2451,48 @@ int args_verify(char ***pargs, int *pargc, } (*pargs)++; } + else if (strcmp(arg,"-attime") == 0) + { + if (!argn) + *badarg = 1; + else + { + long timestamp; + /* interpret the -attime argument as seconds since + * Epoch */ + if (sscanf(argn, "%li", ×tamp) != 1) + { + BIO_printf(bio_err, + "Error parsing timestamp %s\n", + argn); + *badarg = 1; + } + /* on some platforms time_t may be a float */ + at_time = (time_t) timestamp; + } + (*pargs)++; + } + else if (strcmp(arg,"-verify_hostname") == 0) + { + if (!argn) + *badarg = 1; + hostname = (unsigned char *)argn; + (*pargs)++; + } + else if (strcmp(arg,"-verify_email") == 0) + { + if (!argn) + *badarg = 1; + email = (unsigned char *)argn; + (*pargs)++; + } + else if (strcmp(arg,"-verify_ip") == 0) + { + if (!argn) + *badarg = 1; + ipasc = argn; + (*pargs)++; + } else if (!strcmp(arg, "-ignore_critical")) flags |= X509_V_FLAG_IGNORE_CRITICAL; else if (!strcmp(arg, "-issuer_checks")) @@ -2317,6 +2519,16 @@ int args_verify(char ***pargs, int *pargc, flags |= X509_V_FLAG_NOTIFY_POLICY; else if (!strcmp(arg, "-check_ss_sig")) flags |= X509_V_FLAG_CHECK_SS_SIGNATURE; + else if (!strcmp(arg, "-trusted_first")) + flags |= X509_V_FLAG_TRUSTED_FIRST; + else if (!strcmp(arg, "-suiteB_128_only")) + flags |= X509_V_FLAG_SUITEB_128_LOS_ONLY; + else if (!strcmp(arg, "-suiteB_128")) + flags |= X509_V_FLAG_SUITEB_128_LOS; + else if (!strcmp(arg, "-suiteB_192")) + flags |= X509_V_FLAG_SUITEB_192_LOS; + else if (!strcmp(arg, "-partial_chain")) + flags |= X509_V_FLAG_PARTIAL_CHAIN; else return 0; @@ -2334,6 +2546,9 @@ int args_verify(char ***pargs, int *pargc, goto end; } + if (vpm) + X509_VERIFY_PARAM_set1(*pm, vpm); + if (otmp) X509_VERIFY_PARAM_add0_policy(*pm, otmp); if (flags) @@ -2345,6 +2560,18 @@ int args_verify(char ***pargs, int *pargc, if (depth >= 0) X509_VERIFY_PARAM_set_depth(*pm, depth); + if (at_time) + X509_VERIFY_PARAM_set_time(*pm, at_time); + + if (hostname && !X509_VERIFY_PARAM_set1_host(*pm, hostname, 0)) + *badarg = 1; + + if (email && !X509_VERIFY_PARAM_set1_email(*pm, email, 0)) + *badarg = 1; + + if (ipasc && !X509_VERIFY_PARAM_set1_ip_asc(*pm, ipasc)) + *badarg = 1; + end: (*pargs)++; @@ -2637,6 +2864,9 @@ void jpake_client_auth(BIO *out, BIO *conn, const char *secret) BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); + if (psk_key) + OPENSSL_free(psk_key); + psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); BIO_pop(bconn); @@ -2666,6 +2896,9 @@ void jpake_server_auth(BIO *out, BIO *conn, const char *secret) BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); + if (psk_key) + OPENSSL_free(psk_key); + psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); BIO_pop(bconn); @@ -2676,6 +2909,156 @@ void jpake_server_auth(BIO *out, BIO *conn, const char *secret) #endif +#ifndef OPENSSL_NO_TLSEXT +/* next_protos_parse parses a comma separated list of strings into a string + * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. + * outlen: (output) set to the length of the resulting buffer on success. + * err: (maybe NULL) on failure, an error message line is written to this BIO. + * in: a NUL termianted string like "abc,def,ghi" + * + * returns: a malloced buffer or NULL on failure. + */ +unsigned char *next_protos_parse(unsigned short *outlen, const char *in) + { + size_t len; + unsigned char *out; + size_t i, start = 0; + + len = strlen(in); + if (len >= 65535) + return NULL; + + out = OPENSSL_malloc(strlen(in) + 1); + if (!out) + return NULL; + + for (i = 0; i <= len; ++i) + { + if (i == len || in[i] == ',') + { + if (i - start > 255) + { + OPENSSL_free(out); + return NULL; + } + out[start] = i - start; + start = i + 1; + } + else + out[i+1] = in[i]; + } + + *outlen = len + 1; + return out; + } +#endif /* ndef OPENSSL_NO_TLSEXT */ + +void print_cert_checks(BIO *bio, X509 *x, + const unsigned char *checkhost, + const unsigned char *checkemail, + const char *checkip) + { + if (x == NULL) + return; + if (checkhost) + { + BIO_printf(bio, "Hostname %s does%s match certificate\n", + checkhost, X509_check_host(x, checkhost, 0, 0) + ? "" : " NOT"); + } + + if (checkemail) + { + BIO_printf(bio, "Email %s does%s match certificate\n", + checkemail, X509_check_email(x, checkemail, 0, + 0) ? "" : " NOT"); + } + + if (checkip) + { + BIO_printf(bio, "IP %s does%s match certificate\n", + checkip, X509_check_ip_asc(x, checkip, + 0) ? "" : " NOT"); + } + } + +/* Get first http URL from a DIST_POINT structure */ + +static const char *get_dp_url(DIST_POINT *dp) + { + GENERAL_NAMES *gens; + GENERAL_NAME *gen; + int i, gtype; + ASN1_STRING *uri; + if (!dp->distpoint || dp->distpoint->type != 0) + return NULL; + gens = dp->distpoint->name.fullname; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) + { + gen = sk_GENERAL_NAME_value(gens, i); + uri = GENERAL_NAME_get0_value(gen, >ype); + if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) + { + char *uptr = (char *)ASN1_STRING_data(uri); + if (!strncmp(uptr, "http://", 7)) + return uptr; + } + } + return NULL; + } + + +/* Look through a CRLDP structure and attempt to find an http URL to downloads + * a CRL from. + */ + +static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp) + { + int i; + const char *urlptr = NULL; + for (i = 0; i < sk_DIST_POINT_num(crldp); i++) + { + DIST_POINT *dp = sk_DIST_POINT_value(crldp, i); + urlptr = get_dp_url(dp); + if (urlptr) + return load_crl(urlptr, FORMAT_HTTP); + } + return NULL; + } + +/* Example of downloading CRLs from CRLDP: not usable for real world + * as it always downloads, doesn't support non-blocking I/O and doesn't + * cache anything. + */ + +static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm) + { + X509 *x; + STACK_OF(X509_CRL) *crls = NULL; + X509_CRL *crl; + STACK_OF(DIST_POINT) *crldp; + x = X509_STORE_CTX_get_current_cert(ctx); + crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); + crl = load_crl_crldp(crldp); + sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); + if (!crl) + return NULL; + crls = sk_X509_CRL_new_null(); + sk_X509_CRL_push(crls, crl); + /* Try to download delta CRL */ + crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL); + crl = load_crl_crldp(crldp); + sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); + if (crl) + sk_X509_CRL_push(crls, crl); + return crls; + } + +void store_setup_crl_download(X509_STORE *st) + { + X509_STORE_set_lookup_crls_cb(st, crls_http_cb); + } + /* * Platform-specific sections */