net_client_ssl.c revision 5d0dcd9820c04ac52a150525298eaae50c8b3544
/**
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2015 ForgeRock AS.
*/
#include "platform.h"
#include "am.h"
#include "utility.h"
#include "net_client.h"
#ifdef _WIN32
#define AM_SSL_LIB "ssleay32"
#define AM_CRYPTO_LIB "libeay32"
#else
#define AM_SSL_LIB "libssl"
#define AM_CRYPTO_LIB "libcrypto"
#endif
#ifdef _WIN32
#ifndef LOAD_LIBRARY_SEARCH_USER_DIRS
#define LOAD_LIBRARY_SEARCH_USER_DIRS 0x00000400
#endif
static DLL_DIRECTORY_COOKIE dll_directory_cookie = 0;
#else
#endif
static void *crypto_lib = NULL;
struct ssl_func {
const char *name;
void (*ptr)(void);
};
{"SSL_library_init", NULL},
{"SSL_CTX_new", NULL},
{"SSLv23_client_method", NULL},
{"SSL_CTX_ctrl", NULL},
{"SSL_CTX_set_cipher_list", NULL},
{"SSL_CTX_load_verify_locations", NULL},
{"SSL_CTX_use_certificate_file", NULL},
{"SSL_CTX_set_default_passwd_cb_userdata", NULL},
{"SSL_CTX_set_default_passwd_cb", NULL},
{"SSL_CTX_use_PrivateKey_file", NULL},
{"SSL_CTX_check_private_key", NULL},
{"SSL_CTX_set_verify", NULL},
{"SSL_new", NULL},
{"SSL_CTX_set_info_callback", NULL},
{"SSL_CTX_set_msg_callback", NULL},
{"SSL_set_connect_state", NULL},
{"SSL_do_handshake", NULL},
{"SSL_get_error", NULL},
{"SSL_read", NULL},
{"SSL_write", NULL},
{"SSL_connect", NULL},
{"SSL_shutdown", NULL},
{"SSL_CTX_free", NULL},
{"SSL_free", NULL},
{"SSL_get_peer_certificate", NULL},
{"SSL_alert_type_string", NULL},
{"SSL_alert_desc_string", NULL},
{"SSL_alert_desc_string_long", NULL},
{"SSL_set_bio", NULL},
{"SSL_get_verify_result", NULL},
{"SSL_state_string", NULL},
{"SSL_state_string_long", NULL},
{"SSL_state", NULL},
{"SSL_load_error_strings", NULL},
{"SSL_CTX_set_verify_depth", NULL},
#ifndef _WIN32
{"BIO_s_mem", NULL},
{"BIO_new", NULL},
{"BIO_write", NULL},
{"BIO_read", NULL},
{"BIO_ctrl", NULL},
#endif
};
{"CRYPTO_num_locks", NULL},
{"CRYPTO_set_locking_callback", NULL},
{"CRYPTO_set_id_callback", NULL},
{"CRYPTO_set_mem_functions", NULL},
{"OPENSSL_add_all_algorithms_noconf", NULL},
{"X509_get_subject_name", NULL},
{"X509_get_issuer_name", NULL},
{"X509_NAME_oneline", NULL},
{"X509_free", NULL},
{"ERR_get_error", NULL},
{"ERR_error_string", NULL},
#ifdef _WIN32
{"BIO_s_mem", NULL},
{"BIO_new", NULL},
{"BIO_write", NULL},
{"BIO_read", NULL},
{"BIO_ctrl", NULL},
#endif
};
#define SSL_ERROR_NONE 0
#define SSL_ERROR_WANT_READ 2
#define SSL_ERROR_WANT_WRITE 3
#define SSL_OP_NO_SSLv2 0x01000000L
#define SSL_OP_NO_SSLv3 0x02000000L
#define SSL_OP_NO_TLSv1 0x04000000L
#define SSL_OP_NO_TLSv1_2 0x08000000L
#define SSL_OP_NO_TLSv1_1 0x10000000L
#define SSL_FILETYPE_PEM 1
#define SSL_VERIFY_NONE 0
#define SSL_VERIFY_PEER 0x01
#define SSL_CB_LOOP 0x01
#define SSL_CB_EXIT 0x02
#define SSL_CB_READ 0x04
#define SSL_CB_WRITE 0x08
#define SSL_CB_ALERT 0x4000
#define SSL_CB_HANDSHAKE_DONE 0x20
#define SSL_CTRL_OPTIONS 32
#define SSL_CTRL_SET_MSG_CALLBACK_ARG 16
#define SSL_ST_OK 0x03
#define SSL_MODE_AUTO_RETRY 0x4
#define SSL_CTRL_MODE 33
#define SSL_MODE_ENABLE_PARTIAL_WRITE 0x1
#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x2
#define BIO_C_SET_BUF_MEM_EOF_RETURN 130
#define BIO_CTRL_PENDING 10
#define SSL_SESS_CACHE_OFF 0x0000
#define SSL_CTRL_SET_SESS_CACHE_MODE 44
typedef struct ssl_ctx_st SSL_CTX;
typedef struct ssl_method_st SSL_METHOD;
typedef struct x509_store_ctx_st X509_STORE_CTX;
#ifdef _WIN32
#endif
typedef struct X509_name_st X509_NAME;
typedef struct bio_method_st BIO_METHOD;
#define SSL_CTX_load_verify_locations (* (int (*)(SSL_CTX *, const char *, const char *)) ssl_sw[5].ptr)
#define SSL_CTX_set_default_passwd_cb (* (void (*)(SSL_CTX *, int (*callback)(char *, int, int, void *))) ssl_sw[8].ptr)
#define SSL_CTX_set_verify (* (void (*)(SSL_CTX *, int, int (*verify_callback)(int, X509_STORE_CTX *))) ssl_sw[11].ptr)
#define SSL_CTX_set_msg_callback (* (void (*)(SSL_CTX *, void (*callback)(int, int, int, const void *, size_t, SSL *, void *))) ssl_sw[14].ptr)
#ifndef _WIN32
#endif
#define CRYPTO_set_locking_callback (* (void (*)(void (*)(int, int, const char *, int))) crypto_sw[1].ptr)
#define CRYPTO_set_mem_functions (* (int (*)(void *(*m)(size_t),void *(*r)(void *,size_t), void (*f)(void *))) crypto_sw[3].ptr)
#ifdef _WIN32
#endif
#ifdef _WIN32
#else
#endif
}
static void close_library(void *lib) {
#ifdef _WIN32
#else
#endif
}
char name[AM_PATH_SIZE];
int i;
char temp[AM_PATH_SIZE];
#endif
void *lib_handle = NULL;
union {
void *p;
void (*fp)(void);
} u;
#if defined(_WIN32)
"%s.dll"
"%s.dylib"
#ifdef __64BIT__
"%s.a(%s64.so.1.0.0)"
#else
"%s.a(%s.so.1.0.0)"
#endif
#else
"%s.so"
#endif
#if defined(AIX)
#endif
);
#ifdef _WIN32
return NULL;
}
#else
#if defined(__APPLE__)
#else
for (i = 0; i < ARRAY_SIZE(name_variants); i++) {
} else {
}
#if defined(AIX)
#endif
);
if (lib_handle != NULL) {
break;
}
}
#endif
if (lib_handle == NULL) {
return NULL;
}
#endif
}
return NULL;
}
}
return lib_handle;
}
static const char *thisfunc = "show_server_cert():";
char *line;
}
}
}
}
}
static const char *read_ssl_error() {
unsigned long err = ERR_get_error();
}
static const char *thisfunc = "net_ssl_error():";
char *error_string;
switch (ssl_error) {
case SSL_ERROR_NONE:
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
return 0;
}
error_string = (char *) read_ssl_error();
}
}
return 1;
}
if (mode & 1) {
#ifdef _WIN32
#else
#endif
} else {
#ifdef _WIN32
#else
#endif
}
}
static unsigned long ssl_id_callback(void) {
#ifdef _WIN32
return (unsigned long) GetCurrentThreadId();
#else
return (unsigned long) pthread_self();
#endif
}
static
#ifdef _WIN32
#else
void
#endif
#ifdef _WIN32
#endif
) {
int i, size;
#ifdef _WIN32
if (add_directory != NULL) {
}
}
#endif
#ifdef _WIN32
for (i = 0; i < CRYPTO_num_locks(); i++) {
}
#else
for (i = 0; i < CRYPTO_num_locks(); i++) {
}
#endif
} else {
crypto_lib = NULL;
}
#ifdef _WIN32
return TRUE;
#endif
}
void net_init_ssl() {
#ifdef _WIN32
#else
#endif
}
/**
* Reset SSL initialize-once flag. Must not be used outside unit-test module.
*/
void am_net_init_ssl_reset() {
#ifdef _WIN32
#else
#endif
}
void net_shutdown_ssl() {
int i;
&& CRYPTO_set_id_callback && CRYPTO_num_locks) {
if (ssl_mutexes != NULL) {
for (i = 0; i < CRYPTO_num_locks(); i++) {
#ifdef _WIN32
#else
#endif
}
}
}
ssl_mutexes = NULL;
crypto_lib = NULL;
#ifdef _WIN32
if (dll_directory_cookie) {
if (remove_directory != NULL) {
}
dll_directory_cookie = 0;
}
#endif
}
static void write_bio_to_socket(am_net_t *n) {
static const char *thisfunc = "write_bio_to_socket():";
char *buf, *p;
if (pending > 0) {
return;
}
if (hasread > 0) {
p = buf;
while (remaining) {
if (len <= 0) {
#ifdef _WIN32
#else
#endif
}
}
return;
}
p += len;
}
}
}
}
void net_close_ssl_notify(am_net_t *n) {
}
}
void net_close_ssl(am_net_t *n) {
}
}
}
static const char *thisfunc = "net_ssl_msg_callback():";
}
}
}
void net_connect_ssl(am_net_t *n) {
static const char *thisfunc = "net_connect_ssl():";
if (n != NULL) {
/*check whether we have ssl library loaded and symbols are available*/
return;
}
thisfunc, read_ssl_error());
return;
}
/* TODO: SSL_OP_NO_TICKET */
if (c != NULL) {
if (strcasecmp(v, "-SSLv3") == 0) {
continue;
}
if (strcasecmp(v, "-TLSv1") == 0) {
continue;
}
if (strcasecmp(v, "-TLSv1.1") == 0) {
continue;
}
if (strcasecmp(v, "-TLSv1.2") == 0) {
}
}
free(c);
}
}
"%s failed to set cipher list \"%s\"",
}
}
"%s failed to load trusted CA certificates file \"%s\"",
} else {
}
}
"%s failed to load client certificate file \"%s\"",
}
}
}
if (!SSL_CTX_use_PrivateKey_file(n->ssl.ssl_context, n->options->cert_key_file, SSL_FILETYPE_PEM)) {
"%s failed to load private key file \"%s\", %s",
}
"%s private key does not match the public certificate",
thisfunc);
}
}
} else if (cert_ca_file_loaded) {
} else {
/* if we are going to verify the server cert, trusted ca certs file must be present */
"%s unable to verify peer: trusted CA certificates file \"%s\" not loaded",
return;
}
/* do the handshake */
if (status != 1) {
if (!ssl_is_fatal_error(n, err)) {
}
}
}
} else {
thisfunc, read_ssl_error());
}
}
}
static int read_data_after_handshake(am_net_t *n) {
char *buf;
#define AM_SSL_BUFFER_SZ 1024
return AM_ENOMEM;
}
do {
if (ret == 0) {
/* connection closed */
break;
}
if (ret < 0) {
if (!ssl_is_fatal_error(n, err)) {
return AM_EAGAIN;
}
break;
}
} while (ret > 0);
return status;
}
void net_write_ssl(am_net_t *n) {
do {
if (ret == 0) {
/* connection closed */
break;
}
if (ret < 0) {
if (!ssl_is_fatal_error(n, err)) {
}
break;
}
} while (ret > 0);
}
if (sz == 0) {
return AM_EOF;
}
if (ret != 1) {
if (!ssl_is_fatal_error(n, err)) {
}
} else {
net_write_ssl(n);
}
} else {
}
return status;
}