From b8efb6d762890b56b4dfa31de9739067eeda9f5a Mon Sep 17 00:00:00 2001 From: hniksic Date: Wed, 27 Apr 2005 10:15:10 -0700 Subject: [PATCH] [svn] Allow separate specification of certificate type and private key type. --- src/ChangeLog | 10 +++++++ src/http.c | 4 +-- src/init.c | 59 ++++++++++++++++++------------------ src/main.c | 9 ++++-- src/openssl.c | 82 ++++++++++++++++++++++++--------------------------- src/options.h | 14 ++++----- 6 files changed, 93 insertions(+), 85 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index a6d30758..bb03ff3b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2005-04-27 Hrvoje Niksic + + * openssl.c (ssl_init): Ditto. + + * options.h (struct options): Allow separate specification of key + type and certificate type. + + * init.c (cmd_spec_cert_type): Provide a "der" synonym for "asn1" + certificate encoding. + 2005-04-26 Hrvoje Niksic * openssl.c: Renamed "gen_sslfunc.c" to "openssl.c" and diff --git a/src/http.c b/src/http.c index 6fb2b743..5d382deb 100644 --- a/src/http.c +++ b/src/http.c @@ -1203,8 +1203,8 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy) break; case SSLERRCERTKEY: logprintf (LOG_NOTQUIET, - _("Failed to get certificate key from %s\n"), - opt.cert_key); + _("Failed to get private key from %s\n"), + opt.private_key); logprintf (LOG_NOTQUIET, _("Trying without the specified certificate\n")); break; diff --git a/src/init.c b/src/init.c index 22943219..a52ce511 100644 --- a/src/init.c +++ b/src/init.c @@ -74,6 +74,9 @@ static int enable_tilde_expansion; CMD_DECLARE (cmd_boolean); CMD_DECLARE (cmd_bytes); CMD_DECLARE (cmd_bytes_large); +#ifdef HAVE_SSL +CMD_DECLARE (cmd_cert_type); +#endif CMD_DECLARE (cmd_directory_vector); CMD_DECLARE (cmd_lockable_boolean); CMD_DECLARE (cmd_number); @@ -84,9 +87,6 @@ CMD_DECLARE (cmd_directory); CMD_DECLARE (cmd_time); CMD_DECLARE (cmd_vector); -#ifdef HAVE_SSL -CMD_DECLARE (cmd_spec_cert_type); -#endif CMD_DECLARE (cmd_spec_dirstruct); CMD_DECLARE (cmd_spec_header); CMD_DECLARE (cmd_spec_htmlify); @@ -128,8 +128,7 @@ static struct { #ifdef HAVE_SSL { "cadirectory", &opt.ca_directory, cmd_directory }, { "certificate", &opt.cert_file, cmd_file }, - { "certificatekey", &opt.cert_key, cmd_file }, - { "certificatetype", &opt.cert_type, cmd_spec_cert_type }, + { "certificatetype", &opt.cert_type, cmd_cert_type }, { "checkcertificate", &opt.check_cert, cmd_boolean }, #endif { "connecttimeout", &opt.connect_timeout, cmd_time }, @@ -196,6 +195,8 @@ static struct { { "postfile", &opt.post_file_name, cmd_file }, { "preferfamily", NULL, cmd_spec_prefer_family }, { "preservepermissions", &opt.preserve_perm, cmd_boolean }, + { "privatekey", &opt.private_key, cmd_file }, + { "privatekeytype", &opt.private_key_type, cmd_cert_type }, { "progress", &opt.progress_type, cmd_spec_progress }, { "protocoldirectories", &opt.protocol_directories, cmd_boolean }, { "proxypasswd", &opt.proxy_passwd, cmd_string }, @@ -616,6 +617,16 @@ run_command (const char *opt) /* Generic helper functions, for use with `commands'. */ +/* Forward declarations: */ +struct decode_item { + const char *name; + int code; +}; +static int decode_string PARAMS ((const char *, const struct decode_item *, + int, int *)); +static int simple_atoi PARAMS ((const char *, const char *, int *)); +static int simple_atof PARAMS ((const char *, const char *, double *)); + #define CMP1(p, c0) (TOLOWER((p)[0]) == (c0) && (p)[1] == '\0') #define CMP2(p, c0, c1) (TOLOWER((p)[0]) == (c0) \ @@ -696,8 +707,6 @@ cmd_lockable_boolean (const char *com, const char *val, void *place) return 1; } -static int simple_atoi PARAMS ((const char *, const char *, int *)); - /* Set the non-negative integer value from VAL to PLACE. With incorrect specification, the number remains unchanged. */ static int @@ -860,8 +869,6 @@ cmd_directory_vector (const char *com, const char *val, void *place) return 1; } -static int simple_atof PARAMS ((const char *, const char *, double *)); - /* Engine for cmd_bytes and cmd_bytes_large: converts a string such as "100k" or "2.5G" to a floating point number. */ @@ -1025,26 +1032,15 @@ cmd_time (const char *com, const char *val, void *place) *(double *)place = number * mult; return 1; } - -/* Specialized helper functions, used by `commands' to handle some - options specially. */ - -static int check_user_specified_header PARAMS ((const char *)); -/* Forward decl */ -struct decode_item { - const char *name; - int code; -}; -static int decode_string PARAMS ((const char *, const struct decode_item *, - int, int *)); #ifdef HAVE_SSL static int -cmd_spec_cert_type (const char *com, const char *val, void *place) +cmd_cert_type (const char *com, const char *val, void *place) { static const struct decode_item choices[] = { - { "pem", cert_type_pem }, - { "asn1", cert_type_asn1 }, + { "pem", keyfile_pem }, + { "der", keyfile_asn1 }, + { "asn1", keyfile_asn1 }, }; int ok = decode_string (val, choices, countof (choices), place); if (!ok) @@ -1052,6 +1048,11 @@ cmd_spec_cert_type (const char *com, const char *val, void *place) return ok; } #endif + +/* Specialized helper functions, used by `commands' to handle some + options specially. */ + +static int check_user_specified_header PARAMS ((const char *)); static int cmd_spec_dirstruct (const char *com, const char *val, void *place_ignored) @@ -1455,12 +1456,12 @@ cleanup (void) xfree_null (opt.http_user); xfree_null (opt.http_passwd); free_vec (opt.user_headers); -#ifdef HAVE_SSL - xfree_null (opt.sslcertkey); - xfree_null (opt.sslcertfile); -#endif /* HAVE_SSL */ +# ifdef HAVE_SSL + xfree_null (opt.cert_file); + xfree_null (opt.private_key); +# endif xfree_null (opt.bind_address); xfree_null (opt.cookies_input); xfree_null (opt.cookies_output); -#endif +#endif /* DEBUG_MALLOC */ } diff --git a/src/main.c b/src/main.c index e5af97b9..6470c1e0 100644 --- a/src/main.c +++ b/src/main.c @@ -161,7 +161,6 @@ struct cmdline_option option_data[] = { IF_SSL ("ca-directory"), 0, OPT_VALUE, "cadirectory", -1 }, { "cache", 0, OPT_BOOLEAN, "cache", -1 }, { IF_SSL ("certificate"), 0, OPT_VALUE, "certificate", -1 }, - { IF_SSL ("certificate-key"), 0, OPT_VALUE, "certificatekey", -1 }, { IF_SSL ("certificate-type"), 0, OPT_VALUE, "certificatetype", -1 }, { IF_SSL ("check-certificate"), 0, OPT_BOOLEAN, "checkcertificate", -1 }, { "clobber", 0, OPT__CLOBBER, NULL, optional_argument }, @@ -222,6 +221,8 @@ struct cmdline_option option_data[] = { "post-file", 0, OPT_VALUE, "postfile", -1 }, { "prefer-family", 0, OPT_VALUE, "preferfamily", -1 }, { "preserve-permissions", 0, OPT_BOOLEAN, "preservepermissions", -1 }, + { IF_SSL ("private-key"), 0, OPT_VALUE, "privatekey", -1 }, + { IF_SSL ("private-key-type"), 0, OPT_VALUE, "privatekeytype", -1 }, { "progress", 0, OPT_VALUE, "progress", -1 }, { "protocol-directories", 0, OPT_BOOLEAN, "protocoldirectories", -1 }, { "proxy", 0, OPT_BOOLEAN, "useproxy", -1 }, @@ -540,10 +541,12 @@ HTTPS (SSL/TLS) options:\n"), --no-check-certificate don't validate the server's certificate.\n"), N_("\ --certificate=FILE client certificate file.\n"), - N_("\ - --certificate-key=FILE optional key file for this certificate.\n"), N_("\ --certificate-type=TYPE client certificate type, PEM or ASN1.\n"), + N_("\ + --private-key=FILE private key file.\n"), + N_("\ + --private-key-type=TYPE private key type, PEM or ASN1.\n"), N_("\ --ca-certificate=FILE file with the bundle of CA's.\n"), N_("\ diff --git a/src/openssl.c b/src/openssl.c index 664ed1e6..920f5a50 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -154,6 +154,26 @@ ssl_print_errors (void) logprintf (LOG_NOTQUIET, "OpenSSL: %s\n", ERR_error_string (curerr, NULL)); } +/* Convert keyfile type as used by options.h to a type as accepted by + SSL_CTX_use_certificate_file and SSL_CTX_use_PrivateKey_file. + + (options.h intentionally doesn't use values from openssl/ssl.h so + it doesn't depend specifically on OpenSSL for SSL functionality.) */ + +static int +key_type_to_ssl_type (enum keyfile_type type) +{ + switch (type) + { + case keyfile_pem: + return SSL_FILETYPE_PEM; + case keyfile_asn1: + return SSL_FILETYPE_ASN1; + default: + abort (); + } +} + /* Creates a SSL Context and sets some defaults for it */ uerr_t ssl_init () @@ -191,59 +211,33 @@ ssl_init () case secure_protocol_tlsv1: meth = TLSv1_client_method (); break; - } - if (meth == NULL) - { - ssl_print_errors (); - return SSLERRCTXCREATE; + default: + abort (); } ssl_ctx = SSL_CTX_new (meth); - if (meth == NULL) - { - ssl_print_errors (); - return SSLERRCTXCREATE; - } - SSL_CTX_set_default_verify_paths (ssl_ctx); SSL_CTX_load_verify_locations (ssl_ctx, opt.ca_cert, opt.ca_directory); SSL_CTX_set_verify (ssl_ctx, opt.check_cert ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, verify_callback); - if (opt.cert_file != NULL || opt.cert_key != NULL) - { - int ssl_cert_type = SSL_FILETYPE_PEM; - switch (opt.cert_type) - { - case cert_type_pem: - ssl_cert_type = SSL_FILETYPE_PEM; - break; - case cert_type_asn1: - ssl_cert_type = SSL_FILETYPE_ASN1; - break; - } - -#if 0 /* what was this supposed to achieve? */ - if (opt.cert_key == NULL) - opt.cert_key = opt.cert_file; - if (opt.cert_file == NULL) - opt.cert_file = opt.cert_key; -#endif - - if (SSL_CTX_use_certificate_file (ssl_ctx, opt.cert_file, - ssl_cert_type) != 1) - { - ssl_print_errors (); - return SSLERRCERTFILE; - } - if (SSL_CTX_use_PrivateKey_file (ssl_ctx, opt.cert_key, - ssl_cert_type) != 1) - { - ssl_print_errors (); - return SSLERRCERTKEY; - } - } + if (opt.cert_file) + if (SSL_CTX_use_certificate_file (ssl_ctx, opt.cert_file, + key_type_to_ssl_type (opt.cert_type)) + != 1) + { + ssl_print_errors (); + return SSLERRCERTFILE; + } + if (opt.private_key) + if (SSL_CTX_use_PrivateKey_file (ssl_ctx, opt.private_key, + key_type_to_ssl_type (opt.private_key_type)) + != 1) + { + ssl_print_errors (); + return SSLERRCERTKEY; + } return 0; /* Succeded */ } diff --git a/src/options.h b/src/options.h index 48c8fd00..eea4061f 100644 --- a/src/options.h +++ b/src/options.h @@ -167,13 +167,13 @@ struct options } secure_protocol; /* type of secure protocol to use. */ int check_cert; /* whether to validate the server's cert */ char *cert_file; /* external client certificate to use. */ - char *cert_key; /* the keyfile for this certificate - (if not internal) included in the - certfile. */ - enum { - cert_type_pem, - cert_type_asn1 - } cert_type; /* type of client certificate */ + char *private_key; /* private key file (if not internal). */ + enum keyfile_type { + keyfile_pem, + keyfile_asn1 + } cert_type; /* type of client certificate file */ + enum keyfile_type + private_key_type; /* type of private key file */ char *ca_directory; /* CA directory (hash files) */ char *ca_cert; /* CA certificate file to use */ -- 2.39.2