📄 extl_tls.c
字号:
/* eXosip - This is the eXtended osip library. Copyright (C) 2002,2003,2004,2005,2006,2007 Aymeric MOIZARD - jack@atosc.org eXosip is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. eXosip is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifdef ENABLE_MPATROL#include <mpatrol.h>#endif#include "eXosip2.h"#include "eXtransport.h"#ifdef HAVE_OPENSSL_SSL_H#include <openssl/ssl.h>#define SPROTO_TLS 500#define SPROTO_DTLS 501#include <openssl/ssl.h>#include <openssl/err.h>#include <openssl/pem.h>#include <openssl/x509.h>#include <openssl/rand.h>#define SSLDEBUG 1#define PASSWORD "password"#define CLIENT_KEYFILE "ckey.pem"#define CLIENT_CERTFILE "c.pem"#define SERVER_KEYFILE "skey.pem"#define SERVER_CERTFILE "s.pem"#define CA_LIST "cacert.pem"#define RANDOM "random.pem"#define DHFILE "dh1024.pem"#if defined(_WIN32_WCE)#define strerror(X) "-1"#endifSSL_CTX *initialize_client_ctx (const char *keyfile, const char *certfile, const char *password, int transport);SSL_CTX *initialize_server_ctx (const char *keyfile, const char *certfile, const char *password, int transport);static int tls_socket;static struct sockaddr_storage ai_addr;static char tls_firewall_ip[64];static char tls_firewall_port[10];static SSL_CTX *ssl_ctx;static SSL_CTX *client_ctx;/* persistent connection */struct socket_tab{ int socket; char remote_ip[65]; int remote_port; SSL *ssl_conn; SSL_CTX *ssl_ctx; int ssl_state;};#ifndef EXOSIP_MAX_SOCKETS#define EXOSIP_MAX_SOCKETS#endifstatic struct socket_tab tls_socket_tab[EXOSIP_MAX_SOCKETS];static inttls_tl_init(void){ tls_socket=0; ssl_ctx=NULL; client_ctx=NULL; memset(&ai_addr, 0, sizeof(struct sockaddr_storage)); memset(&tls_socket_tab, 0, sizeof(struct socket_tab)*EXOSIP_MAX_SOCKETS); memset(tls_firewall_ip, 0, sizeof(tls_firewall_ip)); memset(tls_firewall_port, 0, sizeof(tls_firewall_port)); return 0;}static inttls_tl_free(void){ int pos; if (ssl_ctx != NULL) SSL_CTX_free (ssl_ctx); if (client_ctx != NULL) SSL_CTX_free (client_ctx); for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (tls_socket_tab[pos].socket > 0) { if (tls_socket_tab[pos].ssl_conn != NULL) { SSL_shutdown (tls_socket_tab[pos].ssl_conn); SSL_shutdown (tls_socket_tab[pos].ssl_conn); SSL_free (tls_socket_tab[pos].ssl_conn); SSL_CTX_free (tls_socket_tab[pos].ssl_ctx); } close(tls_socket_tab[pos].socket); } } memset(&tls_socket_tab, 0, sizeof(struct socket_tab)*EXOSIP_MAX_SOCKETS); memset(tls_firewall_ip, 0, sizeof(tls_firewall_ip)); memset(tls_firewall_port, 0, sizeof(tls_firewall_port)); memset(&ai_addr, 0, sizeof(struct sockaddr_storage)); if (tls_socket>0) close(tls_socket); return 0;}static intpassword_cb (char *buf, int num, int rwflag, void *userdata){ if (userdata == NULL) { return 0; } strncpy (buf, (char *) userdata, num); buf[num - 1] = '\0'; return strlen (buf);}static voidload_dh_params (SSL_CTX * ctx, char *file){ DH *ret = 0; BIO *bio; if ((bio = BIO_new_file (file, "r")) == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't open DH file!\n")); } else { ret = PEM_read_bio_DHparams (bio, NULL, NULL, NULL); BIO_free (bio); if (SSL_CTX_set_tmp_dh (ctx, ret) < 0) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't set DH param!\n")); }}static voidgenerate_eph_rsa_key (SSL_CTX * ctx){ RSA *rsa; rsa = RSA_generate_key (512, RSA_F4, NULL, NULL); if (rsa != NULL) { if (!SSL_CTX_set_tmp_rsa (ctx, rsa)) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't set RSA key!\n")); RSA_free (rsa); }}SSL_CTX *initialize_client_ctx (const char *keyfile, const char *certfile, const char *password, int transport){ SSL_METHOD *meth; SSL_CTX *ctx; char *passwd; if (transport == IPPROTO_UDP) { meth = DTLSv1_client_method (); } else if (transport == IPPROTO_TCP) { meth = TLSv1_client_method (); } else { return NULL; } ctx = SSL_CTX_new (meth); if (ctx == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't create SSL_CTX!\n")); return NULL; } /* SSL_CTX_set_read_ahead(ctx, 1); */ if (password != NULL) { passwd = osip_strdup (password); if (passwd == NULL) return NULL; } else passwd = NULL; SSL_CTX_set_default_passwd_cb_userdata (ctx, passwd); SSL_CTX_set_default_passwd_cb (ctx, password_cb); /* Load our keys and certificates */ if (!(SSL_CTX_use_certificate_file (ctx, certfile, SSL_FILETYPE_PEM))) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't read client certificate file %s!\n", certfile)); } if (!(SSL_CTX_use_PrivateKey_file (ctx, keyfile, SSL_FILETYPE_PEM))) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't read client pkey file %s!\n", keyfile)); if (!(SSL_CTX_use_RSAPrivateKey_file (ctx, keyfile, SSL_FILETYPE_PEM))) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't read client RSA key file %s!\n", keyfile)); /* Load the CAs we trust */ if (!(SSL_CTX_load_verify_locations (ctx, CA_LIST, 0))) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't read CA list\n")); { int verify_mode = SSL_VERIFY_NONE;#if 0 verify_mode = SSL_VERIFY_PEER;#endif SSL_CTX_set_verify(ctx, verify_mode, NULL); SSL_CTX_set_verify_depth (ctx, 3); } SSL_CTX_set_options (ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE); osip_free (passwd); passwd = 0; return ctx;}SSL_CTX *initialize_server_ctx (const char *keyfile, const char *certfile, const char *password, int transport){ SSL_METHOD *meth; SSL_CTX *ctx; char *passwd; int s_server_session_id_context = 1; /* initialization */ SSL_library_init (); SSL_load_error_strings (); if (transport == IPPROTO_UDP) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "DTLSv1 server method\n")); meth = DTLSv1_server_method (); } else if (transport == IPPROTO_TCP) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "TLS server method\n")); meth = TLSv1_server_method (); } else { return NULL; } ctx = SSL_CTX_new (meth); if (ctx == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't create SSL_CTX!\n")); return NULL; } if (password != NULL) { passwd = osip_strdup (password); if (passwd == NULL) return NULL; } else passwd = NULL; SSL_CTX_set_default_passwd_cb_userdata (ctx, passwd); SSL_CTX_set_default_passwd_cb (ctx, password_cb); if (transport == IPPROTO_UDP) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "DTLS read ahead\n")); SSL_CTX_set_read_ahead (ctx, 1); } /* Load our keys and certificates */ if (!(SSL_CTX_use_certificate_file (ctx, certfile, SSL_FILETYPE_PEM))) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't read certificate file!\n")); } /* Load the CAs we trust */ if (!(SSL_CTX_load_verify_locations (ctx, CA_LIST, 0))) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't read CA list\n")); } SSL_CTX_set_verify_depth (ctx, 5); SSL_CTX_set_options (ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE); if (!(SSL_CTX_use_PrivateKey_file (ctx, keyfile, SSL_FILETYPE_PEM))) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't read key file: %s\n", keyfile)); return 0; } if (!SSL_CTX_check_private_key(ctx)) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "check_private_key: Key '%s' does not match the public key of the certificate\n", SSL_FILETYPE_PEM)); return NULL; } /* Load randomness */ if (!(RAND_load_file (RANDOM, 1024 * 1024))) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't load randomness\n")); load_dh_params (ctx, DHFILE); generate_eph_rsa_key (ctx); SSL_CTX_set_session_id_context (ctx, (void *) &s_server_session_id_context, sizeof s_server_session_id_context); osip_free (passwd); passwd = 0; return ctx;}static inttls_tl_open(void){ int res; struct addrinfo *addrinfo = NULL; struct addrinfo *curinfo; int sock = -1; if (eXtl_tls.proto_port < 0) eXtl_tls.proto_port = 5061; ssl_ctx = initialize_server_ctx (SERVER_KEYFILE, SERVER_CERTFILE, PASSWORD, IPPROTO_TCP); client_ctx = initialize_client_ctx (CLIENT_KEYFILE, CLIENT_CERTFILE, PASSWORD, IPPROTO_TCP); res = eXosip_get_addrinfo (&addrinfo, eXtl_tls.proto_ifs, eXtl_tls.proto_port, eXtl_tls.proto_num); if (res) return -1; for (curinfo = addrinfo; curinfo; curinfo = curinfo->ai_next) { socklen_t len; if (curinfo->ai_protocol && curinfo->ai_protocol != eXtl_tls.proto_num) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "eXosip: Skipping protocol %d\n", curinfo->ai_protocol)); continue; } sock = (int) socket (curinfo->ai_family, curinfo->ai_socktype, curinfo->ai_protocol); if (sock < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot create socket %s!\n", strerror (errno))); continue; } if (curinfo->ai_family == AF_INET6) {#ifdef IPV6_V6ONLY if (setsockopt_ipv6only (sock)) { close (sock); sock = -1; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot set socket option %s!\n", strerror (errno))); continue; }#endif /* IPV6_V6ONLY */ } res = bind (sock, curinfo->ai_addr, curinfo->ai_addrlen); if (res < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind socket node:%s family:%d %s\n", eXtl_tls.proto_ifs, curinfo->ai_family, strerror (errno))); close (sock); sock = -1; continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -