📄 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>#include <openssl/err.h>#include <openssl/pem.h>#include <openssl/x509.h>#include <openssl/rand.h>#define SSLDEBUG 1/*#define PATH "D:/conf/"#define PASSWORD "23-+Wert"#define CLIENT_KEYFILE PATH"ckey.pem"#define CLIENT_CERTFILE PATH"c.pem"#define SERVER_KEYFILE PATH"skey.pem"#define SERVER_CERTFILE PATH"s.pem"#define CA_LIST PATH"cacert.pem"#define RANDOM PATH"random.pem"#define DHFILE PATH"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;static eXosip_tls_ctx_t eXosip_tls_ctx_params;/* 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 100#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 OSIP_SUCCESS;}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); } if (tls_socket_tab[pos].ssl_ctx != NULL) SSL_CTX_free (tls_socket_tab[pos].ssl_ctx); close (tls_socket_tab[pos].socket); } } //free error strings (OpenSSL-lib) EVP_cleanup (); ERR_free_strings (); ERR_remove_state (0); //clear the encryption data (OpenSSL-lib) CRYPTO_cleanup_all_ex_data (); 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); //free the memory from our SSL parameters memset (&eXosip_tls_ctx_params, 0, sizeof (eXosip_tls_ctx_t)); return OSIP_SUCCESS;}static intpassword_cb (char *buf, int num, int rwflag, void *userdata){ char *passwd = (char *) userdata; if (passwd == NULL || passwd[0] == '\0') { return OSIP_SUCCESS; } strncpy (buf, passwd, 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); }}eXosip_tls_ctx_erroreXosip_set_tls_ctx (eXosip_tls_ctx_t * ctx){ eXosip_tls_credentials_t *ownClient = &eXosip_tls_ctx_params.client; eXosip_tls_credentials_t *ownServer = &eXosip_tls_ctx_params.server; //get the credentials eXosip_tls_credentials_t *client = &ctx->client; eXosip_tls_credentials_t *server = &ctx->server; //check if public AND private keys are valid if ((client->cert[0] != '\0' && client->priv_key[0] == '\0') || (client->cert[0] == '\0' && client->priv_key[0] != '\0')) { //no, one is missing return TLS_ERR_MISSING_AUTH_PART; } //check if a password is set, when a private key is present if (client->priv_key[0] != '\0' && client->priv_key_pw[0] == '\0') { return TLS_ERR_NO_PW; } //check if public AND private keys are valid if ((server->cert[0] != '\0' && server->priv_key[0] == '\0') || (server->cert[0] == '\0' && server->priv_key[0] != '\0')) { //no, one is missing return TLS_ERR_MISSING_AUTH_PART; } //check if a password is set, when a private key is present if (server->priv_key[0] != '\0' && server->priv_key_pw[0] == '\0') { return TLS_ERR_NO_PW; } //check if the file for diffie hellman is present /*if(ctx->dh_param[0] == '\0') { return TLS_ERR_NO_DH_PARAM; } */ //check if a file with random data is present --> will be verified when random file is needed (see tls_tl_open) /*if(ctx->random_file[0] == '\0') { return TLS_ERR_NO_RAND; } */ //check if a file with the list of possible rootCAs is available /*if(ctx->root_ca_cert[0] == '\0') { return TLS_ERR_NO_ROOT_CA; } */ /* clean up configuration */ memset (&eXosip_tls_ctx_params, 0, sizeof (eXosip_tls_ctx_t)); //check if client has own certificate if (client->cert[0] != '\0') { snprintf (ownClient->cert, sizeof (ownClient->cert), "%s", client->cert); snprintf (ownClient->priv_key, sizeof (ownClient->priv_key), "%s", client->priv_key); snprintf (ownClient->priv_key_pw, sizeof (ownClient->priv_key_pw), "%s", client->priv_key_pw); } else if (server->cert[0] != '\0') { //no, has no certificates -> copy the chars of the server snprintf (ownClient->cert, sizeof (ownClient->cert), "%s", server->cert); snprintf (ownClient->priv_key, sizeof (ownClient->priv_key), "%s", server->priv_key); snprintf (ownClient->priv_key_pw, sizeof (ownClient->priv_key_pw), "%s", server->priv_key_pw); } //check if server has own certificate if (server->cert[0] != '\0') { snprintf (ownServer->cert, sizeof (ownServer->cert), "%s", server->cert); snprintf (ownServer->cert, sizeof (ownServer->cert), "%s", server->priv_key); snprintf (ownServer->cert, sizeof (ownServer->cert), "%s", server->priv_key_pw); } else if (client->cert[0] != '\0') { //no, has no certificates -> copy the chars of the client snprintf (ownServer->cert, sizeof (ownServer->cert), "%s", client->cert); snprintf (ownServer->cert, sizeof (ownServer->cert), "%s", client->priv_key); snprintf (ownServer->cert, sizeof (ownServer->cert), "%s", client->priv_key_pw); } snprintf (eXosip_tls_ctx_params.dh_param, sizeof (ctx->dh_param), "%s", ctx->dh_param); snprintf (eXosip_tls_ctx_params.random_file, sizeof (ctx->random_file), "%s", ctx->random_file); snprintf (eXosip_tls_ctx_params.root_ca_cert, sizeof (ctx->root_ca_cert), "%s", ctx->root_ca_cert); return TLS_OK;}SSL_CTX *initialize_client_ctx (const char *keyfile, const char *certfile, const char *password, int transport){ SSL_METHOD *meth = NULL; SSL_CTX *ctx; if (transport == IPPROTO_UDP) {#if !(OPENSSL_VERSION_NUMBER < 0x00908000L) meth = DTLSv1_client_method ();#endif } 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); */ SSL_CTX_set_default_passwd_cb_userdata (ctx, (void *) password); SSL_CTX_set_default_passwd_cb (ctx, password_cb); if (certfile[0] != '\0') { // 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, eXosip_tls_ctx_params.root_ca_cert, 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); return ctx;}SSL_CTX *initialize_server_ctx (const char *keyfile, const char *certfile, const char *password, int transport){ SSL_METHOD *meth = NULL; SSL_CTX *ctx; int s_server_session_id_context = 1; if (transport == IPPROTO_UDP) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "DTLSv1 server method\n"));#if !(OPENSSL_VERSION_NUMBER < 0x00908000L) meth = DTLSv1_server_method ();#endif } else if (transport == IPPROTO_TCP) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -