diff options
author | bodo <bodo> | 2002-02-28 10:54:15 +0000 |
---|---|---|
committer | bodo <bodo> | 2002-02-28 10:54:15 +0000 |
commit | 6d800d77c1da43cc02aa3985970f7ad64c00245d (patch) | |
tree | f1a078624dc2720c8789c7366b59886c874bc279 | |
parent | abdcdaeb530edba9d4dd3a547edfbffc51687ab1 (diff) | |
download | openssl-6d800d77c1da43cc02aa3985970f7ad64c00245d.tar.gz |
Add 'void *' argument to app_verify_callback.
Submitted by: D. K. Smetters <smetters@parc.xerox.com>
Reviewed by: Bodo Moeller
-rw-r--r-- | CHANGES | 16 | ||||
-rw-r--r-- | demos/easy_tls/easy-tls.c | 1235 | ||||
-rw-r--r-- | doc/ssl/SSL_CTX_set_cert_verify_callback.pod | 75 | ||||
-rw-r--r-- | ssl/ssl.h | 1506 | ||||
-rw-r--r-- | ssl/ssl_cert.c | 654 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 9 | ||||
-rw-r--r-- | ssl/ssltest.c | 36 | ||||
-rw-r--r-- | test/testssl | 127 |
8 files changed, 2947 insertions, 711 deletions
@@ -13,6 +13,22 @@ *) applies to 0.9.6a/0.9.6b/0.9.6c and 0.9.7 +) applies to 0.9.7 only + +) Fix the 'app_verify_callback' interface so that the user-defined + argument is actually passed to the callback: In the + SSL_CTX_set_cert_verify_callback() prototype, the callback + declaration has been changed from + int (*cb)() + into + int (*cb)(X509_STORE_CTX *,void *); + in ssl_verify_cert_chain (ssl/ssl_cert.c), the call + i=s->ctx->app_verify_callback(&ctx) + has been changed into + i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg). + + To update applications using SSL_CTX_set_cert_verify_callback(), + a dummy argument can be added to their callback functions. + [D. K. Smetters <smetters@parc.xerox.com>] + +) Added the '4758cca' ENGINE to support IBM 4758 cards. [Maurice Gittens <maurice@gittens.nl>, touchups by Geoff Thorpe] diff --git a/demos/easy_tls/easy-tls.c b/demos/easy_tls/easy-tls.c new file mode 100644 index 000000000..cff0e30bf --- /dev/null +++ b/demos/easy_tls/easy-tls.c @@ -0,0 +1,1235 @@ +/* -*- Mode: C; c-file-style: "bsd" -*- */ +/* + * easy-tls.c -- generic TLS proxy. + * $Id: easy-tls.c,v 1.2.2.1 2002/02/28 10:55:00 bodo Exp $ + */ +/* + (c) Copyright 1999 Bodo Moeller. All rights reserved. + + This is free software; you can redistributed and/or modify it + unter the terms of either + - the GNU General Public License as published by the + Free Software Foundation, version 1, or (at your option) + any later version, + or + - the following license: +*/ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that each of the following + * conditions is met: + * + * 1. Redistributions qualify as "freeware" or "Open Source Software" under + * one of the following terms: + * + * (a) Redistributions are made at no charge beyond the reasonable cost of + * materials and delivery. + * + * (b) Redistributions are accompanied by a copy of the Source Code + * or by an irrevocable offer to provide a copy of the Source Code + * for up to three years at the cost of materials and delivery. + * Such redistributions must allow further use, modification, and + * redistribution of the Source Code under substantially the same + * terms as this license. + * + * 2. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 3. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 4. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by Bodo Moeller." + * (If available, substitute umlauted o for oe.) + * + * 5. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Bodo Moeller." + * + * THIS SOFTWARE IS PROVIDED BY BODO MOELLER ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BODO MOELLER OR + * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Attribution for OpenSSL library: + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/) + */ + +static char const rcsid[] = +"$Id: easy-tls.c,v 1.2.2.1 2002/02/28 10:55:00 bodo Exp $"; + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include <unistd.h> + +#include <openssl/crypto.h> +#include <openssl/dh.h> +#include <openssl/dsa.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/opensslv.h> +#include <openssl/pem.h> +#include <openssl/rand.h> +#ifndef NO_RSA + #include <openssl/rsa.h> +#endif +#include <openssl/ssl.h> +#include <openssl/x509.h> +#include <openssl/x509_vfy.h> + +#if OPENSSL_VERSION_NUMBER < 0x00904000L /* 0.9.4-dev */ +# error "This program needs OpenSSL 0.9.4 or later." +#endif + +#include "easy-tls.h" /* include after <openssl/ssl.h> if both are needed */ + +#if TLS_INFO_SIZE > PIPE_BUF +# if PIPE_BUF < 512 +# error "PIPE_BUF < 512" /* non-POSIX */ +# endif +# error "TLS_INFO_SIZE > PIPE_BUF" +#endif + +/*****************************************************************************/ + +#ifdef TLS_APP +# include TLS_APP +#endif + +/* Applications can define: + * TLS_APP_PROCESS_INIT -- void ...(int fd, int client_p, void *apparg) + * TLS_CUMULATE_ERRORS + * TLS_ERROR_BUFSIZ + * TLS_APP_ERRFLUSH -- void ...(int child_p, char *, size_t, void *apparg) + */ + +#ifndef TLS_APP_PROCESS_INIT +# define TLS_APP_PROCESS_INIT(fd, client_p, apparg) ((void) 0) +#endif + +#ifndef TLS_ERROR_BUFSIZ +# define TLS_ERROR_BUFSIZ (10*160) +#endif +#if TLS_ERROR_BUFSIZ < 2 /* {'\n',0} */ +# error "TLS_ERROR_BUFSIZE is too small." +#endif + +#ifndef TLS_APP_ERRFLUSH +# define TLS_APP_ERRFLUSH tls_app_errflush +static void +tls_app_errflush(int child_p, char *errbuf, size_t num, void *apparg) +{ + fputs(errbuf, stderr); +} +#endif + +/*****************************************************************************/ + +#ifdef DEBUG_TLS +# define DEBUG_MSG(x) fprintf(stderr," %s\n",x) +# define DEBUG_MSG2(x,y) fprintf(stderr, " %s: %d\n",x,y) +static int tls_loop_count = 0; +static int tls_select_count = 0; +#else +# define DEBUG_MSG(x) (void)0 +# define DEBUG_MSG2(x,y) (void)0 +#endif + +static void tls_rand_seed_uniquely(void); +static void tls_proxy(int clear_fd, int tls_fd, int info_fd, SSL_CTX *ctx, int client_p); +static int tls_socket_nonblocking(int fd); + +static int tls_child_p = 0; +static void *tls_child_apparg; + + +struct tls_start_proxy_args +tls_start_proxy_defaultargs(void) +{ + struct tls_start_proxy_args ret; + + ret.fd = -1; + ret.client_p = -1; + ret.ctx = NULL; + ret.pid = NULL; + ret.infofd = NULL; + + return ret; +} + +/* Slice in TLS proxy process at fd. + * Return value: + * 0 ok (*pid is set to child's PID if pid != NULL), + * < 0 look at errno + * > 0 other error + * (return value encodes place of error) + * + */ +int +tls_start_proxy(struct tls_start_proxy_args a, void *apparg) +{ + int fds[2] = {-1, -1}; + int infofds[2] = {-1, -1}; + int r, getfd, getfl; + int ret; + + DEBUG_MSG2("tls_start_proxy fd", a.fd); + DEBUG_MSG2("tls_start_proxy client_p", a.client_p); + + if (a.fd == -1 || a.client_p == -1 || a.ctx == NULL) + return 1; + + if (a.pid != NULL) { + *a.pid = 0; + } + if (a.infofd != NULL) { + *a.infofd = -1; + } + + r = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); + if (r == -1) + return -1; + if (a.fd >= FD_SETSIZE || fds[0] >= FD_SETSIZE) { + ret = 2; + goto err; + } + if (a.infofd != NULL) { + r = pipe(infofds); + if (r == -1) { + ret = -3; + goto err; + } + } + + r = fork(); + if (r == -1) { + ret = -4; + goto err; + } + if (r == 0) { + DEBUG_MSG("fork"); + tls_child_p = 1; + tls_child_apparg = apparg; + close(fds[1]); + if (infofds[0] != -1) + close(infofds[0]); + TLS_APP_PROCESS_INIT(a.fd, a.client_p, apparg); + DEBUG_MSG("TLS_APP_PROCESS_INIT"); + tls_proxy(fds[0], a.fd, infofds[1], a.ctx, a.client_p); + exit(0); + } + if (a.pid != NULL) + *a.pid = r; + if (infofds[1] != -1) { + close(infofds[1]); + infofds[1] = -1; + } + /* install fds[1] in place of fd: */ + close(fds[0]); + fds[0] = -1; + getfd = fcntl(a.fd, F_GETFD); + getfl = fcntl(a.fd, F_GETFL); + r = dup2(fds[1], a.fd); + close(fds[1]); + fds[1] = -1; + if (r == -1) { + ret = -5; + goto err; + } + if (getfd != 1) + fcntl(a.fd, F_SETFD, getfd); + if (getfl & O_NONBLOCK) + (void)tls_socket_nonblocking(a.fd); + if (a.infofd != NULL) + *a.infofd = infofds[0]; + return 0; + + err: + if (fds[0] != -1) + close(fds[0]); + if (fds[1] != -1) + close(fds[1]); + if (infofds[0] != -1) + close(infofds[0]); + if (infofds[1] != -1) + close(infofds[1]); + return ret; +} + +/*****************************************************************************/ + +static char errbuf[TLS_ERROR_BUFSIZ]; +static size_t errbuf_i = 0; + +static void +tls_errflush(void *apparg) +{ + if (errbuf_i == 0) + return; + + assert(errbuf_i < sizeof errbuf); + assert(errbuf[errbuf_i] == 0); + if (errbuf_i == sizeof errbuf - 1) { + /* make sure we have a newline, even if string has been truncated */ + errbuf[errbuf_i - 1] = '\n'; + } + + /* TLS_APP_ERRFLUSH may modify the string as needed, + * e.g. substitute other characters for \n for convenience */ + TLS_APP_ERRFLUSH(tls_child_p, errbuf, errbuf_i, apparg); + + errbuf_i = 0; +} + +static void +tls_errprintf(int flush, void *apparg, const char *fmt, ...) +{ + va_list args; + int r; + + if (errbuf_i < sizeof errbuf - 1) { + size_t n; + + va_start(args, fmt); + n = (sizeof errbuf) - errbuf_i; + r = vsnprintf(errbuf + errbuf_i, n, fmt, args); + if (r >= n) + r = n - 1; + if (r >= 0) { + errbuf_i += r; + } else { + errbuf_i = sizeof errbuf - 1; + errbuf[errbuf_i] = '\0'; + } + assert(errbuf_i < sizeof errbuf); + assert(errbuf[errbuf_i] == 0); + } +#ifndef TLS_CUMULATE_ERRORS + tls_errflush(apparg); +#else + if (flush) + tls_errflush(apparg); +#endif +} + +/* app_prefix.. are for additional information provided by caller. + * If OpenSSL error queue is empty, print default_text ("???" if NULL). + */ +static char * +tls_openssl_errors(const char *app_prefix_1, const char *app_prefix_2, const char *default_text, void *apparg) +{ + static char reasons[255]; + size_t reasons_i; + unsigned long err; + const char *file; + int line; + const char *data; + int flags; + char *errstring; + int printed_something = 0; + + reasons_i = 0; + + assert(app_prefix_1 != NULL); + assert(app_prefix_2 != NULL); + + if (default_text == NULL) + default_text = "?""?""?"; + + while ((err = ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) { + if (reasons_i < sizeof reasons) { + size_t n; + int r; + + n = (sizeof reasons) - reasons_i; + r = snprintf(reasons + reasons_i, n, "%s%s", (reasons_i > 0 ? ", " : ""), ERR_reason_error_string(err)); + if (r >= n) + r = n - 1; + if (r >= 0) { + reasons_i += r; + } else { + reasons_i = sizeof reasons; + } + assert(reasons_i <= sizeof reasons); + } + + errstring = ERR_error_string(err, NULL); + assert(errstring != NULL); + tls_errprintf(0, apparg, "OpenSSL error%s%s: %s:%s:%d:%s\n", app_prefix_1, app_prefix_2, errstring, file, line, (flags & ERR_TXT_STRING) ? data : ""); + printed_something = 1; + } + + if (!printed_something) { + assert(reasons_i == 0); + snprintf(reasons, sizeof reasons, "%s", default_text); + tls_errprintf(0, apparg, "OpenSSL error%s%s: %s\n", app_prefix_1, app_prefix_2, default_text); + } + +#ifdef TLS_CUMULATE_ERRORS + tls_errflush(apparg); +#endif + assert(errbuf_i == 0); + + return reasons; +} + +/*****************************************************************************/ + +static int tls_init_done = 0; + +static int +tls_init(void *apparg) +{ + if (tls_init_done) + return 0; + + SSL_load_error_strings(); + if (!SSL_library_init() /* aka SSLeay_add_ssl_algorithms() */ ) { + tls_errprintf(1, apparg, "SSL_library_init failed.\n"); + return -1; + } + tls_init_done = 1; + tls_rand_seed(); + return 0; +} + +/*****************************************************************************/ + +static void +tls_rand_seed_uniquely(void) +{ + struct { + pid_t pid; + time_t time; + void *stack; + } data; + + data.pid = getpid(); + data.time = time(NULL); + data.stack = (void *)&data; + + RAND_seed((const void *)&data, sizeof data); +} + +void +tls_rand_seed(void) +{ + struct { + struct utsname uname; + int uname_1; + int uname_2; + uid_t uid; + uid_t euid; + gid_t gid; + gid_t egid; + } data; + + data.uname_1 = uname(&data.uname); + data.uname_2 = errno; /* Let's hope that uname fails randomly :-) */ + + data.uid = getuid(); + data.euid = geteuid(); + data.gid = getgid(); + data.egid = getegid(); + + RAND_seed((const void *)&data, sizeof data); + tls_rand_seed_uniquely(); +} + +static int tls_rand_seeded_p = 0; + +#define my_MIN_SEED_BYTES 256 /* struct stat can be larger than 128 */ +int +tls_rand_seed_from_file(const char *filename, size_t n, void *apparg) +{ + /* Seed OpenSSL's random number generator from file. + Try to read n bytes if n > 0, whole file if n == 0. */ + + int r; + + if (tls_init(apparg) == -1) + return -1; + tls_rand_seed(); + + r = RAND_load_file(filename, (n > 0 && n < LONG_MAX) ? (long)n : LONG_MAX); + /* r is the number of bytes filled into the random number generator, + * which are taken from "stat(filename, ...)" in addition to the + * file contents. + */ + assert(1 < my_MIN_SEED_BYTES); + /* We need to detect at least those cases when the file does not exist + * at all. With current versions of OpenSSL, this should do it: */ + if (n == 0) + n = my_MIN_SEED_BYTES; + if (r < n) { + tls_errprintf(1, apparg, "rand_seed_from_file: could not read %d bytes from %s.\n", n, filename); + return -1; + } else { + tls_rand_seeded_p = 1; + return 0; + } +} + +void +tls_rand_seed_from_memory(const void *buf, size_t n) +{ + size_t i = 0; + + while (i < n) { + size_t rest = n - i; + int chunk = rest < INT_MAX ? (int)rest : INT_MAX; + RAND_seed((const char *)buf + i, chunk); + i += chunk; + } + tls_rand_seeded_p = 1; +} + + +/*****************************************************************************/ + +struct tls_x509_name_string { + char str[100]; +}; + +static void +tls_get_x509_subject_name_oneline(X509 *cert, struct tls_x509_name_string *namestring) +{ + X509_NAME *name; + + if (cert == NULL) { + namestring->str[0] = '\0'; + return; + } + + name = X509_get_subject_name(cert); /* does not increment any reference counter */ + + assert(sizeof namestring->str >= 4); /* "?" or "...", plus 0 */ + + if (name == NULL) { + namestring->str[0] = '?'; + namestring->str[1] = 0; + } else { + size_t len; + + X509_NAME_oneline(name, namestring->str, sizeof namestring->str); + len = strlen(namestring->str); + assert(namestring->str[len] == 0); + assert(len < sizeof namestring->str); + + if (len+1 == sizeof namestring->str) { + /* (Probably something was cut off.) + * Does not really work -- X509_NAME_oneline truncates after + * name components, we cannot tell from the result whether + * anything is missing. */ + + assert(namestring->str[len] == 0); + namestring->str[--len] = '.'; + namestring->str[--len] = '.'; + namestring->str[--len] = '.'; + } + } +} + +/*****************************************************************************/ + +/* to hinder OpenSSL from asking for passphrases */ +static int +no_passphrase_callback(char *buf, int num, int w, void *arg) +{ + return -1; +} + +static int +verify_dont_fail_cb(X509_STORE_CTX *c, void *unused_arg) +{ + int i; + + i = X509_verify_cert(c); /* sets c->error */ +#if OPENSSL_VERSION_NUMBER >= 0x00905000L /* don't allow unverified + * certificates -- they could + * survive session reuse, but + * OpenSSL < 0.9.5-dev does not + * preserve their verify_result */ + if (i == 0) + return 1; + else +#endif + return i; +} + +static DH *tls_dhe1024 = NULL; /* generating these takes a while, so do it just once */ + +void +tls_set_dhe1024(int i, void *apparg) +{ + DSA *dsaparams; + DH *dhparams; + const char *seed[] = { ";-) :-( :-) :-( ", + ";-) :-( :-) :-( ", + "Random String no. 12", + ";-) :-( :-) :-( ", + "hackers have even mo", /* from jargon file */ + }; + unsigned char seedbuf[20]; + + tls_init(apparg); + if (i >= 0) { + i %= sizeof seed / sizeof seed[0]; + assert(strlen(seed[i]) == 20); + memcpy(seedbuf, seed[i], 20); + dsaparams = DSA_generate_parameters(1024, seedbuf, 20, NULL, NULL, 0, NULL); + } else { + /* random parameters (may take a while) */ + dsaparams = DSA_generate_parameters(1024, NULL, 0, NULL, NULL, 0, NULL); + } + + if (dsaparams == NULL) { + tls_openssl_errors("", "", NULL, apparg); + return; + } + dhparams = DSA_dup_DH(dsaparams); + DSA_free(dsaparams); + if (dhparams == NULL) { + tls_openssl_errors("", "", NULL, apparg); + return; + } + if (tls_dhe1024 != NULL) + DH_free(tls_dhe1024); + tls_dhe1024 = dhparams; +} + +struct tls_create_ctx_args +tls_create_ctx_defaultargs(void) +{ + struct tls_create_ctx_args ret; + + ret.client_p = 0; + ret.certificate_file = NULL; + ret.key_file = NULL; + ret.ca_file = NULL; + ret.verify_depth = -1; + ret.fail_unless_verified = 0; + ret.export_p = 0; + + return ret; +} + +SSL_CTX * +tls_create_ctx(struct tls_create_ctx_args a, void *apparg) +{ + int r; + static long context_num = 0; + SSL_CTX *ret; + const char *err_pref_1 = "", *err_pref_2 = ""; + + if (tls_init(apparg) == -1) + return NULL; + + ret = SSL_CTX_new((a.client_p? SSLv23_client_method:SSLv23_server_method)()); + + if (ret == NULL) + goto err; + + SSL_CTX_set_default_passwd_cb(ret, no_passphrase_callback); + SSL_CTX_set_mode(ret, SSL_MODE_ENABLE_PARTIAL_WRITE); + + if ((a.certificate_file != NULL) || (a.key_file != NULL)) { + if (a.key_file == NULL) { + tls_errprintf(1, apparg, "Need a key file.\n"); + goto err_return; + } + if (a.certificate_file == NULL) { + tls_errprintf(1, apparg, "Need a certificate chain file.\n"); + goto err_return; + } + + if (!SSL_CTX_use_PrivateKey_file(ret, a.key_file, SSL_FILETYPE_PEM)) + goto err; + if (!tls_rand_seeded_p) { + /* particularly paranoid people may not like this -- + * so provide your own random seeding before calling this */ + if (tls_rand_seed_from_file(a.key_file, 0, apparg) == -1) + goto err_return; + } + if (!SSL_CTX_use_certificate_chain_file(ret, a.certificate_file)) + goto err; + if (!SSL_CTX_check_private_key(ret)) { + tls_errprintf(1, apparg, "Private key \"%s\" does not match certificate \"%s\".\n", a.key_file, a.certificate_file); + goto err_peek; + } + } + + if ((a.ca_file != NULL) || (a.verify_depth > 0)) { + context_num++; + r = SSL_CTX_set_session_id_context(ret, (const void *)&context_num, (unsigned int)sizeof context_num); + if (!r) + goto err; + + SSL_CTX_set_verify(ret, SSL_VERIFY_PEER | (a.fail_unless_verified ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0), 0); + if (!a.fail_unless_verified) + SSL_CTX_set_cert_verify_callback(ret, verify_dont_fail_cb, NULL); + + if (a.verify_depth > 0) + SSL_CTX_set_verify_depth(ret, a.verify_depth); + + if (a.ca_file != NULL) { + r = SSL_CTX_load_verify_locations(ret, a.ca_file, NULL /* no CA-directory */); /* does not report failure if file does not exist ... */ + if (!r) { + err_pref_1 = " while processing certificate file "; + err_pref_2 = a.ca_file; + goto err; + } + + if (!a.client_p) { + /* SSL_load_client_CA_file is a misnomer, it just creates a list of CNs. */ + SSL_CTX_set_client_CA_list(ret, SSL_load_client_CA_file(a.ca_file)); + /* SSL_CTX_set_client_CA_list does not have a return value; + * it does not really need one, but make sure + * (we really test if SSL_load_client_CA_file worked) */ + if (SSL_CTX_get_client_CA_list(ret) == NULL) { + tls_errprintf(1, apparg, "Could not set client CA list from \"%s\".\n", a.ca_file); + goto err_peek; + } + } + } + } + + if (!a.client_p) { + if (tls_dhe1024 == NULL) { + int i; + + RAND_bytes((unsigned char *) &i, sizeof i); + /* make sure that i is non-negative -- pick one of the provided + * seeds */ + if (i < 0) + i = -i; + if (i < 0) + i = 0; + tls_set_dhe1024(i, apparg); + if (tls_dhe1024 == NULL) + goto err_return; + } + + if (!SSL_CTX_set_tmp_dh(ret, tls_dhe1024)) + goto err; + + /* avoid small subgroup attacks: */ + SSL_CTX_set_options(ret, SSL_OP_SINGLE_DH_USE); + } + +#ifndef NO_RSA + if (!a.client_p && a.export_p) { + RSA *tmpkey; + + tmpkey = RSA_generate_key(512, RSA_F4, 0, NULL); + if (tmpkey == NULL) + goto err; + if (!SSL_CTX_set_tmp_rsa(ret, tmpkey)) { + RSA_free(tmpkey); + goto err; + } + RSA_free(tmpkey); /* SSL_CTX_set_tmp_rsa uses a duplicate. */ + } +#endif + + return ret; + + err_peek: + if (!ERR_peek_error()) + goto err_return; + err: + tls_openssl_errors(err_pref_1, err_pref_2, NULL, apparg); + err_return: + if (ret != NULL) + SSL_CTX_free(ret); + return NULL; +} + + +/*****************************************************************************/ + +static int +tls_socket_nonblocking(int fd) +{ + int v, r; + + v = fcntl(fd, F_GETFL, 0); + if (v == -1) { + if (errno == EINVAL) + return 0; /* already shut down -- ignore */ + return -1; + } + r = fcntl(fd, F_SETFL, v | O_NONBLOCK); + if (r == -1) { + if (errno == EINVAL) + return 0; /* already shut down -- ignore */ + return -1; + } + return 0; +} + +static int +max(int a, int b) +{ + return a > b ? a : b; +} + +static void +tls_sockets_select(int read_select_1, int read_select_2, int write_select_1, int write_select_2, int seconds /* timeout, -1 means no timeout */) +{ + int maxfd, n; + fd_set reads, writes; + struct timeval timeout; + struct timeval *timeout_p; + + assert(read_select_1 >= -1 && read_select_2 >= -1 && write_select_1 >= -1 && write_select_2 >= -1); + assert(read_select_1 < FD_SETSIZE && read_select_2 < FD_SETSIZE -1 && write_select_1 < FD_SETSIZE -1 && write_select_2 < FD_SETSIZE -1); + + maxfd = max(max(read_select_1, read_select_2), max(write_select_1, write_select_2)); + assert(maxfd >= 0); + + FD_ZERO(&reads); + FD_ZERO(&writes); + + for(n = 0; n < 4; ++n) { + int i = n % 2; + int w = n >= 2; + /* loop over all (i, w) in {0,1}x{0,1} */ + int fd; + + if (i == 0 && w == 0) + fd = read_select_1; + else if (i == 1 && w == 0) + fd = read_select_2; + else if (i == 0 && w == 1) + fd = write_select_1; + else { + assert(i == 1 && w == 1); + fd = write_select_2; + } + + if (fd >= 0) { + if (w == 0) + FD_SET(fd, &reads); + else /* w == 1 */ + FD_SET(fd, &writes); + } + } + + if (seconds >= 0) { + timeout.tv_sec = seconds; + timeout.tv_usec = 0; + timeout_p = &timeout; + } else + timeout_p = NULL; + + DEBUG_MSG2("select no.", ++tls_select_count); + select(maxfd + 1, &reads, &writes, (fd_set *) NULL, timeout_p); + DEBUG_MSG("cont."); +} + +/*****************************************************************************/ + +#define TUNNELBUFSIZE (16*1024) +struct tunnelbuf { + char buf[TUNNELBUFSIZE]; + size_t len; + size_t offset; +}; + +static int tls_connect_attempt(SSL *, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref); + +static int tls_accept_attempt(SSL *, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref); + +static int tls_write_attempt(SSL *, struct tunnelbuf *, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref); + +static int tls_read_attempt(SSL *, struct tunnelbuf *, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref); + +static int write_attempt(int fd, struct tunnelbuf *, int *select, int *closed, int *progress); + +static int read_attempt(int fd, struct tunnelbuf *, int *select, int *closed, int *progress); + +static void write_info(SSL *ssl, int *info_fd) +{ + if (*info_fd != -1) { + long v; + int v_ok; + struct tls_x509_name_string peer; + char infobuf[TLS_INFO_SIZE]; + int r; + + DEBUG_MSG("write_info"); + v = SSL_get_verify_result(ssl); + v_ok = (v == X509_V_OK) ? 'A' : 'E'; /* Auth./Error */ + { + X509 *peercert; + + peercert = SSL_get_peer_certificate(ssl); + tls_get_x509_subject_name_oneline(peercert, &peer); + if (peercert != NULL) + X509_free(peercert); + } + if (peer.str[0] == '\0') + v_ok = '0'; /* no cert at all */ + else + if (strchr(peer.str, '\n')) { + /* should not happen, but make sure */ + *strchr(peer.str, '\n') = '\0'; + } + r = snprintf(infobuf, sizeof infobuf, "%c:%s\n%s\n", v_ok, X509_verify_cert_error_string(v), peer.str); + DEBUG_MSG2("snprintf", r); + if (r == -1 || r >= sizeof infobuf) + r = sizeof infobuf - 1; + write(*info_fd, infobuf, r); + close (*info_fd); + *info_fd = -1; + } +} + + +/* tls_proxy expects that all fds are closed after return */ +static void +tls_proxy(int clear_fd, int tls_fd, int info_fd, SSL_CTX *ctx, int client_p) +{ + struct tunnelbuf clear_to_tls, tls_to_clear; + SSL *ssl; + BIO *rbio, *wbio; + int closed, in_handshake; + const char *err_pref_1 = "", *err_pref_2 = ""; + const char *err_def = NULL; + + assert(clear_fd != -1); + assert(tls_fd != -1); + assert(clear_fd < FD_SETSIZE); + assert(tls_fd < FD_SETSIZE); + /* info_fd may be -1 */ + assert(ctx != NULL); + + tls_rand_seed_uniquely(); + + tls_socket_nonblocking(clear_fd); + DEBUG_MSG2("clear_fd", clear_fd); + tls_socket_nonblocking(tls_fd); + DEBUG_MSG2("tls_fd", tls_fd); + + ssl = SSL_new(ctx); + if (ssl == NULL) + goto err; + DEBUG_MSG("SSL_new"); + if (!SSL_set_fd(ssl, tls_fd)) + goto err; + rbio = SSL_get_rbio(ssl); + wbio = SSL_get_wbio(ssl); /* should be the same, but who cares */ + assert(rbio != NULL); + assert(wbio != NULL); + if (client_p) + SSL_set_connect_state(ssl); + else + SSL_set_accept_state(ssl); + + closed = 0; + in_handshake = 1; + tls_to_clear.len = 0; + tls_to_clear.offset = 0; + clear_to_tls.len = 0; + clear_to_tls.offset = 0; + + err_def = "I/O error"; + + /* loop finishes as soon as we detect that one side closed; + * when all (program and OS) buffers have enough space, + * the data from the last succesful read in each direction is transferred + * before close */ + do { + int clear_read_select = 0, clear_write_select = 0, + tls_read_select = 0, tls_write_select = 0, + progress = 0; + int r; + unsigned long num_read = BIO_number_read(rbio), + num_written = BIO_number_written(wbio); + + DEBUG_MSG2("loop iteration", ++tls_loop_count); + + if (in_handshake) { + DEBUG_MSG("in_handshake"); + if (client_p) + r = tls_connect_attempt(ssl, &tls_write_select, &tls_read_select, &closed, &progress, &err_pref_1); + else + r = tls_accept_attempt(ssl, &tls_write_select, &tls_read_select, &closed, &progress, &err_pref_1); + if (r != 0) { + write_info(ssl, &info_fd); + goto err; + } + if (closed) + goto err_return; + if (!SSL_in_init(ssl)) { + in_handshake = 0; + write_info(ssl, &info_fd); + } + } + + if (clear_to_tls.len != 0 && !in_handshake) { + assert(!closed); + + r = tls_write_attempt(ssl, &clear_to_tls, &tls_write_select, &tls_read_select, &closed, &progress, &err_pref_1); + if (r != 0) + goto err; + if (closed) { + assert(progress); + tls_to_clear.offset = 0; + tls_to_clear.len = 0; + } + } + + if (tls_to_clear.len != 0) { + assert(!closed); + + r = write_attempt(clear_fd, &tls_to_clear, &clear_write_select, &closed, &progress); + if (r != 0) + goto err_return; + if (closed) { + assert(progress); + clear_to_tls.offset = 0; + clear_to_tls.len = 0; + } + } + + if (!closed) { + if (clear_to_tls.offset + clear_to_tls.len < sizeof clear_to_tls.buf) { + r = read_attempt(clear_fd, &clear_to_tls, &clear_read_select, &closed, &progress); + if (r != 0) + goto err_return; + if (closed) { + r = SSL_shutdown(ssl); + DEBUG_MSG2("SSL_shutdown", r); + } + } + } + + if (!closed && !in_handshake) { + if (tls_to_clear.offset + tls_to_clear.len < sizeof tls_to_clear.buf) { + r = tls_read_attempt(ssl, &tls_to_clear, &tls_write_select, &tls_read_select, &closed, &progress, &err_pref_1); + if (r != 0) + goto err; + if (closed) { + r = SSL_shutdown(ssl); + DEBUG_MSG2("SSL_shutdown", r); + } + } + } + + if (!progress) { + DEBUG_MSG("!progress?"); + if (num_read != BIO_number_read(rbio) || num_written != BIO_number_written(wbio)) + progress = 1; + + if (!progress) { + DEBUG_MSG("!progress"); + assert(clear_read_select || tls_read_select || clear_write_select || tls_write_select); + tls_sockets_select(clear_read_select ? clear_fd : -1, tls_read_select ? tls_fd : -1, clear_write_select ? clear_fd : -1, tls_write_select ? tls_fd : -1, -1); + } + } + } while (!closed); + return; + + err: + tls_openssl_errors(err_pref_1, err_pref_2, err_def, tls_child_apparg); + err_return: + return; +} + + +static int +tls_get_error(SSL *ssl, int r, int *write_select, int *read_select, int *closed, int *progress) +{ + int err = SSL_get_error(ssl, r); + + if (err == SSL_ERROR_NONE) { + assert(r > 0); + *progress = 1; + return 0; + } + + assert(r <= 0); + + switch (err) { + case SSL_ERROR_ZERO_RETURN: + assert(r == 0); + *closed = 1; + *progress = 1; + return 0; + + case SSL_ERROR_WANT_WRITE: + *write_select = 1; + return 0; + + case SSL_ERROR_WANT_READ: + *read_select = 1; + return 0; + } + + return -1; +} + +static int +tls_connect_attempt(SSL *ssl, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref) +{ + int n, r; + + DEBUG_MSG("tls_connect_attempt"); + n = SSL_connect(ssl); + DEBUG_MSG2("SSL_connect",n); + r = tls_get_error(ssl, n, write_select, read_select, closed, progress); + if (r == -1) + *err_pref = " during SSL_connect"; + return r; +} + +static int +tls_accept_attempt(SSL *ssl, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref) +{ + int n, r; + + DEBUG_MSG("tls_accept_attempt"); + n = SSL_accept(ssl); + DEBUG_MSG2("SSL_accept",n); + r = tls_get_error(ssl, n, write_select, read_select, closed, progress); + if (r == -1) + *err_pref = " during SSL_accept"; + return r; +} + +static int +tls_write_attempt(SSL *ssl, struct tunnelbuf *buf, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref) +{ + int n, r; + + DEBUG_MSG("tls_write_attempt"); + n = SSL_write(ssl, buf->buf + buf->offset, buf->len); + DEBUG_MSG2("SSL_write",n); + r = tls_get_error(ssl, n, write_select, read_select, closed, progress); + if (n > 0) { + buf->len -= n; + assert(buf->len >= 0); + if (buf->len == 0) + buf->offset = 0; + else + buf->offset += n; + } + if (r == -1) + *err_pref = " during SSL_write"; + return r; +} + +static int +tls_read_attempt(SSL *ssl, struct tunnelbuf *buf, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref) +{ + int n, r; + size_t total; + + DEBUG_MSG("tls_read_attempt"); + total = buf->offset + buf->len; + assert(total < sizeof buf->buf); + n = SSL_read(ssl, buf->buf + total, (sizeof buf->buf) - total); + DEBUG_MSG2("SSL_read",n); + r = tls_get_error(ssl, n, write_select, read_select, closed, progress); + if (n > 0) { + buf->len += n; + assert(buf->offset + buf->len <= sizeof buf->buf); + } + if (r == -1) + *err_pref = " during SSL_read"; + return r; +} + +static int +get_error(int r, int *select, int *closed, int *progress) +{ + if (r >= 0) { + *progress = 1; + if (r == 0) + *closed = 1; + return 0; + } else { + assert(r == -1); + if (errno == EAGAIN || errno == EWOULDBLOCK) { + *select = 1; + return 0; + } else if (errno == EPIPE) { + *progress = 1; + *closed = 1; + return 0; + } else + return -1; + } +} + +static int write_attempt(int fd, struct tunnelbuf *buf, int *select, int *closed, int *progress) +{ + int n, r; + + DEBUG_MSG("write_attempt"); + n = write(fd, buf->buf + buf->offset, buf->len); + DEBUG_MSG2("write",n); + r = get_error(n, select, closed, progress); + if (n > 0) { + buf->len -= n; + assert(buf->len >= 0); + if (buf->len == 0) + buf->offset = 0; + else + buf->offset += n; + } + if (r == -1) + tls_errprintf(1, tls_child_apparg, "write error: %s\n", strerror(errno)); + return r; +} + +static int +read_attempt(int fd, struct tunnelbuf *buf, int *select, int *closed, int *progress) +{ + int n, r; + size_t total; + + DEBUG_MSG("read_attempt"); + total = buf->offset + buf->len; + assert(total < sizeof buf->buf); + n = read(fd, buf->buf + total, (sizeof buf->buf) - total); + DEBUG_MSG2("read",n); + r = get_error(n, select, closed, progress); + if (n > 0) { + buf->len += n; + assert(buf->offset + buf->len <= sizeof buf->buf); + } + if (r == -1) + tls_errprintf(1, tls_child_apparg, "read error: %s\n", strerror(errno)); + return r; +} diff --git a/doc/ssl/SSL_CTX_set_cert_verify_callback.pod b/doc/ssl/SSL_CTX_set_cert_verify_callback.pod new file mode 100644 index 000000000..c0f4f8570 --- /dev/null +++ b/doc/ssl/SSL_CTX_set_cert_verify_callback.pod @@ -0,0 +1,75 @@ +=pod + +=head1 NAME + +SSL_CTX_set_cert_verify_callback - set peer certificate verification procedure + +=head1 SYNOPSIS + + #include <openssl/ssl.h> + + void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*callback)(X509_STORE_CTX *,void *), void *arg); + +=head1 DESCRIPTION + +SSL_CTX_set_cert_verify_callback() sets the verification callback function for +I<ctx>. SSL objects that are created from I<ctx> inherit the setting valid at +the time when L<SSL_new(3)|SSL_new(3)> is called. + +=head1 NOTES + +Whenever a certificate is verified during a SSL/TLS handshake, a verification +function is called. If the application does not explicitly specify a +verification callback function, the built-in verification function is used. +If a verification callback I<callback> is specified via +SSL_CTX_set_cert_verify_callback(), the supplied callback function is called +instead. By setting I<callback> to NULL, the default behaviour is restored. + +When the verification must be performed, I<callback> will be called with +the arguments callback(X509_STORE_CTX *x509_store_ctx, void *arg). The +argument I<arg> is specified by the application when setting I<callback>. + +I<callback> should return 1 to indicate verification success and 0 to +indicate verification failure. If SSL_VERIFY_PEER is set and I<callback> +returns 0, the handshake will fail. As the verification procedure may +allow to continue the connection in case of failure (by always returning 1) +the verification result must be set in any case using the B<error> +member of I<x509_store_ctx> so that the calling application will be informed +about the detailed result of the verification procedure! + +Within I<x509_store_ctx>, I<callback> has access to the I<verify_callback> +function set using L<SSL_CTX_set_verify(3)|SSL_CTX_set_verify(3)>. + +=head1 WARNINGS + +Do not mix the verification callback described in this function with the +B<verify_callback> function called during the verification process. The +latter is set using the L<SSL_CTX_set_verify(3)|SSL_CTX_set_verify(3)> +family of functions. + +Providing a complete verification procedure including certificate purpose +settings etc is a complex task. The built-in procedure is quite powerful +and in most cases it should be sufficient to modify its behaviour using +the B<verify_callback> function. + +=head1 BUGS + +=head1 RETURN VALUES + +SSL_CTX_set_cert_verify_callback() does not provide diagnostic information. + +=head1 SEE ALSO + +L<ssl(3)|ssl(3)>, L<SSL_CTX_set_verify(3)|SSL_CTX_set_verify(3)>, +L<SSL_get_verify_result(3)|SSL_get_verify_result(3)>, +L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)> + +=head1 HISTORY + +Previous to OpenSSL 0.9.7, the I<arg> argument to B<SSL_CTX_set_cert_verify_callback> +was ignored, and I<callback> was called simply as + int (*callback)(X509_STORE_CTX *) +To compile software written for previous versions of OpenSSL, a dummy +argument will have to be added to I<callback>. + +=cut @@ -55,10 +55,131 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ #ifndef HEADER_SSL_H #define HEADER_SSL_H +#include <openssl/e_os2.h> + +#ifndef OPENSSL_NO_COMP +#include <openssl/comp.h> +#endif +#ifndef OPENSSL_NO_BIO +#include <openssl/bio.h> +#endif +#ifndef OPENSSL_NO_X509 +#include <openssl/x509.h> +#endif +#include <openssl/kssl.h> +#include <openssl/safestack.h> +#include <openssl/symhacks.h> + #ifdef __cplusplus extern "C" { #endif @@ -81,7 +202,18 @@ extern "C" { #define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 #define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA +/* VRS Additional Kerberos5 entries + */ +#define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA +#define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5 +#define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA +#define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5 +#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA +#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5 +#define SSL_MAX_KRB5_PRINCIPAL_LENGTH 256 + #define SSL_MAX_SSL_SESSION_ID_LENGTH 32 +#define SSL_MAX_SID_CTX_LENGTH 32 #define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8) #define SSL_MAX_KEY_ARG_LENGTH 8 @@ -100,6 +232,10 @@ extern "C" { #define SSL_TXT_eNULL "eNULL" #define SSL_TXT_NULL "NULL" +#define SSL_TXT_kKRB5 "kKRB5" +#define SSL_TXT_aKRB5 "aKRB5" +#define SSL_TXT_KRB5 "KRB5" + #define SSL_TXT_kRSA "kRSA" #define SSL_TXT_kDHr "kDHr" #define SSL_TXT_kDHd "kDHd" @@ -117,11 +253,14 @@ extern "C" { #define SSL_TXT_RC4 "RC4" #define SSL_TXT_RC2 "RC2" #define SSL_TXT_IDEA "IDEA" +#define SSL_TXT_AES "AES" #define SSL_TXT_MD5 "MD5" #define SSL_TXT_SHA1 "SHA1" #define SSL_TXT_SHA "SHA" #define SSL_TXT_EXP "EXP" #define SSL_TXT_EXPORT "EXPORT" +#define SSL_TXT_EXP40 "EXPORT40" +#define SSL_TXT_EXP56 "EXPORT56" #define SSL_TXT_SSLV2 "SSLv2" #define SSL_TXT_SSLV3 "SSLv3" #define SSL_TXT_TLSV1 "TLSv1" @@ -129,22 +268,30 @@ extern "C" { /* 'DEFAULT' at the start of the cipher list insert the following string * in addition to this being the default cipher string */ -#ifndef NO_RSA -#define SSL_DEFAULT_CIPHER_LIST "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP" -#else -#define SSL_ALLOW_ADH -#define SSL_DEFAULT_CIPHER_LIST "HIGH:MEDIUM:LOW:ADH+3DES:ADH+RC4:ADH+DES:+EXP" -#endif +#define SSL_DEFAULT_CIPHER_LIST "ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH" /* Used in SSL_set_shutdown()/SSL_get_shutdown(); */ #define SSL_SENT_SHUTDOWN 1 #define SSL_RECEIVED_SHUTDOWN 2 -#include "crypto.h" -#include "lhash.h" -#include "buffer.h" -#include "bio.h" -#include "x509.h" +#ifdef __cplusplus +} +#endif + +#include <openssl/crypto.h> +#include <openssl/lhash.h> +#include <openssl/buffer.h> +#include <openssl/bio.h> +#include <openssl/pem.h> +#include <openssl/x509.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2) +#define OPENSSL_NO_SSL2 +#endif #define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 #define SSL_FILETYPE_PEM X509_FILETYPE_PEM @@ -158,38 +305,50 @@ typedef struct ssl_st *ssl_crock_st; typedef struct ssl_cipher_st { int valid; - char *name; /* text name */ + const char *name; /* text name */ unsigned long id; /* id, 4 bytes, first is version */ unsigned long algorithms; /* what ciphers are used */ + unsigned long algo_strength; /* strength and export flags */ unsigned long algorithm2; /* Extra flags */ + int strength_bits; /* Number of bits really used */ + int alg_bits; /* Number of bits for algorithm */ unsigned long mask; /* used for matching */ + unsigned long mask_strength; /* also used for matching */ } SSL_CIPHER; +DECLARE_STACK_OF(SSL_CIPHER) + +typedef struct ssl_st SSL; +typedef struct ssl_ctx_st SSL_CTX; + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ typedef struct ssl_method_st { int version; - int (*ssl_new)(); - void (*ssl_clear)(); - void (*ssl_free)(); - int (*ssl_accept)(); - int (*ssl_connect)(); - int (*ssl_read)(); - int (*ssl_peek)(); - int (*ssl_write)(); - int (*ssl_shutdown)(); - int (*ssl_renegotiate)(); - int (*ssl_renegotiate_check)(); - long (*ssl_ctrl)(); - long (*ssl_ctx_ctrl)(); - SSL_CIPHER *(*get_cipher_by_char)(); - int (*put_cipher_by_char)(); - int (*ssl_pending)(); - int (*num_ciphers)(); - SSL_CIPHER *(*get_cipher)(); - struct ssl_method_st *(*get_ssl_method)(); - long (*get_timeout)(); + int (*ssl_new)(SSL *s); + void (*ssl_clear)(SSL *s); + void (*ssl_free)(SSL *s); + int (*ssl_accept)(SSL *s); + int (*ssl_connect)(SSL *s); + int (*ssl_read)(SSL *s,void *buf,int len); + int (*ssl_peek)(SSL *s,void *buf,int len); + int (*ssl_write)(SSL *s,const void *buf,int len); + int (*ssl_shutdown)(SSL *s); + int (*ssl_renegotiate)(SSL *s); + int (*ssl_renegotiate_check)(SSL *s); + long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg); + long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg); + SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr); + int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr); + int (*ssl_pending)(SSL *s); + int (*num_ciphers)(void); + SSL_CIPHER *(*get_cipher)(unsigned ncipher); + struct ssl_method_st *(*get_ssl_method)(int version); + long (*get_timeout)(void); struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */ + int (*ssl_version)(); + long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)()); + long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)()); } SSL_METHOD; /* Lets make this into an ASN.1 type structure as follows @@ -203,7 +362,9 @@ typedef struct ssl_method_st * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate - * Compression [4] IMPLICIT ASN1_OBJECT -- compression OID XXXXX + * Session_ID_context [ 4 ] EXPLICIT OCTET_STRING, -- the Session ID context + * Verify_result [ 5 ] EXPLICIT INTEGER -- X509_V_... code for `Peer' + * Compression [6] IMPLICIT ASN1_OBJECT -- compression OID XXXXX * } * Look in ssl/ssl_asn1.c for more details * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-). @@ -221,32 +382,43 @@ typedef struct ssl_session_st /* session_id - valid? */ unsigned int session_id_length; unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + /* this is used to determine whether the session is being reused in + * the appropriate context. It is up to the application to set this, + * via SSL_new */ + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + +#ifndef OPENSSL_NO_KRB5 + unsigned int krb5_client_princ_len; + unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH]; +#endif /* OPENSSL_NO_KRB5 */ int not_resumable; /* The cert is the certificate used to establish this connection */ - struct cert_st /* CERT */ *cert; + struct sess_cert_st /* SESS_CERT */ *sess_cert; - /* This is the cert for the other end. On servers, it will be - * the same as cert->x509 */ + /* This is the cert for the other end. + * On clients, it will be the same as sess_cert->peer_key->x509 + * (the latter is not enough as sess_cert is not retained + * in the external representation of sessions, see ssl_asn1.c). */ X509 *peer; + /* when app_verify_callback accepts a session where the peer's certificate + * is not ok, we must remember the error for session reuse: */ + long verify_result; /* only for servers */ int references; long timeout; long time; -#ifdef HEADER_COMP_H - COMP_CTX *compress_meth; -#else - char *compress_meth; -#endif + int compress_meth; /* Need to lookup the method */ SSL_CIPHER *cipher; unsigned long cipher_id; /* when ASN.1 loaded, this * needs to be used to load * the 'cipher' structure */ - STACK /* SSL_CIPHER */ *ciphers; /* shared ciphers? */ + STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */ CRYPTO_EX_DATA ex_data; /* application specific data */ @@ -265,49 +437,124 @@ typedef struct ssl_session_st #define SSL_OP_TLS_D5_BUG 0x00000100L #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L -/* If set, only use tmp_dh parameters once */ +/* If set, always create a new key when using tmp_dh parameters */ #define SSL_OP_SINGLE_DH_USE 0x00100000L -/* Set to also use the tmp_rsa key when doing RSA operations. */ +/* Set to always use the tmp_rsa key when doing RSA operations, + * even when this violates protocol specs */ #define SSL_OP_EPHEMERAL_RSA 0x00200000L - -/* The next flag deliberatly changes the ciphertest, this is a check +/* Set on servers to choose the cipher according to the server's + * preferences */ +#define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L +/* If set, a server will allow a client to issue a SSLv3.0 version number + * as latest version supported in the premaster secret, even when TLSv1.0 + * (version 3.1) was announced in the client hello. Normally this is + * forbidden to prevent version rollback attacks. */ +#define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L +/* As server, disallow session resumption on renegotiation */ +#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x01000000L + +/* The next flag deliberately changes the ciphertest, this is a check * for the PKCS#1 attack */ #define SSL_OP_PKCS1_CHECK_1 0x08000000L #define SSL_OP_PKCS1_CHECK_2 0x10000000L #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L -#define SSL_OP_NON_EXPORT_FIRST 0x40000000L -#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x80000000L +#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L #define SSL_OP_ALL 0x000FFFFFL -#define SSL_CTX_set_options(ctx,op) ((ctx)->options|=(op)) -#define SSL_set_options(ssl,op) ((ssl)->options|=(op)) - #define SSL_OP_NO_SSLv2 0x01000000L #define SSL_OP_NO_SSLv3 0x02000000L #define SSL_OP_NO_TLSv1 0x04000000L -/* Normally you will only use these if your application wants to use - * the certificate store in other places, perhaps PKCS7 */ -#define SSL_CTX_get_cert_store(ctx) ((ctx)->cert_store) -#define SSL_CTX_set_cert_store(ctx,cs) \ - (X509_STORE_free((ctx)->cert_store),(ctx)->cert_store=(cs)) - +/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success + * when just a single record has been written): */ +#define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001L +/* Make it possible to retry SSL_write() with changed buffer location + * (buffer contents must stay the same!); this is not the default to avoid + * the misconception that non-blocking SSL_write() behaves like + * non-blocking write(): */ +#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L +/* Never bother the application with retries if the transport + * is blocking: */ +#define SSL_MODE_AUTO_RETRY 0x00000004L + +/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, + * they cannot be used to clear bits. */ + +#define SSL_CTX_set_options(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL) +#define SSL_CTX_get_options(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL) +#define SSL_set_options(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL) +#define SSL_get_options(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL) + +#define SSL_CTX_set_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) +#define SSL_CTX_get_mode(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL) +#define SSL_set_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) +#define SSL_get_mode(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL) + + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); +void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); +#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) +#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) + + + +#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32) +#define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */ +#else +#define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */ +#endif #define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20) -typedef struct ssl_ctx_st +/* This callback type is used inside SSL_CTX, SSL, and in the functions that set + * them. It is used to override the generation of SSL/TLS session IDs in a + * server. Return value should be zero on an error, non-zero to proceed. Also, + * callbacks should themselves check if the id they generate is unique otherwise + * the SSL handshake will fail with an error - callbacks can do this using the + * 'ssl' value they're passed by; + * SSL_has_matching_session_id(ssl, id, *id_len) + * The length value passed in is set at the maximum size the session ID can be. + * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback + * can alter this length to be less if desired, but under SSLv2 session IDs are + * supposed to be fixed at 16 bytes so the id will be padded after the callback + * returns in this case. It is also an error for the callback to set the size to + * zero. */ +typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id, + unsigned int *id_len); + +typedef struct ssl_comp_st + { + int id; + char *name; +#ifndef OPENSSL_NO_COMP + COMP_METHOD *method; +#else + char *method; +#endif + } SSL_COMP; + +DECLARE_STACK_OF(SSL_COMP) + +struct ssl_ctx_st { SSL_METHOD *method; - unsigned long options; - STACK /* SSL_CIPHER */ *cipher_list; + STACK_OF(SSL_CIPHER) *cipher_list; /* same as above but sorted for lookup */ - STACK /* SSL_CIPHER */ *cipher_list_by_id; + STACK_OF(SSL_CIPHER) *cipher_list_by_id; struct x509_store_st /* X509_STORE */ *cert_store; - struct lhash_st /* LHASH */ *sessions; /* a set of SSL_SESSION's */ + struct lhash_st /* LHASH */ *sessions; /* a set of SSL_SESSIONs */ /* Most session-ids that will be cached, default is - * SSL_SESSION_CACHE_SIZE_DEFAULT. 0 is unlimited. */ + * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */ unsigned long session_cache_size; struct ssl_session_st *session_cache_head; struct ssl_session_st *session_cache_tail; @@ -330,69 +577,95 @@ typedef struct ssl_ctx_st * SSL_SESSION_free() when it has finished using it. Otherwise, * on 0, it means the callback has finished with it. * If remove_session_cb is not null, it will be called when - * a session-id is removed from the cache. Again, a return - * of 0 mens that SSLeay should not SSL_SESSION_free() since - * the application is doing something with it. */ -#ifndef NOPROTO + * a session-id is removed from the cache. After the call, + * OpenSSL will SSL_SESSION_free() it. */ int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess); void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess); SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy); -#else - int (*new_session_cb)(); - void (*remove_session_cb)(); - SSL_SESSION *(*get_session_cb)(); -#endif - int sess_connect; /* SSL new connection - started */ - int sess_connect_renegotiate;/* SSL renegotiatene - requested */ - int sess_connect_good; /* SSL new connection/renegotiate - finished */ - int sess_accept; /* SSL new accept - started */ - int sess_accept_renegotiate;/* SSL renegotiatene - requested */ - int sess_accept_good; /* SSL accept/renegotiate - finished */ - int sess_miss; /* session lookup misses */ - int sess_timeout; /* session reuse attempt on timeouted session */ - int sess_cache_full; /* session removed due to full cache */ - int sess_hit; /* session reuse actually done */ - int sess_cb_hit; /* session-id that was not in the cache was - * passed back via the callback. This - * indicates that the application is supplying - * session-id's from other processes - - * spooky :-) */ + struct + { + int sess_connect; /* SSL new conn - started */ + int sess_connect_renegotiate;/* SSL reneg - requested */ + int sess_connect_good; /* SSL new conne/reneg - finished */ + int sess_accept; /* SSL new accept - started */ + int sess_accept_renegotiate;/* SSL reneg - requested */ + int sess_accept_good; /* SSL accept/reneg - finished */ + int sess_miss; /* session lookup misses */ + int sess_timeout; /* reuse attempt on timeouted session */ + int sess_cache_full; /* session removed due to full cache */ + int sess_hit; /* session reuse actually done */ + int sess_cb_hit; /* session-id that was not + * in the cache was + * passed back via the callback. This + * indicates that the application is + * supplying session-id's from other + * processes - spooky :-) */ + } stats; int references; - void (*info_callback)(); - /* if defined, these override the X509_verify_cert() calls */ - int (*app_verify_callback)(); - char *app_verify_arg; - - /* default values to use in SSL structures */ - struct cert_st /* CERT */ *default_cert; - int default_read_ahead; - int default_verify_mode; - int (*default_verify_callback)(); + int (*app_verify_callback)(X509_STORE_CTX *, void *); + void *app_verify_arg; + /* before OpenSSL 0.9.7, 'app_verify_arg' was ignored + * ('app_verify_callback' was called with just one argument) */ /* Default password callback. */ - int (*default_passwd_callback)(); + pem_password_cb *default_passwd_callback; + + /* Default password callback user data. */ + void *default_passwd_callback_userdata; /* get client cert callback */ - int (*client_cert_cb)(/* SSL *ssl, X509 **x509, EVP_PKEY **pkey */); + int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey); - /* what we put in client requests */ - STACK *client_CA; + CRYPTO_EX_DATA ex_data; - int quiet_shutdown; + const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */ + const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */ + const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */ - CRYPTO_EX_DATA ex_data; + STACK_OF(X509) *extra_certs; + STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */ + + + /* Default values used when no per-SSL value is defined follow */ - EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */ - EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */ - EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */ + void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */ - STACK *extra_certs; - } SSL_CTX; + /* what we put in client cert requests */ + STACK_OF(X509_NAME) *client_CA; + + + /* Default values to use in SSL structures follow (these are copied by SSL_new) */ + + unsigned long options; + unsigned long mode; + long max_cert_list; + + struct cert_st /* CERT */ *cert; + int read_ahead; + + /* callback that allows applications to peek at protocol messages */ + void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg); + void *msg_callback_arg; + + int verify_mode; + int verify_depth; + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */ + + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + + int purpose; /* Purpose setting */ + int trust; /* Trust setting */ + + int quiet_shutdown; + }; #define SSL_SESS_CACHE_OFF 0x0000 #define SSL_SESS_CACHE_CLIENT 0x0001 @@ -404,23 +677,31 @@ typedef struct ssl_ctx_st * defined, this will still get called. */ #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100 -#define SSL_CTX_sessions(ctx) ((ctx)->sessions) -/* You will need to include lhash.h to access the following #define */ -#define SSL_CTX_sess_number(ctx) ((ctx)->sessions->num_items) -#define SSL_CTX_sess_connect(ctx) ((ctx)->sess_connect) -#define SSL_CTX_sess_connect_good(ctx) ((ctx)->sess_connect_good) -#define SSL_CTX_sess_accept(ctx) ((ctx)->sess_accept) -#define SSL_CTX_sess_accept_renegotiate(ctx) ((ctx)->sess_accept_renegotiate) -#define SSL_CTX_sess_connect_renegotiate(ctx) ((ctx)->sess_connect_renegotiate) -#define SSL_CTX_sess_accept_good(ctx) ((ctx)->sess_accept_good) -#define SSL_CTX_sess_hits(ctx) ((ctx)->sess_hit) -#define SSL_CTX_sess_cb_hits(ctx) ((ctx)->sess_cb_hit) -#define SSL_CTX_sess_misses(ctx) ((ctx)->sess_miss) -#define SSL_CTX_sess_timeouts(ctx) ((ctx)->sess_timeout) -#define SSL_CTX_sess_cache_full(ctx) ((ctx)->sess_cache_full) - -#define SSL_CTX_sess_set_cache_size(ctx,t) ((ctx)->session_cache_size=(t)) -#define SSL_CTX_sess_get_cache_size(ctx) ((ctx)->session_cache_size) + struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx); +#define SSL_CTX_sess_number(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL) +#define SSL_CTX_sess_connect(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL) +#define SSL_CTX_sess_connect_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL) +#define SSL_CTX_sess_connect_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL) +#define SSL_CTX_sess_accept(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL) +#define SSL_CTX_sess_accept_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL) +#define SSL_CTX_sess_accept_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL) +#define SSL_CTX_sess_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL) +#define SSL_CTX_sess_cb_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL) +#define SSL_CTX_sess_misses(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL) +#define SSL_CTX_sess_timeouts(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL) +#define SSL_CTX_sess_cache_full(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL) #define SSL_CTX_sess_set_new_cb(ctx,cb) ((ctx)->new_session_cb=(cb)) #define SSL_CTX_sess_get_new_cb(ctx) ((ctx)->new_session_cb) @@ -428,15 +709,8 @@ typedef struct ssl_ctx_st #define SSL_CTX_sess_get_remove_cb(ctx) ((ctx)->remove_session_cb) #define SSL_CTX_sess_set_get_cb(ctx,cb) ((ctx)->get_session_cb=(cb)) #define SSL_CTX_sess_get_get_cb(ctx) ((ctx)->get_session_cb) -#define SSL_CTX_set_session_cache_mode(ctx,m) ((ctx)->session_cache_mode=(m)) -#define SSL_CTX_get_session_cache_mode(ctx) ((ctx)->session_cache_mode) -#define SSL_CTX_set_timeout(ctx,t) ((ctx)->session_timeout=(t)) -#define SSL_CTX_get_timeout(ctx) ((ctx)->session_timeout) - #define SSL_CTX_set_info_callback(ctx,cb) ((ctx)->info_callback=(cb)) #define SSL_CTX_get_info_callback(ctx) ((ctx)->info_callback) -#define SSL_CTX_set_default_read_ahead(ctx,m) (((ctx)->default_read_ahead)=(m)) - #define SSL_CTX_set_client_cert_cb(ctx,cb) ((ctx)->client_cert_cb=(cb)) #define SSL_CTX_get_client_cert_cb(ctx) ((ctx)->client_cert_cb) @@ -446,18 +720,16 @@ typedef struct ssl_ctx_st #define SSL_X509_LOOKUP 4 /* These will only be used when doing non-blocking IO */ -#define SSL_want(s) ((s)->rwstate) -#define SSL_want_nothing(s) ((s)->rwstate == SSL_NOTHING) -#define SSL_want_read(s) ((s)->rwstate == SSL_READING) -#define SSL_want_write(s) ((s)->rwstate == SSL_WRITING) -#define SSL_want_x509_lookup(s) ((s)->rwstate == SSL_X509_LOOKUP) +#define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING) +#define SSL_want_read(s) (SSL_want(s) == SSL_READING) +#define SSL_want_write(s) (SSL_want(s) == SSL_WRITING) +#define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP) -typedef struct ssl_st +struct ssl_st { - /* procol version - * 2 for SSLv2 - * 3 for SSLv3 - * -3 for SSLv3 but accept SSLv2 */ + /* protocol version + * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION) + */ int version; int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */ @@ -467,10 +739,10 @@ typedef struct ssl_st * same. This is so data can be read and written to different * handlers */ -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO BIO *rbio; /* used by SSL_read */ BIO *wbio; /* used by SSL_write */ - BIO *bbio; /* used during session-id reuse to concatinate + BIO *bbio; /* used during session-id reuse to concatenate * messages */ #else char *rbio; /* used by SSL_read */ @@ -487,9 +759,22 @@ typedef struct ssl_st int in_handshake; int (*handshake_func)(); -/* int server;*/ /* are we the server side? */ - - int new_session;/* 1 if we are to use a new session */ + /* Imagine that here's a boolean member "init" that is + * switched as soon as SSL_set_{accept/connect}_state + * is called for the first time, so that "state" and + * "handshake_func" are properly initialized. But as + * handshake_func is == 0 until then, we use this + * test instead of an "init" member. + */ + + int server; /* are we the server side? - mostly used by SSL_clear*/ + + int new_session;/* 1 if we are to use a new session. + * 2 if we are a server and are inside a handshake + * (i.e. not just sending a HelloRequest) + * NB: For servers, the 'new' session may actually be a previously + * cached session or even the previous session unless + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ int quiet_shutdown;/* don't send shutdown packets */ int shutdown; /* we have shut things down, 0x01 sent, 0x02 * for received */ @@ -497,6 +782,7 @@ typedef struct ssl_st int rstate; /* where we are when reading */ BUF_MEM *init_buf; /* buffer used during init */ + void *init_msg; /* pointer to handshake message body, set by ssl3_get_message() */ int init_num; /* amount read/written */ int init_off; /* amount read/written */ @@ -504,30 +790,39 @@ typedef struct ssl_st unsigned char *packet; unsigned int packet_length; - struct ssl2_ctx_st *s2; /* SSLv2 variables */ - struct ssl3_ctx_st *s3; /* SSLv3 variables */ + struct ssl2_state_st *s2; /* SSLv2 variables */ + struct ssl3_state_st *s3; /* SSLv3 variables */ + + int read_ahead; /* Read as many input bytes as possible + * (for non-blocking reads) */ + + /* callback that allows applications to peek at protocol messages */ + void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg); + void *msg_callback_arg; - int read_ahead; /* Read as many input bytes as possible */ int hit; /* reusing a previous session */ + int purpose; /* Purpose setting */ + int trust; /* Trust setting */ + /* crypto */ - STACK /* SSL_CIPHER */ *cipher_list; - STACK /* SSL_CIPHER */ *cipher_list_by_id; + STACK_OF(SSL_CIPHER) *cipher_list; + STACK_OF(SSL_CIPHER) *cipher_list_by_id; - /* These are the ones being used, the ones is SSL_SESSION are + /* These are the ones being used, the ones in SSL_SESSION are * the ones to be 'copied' into these ones */ EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */ - EVP_MD *read_hash; /* used for mac generation */ -#ifdef HEADER_COMP_H + const EVP_MD *read_hash; /* used for mac generation */ +#ifndef OPENSSL_NO_COMP COMP_CTX *expand; /* uncompress */ #else char *expand; #endif EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ - EVP_MD *write_hash; /* used for mac generation */ -#ifdef HEADER_COMP_H + const EVP_MD *write_hash; /* used for mac generation */ +#ifndef OPENSSL_NO_COMP COMP_CTX *compress; /* compression */ #else char *compress; @@ -539,18 +834,32 @@ typedef struct ssl_st /* This is used to hold the server certificate used */ struct cert_st /* CERT */ *cert; + /* the session_id_context is used to ensure sessions are only reused + * in the appropriate context */ + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + /* This can also be in the session once a session is established */ SSL_SESSION *session; + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + /* Used in SSL2 and SSL3 */ int verify_mode; /* 0 don't care about verify failure. * 1 fail if verify fails */ - int (*verify_callback)(); /* fail if callback returns 0 */ - void (*info_callback)(); /* optional informational callback */ + int verify_depth; + int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */ + + void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */ int error; /* error bytes to be written */ int error_code; /* actual code */ +#ifndef OPENSSL_NO_KRB5 + KSSL_CTX *kssl_ctx; /* Kerberos 5 context */ +#endif /* OPENSSL_NO_KRB5 */ + SSL_CTX *ctx; /* set this flag to 1 and a sleep(1) is put into all SSL_read() * and SSL_write() calls, good for nbio debuging :-) */ @@ -561,19 +870,31 @@ typedef struct ssl_st CRYPTO_EX_DATA ex_data; /* for server side, keep the list of CA_dn we can use */ - STACK /* X509_NAME */ *client_CA; + STACK_OF(X509_NAME) *client_CA; int references; - unsigned long options; + unsigned long options; /* protocol behaviour */ + unsigned long mode; /* API behaviour */ + long max_cert_list; int first_packet; - } SSL; + int client_version; /* what was passed, used for + * SSLv3/TLS rollback check */ + }; + +#ifdef __cplusplus +} +#endif + +#include <openssl/ssl2.h> +#include <openssl/ssl3.h> +#include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */ +#include <openssl/ssl23.h> -#include "ssl2.h" -#include "ssl3.h" -#include "tls1.h" /* This is mostly sslv3 with a few tweaks */ -#include "ssl23.h" +#ifdef __cplusplus +extern "C" { +#endif -/* compatablity */ +/* compatibility */ #define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)arg)) #define SSL_get_app_data(s) (SSL_get_ex_data(s,0)) #define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0,(char *)a)) @@ -582,7 +903,7 @@ typedef struct ssl_st #define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0,(char *)arg)) /* The following are the possible values for ssl->state are are - * used to indicate where we are upto in the SSL connection establishment. + * used to indicate where we are up to in the SSL connection establishment. * The macros that follow are about the only things you should need to use * and even then, only when using non-blocking IO. * It can also be useful to work out where you were when the connection @@ -624,6 +945,13 @@ typedef struct ssl_st #define SSL_ST_READ_BODY 0xF1 #define SSL_ST_READ_DONE 0xF2 +/* Obtain latest Finished message + * -- that we sent (SSL_get_finished) + * -- that we expected from peer (SSL_get_peer_finished). + * Returns length (0 == no Finished so far), copies up to 'count' bytes. */ +size_t SSL_get_finished(SSL *s, void *buf, size_t count); +size_t SSL_get_peer_finished(SSL *s, void *buf, size_t count); + /* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options * are 'ored' with SSL_VERIFY_PEER if they are desired */ #define SSL_VERIFY_NONE 0x00 @@ -631,7 +959,10 @@ typedef struct ssl_st #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 #define SSL_VERIFY_CLIENT_ONCE 0x04 -/* this is for backward compatablility */ +#define OpenSSL_add_ssl_algorithms() SSL_library_init() +#define SSLeay_add_ssl_algorithms() SSL_library_init() + +/* this is for backward compatibility */ #if 0 /* NEW_SSLEAY */ #define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c) #define SSL_set_pref_cipher(c,n) SSL_set_cipher_list(c,n) @@ -639,7 +970,7 @@ typedef struct ssl_st #define SSL_remove_session(a,b) SSL_CTX_remove_session((a),(b)) #define SSL_flush_sessions(a,b) SSL_CTX_flush_sessions((a),(b)) #endif -/* More backward compatablity */ +/* More backward compatibility */ #define SSL_get_cipher(s) \ SSL_CIPHER_get_name(SSL_get_current_cipher(s)) #define SSL_get_cipher_bits(s,np) \ @@ -653,26 +984,22 @@ typedef struct ssl_st #define SSL_get_timeout(a) SSL_SESSION_get_timeout(a) #define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b)) -/* VMS linker has a 31 char name limit */ -#define SSL_CTX_set_cert_verify_callback(a,b,c) \ - SSL_CTX_set_cert_verify_cb((a),(b),(c)) - #if 1 /*SSLEAY_MACROS*/ #define d2i_SSL_SESSION_bio(bp,s_id) (SSL_SESSION *)ASN1_d2i_bio( \ (char *(*)())SSL_SESSION_new,(char *(*)())d2i_SSL_SESSION, \ (bp),(unsigned char **)(s_id)) #define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio(i2d_SSL_SESSION, \ bp,(unsigned char *)s_id) -#define PEM_read_SSL_SESSION(fp,x,cb) (SSL_SESSION *)PEM_ASN1_read( \ - (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb) -#define PEM_read_bio_SSL_SESSION(bp,x,cb) (SSL_SESSION *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb) +#define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \ + (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u) +#define PEM_read_bio_SSL_SESSION(bp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb,u) #define PEM_write_SSL_SESSION(fp,x) \ PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \ - PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL) + PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL) #define PEM_write_bio_SSL_SESSION(bp,x) \ PEM_ASN1_write_bio((int (*)())i2d_SSL_SESSION, \ - PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL) + PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL,NULL) #endif #define SSL_AD_REASON_OFFSET 1000 @@ -695,11 +1022,11 @@ typedef struct ssl_st #define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED /* fatal */ #define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR /* fatal */ #define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR -#define SSL_AD_EXPORT_RESTRICION TLS1_AD_EXPORT_RESTRICION/* fatal */ +#define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION/* fatal */ #define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION /* fatal */ #define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY/* fatal */ #define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR /* fatal */ -#define SSL_AD_USER_CANCLED TLS1_AD_USER_CANCLED +#define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED #define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION #define SSL_ERROR_NONE 0 @@ -707,24 +1034,53 @@ typedef struct ssl_st #define SSL_ERROR_WANT_READ 2 #define SSL_ERROR_WANT_WRITE 3 #define SSL_ERROR_WANT_X509_LOOKUP 4 -#define SSL_ERROR_SYSCALL 5 /* look at errno */ +#define SSL_ERROR_SYSCALL 5 /* look at error stack/return value/errno */ #define SSL_ERROR_ZERO_RETURN 6 #define SSL_ERROR_WANT_CONNECT 7 +#define SSL_ERROR_WANT_ACCEPT 8 #define SSL_CTRL_NEED_TMP_RSA 1 #define SSL_CTRL_SET_TMP_RSA 2 #define SSL_CTRL_SET_TMP_DH 3 #define SSL_CTRL_SET_TMP_RSA_CB 4 #define SSL_CTRL_SET_TMP_DH_CB 5 -/* Add these ones */ + #define SSL_CTRL_GET_SESSION_REUSED 6 #define SSL_CTRL_GET_CLIENT_CERT_REQUEST 7 #define SSL_CTRL_GET_NUM_RENEGOTIATIONS 8 #define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 9 #define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 10 #define SSL_CTRL_GET_FLAGS 11 - -#define SSL_CTRL_EXTRA_CHAIN_CERT 11 +#define SSL_CTRL_EXTRA_CHAIN_CERT 12 + +#define SSL_CTRL_SET_MSG_CALLBACK 13 +#define SSL_CTRL_SET_MSG_CALLBACK_ARG 14 + +/* Stats */ +#define SSL_CTRL_SESS_NUMBER 20 +#define SSL_CTRL_SESS_CONNECT 21 +#define SSL_CTRL_SESS_CONNECT_GOOD 22 +#define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23 +#define SSL_CTRL_SESS_ACCEPT 24 +#define SSL_CTRL_SESS_ACCEPT_GOOD 25 +#define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26 +#define SSL_CTRL_SESS_HIT 27 +#define SSL_CTRL_SESS_CB_HIT 28 +#define SSL_CTRL_SESS_MISSES 29 +#define SSL_CTRL_SESS_TIMEOUTS 30 +#define SSL_CTRL_SESS_CACHE_FULL 31 +#define SSL_CTRL_OPTIONS 32 +#define SSL_CTRL_MODE 33 + +#define SSL_CTRL_GET_READ_AHEAD 40 +#define SSL_CTRL_SET_READ_AHEAD 41 +#define SSL_CTRL_SET_SESS_CACHE_SIZE 42 +#define SSL_CTRL_GET_SESS_CACHE_SIZE 43 +#define SSL_CTRL_SET_SESS_CACHE_MODE 44 +#define SSL_CTRL_GET_SESS_CACHE_MODE 45 + +#define SSL_CTRL_GET_MAX_CERT_LIST 50 +#define SSL_CTRL_SET_MAX_CERT_LIST 51 #define SSL_session_reused(ssl) \ SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL) @@ -742,21 +1098,17 @@ typedef struct ssl_st #define SSL_CTX_set_tmp_dh(ctx,dh) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh) -/* For the next 2, the callbacks are - * RSA *tmp_rsa_cb(SSL *ssl,int export) - * DH *tmp_dh_cb(SSL *ssl,int export) - */ -#define SSL_CTX_set_tmp_rsa_callback(ctx,cb) \ - SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,0,(char *)cb) -#define SSL_CTX_set_tmp_dh_callback(ctx,dh) \ - SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,0,(char *)dh) +#define SSL_need_tmp_RSA(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL) +#define SSL_set_tmp_rsa(ssl,rsa) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa) +#define SSL_set_tmp_dh(ssl,dh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh) #define SSL_CTX_add_extra_chain_cert(ctx,x509) \ SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509) -#ifndef NOPROTO - -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO BIO_METHOD *BIO_f_ssl(void); BIO *BIO_new_ssl(SSL_CTX *ctx,int client); BIO *BIO_new_ssl_connect(SSL_CTX *ctx); @@ -766,60 +1118,84 @@ void BIO_ssl_shutdown(BIO *ssl_bio); #endif -int SSL_CTX_set_cipher_list(SSL_CTX *,char *str); +int SSL_CTX_set_cipher_list(SSL_CTX *,const char *str); SSL_CTX *SSL_CTX_new(SSL_METHOD *meth); void SSL_CTX_free(SSL_CTX *); -void SSL_clear(SSL *s); +long SSL_CTX_set_timeout(SSL_CTX *ctx,long t); +long SSL_CTX_get_timeout(SSL_CTX *ctx); +X509_STORE *SSL_CTX_get_cert_store(SSL_CTX *); +void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *); +int SSL_want(SSL *s); +int SSL_clear(SSL *s); + void SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm); SSL_CIPHER *SSL_get_current_cipher(SSL *s); int SSL_CIPHER_get_bits(SSL_CIPHER *c,int *alg_bits); char * SSL_CIPHER_get_version(SSL_CIPHER *c); -char * SSL_CIPHER_get_name(SSL_CIPHER *c); +const char * SSL_CIPHER_get_name(SSL_CIPHER *c); int SSL_get_fd(SSL *s); -char * SSL_get_cipher_list(SSL *s,int n); +int SSL_get_rfd(SSL *s); +int SSL_get_wfd(SSL *s); +const char * SSL_get_cipher_list(SSL *s,int n); char * SSL_get_shared_ciphers(SSL *s, char *buf, int len); int SSL_get_read_ahead(SSL * s); int SSL_pending(SSL *s); -#ifndef NO_SOCK +#ifndef OPENSSL_NO_SOCK int SSL_set_fd(SSL *s, int fd); int SSL_set_rfd(SSL *s, int fd); int SSL_set_wfd(SSL *s, int fd); #endif -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO void SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio); BIO * SSL_get_rbio(SSL *s); BIO * SSL_get_wbio(SSL *s); #endif -int SSL_set_cipher_list(SSL *s, char *str); +int SSL_set_cipher_list(SSL *s, const char *str); void SSL_set_read_ahead(SSL *s, int yes); int SSL_get_verify_mode(SSL *s); -int (*SSL_get_verify_callback(SSL *s))(); -void SSL_set_verify(SSL *s, int mode, int (*callback) ()); +int SSL_get_verify_depth(SSL *s); +int (*SSL_get_verify_callback(SSL *s))(int,X509_STORE_CTX *); +void SSL_set_verify(SSL *s, int mode, + int (*callback)(int ok,X509_STORE_CTX *ctx)); +void SSL_set_verify_depth(SSL *s, int depth); +#ifndef OPENSSL_NO_RSA int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); +#endif int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len); int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); int SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, unsigned char *d, long len); int SSL_use_certificate(SSL *ssl, X509 *x); -int SSL_use_certificate_ASN1(SSL *ssl, int len, unsigned char *d); - -#ifndef NO_STDIO -int SSL_use_RSAPrivateKey_file(SSL *ssl, char *file, int type); -int SSL_use_PrivateKey_file(SSL *ssl, char *file, int type); -int SSL_use_certificate_file(SSL *ssl, char *file, int type); -int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, char *file, int type); -int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, char *file, int type); -int SSL_CTX_use_certificate_file(SSL_CTX *ctx, char *file, int type); -STACK * SSL_load_client_CA_file(char *file); +int SSL_use_certificate_ASN1(SSL *ssl, unsigned char *d, int len); + +#ifndef OPENSSL_NO_STDIO +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); +int SSL_use_certificate_file(SSL *ssl, const char *file, int type); +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */ +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *file); +#ifndef OPENSSL_SYS_WIN32 +#ifndef OPENSSL_SYS_VMS +#ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */ +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *dir); +#endif +#endif +#endif + #endif -void ERR_load_SSL_strings(void ); void SSL_load_error_strings(void ); -char * SSL_state_string(SSL *s); -char * SSL_rstate_string(SSL *s); -char * SSL_state_string_long(SSL *s); -char * SSL_rstate_string_long(SSL *s); +const char *SSL_state_string(const SSL *s); +const char *SSL_rstate_string(const SSL *s); +const char *SSL_state_string_long(const SSL *s); +const char *SSL_rstate_string_long(const SSL *s); long SSL_SESSION_get_time(SSL_SESSION *s); long SSL_SESSION_set_time(SSL_SESSION *s, long t); long SSL_SESSION_get_timeout(SSL_SESSION *s); @@ -829,10 +1205,10 @@ void SSL_copy_session_id(SSL *to,SSL *from); SSL_SESSION *SSL_SESSION_new(void); unsigned long SSL_SESSION_hash(SSL_SESSION *a); int SSL_SESSION_cmp(SSL_SESSION *a,SSL_SESSION *b); -#ifndef NO_FP_API +#ifndef OPENSSL_NO_FP_API int SSL_SESSION_print_fp(FILE *fp,SSL_SESSION *ses); #endif -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO int SSL_SESSION_print(BIO *fp,SSL_SESSION *ses); #endif void SSL_SESSION_free(SSL_SESSION *ses); @@ -840,19 +1216,28 @@ int i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp); int SSL_set_session(SSL *to, SSL_SESSION *session); int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c); int SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c); +int SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB); +int SSL_set_generate_session_id(SSL *, GEN_SESSION_CB); +int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, + unsigned int id_len); SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,unsigned char **pp,long length); #ifdef HEADER_X509_H X509 * SSL_get_peer_certificate(SSL *s); #endif -STACK * SSL_get_peer_cert_chain(SSL *s); +STACK_OF(X509) *SSL_get_peer_cert_chain(SSL *s); int SSL_CTX_get_verify_mode(SSL_CTX *ctx); -int (*SSL_CTX_get_verify_callback(SSL_CTX *ctx))(); -void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*callback)()); -void SSL_CTX_set_cert_verify_cb(SSL_CTX *ctx, int (*cb)(),char *arg); +int SSL_CTX_get_verify_depth(SSL_CTX *ctx); +int (*SSL_CTX_get_verify_callback(SSL_CTX *ctx))(int,X509_STORE_CTX *); +void SSL_CTX_set_verify(SSL_CTX *ctx,int mode, + int (*callback)(int, X509_STORE_CTX *)); +void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth); +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg); +#ifndef OPENSSL_NO_RSA int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); +#endif int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len); int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx, @@ -860,24 +1245,37 @@ int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx, int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d); -void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,int (*cb)()); +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb); +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u); int SSL_CTX_check_private_key(SSL_CTX *ctx); int SSL_check_private_key(SSL *ctx); +int SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + SSL * SSL_new(SSL_CTX *ctx); -void SSL_clear(SSL *s); +int SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + +int SSL_CTX_set_purpose(SSL_CTX *s, int purpose); +int SSL_set_purpose(SSL *s, int purpose); +int SSL_CTX_set_trust(SSL_CTX *s, int trust); +int SSL_set_trust(SSL *s, int trust); + void SSL_free(SSL *ssl); int SSL_accept(SSL *ssl); int SSL_connect(SSL *ssl); -int SSL_read(SSL *ssl,char *buf,int num); -int SSL_peek(SSL *ssl,char *buf,int num); -int SSL_write(SSL *ssl,char *buf,int num); -long SSL_ctrl(SSL *ssl,int cmd, long larg, char *parg); -long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, char *parg); +int SSL_read(SSL *ssl,void *buf,int num); +int SSL_peek(SSL *ssl,void *buf,int num); +int SSL_write(SSL *ssl,const void *buf,int num); +long SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg); +long SSL_callback_ctrl(SSL *, int, void (*)()); +long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg); +long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)()); int SSL_get_error(SSL *s,int ret_code); -char * SSL_get_version(SSL *s); +const char *SSL_get_version(SSL *s); /* This sets the 'default' SSL version that SSL_new() will create */ int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth); @@ -898,23 +1296,24 @@ SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */ SSL_METHOD *TLSv1_server_method(void); /* TLSv1.0 */ SSL_METHOD *TLSv1_client_method(void); /* TLSv1.0 */ -STACK *SSL_get_ciphers(SSL *s); +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(SSL *s); int SSL_do_handshake(SSL *s); int SSL_renegotiate(SSL *s); +int SSL_renegotiate_pending(SSL *s); int SSL_shutdown(SSL *s); SSL_METHOD *SSL_get_ssl_method(SSL *s); int SSL_set_ssl_method(SSL *s,SSL_METHOD *method); -char *SSL_alert_type_string_long(int value); -char *SSL_alert_type_string(int value); -char *SSL_alert_desc_string_long(int value); -char *SSL_alert_desc_string(int value); - -void SSL_set_client_CA_list(SSL *s, STACK *list); -void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK *list); -STACK *SSL_get_client_CA_list(SSL *s); -STACK *SSL_CTX_get_client_CA_list(SSL_CTX *s); +const char *SSL_alert_type_string_long(int value); +const char *SSL_alert_type_string(int value); +const char *SSL_alert_desc_string_long(int value); +const char *SSL_alert_desc_string(int value); + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *list); +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *list); +STACK_OF(X509_NAME) *SSL_get_client_CA_list(SSL *s); +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(SSL_CTX *s); int SSL_add_client_CA(SSL *ssl,X509 *x); int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x); @@ -923,10 +1322,10 @@ void SSL_set_accept_state(SSL *s); long SSL_get_default_timeout(SSL *s); -void SSLeay_add_ssl_algorithms(void ); +int SSL_library_init(void ); char *SSL_CIPHER_description(SSL_CIPHER *,char *buf,int size); -STACK *SSL_dup_CA_list(STACK *sk); +STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk); SSL *SSL_dup(SSL *ssl); @@ -941,247 +1340,92 @@ void SSL_set_shutdown(SSL *ssl,int mode); int SSL_get_shutdown(SSL *ssl); int SSL_version(SSL *ssl); int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); -int SSL_CTX_load_verify_locations(SSL_CTX *ctx,char *CAfile,char *CApath); +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); +#define SSL_get0_session SSL_get_session /* just peek at pointer */ SSL_SESSION *SSL_get_session(SSL *ssl); +SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */ SSL_CTX *SSL_get_SSL_CTX(SSL *ssl); -void SSL_set_info_callback(SSL *ssl,void (*cb)()); -void (*SSL_get_info_callback(SSL *ssl))(); +void SSL_set_info_callback(SSL *ssl, + void (*cb)(const SSL *ssl,int type,int val)); +void (*SSL_get_info_callback(SSL *ssl))(const SSL *ssl,int type,int val); int SSL_state(SSL *ssl); void SSL_set_verify_result(SSL *ssl,long v); long SSL_get_verify_result(SSL *ssl); -int SSL_set_ex_data(SSL *ssl,int idx,char *data); -char *SSL_get_ex_data(SSL *ssl,int idx); -int SSL_get_ex_new_index(long argl, char *argp, int (*new_func)(), - int (*dup_func)(), void (*free_func)()); +int SSL_set_ex_data(SSL *ssl,int idx,void *data); +void *SSL_get_ex_data(SSL *ssl,int idx); +int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); -int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,char *data); -char *SSL_SESSION_get_ex_data(SSL_SESSION *ss,int idx); -int SSL_SESSION_get_ex_new_index(long argl, char *argp, int (*new_func)(), - int (*dup_func)(), void (*free_func)()); +int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data); +void *SSL_SESSION_get_ex_data(SSL_SESSION *ss,int idx); +int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); -int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,char *data); -char *SSL_CTX_get_ex_data(SSL_CTX *ssl,int idx); -int SSL_CTX_get_ex_new_index(long argl, char *argp, int (*new_func)(), - int (*dup_func)(), void (*free_func)()); +int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data); +void *SSL_CTX_get_ex_data(SSL_CTX *ssl,int idx); +int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); int SSL_get_ex_data_X509_STORE_CTX_idx(void ); -#else - -BIO_METHOD *BIO_f_ssl(); -BIO *BIO_new_ssl(); -BIO *BIO_new_ssl_connect(); -BIO *BIO_new_buffer_ssl_connect(); -int BIO_ssl_copy_session_id(); -void BIO_ssl_shutdown(); - -int SSL_CTX_set_cipher_list(); -SSL_CTX *SSL_CTX_new(); -void SSL_CTX_free(); -void SSL_clear(); -void SSL_CTX_flush_sessions(); - -SSL_CIPHER *SSL_get_current_cipher(); -int SSL_CIPHER_get_bits(); -char * SSL_CIPHER_get_version(); -char * SSL_CIPHER_get_name(); - -int SSL_get_fd(); -char * SSL_get_cipher_list(); -char * SSL_get_shared_ciphers(); -int SSL_get_read_ahead(); -int SSL_pending(); -#ifndef NO_SOCK -int SSL_set_fd(); -int SSL_set_rfd(); -int SSL_set_wfd(); -#endif -#ifdef HEADER_BIO_H -void SSL_set_bio(); -BIO * SSL_get_rbio(); -BIO * SSL_get_wbio(); -#endif -int SSL_set_cipher_list(); -void SSL_set_read_ahead(); -int SSL_get_verify_mode(); - -void SSL_set_verify(); -int SSL_use_RSAPrivateKey(); -int SSL_use_RSAPrivateKey_ASN1(); -int SSL_use_PrivateKey(); -int SSL_use_PrivateKey_ASN1(); -int SSL_use_certificate(); -int SSL_use_certificate_ASN1(); - -#ifndef NO_STDIO -int SSL_use_RSAPrivateKey_file(); -int SSL_use_PrivateKey_file(); -int SSL_use_certificate_file(); -int SSL_CTX_use_RSAPrivateKey_file(); -int SSL_CTX_use_PrivateKey_file(); -int SSL_CTX_use_certificate_file(); -STACK * SSL_load_client_CA_file(); -#endif - -void ERR_load_SSL_strings(); -void SSL_load_error_strings(); -char * SSL_state_string(); -char * SSL_rstate_string(); -char * SSL_state_string_long(); -char * SSL_rstate_string_long(); -long SSL_SESSION_get_time(); -long SSL_SESSION_set_time(); -long SSL_SESSION_get_timeout(); -long SSL_SESSION_set_timeout(); -void SSL_copy_session_id(); - -SSL_SESSION *SSL_SESSION_new(); -unsigned long SSL_SESSION_hash(); -int SSL_SESSION_cmp(); -#ifndef NO_FP_API -int SSL_SESSION_print_fp(); -#endif -#ifdef HEADER_BIO_H -int SSL_SESSION_print(); -#endif -void SSL_SESSION_free(); -int i2d_SSL_SESSION(); -int SSL_set_session(); -int SSL_CTX_add_session(); -int SSL_CTX_remove_session(); -SSL_SESSION *d2i_SSL_SESSION(); - -#ifdef HEADER_X509_H -X509 * SSL_get_peer_certificate(); +#define SSL_CTX_sess_set_cache_size(ctx,t) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL) +#define SSL_CTX_sess_get_cache_size(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL) +#define SSL_CTX_set_session_cache_mode(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL) +#define SSL_CTX_get_session_cache_mode(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL) + +#define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx) +#define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m) +#define SSL_CTX_get_read_ahead(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL) +#define SSL_CTX_set_read_ahead(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL) +#define SSL_CTX_get_max_cert_list(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +#define SSL_CTX_set_max_cert_list(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) +#define SSL_get_max_cert_list(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +#define SSL_set_max_cert_list(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) + + /* NB: the keylength is only applicable when is_export is true */ +#ifndef OPENSSL_NO_RSA +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, + RSA *(*cb)(SSL *ssl,int is_export, + int keylength)); + +void SSL_set_tmp_rsa_callback(SSL *ssl, + RSA *(*cb)(SSL *ssl,int is_export, + int keylength)); #endif - -STACK * SSL_get_peer_cert_chain(); - -int SSL_CTX_get_verify_mode(); -int (*SSL_CTX_get_verify_callback())(); -void SSL_CTX_set_verify(); -void SSL_CTX_set_cert_verify_cb(); -int SSL_CTX_use_RSAPrivateKey(); -int SSL_CTX_use_RSAPrivateKey_ASN1(); -int SSL_CTX_use_PrivateKey(); -int SSL_CTX_use_PrivateKey_ASN1(); -int SSL_CTX_use_certificate(); -int SSL_CTX_use_certificate_ASN1(); - -void SSL_CTX_set_default_passwd_cb(); - -int SSL_CTX_check_private_key(); -int SSL_check_private_key(); - -SSL * SSL_new(); -void SSL_clear(); -void SSL_free(); -int SSL_accept(); -int SSL_connect(); -int SSL_read(); -int SSL_peek(); -int SSL_write(); -long SSL_ctrl(); -long SSL_CTX_ctrl(); - -int SSL_get_error(); -char * SSL_get_version(); - -int SSL_CTX_set_ssl_version(); - -SSL_METHOD *SSLv2_method(); -SSL_METHOD *SSLv2_server_method(); -SSL_METHOD *SSLv2_client_method(); - -SSL_METHOD *SSLv3_method(); -SSL_METHOD *SSLv3_server_method(); -SSL_METHOD *SSLv3_client_method(); - -SSL_METHOD *SSLv23_method(); -SSL_METHOD *SSLv23_server_method(); -SSL_METHOD *SSLv23_client_method(); - -SSL_METHOD *TLSv1_method(); -SSL_METHOD *TLSv1_server_method(); -SSL_METHOD *TLSv1_client_method(); - -STACK *SSL_get_ciphers(); - -int SSL_do_handshake(); -int SSL_renegotiate(); -int SSL_shutdown(); - -SSL_METHOD *SSL_get_ssl_method(); -int SSL_set_ssl_method(); -char *SSL_alert_type_string_long(); -char *SSL_alert_type_string(); -char *SSL_alert_desc_string_long(); -char *SSL_alert_desc_string(); - -void SSL_set_client_CA_list(); -void SSL_CTX_set_client_CA_list(); -STACK *SSL_get_client_CA_list(); -STACK *SSL_CTX_get_client_CA_list(); -int SSL_add_client_CA(); -int SSL_CTX_add_client_CA(); - -void SSL_set_connect_state(); -void SSL_set_accept_state(); - -long SSL_get_default_timeout(); - -void SSLeay_add_ssl_algorithms(); - -char *SSL_CIPHER_description(); -STACK *SSL_dup_CA_list(); - -SSL *SSL_dup(); - -X509 *SSL_get_certificate(); -/* EVP * */ struct evp_pkey_st *SSL_get_privatekey(); - -#ifdef this_is_for_mk1mf_pl -EVP *SSL_get_privatekey(); +#ifndef OPENSSL_NO_DH +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*dh)(SSL *ssl,int is_export, + int keylength)); +void SSL_set_tmp_dh_callback(SSL *ssl, + DH *(*dh)(SSL *ssl,int is_export, + int keylength)); #endif -void SSL_CTX_set_quiet_shutdown(); -int SSL_CTX_get_quiet_shutdown(); -void SSL_set_quiet_shutdown(); -int SSL_get_quiet_shutdown(); -void SSL_set_shutdown(); -int SSL_get_shutdown(); -int SSL_version(); -int SSL_CTX_set_default_verify_paths(); -int SSL_CTX_load_verify_locations(); -SSL_SESSION *SSL_get_session(); -SSL_CTX *SSL_get_SSL_CTX(); -void SSL_set_info_callback(); -void (*SSL_get_info_callback())(); -int SSL_state(); -void SSL_set_verify_result(); -long SSL_get_verify_result(); - -int SSL_set_ex_data(); -char *SSL_get_ex_data(); -int SSL_get_ex_new_index(); - -int SSL_SESSION_set_ex_data(); -char *SSL_SESSION_get_ex_data(); -int SSL_SESSION_get_ex_new_index(); - -int SSL_CTX_set_ex_data(); -char *SSL_CTX_get_ex_data(); -int SSL_CTX_get_ex_new_index(); - -int SSL_get_ex_data_X509_STORE_CTX_idx(); - -/* #endif */ - +#ifndef OPENSSL_NO_COMP +int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm); +#else +int SSL_COMP_add_compression_method(int id,char *cm); #endif /* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_SSL_strings(void); + /* Error codes for the SSL functions. */ /* Function codes. */ @@ -1205,21 +1449,27 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(); #define SSL_F_SSL23_CONNECT 117 #define SSL_F_SSL23_GET_CLIENT_HELLO 118 #define SSL_F_SSL23_GET_SERVER_HELLO 119 +#define SSL_F_SSL23_PEEK 237 #define SSL_F_SSL23_READ 120 #define SSL_F_SSL23_WRITE 121 #define SSL_F_SSL2_ACCEPT 122 #define SSL_F_SSL2_CONNECT 123 #define SSL_F_SSL2_ENC_INIT 124 +#define SSL_F_SSL2_PEEK 234 #define SSL_F_SSL2_READ 125 +#define SSL_F_SSL2_READ_INTERNAL 236 #define SSL_F_SSL2_SET_CERTIFICATE 126 #define SSL_F_SSL2_WRITE 127 #define SSL_F_SSL3_ACCEPT 128 +#define SSL_F_SSL3_CALLBACK_CTRL 233 #define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 #define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 #define SSL_F_SSL3_CLIENT_HELLO 131 #define SSL_F_SSL3_CONNECT 132 +#define SSL_F_SSL3_CTRL 213 #define SSL_F_SSL3_CTX_CTRL 133 #define SSL_F_SSL3_ENC 134 +#define SSL_F_SSL3_GENERATE_KEY_BLOCK 238 #define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135 #define SSL_F_SSL3_GET_CERT_VERIFY 136 #define SSL_F_SSL3_GET_CLIENT_CERTIFICATE 137 @@ -1233,6 +1483,7 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(); #define SSL_F_SSL3_GET_SERVER_DONE 145 #define SSL_F_SSL3_GET_SERVER_HELLO 146 #define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147 +#define SSL_F_SSL3_PEEK 235 #define SSL_F_SSL3_READ_BYTES 148 #define SSL_F_SSL3_READ_N 149 #define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST 150 @@ -1245,64 +1496,85 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(); #define SSL_F_SSL3_SETUP_KEY_BLOCK 157 #define SSL_F_SSL3_WRITE_BYTES 158 #define SSL_F_SSL3_WRITE_PENDING 159 +#define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215 +#define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216 #define SSL_F_SSL_BAD_METHOD 160 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +#define SSL_F_SSL_CERT_DUP 221 +#define SSL_F_SSL_CERT_INST 222 +#define SSL_F_SSL_CERT_INSTANTIATE 214 #define SSL_F_SSL_CERT_NEW 162 #define SSL_F_SSL_CHECK_PRIVATE_KEY 163 -#define SSL_F_SSL_CREATE_CIPHER_LIST 164 -#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 165 -#define SSL_F_SSL_CTX_NEW 166 -#define SSL_F_SSL_CTX_SET_SSL_VERSION 167 -#define SSL_F_SSL_CTX_USE_CERTIFICATE 168 -#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 169 -#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 170 -#define SSL_F_SSL_CTX_USE_PRIVATEKEY 171 -#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 172 -#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 173 -#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 174 -#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 175 -#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 176 -#define SSL_F_SSL_DO_HANDSHAKE 177 -#define SSL_F_SSL_GET_NEW_SESSION 178 -#define SSL_F_SSL_GET_SERVER_SEND_CERT 179 -#define SSL_F_SSL_GET_SIGN_PKEY 180 -#define SSL_F_SSL_INIT_WBIO_BUFFER 181 -#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 182 -#define SSL_F_SSL_NEW 183 -#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 184 -#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 185 -#define SSL_F_SSL_SESSION_NEW 186 -#define SSL_F_SSL_SESSION_PRINT_FP 187 -#define SSL_F_SSL_SET_CERT 188 -#define SSL_F_SSL_SET_FD 189 -#define SSL_F_SSL_SET_PKEY 190 -#define SSL_F_SSL_SET_RFD 191 -#define SSL_F_SSL_SET_SESSION 192 -#define SSL_F_SSL_SET_WFD 193 -#define SSL_F_SSL_UNDEFINED_FUNCTION 194 -#define SSL_F_SSL_USE_CERTIFICATE 195 -#define SSL_F_SSL_USE_CERTIFICATE_ASN1 196 -#define SSL_F_SSL_USE_CERTIFICATE_FILE 197 -#define SSL_F_SSL_USE_PRIVATEKEY 198 -#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 199 -#define SSL_F_SSL_USE_PRIVATEKEY_FILE 200 -#define SSL_F_SSL_USE_RSAPRIVATEKEY 201 -#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 202 -#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 203 -#define SSL_F_SSL_VERIFY_CERT_CHAIN 204 -#define SSL_F_SSL_WRITE 205 -#define SSL_F_TLS1_CHANGE_CIPHER_STATE 206 -#define SSL_F_TLS1_ENC 207 -#define SSL_F_TLS1_SETUP_KEY_BLOCK 208 -#define SSL_F_WRITE_PENDING 209 +#define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230 +#define SSL_F_SSL_CIPHER_STRENGTH_SORT 231 +#define SSL_F_SSL_CLEAR 164 +#define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165 +#define SSL_F_SSL_CREATE_CIPHER_LIST 166 +#define SSL_F_SSL_CTRL 232 +#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168 +#define SSL_F_SSL_CTX_NEW 169 +#define SSL_F_SSL_CTX_SET_PURPOSE 226 +#define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219 +#define SSL_F_SSL_CTX_SET_SSL_VERSION 170 +#define SSL_F_SSL_CTX_SET_TRUST 229 +#define SSL_F_SSL_CTX_USE_CERTIFICATE 171 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE 220 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY 174 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179 +#define SSL_F_SSL_DO_HANDSHAKE 180 +#define SSL_F_SSL_GET_NEW_SESSION 181 +#define SSL_F_SSL_GET_PREV_SESSION 217 +#define SSL_F_SSL_GET_SERVER_SEND_CERT 182 +#define SSL_F_SSL_GET_SIGN_PKEY 183 +#define SSL_F_SSL_INIT_WBIO_BUFFER 184 +#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185 +#define SSL_F_SSL_NEW 186 +#define SSL_F_SSL_READ 223 +#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187 +#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188 +#define SSL_F_SSL_SESSION_NEW 189 +#define SSL_F_SSL_SESSION_PRINT_FP 190 +#define SSL_F_SSL_SESS_CERT_NEW 225 +#define SSL_F_SSL_SET_CERT 191 +#define SSL_F_SSL_SET_FD 192 +#define SSL_F_SSL_SET_PKEY 193 +#define SSL_F_SSL_SET_PURPOSE 227 +#define SSL_F_SSL_SET_RFD 194 +#define SSL_F_SSL_SET_SESSION 195 +#define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218 +#define SSL_F_SSL_SET_TRUST 228 +#define SSL_F_SSL_SET_WFD 196 +#define SSL_F_SSL_SHUTDOWN 224 +#define SSL_F_SSL_UNDEFINED_FUNCTION 197 +#define SSL_F_SSL_USE_CERTIFICATE 198 +#define SSL_F_SSL_USE_CERTIFICATE_ASN1 199 +#define SSL_F_SSL_USE_CERTIFICATE_FILE 200 +#define SSL_F_SSL_USE_PRIVATEKEY 201 +#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202 +#define SSL_F_SSL_USE_PRIVATEKEY_FILE 203 +#define SSL_F_SSL_USE_RSAPRIVATEKEY 204 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206 +#define SSL_F_SSL_VERIFY_CERT_CHAIN 207 +#define SSL_F_SSL_WRITE 208 +#define SSL_F_TLS1_CHANGE_CIPHER_STATE 209 +#define SSL_F_TLS1_ENC 210 +#define SSL_F_TLS1_SETUP_KEY_BLOCK 211 +#define SSL_F_WRITE_PENDING 212 /* Reason codes. */ #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272 #define SSL_R_BAD_ALERT_RECORD 101 #define SSL_R_BAD_AUTHENTICATION_TYPE 102 #define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 #define SSL_R_BAD_CHECKSUM 104 -#define SSL_R_BAD_CLIENT_REQUEST 105 #define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 #define SSL_R_BAD_DECOMPRESSION 107 #define SSL_R_BAD_DH_G_LENGTH 108 @@ -1310,6 +1582,8 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(); #define SSL_R_BAD_DH_P_LENGTH 110 #define SSL_R_BAD_DIGEST_LENGTH 111 #define SSL_R_BAD_DSA_SIGNATURE 112 +#define SSL_R_BAD_HELLO_REQUEST 105 +#define SSL_R_BAD_LENGTH 271 #define SSL_R_BAD_MAC_DECODE 113 #define SSL_R_BAD_MESSAGE_TYPE 114 #define SSL_R_BAD_PACKET_LENGTH 115 @@ -1345,20 +1619,38 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(); #define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 145 #define SSL_R_DATA_LENGTH_TOO_LONG 146 #define SSL_R_DECRYPTION_FAILED 147 +#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 1109 #define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148 #define SSL_R_DIGEST_CHECK_FAILED 149 #define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150 +#define SSL_R_ERROR_GENERATING_TMP_RSA_KEY 1092 #define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151 #define SSL_R_EXCESSIVE_MESSAGE_SIZE 152 #define SSL_R_EXTRA_DATA_IN_MESSAGE 153 #define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154 #define SSL_R_HTTPS_PROXY_REQUEST 155 #define SSL_R_HTTP_REQUEST 156 -#define SSL_R_INTERNAL_ERROR 157 +#define SSL_R_ILLEGAL_PADDING 1110 #define SSL_R_INVALID_CHALLENGE_LENGTH 158 +#define SSL_R_INVALID_COMMAND 280 +#define SSL_R_INVALID_PURPOSE 278 +#define SSL_R_INVALID_TRUST 279 +#define SSL_R_KRB5 1104 +#define SSL_R_KRB5_C_CC_PRINC 1094 +#define SSL_R_KRB5_C_GET_CRED 1095 +#define SSL_R_KRB5_C_INIT 1096 +#define SSL_R_KRB5_C_MK_REQ 1097 +#define SSL_R_KRB5_S_BAD_TICKET 1098 +#define SSL_R_KRB5_S_INIT 1099 +#define SSL_R_KRB5_S_RD_REQ 1108 +#define SSL_R_KRB5_S_TKT_EXPIRED 1105 +#define SSL_R_KRB5_S_TKT_NYV 1106 +#define SSL_R_KRB5_S_TKT_SKEW 1107 #define SSL_R_LENGTH_MISMATCH 159 #define SSL_R_LENGTH_TOO_SHORT 160 +#define SSL_R_LIBRARY_BUG 274 #define SSL_R_LIBRARY_HAS_NO_CIPHERS 161 +#define SSL_R_MESSAGE_TOO_LONG 1111 #define SSL_R_MISSING_DH_DSA_CERT 162 #define SSL_R_MISSING_DH_KEY 163 #define SSL_R_MISSING_DH_RSA_CERT 164 @@ -1385,39 +1677,44 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(); #define SSL_R_NO_CIPHER_MATCH 185 #define SSL_R_NO_CLIENT_CERT_RECEIVED 186 #define SSL_R_NO_COMPRESSION_SPECIFIED 187 -#define SSL_R_NO_PRIVATEKEY 188 -#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 189 -#define SSL_R_NO_PROTOCOLS_AVAILABLE 190 -#define SSL_R_NO_PUBLICKEY 191 -#define SSL_R_NO_SHARED_CIPHER 192 -#define SSL_R_NO_VERIFY_CALLBACK 193 -#define SSL_R_NULL_SSL_CTX 194 -#define SSL_R_NULL_SSL_METHOD_PASSED 195 -#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 196 -#define SSL_R_PACKET_LENGTH_TOO_LONG 197 -#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 198 -#define SSL_R_PEER_ERROR 199 -#define SSL_R_PEER_ERROR_CERTIFICATE 200 -#define SSL_R_PEER_ERROR_NO_CERTIFICATE 201 -#define SSL_R_PEER_ERROR_NO_CIPHER 202 -#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 203 -#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 204 -#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 205 -#define SSL_R_PROTOCOL_IS_SHUTDOWN 206 -#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 207 -#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 208 -#define SSL_R_PUBLIC_KEY_NOT_RSA 209 -#define SSL_R_READ_BIO_NOT_SET 210 -#define SSL_R_READ_WRONG_PACKET_TYPE 211 -#define SSL_R_RECORD_LENGTH_MISMATCH 212 -#define SSL_R_RECORD_TOO_LARGE 213 -#define SSL_R_REQUIRED_CIPHER_MISSING 214 -#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 215 -#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 216 -#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 217 -#define SSL_R_SHORT_READ 218 -#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 219 -#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 220 +#define SSL_R_NO_METHOD_SPECIFIED 188 +#define SSL_R_NO_PRIVATEKEY 189 +#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190 +#define SSL_R_NO_PROTOCOLS_AVAILABLE 191 +#define SSL_R_NO_PUBLICKEY 192 +#define SSL_R_NO_SHARED_CIPHER 193 +#define SSL_R_NO_VERIFY_CALLBACK 194 +#define SSL_R_NULL_SSL_CTX 195 +#define SSL_R_NULL_SSL_METHOD_PASSED 196 +#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 +#define SSL_R_PACKET_LENGTH_TOO_LONG 198 +#define SSL_R_PATH_TOO_LONG 270 +#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199 +#define SSL_R_PEER_ERROR 200 +#define SSL_R_PEER_ERROR_CERTIFICATE 201 +#define SSL_R_PEER_ERROR_NO_CERTIFICATE 202 +#define SSL_R_PEER_ERROR_NO_CIPHER 203 +#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 204 +#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 205 +#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 206 +#define SSL_R_PROTOCOL_IS_SHUTDOWN 207 +#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 208 +#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 209 +#define SSL_R_PUBLIC_KEY_NOT_RSA 210 +#define SSL_R_READ_BIO_NOT_SET 211 +#define SSL_R_READ_WRONG_PACKET_TYPE 212 +#define SSL_R_RECORD_LENGTH_MISMATCH 213 +#define SSL_R_RECORD_TOO_LARGE 214 +#define SSL_R_RECORD_TOO_SMALL 1093 +#define SSL_R_REQUIRED_CIPHER_MISSING 215 +#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216 +#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217 +#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 218 +#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277 +#define SSL_R_SHORT_READ 219 +#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 +#define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221 +#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222 #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 #define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 @@ -1427,70 +1724,75 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(); #define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 #define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 #define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 -#define SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE 221 -#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE 222 -#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER 223 -#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 224 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE 223 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE 224 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER 225 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 226 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 -#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE 225 +#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE 227 #define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 -#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 226 -#define SSL_R_SSL_HANDSHAKE_FAILURE 227 -#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 228 -#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 229 +#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 228 +#define SSL_R_SSL_HANDSHAKE_FAILURE 229 +#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 230 +#define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 1102 +#define SSL_R_SSL_SESSION_ID_CONFLICT 1103 +#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 273 +#define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH 1101 +#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 231 #define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 #define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 #define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021 #define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 -#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICION 1060 +#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 #define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 #define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 #define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 #define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 #define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 #define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 -#define SSL_R_TLSV1_ALERT_USER_CANCLED 1090 -#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 230 -#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 231 -#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 232 -#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 233 -#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 234 -#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 235 -#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 236 -#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 237 -#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 238 -#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES 239 -#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 240 -#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 241 -#define SSL_R_UNEXPECTED_MESSAGE 242 -#define SSL_R_UNEXPECTED_RECORD 243 -#define SSL_R_UNKNOWN_ALERT_TYPE 244 -#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 245 -#define SSL_R_UNKNOWN_CIPHER_RETURNED 246 -#define SSL_R_UNKNOWN_CIPHER_TYPE 247 -#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 248 -#define SSL_R_UNKNOWN_PKEY_TYPE 249 -#define SSL_R_UNKNOWN_PROTOCOL 250 -#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 251 -#define SSL_R_UNKNOWN_SSL_VERSION 252 -#define SSL_R_UNKNOWN_STATE 253 -#define SSL_R_UNSUPPORTED_CIPHER 254 -#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 255 -#define SSL_R_UNSUPPORTED_PROTOCOL 256 -#define SSL_R_UNSUPPORTED_SSL_VERSION 257 -#define SSL_R_WRITE_BIO_NOT_SET 258 -#define SSL_R_WRONG_CIPHER_RETURNED 259 -#define SSL_R_WRONG_MESSAGE_TYPE 260 -#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 261 -#define SSL_R_WRONG_SIGNATURE_LENGTH 262 -#define SSL_R_WRONG_SIGNATURE_SIZE 263 -#define SSL_R_WRONG_SSL_VERSION 264 -#define SSL_R_WRONG_VERSION_NUMBER 265 -#define SSL_R_X509_LIB 266 -#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 267 - +#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 +#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232 +#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233 +#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 234 +#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 235 +#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 236 +#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 237 +#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 238 +#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239 +#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 240 +#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES 241 +#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242 +#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243 +#define SSL_R_UNEXPECTED_MESSAGE 244 +#define SSL_R_UNEXPECTED_RECORD 245 +#define SSL_R_UNINITIALIZED 276 +#define SSL_R_UNKNOWN_ALERT_TYPE 246 +#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247 +#define SSL_R_UNKNOWN_CIPHER_RETURNED 248 +#define SSL_R_UNKNOWN_CIPHER_TYPE 249 +#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 250 +#define SSL_R_UNKNOWN_PKEY_TYPE 251 +#define SSL_R_UNKNOWN_PROTOCOL 252 +#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 253 +#define SSL_R_UNKNOWN_SSL_VERSION 254 +#define SSL_R_UNKNOWN_STATE 255 +#define SSL_R_UNSUPPORTED_CIPHER 256 +#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257 +#define SSL_R_UNSUPPORTED_OPTION 1091 +#define SSL_R_UNSUPPORTED_PROTOCOL 258 +#define SSL_R_UNSUPPORTED_SSL_VERSION 259 +#define SSL_R_WRITE_BIO_NOT_SET 260 +#define SSL_R_WRONG_CIPHER_RETURNED 261 +#define SSL_R_WRONG_MESSAGE_TYPE 262 +#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 263 +#define SSL_R_WRONG_SIGNATURE_LENGTH 264 +#define SSL_R_WRONG_SIGNATURE_SIZE 265 +#define SSL_R_WRONG_SSL_VERSION 266 +#define SSL_R_WRONG_VERSION_NUMBER 267 +#define SSL_R_X509_LIB 268 +#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269 + #ifdef __cplusplus } #endif #endif - diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 783c079e1..1a873d2cb 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -1,4 +1,4 @@ -/* ssl/ssl_cert.c */ +/*! \file ssl/ssl_cert.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -55,44 +55,113 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ #include <stdio.h> -#include "objects.h" -#include "bio.h" -#include "pem.h" + +#include "e_os.h" +#ifndef NO_SYS_TYPES_H +# include <sys/types.h> +#endif + +#if !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_VMS) && !defined(NeXT) && !defined(MAC_OS_pre_X) +#include <dirent.h> +#endif + +#if defined(WIN32) +#include <windows.h> +#endif + +#ifdef NeXT +#include <sys/dir.h> +#define dirent direct +#endif + +#include <openssl/objects.h> +#include <openssl/bio.h> +#include <openssl/pem.h> +#include <openssl/x509v3.h> #include "ssl_locl.h" -int SSL_get_ex_data_X509_STORE_CTX_idx() +int SSL_get_ex_data_X509_STORE_CTX_idx(void) { - static int ssl_x509_store_ctx_idx= -1; + static volatile int ssl_x509_store_ctx_idx= -1; if (ssl_x509_store_ctx_idx < 0) { - ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index( - 0,"SSL for verifiy callback",NULL,NULL,NULL); + /* any write lock will do; usually this branch + * will only be taken once anyway */ + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + + if (ssl_x509_store_ctx_idx < 0) + { + ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index( + 0,"SSL for verify callback",NULL,NULL,NULL); + } + + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); } - return(ssl_x509_store_ctx_idx); + return ssl_x509_store_ctx_idx; } -CERT *ssl_cert_new() +CERT *ssl_cert_new(void) { CERT *ret; - ret=(CERT *)Malloc(sizeof(CERT)); + ret=(CERT *)OPENSSL_malloc(sizeof(CERT)); if (ret == NULL) { SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE); return(NULL); } memset(ret,0,sizeof(CERT)); -/* - ret->valid=0; - ret->mask=0; - ret->export_mask=0; - ret->cert_type=0; - ret->key->x509=NULL; - ret->key->publickey=NULL; - ret->key->privatekey=NULL; */ ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]); ret->references=1; @@ -100,11 +169,151 @@ CERT *ssl_cert_new() return(ret); } -void ssl_cert_free(c) -CERT *c; +CERT *ssl_cert_dup(CERT *cert) { + CERT *ret; int i; + ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); + if (ret == NULL) + { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); + return(NULL); + } + + memset(ret, 0, sizeof(CERT)); + + ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; + /* or ret->key = ret->pkeys + (cert->key - cert->pkeys), + * if you find that more readable */ + + ret->valid = cert->valid; + ret->mask = cert->mask; + ret->export_mask = cert->export_mask; + +#ifndef OPENSSL_NO_RSA + if (cert->rsa_tmp != NULL) + { + RSA_up_ref(cert->rsa_tmp); + ret->rsa_tmp = cert->rsa_tmp; + } + ret->rsa_tmp_cb = cert->rsa_tmp_cb; +#endif + +#ifndef OPENSSL_NO_DH + if (cert->dh_tmp != NULL) + { + /* DH parameters don't have a reference count */ + ret->dh_tmp = DHparams_dup(cert->dh_tmp); + if (ret->dh_tmp == NULL) + { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB); + goto err; + } + if (cert->dh_tmp->priv_key) + { + BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); + if (!b) + { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); + goto err; + } + ret->dh_tmp->priv_key = b; + } + if (cert->dh_tmp->pub_key) + { + BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); + if (!b) + { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); + goto err; + } + ret->dh_tmp->pub_key = b; + } + } + ret->dh_tmp_cb = cert->dh_tmp_cb; +#endif + + for (i = 0; i < SSL_PKEY_NUM; i++) + { + if (cert->pkeys[i].x509 != NULL) + { + ret->pkeys[i].x509 = cert->pkeys[i].x509; + CRYPTO_add(&ret->pkeys[i].x509->references, 1, + CRYPTO_LOCK_X509); + } + + if (cert->pkeys[i].privatekey != NULL) + { + ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; + CRYPTO_add(&ret->pkeys[i].privatekey->references, 1, + CRYPTO_LOCK_EVP_PKEY); + + switch(i) + { + /* If there was anything special to do for + * certain types of keys, we'd do it here. + * (Nothing at the moment, I think.) */ + + case SSL_PKEY_RSA_ENC: + case SSL_PKEY_RSA_SIGN: + /* We have an RSA key. */ + break; + + case SSL_PKEY_DSA_SIGN: + /* We have a DSA key. */ + break; + + case SSL_PKEY_DH_RSA: + case SSL_PKEY_DH_DSA: + /* We have a DH key. */ + break; + + default: + /* Can't happen. */ + SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG); + } + } + } + + /* ret->extra_certs *should* exist, but currently the own certificate + * chain is held inside SSL_CTX */ + + ret->references=1; + + return(ret); + +#ifndef OPENSSL_NO_DH /* avoid 'unreferenced label' warning if OPENSSL_NO_DH is defined */ +err: +#endif +#ifndef OPENSSL_NO_RSA + if (ret->rsa_tmp != NULL) + RSA_free(ret->rsa_tmp); +#endif +#ifndef OPENSSL_NO_DH + if (ret->dh_tmp != NULL) + DH_free(ret->dh_tmp); +#endif + + for (i = 0; i < SSL_PKEY_NUM; i++) + { + if (ret->pkeys[i].x509 != NULL) + X509_free(ret->pkeys[i].x509); + if (ret->pkeys[i].privatekey != NULL) + EVP_PKEY_free(ret->pkeys[i].privatekey); + } + + return NULL; + } + + +void ssl_cert_free(CERT *c) + { + int i; + + if(c == NULL) + return; + i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT); #ifdef REF_PRINT REF_PRINT("CERT",c); @@ -118,10 +327,10 @@ CERT *c; } #endif -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (c->rsa_tmp) RSA_free(c->rsa_tmp); #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH if (c->dh_tmp) DH_free(c->dh_tmp); #endif @@ -136,40 +345,152 @@ CERT *c; EVP_PKEY_free(c->pkeys[i].publickey); #endif } - if (c->cert_chain != NULL) - sk_pop_free(c->cert_chain,X509_free); - Free(c); + OPENSSL_free(c); + } + +int ssl_cert_inst(CERT **o) + { + /* Create a CERT if there isn't already one + * (which cannot really happen, as it is initially created in + * SSL_CTX_new; but the earlier code usually allows for that one + * being non-existant, so we follow that behaviour, as it might + * turn out that there actually is a reason for it -- but I'm + * not sure that *all* of the existing code could cope with + * s->cert being NULL, otherwise we could do without the + * initialization in SSL_CTX_new). + */ + + if (o == NULL) + { + SSLerr(SSL_F_SSL_CERT_INST, ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if (*o == NULL) + { + if ((*o = ssl_cert_new()) == NULL) + { + SSLerr(SSL_F_SSL_CERT_INST, ERR_R_MALLOC_FAILURE); + return(0); + } + } + return(1); + } + + +SESS_CERT *ssl_sess_cert_new(void) + { + SESS_CERT *ret; + + ret = OPENSSL_malloc(sizeof *ret); + if (ret == NULL) + { + SSLerr(SSL_F_SSL_SESS_CERT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(ret, 0 ,sizeof *ret); + ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]); + ret->references = 1; + + return ret; + } + +void ssl_sess_cert_free(SESS_CERT *sc) + { + int i; + + if (sc == NULL) + return; + + i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT); +#ifdef REF_PRINT + REF_PRINT("SESS_CERT", sc); +#endif + if (i > 0) + return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"ssl_sess_cert_free, bad reference count\n"); + abort(); /* ok */ + } +#endif + + /* i == 0 */ + if (sc->cert_chain != NULL) + sk_X509_pop_free(sc->cert_chain, X509_free); + for (i = 0; i < SSL_PKEY_NUM; i++) + { + if (sc->peer_pkeys[i].x509 != NULL) + X509_free(sc->peer_pkeys[i].x509); +#if 0 /* We don't have the peer's private key. These lines are just + * here as a reminder that we're still using a not-quite-appropriate + * data structure. */ + if (sc->peer_pkeys[i].privatekey != NULL) + EVP_PKEY_free(sc->peer_pkeys[i].privatekey); +#endif + } + +#ifndef OPENSSL_NO_RSA + if (sc->peer_rsa_tmp != NULL) + RSA_free(sc->peer_rsa_tmp); +#endif +#ifndef OPENSSL_NO_DH + if (sc->peer_dh_tmp != NULL) + DH_free(sc->peer_dh_tmp); +#endif + + OPENSSL_free(sc); } -int ssl_set_cert_type(c, type) -CERT *c; -int type; +int ssl_set_peer_cert_type(SESS_CERT *sc,int type) { - c->cert_type=type; + sc->peer_cert_type = type; return(1); } -int ssl_verify_cert_chain(s,sk) -SSL *s; -STACK *sk; +int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk) { X509 *x; int i; X509_STORE_CTX ctx; - if ((sk == NULL) || (sk_num(sk) == 0)) + if ((sk == NULL) || (sk_X509_num(sk) == 0)) return(0); - x=(X509 *)sk_value(sk,0); - X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk); - X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(), - (char *)s); + x=sk_X509_value(sk,0); + if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk)) + { + SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB); + return(0); + } + if (SSL_get_verify_depth(s) >= 0) + X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s)); + X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s); + + /* We need to set the verify purpose. The purpose can be determined by + * the context: if its a server it will verify SSL client certificates + * or vice versa. + */ + if (s->server) + i = X509_PURPOSE_SSL_CLIENT; + else + i = X509_PURPOSE_SSL_SERVER; + + X509_STORE_CTX_purpose_inherit(&ctx, i, s->purpose, s->trust); + + if (s->verify_callback) + X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); if (s->ctx->app_verify_callback != NULL) - i=s->ctx->app_verify_callback(&ctx); +#if 1 /* new with OpenSSL 0.9.7 */ + i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); +#else + i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */ +#endif else { -#ifndef NO_X509_VERIFY +#ifndef OPENSSL_NO_X509_VERIFY i=X509_verify_cert(&ctx); #else i=0; @@ -184,58 +505,49 @@ STACK *sk; return(i); } -static void set_client_CA_list(ca_list,list) -STACK **ca_list; -STACK *list; +static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *list) { if (*ca_list != NULL) - sk_pop_free(*ca_list,X509_NAME_free); + sk_X509_NAME_pop_free(*ca_list,X509_NAME_free); *ca_list=list; } -STACK *SSL_dup_CA_list(sk) -STACK *sk; +STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk) { int i; - STACK *ret; + STACK_OF(X509_NAME) *ret; X509_NAME *name; - ret=sk_new_null(); - for (i=0; i<sk_num(sk); i++) + ret=sk_X509_NAME_new_null(); + for (i=0; i<sk_X509_NAME_num(sk); i++) { - name=X509_NAME_dup((X509_NAME *)sk_value(sk,i)); - if ((name == NULL) || !sk_push(ret,(char *)name)) + name=X509_NAME_dup(sk_X509_NAME_value(sk,i)); + if ((name == NULL) || !sk_X509_NAME_push(ret,name)) { - sk_pop_free(ret,X509_NAME_free); + sk_X509_NAME_pop_free(ret,X509_NAME_free); return(NULL); } } return(ret); } -void SSL_set_client_CA_list(s,list) -SSL *s; -STACK *list; +void SSL_set_client_CA_list(SSL *s,STACK_OF(X509_NAME) *list) { set_client_CA_list(&(s->client_CA),list); } -void SSL_CTX_set_client_CA_list(ctx,list) -SSL_CTX *ctx; -STACK *list; +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *list) { set_client_CA_list(&(ctx->client_CA),list); } -STACK *SSL_CTX_get_client_CA_list(ctx) -SSL_CTX *ctx; +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(SSL_CTX *ctx) { return(ctx->client_CA); } -STACK *SSL_get_client_CA_list(s) -SSL *s; +STACK_OF(X509_NAME) *SSL_get_client_CA_list(SSL *s) { if (s->type == SSL_ST_CONNECT) { /* we are in the client */ @@ -254,20 +566,18 @@ SSL *s; } } -static int add_client_CA(sk,x) -STACK **sk; -X509 *x; +static int add_client_CA(STACK_OF(X509_NAME) **sk,X509 *x) { X509_NAME *name; if (x == NULL) return(0); - if ((*sk == NULL) && ((*sk=sk_new_null()) == NULL)) + if ((*sk == NULL) && ((*sk=sk_X509_NAME_new_null()) == NULL)) return(0); if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL) return(0); - if (!sk_push(*sk,(char *)name)) + if (!sk_X509_NAME_push(*sk,name)) { X509_NAME_free(name); return(0); @@ -275,37 +585,39 @@ X509 *x; return(1); } -int SSL_add_client_CA(ssl,x) -SSL *ssl; -X509 *x; +int SSL_add_client_CA(SSL *ssl,X509 *x) { return(add_client_CA(&(ssl->client_CA),x)); } -int SSL_CTX_add_client_CA(ctx,x) -SSL_CTX *ctx; -X509 *x; +int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x) { return(add_client_CA(&(ctx->client_CA),x)); } -static int name_cmp(a,b) -X509_NAME **a,**b; +static int xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b) { return(X509_NAME_cmp(*a,*b)); } -#ifndef NO_STDIO -STACK *SSL_load_client_CA_file(file) -char *file; +#ifndef OPENSSL_NO_STDIO +/*! + * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; + * it doesn't really have anything to do with clients (except that a common use + * for a stack of CAs is to send it to the client). Actually, it doesn't have + * much to do with CAs, either, since it will load any old cert. + * \param file the file containing one or more certs. + * \return a ::STACK containing the certs. + */ +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) { BIO *in; X509 *x=NULL; X509_NAME *xn=NULL; - STACK *ret,*sk; + STACK_OF(X509_NAME) *ret,*sk; - ret=sk_new(NULL); - sk=sk_new(name_cmp); + ret=sk_X509_NAME_new_null(); + sk=sk_X509_NAME_new(xname_cmp); in=BIO_new(BIO_s_file_internal()); @@ -320,31 +632,199 @@ char *file; for (;;) { - if (PEM_read_bio_X509(in,&x,NULL) == NULL) + if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) break; if ((xn=X509_get_subject_name(x)) == NULL) goto err; /* check for duplicates */ xn=X509_NAME_dup(xn); if (xn == NULL) goto err; - if (sk_find(sk,(char *)xn) >= 0) + if (sk_X509_NAME_find(sk,xn) >= 0) X509_NAME_free(xn); else { - sk_push(sk,(char *)xn); - sk_push(ret,(char *)xn); + sk_X509_NAME_push(sk,xn); + sk_X509_NAME_push(ret,xn); } } if (0) { err: - if (ret != NULL) sk_pop_free(ret,X509_NAME_free); + if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free); ret=NULL; } - if (sk != NULL) sk_free(sk); + if (sk != NULL) sk_X509_NAME_free(sk); if (in != NULL) BIO_free(in); if (x != NULL) X509_free(x); return(ret); } #endif +/*! + * Add a file of certs to a stack. + * \param stack the stack to add to. + * \param file the file to add from. All certs in this file that are not + * already in the stack will be added. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *file) + { + BIO *in; + X509 *x=NULL; + X509_NAME *xn=NULL; + int ret=1; + int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b); + + oldcmp=sk_X509_NAME_set_cmp_func(stack,xname_cmp); + + in=BIO_new(BIO_s_file_internal()); + + if (in == NULL) + { + SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in,file)) + goto err; + + for (;;) + { + if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) + break; + if ((xn=X509_get_subject_name(x)) == NULL) goto err; + xn=X509_NAME_dup(xn); + if (xn == NULL) goto err; + if (sk_X509_NAME_find(stack,xn) >= 0) + X509_NAME_free(xn); + else + sk_X509_NAME_push(stack,xn); + } + + if (0) + { +err: + ret=0; + } + if(in != NULL) + BIO_free(in); + if(x != NULL) + X509_free(x); + + sk_X509_NAME_set_cmp_func(stack,oldcmp); + + return ret; + } + +/*! + * Add a directory of certs to a stack. + * \param stack the stack to append to. + * \param dir the directory to append from. All files in this directory will be + * examined as potential certs. Any that are acceptable to + * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be + * included. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +#ifndef OPENSSL_SYS_WIN32 +#ifndef OPENSSL_SYS_VMS /* XXXX This may be fixed in the future */ +#ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! */ + +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *dir) + { + DIR *d; + struct dirent *dstruct; + int ret = 0; + + CRYPTO_w_lock(CRYPTO_LOCK_READDIR); + d = opendir(dir); + + /* Note that a side effect is that the CAs will be sorted by name */ + if(!d) + { + SYSerr(SYS_F_OPENDIR, get_last_sys_error()); + ERR_add_error_data(3, "opendir('", dir, "')"); + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB); + goto err; + } + + while((dstruct=readdir(d))) + { + char buf[1024]; + int r; + + if(strlen(dir)+strlen(dstruct->d_name)+2 > sizeof buf) + { + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG); + goto err; + } + + r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,dstruct->d_name); + if (r <= 0 || r >= sizeof buf) + goto err; + if(!SSL_add_file_cert_subjects_to_stack(stack,buf)) + goto err; + } + ret = 1; + +err: + CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); + return ret; + } + +#endif +#endif + +#else + +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *dir) + { + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + int ret = 0; + + CRYPTO_w_lock(CRYPTO_LOCK_READDIR); + + hFind = FindFirstFile(dir, &FindFileData); + /* Note that a side effect is that the CAs will be sorted by name */ + if(hFind == INVALID_HANDLE_VALUE) + { + SYSerr(SYS_F_OPENDIR, get_last_sys_error()); + ERR_add_error_data(3, "opendir('", dir, "')"); + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB); + goto err; + } + + do + { + char buf[1024]; + int r; + + if(strlen(dir)+strlen(FindFileData.cFileName)+2 > sizeof buf) + { + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG); + goto err; + } + + r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,FindFileData.cFileName); + if (r <= 0 || r >= sizeof buf) + goto err; + if(!SSL_add_file_cert_subjects_to_stack(stack,buf)) + goto err; + } + while (FindNextFile(hFind, &FindFileData) != FALSE); + FindClose(hFind); + ret = 1; + +err: + CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); + return ret; + } + +#endif diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index eaf1abdd1..df307a80c 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1443,15 +1443,10 @@ void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,void *u) ctx->default_passwd_callback_userdata=u; } -void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,int (*cb)(),char *arg) +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg) { - /* now - * int (*cb)(X509_STORE_CTX *), - * but should be - * int (*cb)(X509_STORE_CTX *, void *arg) - */ ctx->app_verify_callback=cb; - ctx->app_verify_arg=arg; /* never used */ + ctx->app_verify_arg=arg; } void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*cb)(int, X509_STORE_CTX *)) diff --git a/ssl/ssltest.c b/ssl/ssltest.c index 7d6b53eed..2ef9ae760 100644 --- a/ssl/ssltest.c +++ b/ssl/ssltest.c @@ -158,6 +158,10 @@ static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx); static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export,int keylength); static void free_tmp_rsa(void); #endif +static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg); +#define APP_CALLBACK "Test Callback Argument" +static char *app_verify_arg = APP_CALLBACK; + #ifndef OPENSSL_NO_DH static DH *get_dh512(void); static DH *get_dh1024(void); @@ -336,6 +340,7 @@ int main(int argc, char *argv[]) int tls1=0,ssl2=0,ssl3=0,ret=1; int client_auth=0; int server_auth=0,i; + int app_verify=0; char *server_cert=TEST_SERVER_CERT; char *server_key=NULL; char *client_cert=TEST_CLIENT_CERT; @@ -489,6 +494,10 @@ int main(int argc, char *argv[]) { comp = COMP_RLE; } + else if (strcmp(*argv,"-app_verify") == 0) + { + app_verify = 1; + } else { fprintf(stderr,"unknown option %s\n",*argv); @@ -640,12 +649,20 @@ bad: SSL_CTX_set_verify(s_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); + if (app_verify) + { + SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg); + } } if (server_auth) { BIO_printf(bio_err,"server authentication\n"); SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER, verify_callback); + if (app_verify) + { + SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg); + } } { @@ -1433,6 +1450,25 @@ static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) return(ok); } +static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg) + { + char *s = NULL,buf[256]; + int ok=1; + + fprintf(stderr, "In app_verify_callback, allowing cert. "); + fprintf(stderr, "Arg is: %s\n", (char *)arg); + fprintf(stderr, "Finished printing do we have a context? 0x%x a cert? 0x%x\n", + (unsigned int)ctx, (unsigned int)ctx->cert); + if (ctx->cert) + s=X509_NAME_oneline(X509_get_subject_name(ctx->cert),buf,256); + if (s != NULL) + { + fprintf(stderr,"cert depth=%d %s\n",ctx->error_depth,buf); + } + + return(ok); + } + #ifndef OPENSSL_NO_RSA static RSA *rsa_tmp=NULL; diff --git a/test/testssl b/test/testssl index f115adb8e..ba5e41c86 100644 --- a/test/testssl +++ b/test/testssl @@ -1,40 +1,137 @@ #!/bin/sh +if [ "$1" = "" ]; then + key=../apps/server.pem +else + key="$1" +fi +if [ "$2" = "" ]; then + cert=../apps/server.pem +else + cert="$2" +fi +ssltest="./ssltest -key $key -cert $cert -c_key $key -c_cert $cert" + +if ../apps/openssl x509 -in $cert -text -noout | fgrep 'DSA Public Key' >/dev/null; then + dsa_cert=YES +else + dsa_cert=NO +fi + +if [ "$3" = "" ]; then + CA="-CApath ../certs" +else + CA="-CAfile $3" +fi + +if [ "$4" = "" ]; then + extra="" +else + extra="$4" +fi + +############################################################################# + echo test sslv2 -./ssltest -ssl2 || exit 1 +$ssltest -ssl2 $extra || exit 1 echo test sslv2 with server authentication -./ssltest -ssl2 -server_auth -CApath ../certs || exit 1 +$ssltest -ssl2 -server_auth $CA $extra || exit 1 -echo test sslv2 with client authentication -./ssltest -ssl2 -client_auth -CApath ../certs || exit 1 +if [ $dsa_cert = NO ]; then + echo test sslv2 with client authentication + $ssltest -ssl2 -client_auth $CA $extra || exit 1 -echo test sslv2 with both client and server authentication -./ssltest -ssl2 -server_auth -client_auth -CApath ../certs || exit 1 + echo test sslv2 with both client and server authentication + $ssltest -ssl2 -server_auth -client_auth $CA $extra || exit 1 +fi echo test sslv3 -./ssltest -ssl3 || exit 1 +$ssltest -ssl3 $extra || exit 1 echo test sslv3 with server authentication -./ssltest -ssl3 -server_auth -CApath ../certs || exit 1 +$ssltest -ssl3 -server_auth $CA $extra || exit 1 echo test sslv3 with client authentication -./ssltest -ssl3 -client_auth -CApath ../certs || exit 1 +$ssltest -ssl3 -client_auth $CA $extra || exit 1 echo test sslv3 with both client and server authentication -./ssltest -ssl3 -server_auth -client_auth -CApath ../certs || exit 1 +$ssltest -ssl3 -server_auth -client_auth $CA $extra || exit 1 echo test sslv2/sslv3 -./ssltest || exit 1 +$ssltest $extra || exit 1 echo test sslv2/sslv3 with server authentication -./ssltest -server_auth -CApath ../certs || exit 1 +$ssltest -server_auth $CA $extra || exit 1 echo test sslv2/sslv3 with client authentication -./ssltest -client_auth -CApath ../certs || exit 1 +$ssltest -client_auth $CA $extra || exit 1 echo test sslv2/sslv3 with both client and server authentication -./ssltest -server_auth -client_auth -CApath ../certs || exit 1 +$ssltest -server_auth -client_auth $CA $extra || exit 1 -exit 0 +echo test sslv2 via BIO pair +$ssltest -bio_pair -ssl2 $extra || exit 1 + +echo test sslv2 with server authentication via BIO pair +$ssltest -bio_pair -ssl2 -server_auth $CA $extra || exit 1 + +if [ $dsa_cert = NO ]; then + echo test sslv2 with client authentication via BIO pair + $ssltest -bio_pair -ssl2 -client_auth $CA $extra || exit 1 + + echo test sslv2 with both client and server authentication via BIO pair + $ssltest -bio_pair -ssl2 -server_auth -client_auth $CA $extra || exit 1 +fi + +echo test sslv3 via BIO pair +$ssltest -bio_pair -ssl3 $extra || exit 1 + +echo test sslv3 with server authentication via BIO pair +$ssltest -bio_pair -ssl3 -server_auth $CA $extra || exit 1 + +echo test sslv3 with client authentication via BIO pair +$ssltest -bio_pair -ssl3 -client_auth $CA $extra || exit 1 + +echo test sslv3 with both client and server authentication via BIO pair +$ssltest -bio_pair -ssl3 -server_auth -client_auth $CA $extra || exit 1 +echo test sslv2/sslv3 via BIO pair +$ssltest $extra || exit 1 + +if [ $dsa_cert = NO ]; then + echo test sslv2/sslv3 w/o DHE via BIO pair + $ssltest -bio_pair -no_dhe $extra || exit 1 +fi + +echo test sslv2/sslv3 with 1024bit DHE via BIO pair +$ssltest -bio_pair -dhe1024dsa -v $extra || exit 1 + +echo test sslv2/sslv3 with server authentication +$ssltest -bio_pair -server_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with client authentication via BIO pair +$ssltest -bio_pair -client_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with both client and server authentication via BIO pair +$ssltest -bio_pair -server_auth -client_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with both client and server authentication via BIO pair and app verify +$ssltest -bio_pair -server_auth -client_auth -app_verify $CA $extra || exit 1 + +############################################################################# + +echo test tls1 with 1024bit anonymous DH, multiple handshakes +$ssltest -v -bio_pair -tls1 -cipher ADH -dhe1024dsa -num 10 -f -time $extra || exit 1 + +if ../apps/openssl no-rsa; then + echo skipping RSA tests +else + echo test tls1 with 1024bit RSA, no DHE, multiple handshakes + ./ssltest -v -bio_pair -tls1 -cert ../apps/server2.pem -no_dhe -num 10 -f -time $extra || exit 1 + + echo test tls1 with 1024bit RSA, 1024bit DHE, multiple handshakes + ./ssltest -v -bio_pair -tls1 -cert ../apps/server2.pem -dhe1024dsa -num 10 -f -time $extra || exit 1 +fi + +exit 0 |