X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fapps.c;h=39ca963b5f09c4c34d80df651da102dd1f37a00f;hp=797e250c65f2526e4de86e8a8b22dd6c6d329867;hb=4428c7dba8f6f407d915c1226f4e0f673e8be241;hpb=b4faea50c35d92a67d1369355b49cc3efba78406 diff --git a/apps/apps.c b/apps/apps.c index 797e250c65..39ca963b5f 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -121,10 +121,15 @@ #if !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_WINCE) && !defined(NETWARE_CLIB) # include #endif -#include +#ifndef NO_SYS_TYPES_H +# include +#endif +#ifndef OPENSSL_NO_POSIX_IO +# include +# include +#endif #include #include -#include #include #include #include @@ -164,18 +169,12 @@ static int set_table_opts(unsigned long *flags, const char *arg, static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL * in_tbl); -#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) -/* Looks like this stuff is worth moving into separate function */ -static EVP_PKEY *load_netscape_key(BIO *key, const char *file, - const char *key_descrip, int format); -#endif - int app_init(long mesgwin); int chopup_args(ARGS *arg, char *buf) { int quoted; - char c, *p; + char c = '\0', *p = NULL; arg->argc = 0; if (arg->size == 0) { @@ -228,11 +227,17 @@ int app_init(long mesgwin) } #endif -int ctx_set_verify_locations(SSL_CTX *ctx, - const char *CAfile, const char *CApath) +int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath, int noCAfile, int noCApath) { - if (CAfile == NULL && CApath == NULL) - return SSL_CTX_set_default_verify_paths(ctx); + if (CAfile == NULL && CApath == NULL) { + if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0) + return 0; + if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0) + return 0; + + return 1; + } return SSL_CTX_load_verify_locations(ctx, CAfile, CApath); } @@ -428,9 +433,10 @@ static char *app_get_pass(char *arg, int keepbio) char *tmp, tpass[APP_PASS_LEN]; static BIO *pwdbio = NULL; int i; - if (!strncmp(arg, "pass:", 5)) + + if (strncmp(arg, "pass:", 5) == 0) return BUF_strdup(arg + 5); - if (!strncmp(arg, "env:", 4)) { + if (strncmp(arg, "env:", 4) == 0) { tmp = getenv(arg + 4); if (!tmp) { BIO_printf(bio_err, "Can't read environment variable %s\n", arg + 4); @@ -439,7 +445,7 @@ static char *app_get_pass(char *arg, int keepbio) return BUF_strdup(tmp); } if (!keepbio || !pwdbio) { - if (!strncmp(arg, "file:", 5)) { + if (strncmp(arg, "file:", 5) == 0) { pwdbio = BIO_new_file(arg + 5, "r"); if (!pwdbio) { BIO_printf(bio_err, "Can't open file %s\n", arg + 5); @@ -454,7 +460,7 @@ static char *app_get_pass(char *arg, int keepbio) * on real Windows descriptors, such as those obtained * with CreateFile. */ - } else if (!strncmp(arg, "fd:", 3)) { + } else if (strncmp(arg, "fd:", 3) == 0) { BIO *btmp; i = atoi(arg + 3); if (i >= 0) @@ -469,8 +475,8 @@ static char *app_get_pass(char *arg, int keepbio) btmp = BIO_new(BIO_f_buffer()); pwdbio = BIO_push(btmp, pwdbio); #endif - } else if (!strcmp(arg, "stdin")) { - pwdbio = dup_bio_in(); + } else if (strcmp(arg, "stdin") == 0) { + pwdbio = dup_bio_in(FORMAT_TEXT); if (!pwdbio) { BIO_printf(bio_err, "Can't open BIO for stdin\n"); return NULL; @@ -495,17 +501,84 @@ static char *app_get_pass(char *arg, int keepbio) return BUF_strdup(tpass); } +static CONF *app_load_config_(BIO *in, const char *filename) +{ + long errorline = -1; + CONF *conf; + int i; + + conf = NCONF_new(NULL); + i = NCONF_load_bio(conf, in, &errorline); + if (i > 0) + return conf; + + if (errorline <= 0) + BIO_printf(bio_err, "%s: Can't load config file \"%s\"\n", + opt_getprog(), filename); + else + BIO_printf(bio_err, "%s: Error on line %ld of config file \"%s\"\n", + opt_getprog(), errorline, filename); + NCONF_free(conf); + return NULL; +} +CONF *app_load_config(const char *filename) +{ + BIO *in; + CONF *conf; + + in = bio_open_default(filename, 'r', FORMAT_TEXT); + if (in == NULL) + return NULL; + + conf = app_load_config_(in, filename); + BIO_free(in); + return conf; +} +CONF *app_load_config_quiet(const char *filename) +{ + BIO *in; + CONF *conf; + + in = bio_open_default_quiet(filename, 'r', FORMAT_TEXT); + if (in == NULL) + return NULL; + + conf = app_load_config_(in, filename); + BIO_free(in); + return conf; +} + +int app_load_modules(const CONF *config) +{ + CONF *to_free = NULL; + + if (config == NULL) + config = to_free = app_load_config_quiet(default_config_file); + if (config == NULL) + return 1; + + if (CONF_modules_load(config, NULL, 0) <= 0) { + BIO_printf(bio_err, "Error configuring OpenSSL modules\n"); + ERR_print_errors(bio_err); + NCONF_free(to_free); + return 0; + } + NCONF_free(to_free); + return 1; +} + int add_oid_section(CONF *conf) { char *p; STACK_OF(CONF_VALUE) *sktmp; CONF_VALUE *cnf; int i; - if (!(p = NCONF_get_string(conf, NULL, "oid_section"))) { + + if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) { ERR_clear_error(); return 1; } - if (!(sktmp = NCONF_get_section(conf, p))) { + if ((sktmp = NCONF_get_section(conf, p)) == NULL) { BIO_printf(bio_err, "problem loading oid section %s\n", p); return 0; } @@ -620,30 +693,15 @@ X509 *load_cert(const char *file, int format, if (file == NULL) { unbuffer(stdin); - cert = dup_bio_in(); + cert = dup_bio_in(format); } else - cert = bio_open_default(file, RB(format)); + cert = bio_open_default(file, 'r', format); if (cert == NULL) goto end; if (format == FORMAT_ASN1) x = d2i_X509_bio(cert, NULL); - else if (format == FORMAT_NETSCAPE) { - NETSCAPE_X509 *nx; - nx = ASN1_item_d2i_bio(ASN1_ITEM_rptr(NETSCAPE_X509), cert, NULL); - if (nx == NULL) - goto end; - - if ((strncmp(NETSCAPE_CERT_HDR, (char *)nx->header->data, - nx->header->length) != 0)) { - NETSCAPE_X509_free(nx); - BIO_printf(bio_err, "Error reading header on certificate\n"); - goto end; - } - x = nx->cert; - nx->cert = NULL; - NETSCAPE_X509_free(nx); - } else if (format == FORMAT_PEM) + else if (format == FORMAT_PEM) x = PEM_read_bio_X509_AUX(cert, NULL, (pem_password_cb *)password_callback, NULL); else if (format == FORMAT_PKCS12) { @@ -672,7 +730,7 @@ X509_CRL *load_crl(const char *infile, int format) return x; } - in = bio_open_default(infile, RB(format)); + in = bio_open_default(infile, 'r', format); if (in == NULL) goto end; if (format == FORMAT_ASN1) @@ -724,9 +782,9 @@ EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, #endif if (file == NULL && maybe_stdin) { unbuffer(stdin); - key = dup_bio_in(); + key = dup_bio_in(format); } else - key = bio_open_default(file, RB(format)); + key = bio_open_default(file, 'r', format); if (key == NULL) goto end; if (format == FORMAT_ASN1) { @@ -736,10 +794,6 @@ EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, (pem_password_cb *)password_callback, &cb_data); } -#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) - else if (format == FORMAT_NETSCAPE) - pkey = load_netscape_key(key, file, key_descrip, format); -#endif else if (format == FORMAT_PKCS12) { if (!load_pkcs12(key, key_descrip, (pem_password_cb *)password_callback, &cb_data, @@ -766,13 +820,6 @@ EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, return (pkey); } -static const char *key_file_format(int format) -{ - if (format == FORMAT_PEM || format == FORMAT_PEMRSA) - return "r"; - return "rb"; -} - EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *key_descrip) { @@ -798,9 +845,9 @@ EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, #endif if (file == NULL && maybe_stdin) { unbuffer(stdin); - key = dup_bio_in(); + key = dup_bio_in(format); } else - key = bio_open_default(file, key_file_format(format)); + key = bio_open_default(file, 'r', format); if (key == NULL) goto end; if (format == FORMAT_ASN1) { @@ -836,10 +883,6 @@ EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, (pem_password_cb *)password_callback, &cb_data); } -#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) - else if (format == FORMAT_NETSCAPE) - pkey = load_netscape_key(key, file, key_descrip, format); -#endif #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) else if (format == FORMAT_MSBLOB) pkey = b2i_PublicKey_bio(key); @@ -851,47 +894,6 @@ EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, return (pkey); } -#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) -static EVP_PKEY *load_netscape_key(BIO *key, const char *file, - const char *key_descrip, int format) -{ - EVP_PKEY *pkey; - BUF_MEM *buf; - RSA *rsa; - const unsigned char *p; - int size, i; - - buf = BUF_MEM_new(); - pkey = EVP_PKEY_new(); - size = 0; - if (buf == NULL || pkey == NULL) - goto error; - for (;;) { - if (!BUF_MEM_grow_clean(buf, size + 1024 * 10)) - goto error; - i = BIO_read(key, &(buf->data[size]), 1024 * 10); - size += i; - if (i == 0) - break; - if (i < 0) { - BIO_printf(bio_err, "Error reading %s %s", key_descrip, file); - goto error; - } - } - p = (unsigned char *)buf->data; - rsa = d2i_RSA_NET(NULL, &p, (long)size, NULL, 0); - if (rsa == NULL) - goto error; - BUF_MEM_free(buf); - EVP_PKEY_set1_RSA(pkey, rsa); - return pkey; - error: - BUF_MEM_free(buf); - EVP_PKEY_free(pkey); - return NULL; -} -#endif /* ndef OPENSSL_NO_RC4 */ - static int load_certs_crls(const char *file, int format, const char *pass, ENGINE *e, const char *desc, STACK_OF(X509) **pcerts, @@ -912,7 +914,7 @@ static int load_certs_crls(const char *file, int format, return 0; } - bio = bio_open_default(file, "r"); + bio = bio_open_default(file, 'r', FORMAT_PEM); if (bio == NULL) return 0; @@ -1078,16 +1080,20 @@ int set_name_ex(unsigned long *flags, const char *arg) {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, {NULL, 0, 0} }; - return set_multi_opts(flags, arg, ex_tbl); + if (set_multi_opts(flags, arg, ex_tbl) == 0) + return 0; + if ((*flags & XN_FLAG_SEP_MASK) == 0) + *flags |= XN_FLAG_SEP_CPLUS_SPC; + return 1; } int set_ext_copy(int *copy_type, const char *arg) { - if (!strcasecmp(arg, "none")) + if (strcasecmp(arg, "none") == 0) *copy_type = EXT_COPY_NONE; - else if (!strcasecmp(arg, "copy")) + else if (strcasecmp(arg, "copy") == 0) *copy_type = EXT_COPY_ADD; - else if (!strcasecmp(arg, "copyall")) + else if (strcasecmp(arg, "copyall") == 0) *copy_type = EXT_COPY_ALL; else return 0; @@ -1169,7 +1175,7 @@ static int set_table_opts(unsigned long *flags, const char *arg, c = 1; for (ptbl = in_tbl; ptbl->name; ptbl++) { - if (!strcasecmp(arg, ptbl->name)) { + if (strcasecmp(arg, ptbl->name) == 0) { *flags &= ~ptbl->mask; if (c) *flags |= ptbl->flag; @@ -1244,34 +1250,39 @@ void print_array(BIO *out, const char* title, int len, const unsigned char* d) BIO_printf(out, "\n};\n"); } -X509_STORE *setup_verify(char *CAfile, char *CApath) +X509_STORE *setup_verify(char *CAfile, char *CApath, int noCAfile, int noCApath) { X509_STORE *store = X509_STORE_new(); X509_LOOKUP *lookup; if (!store) goto end; - lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); - if (lookup == NULL) - goto end; - if (CAfile) { - if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { - BIO_printf(bio_err, "Error loading file %s\n", CAfile); + + if(CAfile != NULL || !noCAfile) { + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (lookup == NULL) goto end; - } - } else - X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + if (CAfile) { + if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { + BIO_printf(bio_err, "Error loading file %s\n", CAfile); + goto end; + } + } else + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + } - lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); - if (lookup == NULL) - goto end; - if (CApath) { - if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { - BIO_printf(bio_err, "Error loading directory %s\n", CApath); + if(CApath != NULL || !noCApath) { + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) goto end; - } - } else - X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + if (CApath) { + if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { + BIO_printf(bio_err, "Error loading directory %s\n", CApath); + goto end; + } + } else + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + } ERR_clear_error(); return store; @@ -1557,8 +1568,7 @@ CA_DB *load_index(char *dbfile, DB_ATTR *db_attr) TXT_DB *tmpdb = NULL; BIO *in; CONF *dbattr_conf = NULL; - char buf[1][BSIZE]; - long errorline = -1; + char buf[BSIZE]; in = BIO_new_file(dbfile, "r"); if (in == NULL) { @@ -1569,22 +1579,11 @@ CA_DB *load_index(char *dbfile, DB_ATTR *db_attr) goto err; #ifndef OPENSSL_SYS_VMS - BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile); + BIO_snprintf(buf, sizeof buf, "%s.attr", dbfile); #else - BIO_snprintf(buf[0], sizeof buf[0], "%s-attr", dbfile); + BIO_snprintf(buf, sizeof buf, "%s-attr", dbfile); #endif - dbattr_conf = NCONF_new(NULL); - if (NCONF_load(dbattr_conf, buf[0], &errorline) <= 0) { - if (errorline > 0) { - BIO_printf(bio_err, - "error on line %ld of db attribute file '%s'\n", - errorline, buf[0]); - goto err; - } else { - NCONF_free(dbattr_conf); - dbattr_conf = NULL; - } - } + dbattr_conf = app_load_config(buf); retdb = app_malloc(sizeof(*retdb), "new DB"); retdb->db = tmpdb; @@ -2200,7 +2199,6 @@ 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. @@ -2236,7 +2234,6 @@ unsigned char *next_protos_parse(unsigned short *outlen, const char *in) *outlen = len + 1; return out; } -#endif /* ndef OPENSSL_NO_TLSEXT */ void print_cert_checks(BIO *bio, X509 *x, const char *checkhost, @@ -2279,7 +2276,7 @@ static const char *get_dp_url(DIST_POINT *dp) 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)) + if (strncmp(uptr, "http://", 7) == 0) return uptr; } } @@ -2365,7 +2362,7 @@ static int WIN32_rename(const char *from, const char *to) } else { /* UNICODE path */ size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1; - tfrom = malloc(*sizeof(*tfrom) * (flen + tlen)); + tfrom = malloc(sizeof(*tfrom) * (flen + tlen)); if (tfrom == NULL) goto err; tto = tfrom + flen; @@ -2731,3 +2728,162 @@ int raw_write_stdout(const void *buf, int siz) return write(fileno(stdout), buf, siz); } #endif + +/* + * Centralized handling if input and output files with format specification + * The format is meant to show what the input and output is supposed to be, + * and is therefore a show of intent more than anything else. However, it + * does impact behavior on some platform, such as differentiating between + * text and binary input/output on non-Unix platforms + */ +static int istext(int format) +{ + return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT; +} + +BIO *dup_bio_in(int format) +{ + return BIO_new_fp(stdin, + BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); +} + +BIO *dup_bio_out(int format) +{ + BIO *b = BIO_new_fp(stdout, + BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); +#ifdef OPENSSL_SYS_VMS + if (istext(format)) + b = BIO_push(BIO_new(BIO_f_linebuffer()), b); +#endif + return b; +} + +void unbuffer(FILE *fp) +{ + setbuf(fp, NULL); +} + +static const char *modestr(char mode, int format) +{ + OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w'); + + switch (mode) { + case 'a': + return istext(format) ? "a" : "ab"; + case 'r': + return istext(format) ? "r" : "rb"; + case 'w': + return istext(format) ? "w" : "wb"; + } + /* The assert above should make sure we never reach this point */ + return NULL; +} + +static const char *modeverb(char mode) +{ + switch (mode) { + case 'a': + return "appending"; + case 'r': + return "reading"; + case 'w': + return "writing"; + } + return "(doing something)"; +} + +/* + * Open a file for writing, owner-read-only. + */ +BIO *bio_open_owner(const char *filename, int format, int private) +{ + FILE *fp = NULL; + BIO *b = NULL; + int fd = -1, bflags, mode, binmode; + + if (!private || filename == NULL || strcmp(filename, "-") == 0) + return bio_open_default(filename, 'w', format); + + mode = O_WRONLY; +#ifdef O_CREAT + mode |= O_CREAT; +#endif +#ifdef O_TRUNC + mode |= O_TRUNC; +#endif + binmode = istext(format); + if (binmode) { +#ifdef O_BINARY + mode |= O_BINARY; +#elif defined(_O_BINARY) + mode |= _O_BINARY; +#endif + } + + fd = open(filename, mode, 0600); + if (fd < 0) + goto err; + fp = fdopen(fd, modestr('w', format)); + if (fp == NULL) + goto err; + bflags = BIO_CLOSE; + if (!binmode) + bflags |= BIO_FP_TEXT; + b = BIO_new_fp(fp, bflags); + if (b) + return b; + + err: + BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n", + opt_getprog(), filename, strerror(errno)); + ERR_print_errors(bio_err); + /* If we have fp, then fdopen took over fd, so don't close both. */ + if (fp) + fclose(fp); + else if (fd >= 0) + close(fd); + return NULL; +} + +static BIO *bio_open_default_(const char *filename, char mode, int format, + int quiet) +{ + BIO *ret; + + if (filename == NULL || strcmp(filename, "-") == 0) { + ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open %s, %s\n", + mode == 'r' ? "stdin" : "stdout", strerror(errno)); + } else { + ret = BIO_new_file(filename, modestr(mode, format)); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open %s for %s, %s\n", + filename, modeverb(mode), strerror(errno)); + } + ERR_print_errors(bio_err); + return NULL; +} + +BIO *bio_open_default(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 0); +} + +BIO *bio_open_default_quiet(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 1); +} +