⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 extl_dtls.c

📁 libeXosip2-3.0.3.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  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"#endif#ifdef _WIN32_WCE#include "inet_ntop.h"#elif WIN32#include "inet_ntop.h"#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);extern eXosip_t eXosip;static int dtls_socket;static struct sockaddr_storage ai_addr;static char dtls_firewall_ip[64];static char dtls_firewall_port[10];static SSL_CTX *server_ctx;static SSL_CTX *client_ctx;/* persistent connection */struct socket_tab{  char remote_ip[65];  int remote_port;  SSL *ssl_conn;  int ssl_state;  int ssl_type;};#ifndef EXOSIP_MAX_SOCKETS#define EXOSIP_MAX_SOCKETS#endifstatic struct socket_tab dtls_socket_tab[EXOSIP_MAX_SOCKETS];static intdtls_tl_init(void){  dtls_socket=0;  server_ctx=NULL;  client_ctx=NULL;  memset(&ai_addr, 0, sizeof(struct sockaddr_storage));  memset(&dtls_socket_tab, 0, sizeof(struct socket_tab)*EXOSIP_MAX_SOCKETS);  memset(dtls_firewall_ip, 0, sizeof(dtls_firewall_ip));  memset(dtls_firewall_port, 0, sizeof(dtls_firewall_port));  return 0;}intstatic print_ssl_error (int err){  switch (err)    {    case SSL_ERROR_NONE:      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_ERROR, NULL,		   "SSL ERROR NONE - OK\n"));      break;    case SSL_ERROR_ZERO_RETURN:      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_ERROR, NULL,		   "SSL ERROR ZERO RETURN - SHUTDOWN\n"));      break;    case SSL_ERROR_WANT_READ:      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_ERROR, NULL, "SSL want read\n"));      break;    case SSL_ERROR_WANT_WRITE:      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_ERROR, NULL, "SSL want write\n"));      break;    case SSL_ERROR_SSL:      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_ERROR, NULL, "SSL ERROR\n"));      break;    case SSL_ERROR_SYSCALL:      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_ERROR, NULL,		   "SSL ERROR SYSCALL\n"));      break;    default:      OSIP_TRACE (osip_trace		  (__FILE__, __LINE__, OSIP_ERROR, NULL, "SSL problem\n"));    }  return 0;}static intshutdown_free_server_dtls (int pos){  int i, err;  if (dtls_socket_tab[pos].ssl_type == 1)    {      if (dtls_socket_tab[pos].ssl_conn != NULL)	{#ifdef SSLDEBUG	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL,				  "DTLS server SSL_shutdown\n"));#endif	  i = SSL_shutdown (dtls_socket_tab[pos].ssl_conn);	  if (i <= 0)	    {	      err = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i);	      print_ssl_error (err);#ifdef SSLDEBUG	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,				      "DTLS server shutdown <= 0\n"));#endif	    }	  else	    {#ifdef SSLDEBUG	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL,				      "DTLS server shutdown > 0\n"));#endif	    }	  SSL_free (dtls_socket_tab[pos].ssl_conn);#if 0	  if (dtls_socket_tab[pos].ssl_ctx != NULL)	    SSL_CTX_free (dtls_socket_tab[pos].ssl_ctx);#endif	  memset (&(dtls_socket_tab[pos]), 0,		  sizeof (struct socket_tab));	  return 0;	}      else	{	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,				  "DTLS server shutdown: invalid SSL object!\n"));	  return -1;	}    }  return -1;}static intshutdown_free_client_dtls (int pos){  int i, err;  BIO *rbio;  struct addrinfo *addrinfo;  struct __eXosip_sockaddr addr;  if (dtls_socket_tab[pos].ssl_type == 2)    {      if (dtls_socket_tab[pos].ssl_conn != NULL)	{	  i = eXosip_get_addrinfo (&addrinfo,				   dtls_socket_tab[pos].remote_ip,				   dtls_socket_tab[pos].remote_port,				   IPPROTO_UDP);	  if (i != 0)	    {	      return -1;	    }	  memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);	  eXosip_freeaddrinfo (addrinfo);	  rbio = BIO_new_dgram (dtls_socket,				BIO_NOCLOSE);	  BIO_dgram_set_peer (rbio, &addr);	  (dtls_socket_tab[pos].ssl_conn)->rbio = rbio;	  i = SSL_shutdown (dtls_socket_tab[pos].ssl_conn);	  if (i <= 0)	    {	      err = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i);#ifdef SSLDEBUG	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,				      "DTLS client shutdown error %d <= 0\n",				      i));#endif	      print_ssl_error (err);	    }	  else	    {#ifdef SSLDEBUG	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL,				      "DTLS client shutdown > 0\n"));#endif	    }	  SSL_free (dtls_socket_tab[pos].ssl_conn);#if 0	  if (dtls_socket_tab[pos].ssl_ctx != NULL)	    SSL_CTX_free (dtls_socket_tab[pos].ssl_ctx);#endif	  memset (&(dtls_socket_tab[pos]), 0,		  sizeof (struct socket_tab));	  return 0;	}      else	{	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,				  "DTLS client shutdown: invalid SSL object!\n"));	  return -1;	}    }  return -1;}static intdtls_tl_free(void){  int pos;  if (server_ctx != NULL)    SSL_CTX_free (server_ctx);  if (client_ctx != NULL)    SSL_CTX_free (client_ctx);  for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)    {      if (dtls_socket_tab[pos].ssl_conn != NULL)	{	  shutdown_free_client_dtls (pos);	  shutdown_free_server_dtls (pos);	}    }  memset(&dtls_socket_tab, 0, sizeof(struct socket_tab)*EXOSIP_MAX_SOCKETS);  memset(dtls_firewall_ip, 0, sizeof(dtls_firewall_ip));  memset(dtls_firewall_port, 0, sizeof(dtls_firewall_port));  memset(&ai_addr, 0, sizeof(struct sockaddr_storage));  if (dtls_socket>0)    close(dtls_socket);  dtls_socket = 0;  return 0;}static intdtls_tl_open(void){  int res;  struct addrinfo *addrinfo = NULL;  struct addrinfo *curinfo;  int sock = -1;  if (eXtl_dtls.proto_port < 0)    eXtl_dtls.proto_port = 5061;  server_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_dtls.proto_ifs,			     eXtl_dtls.proto_port,			     eXtl_dtls.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_dtls.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_dtls.proto_ifs, curinfo->ai_family, strerror (errno)));          close (sock);          sock = -1;          continue;        }      len = sizeof (ai_addr);      res = getsockname (sock, (struct sockaddr *) &ai_addr, &len);      if (res != 0)        {          OSIP_TRACE (osip_trace                      (__FILE__, __LINE__, OSIP_ERROR, NULL,                       "eXosip: Cannot get socket name (%s)\n", strerror (errno)));          memcpy (&ai_addr, curinfo->ai_addr, curinfo->ai_addrlen);        }      if (eXtl_dtls.proto_num == IPPROTO_TCP)        {          res = listen (sock, SOMAXCONN);          if (res < 0)            {              OSIP_TRACE (osip_trace                          (__FILE__, __LINE__, OSIP_ERROR, NULL,                           "eXosip: Cannot bind socket node:%s family:%d %s\n",                           eXtl_dtls.proto_ifs, curinfo->ai_family, strerror (errno)));              close (sock);              sock = -1;              continue;            }        }      break;    }  eXosip_freeaddrinfo (addrinfo);  if (sock < 0)    {      OSIP_TRACE (osip_trace                  (__FILE__, __LINE__, OSIP_ERROR, NULL,                   "eXosip: Cannot bind on port: %i\n", eXtl_dtls.proto_port));      return -1;    }  dtls_socket = sock;  if (eXtl_dtls.proto_port == 0)    {      /* get port number from socket */      if (eXtl_dtls.proto_family == AF_INET)        eXtl_dtls.proto_port = ntohs (((struct sockaddr_in *) &ai_addr)->sin_port);      else        eXtl_dtls.proto_port = ntohs (((struct sockaddr_in6 *) &ai_addr)->sin6_port);      OSIP_TRACE (osip_trace                  (__FILE__, __LINE__, OSIP_INFO1, NULL,                   "eXosip: Binding on port %i!\n", eXtl_dtls.proto_port));    }  snprintf(dtls_firewall_port, sizeof(dtls_firewall_port), "%i", eXtl_dtls.proto_port);  return 0;}#define EXOSIP_AS_A_SERVER 1#define EXOSIP_AS_A_CLIENT 2static intdtls_tl_set_fdset(fd_set *osip_fdset, int *fd_max){  if (dtls_socket<=0)    return -1;  eXFD_SET (dtls_socket, osip_fdset);  if (dtls_socket > *fd_max)    *fd_max = dtls_socket;  return 0;}static intdtls_tl_read_message(fd_set *osip_fdset){  char *enc_buf;  char *dec_buf;  int i;  int enc_buf_len;  if (dtls_socket<=0)    return -1;    if (FD_ISSET (dtls_socket, osip_fdset))    {      struct sockaddr_storage sa;      #ifdef __linux      socklen_t slen;#else      int slen;#endif      if (eXtl_dtls.proto_family == AF_INET)	slen = sizeof (struct sockaddr_in);      else	slen = sizeof (struct sockaddr_in6);            enc_buf = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH * sizeof (char) + 1);      if (enc_buf==NULL)	return -1;      enc_buf_len = recvfrom (dtls_socket, enc_buf,		    SIP_MESSAGE_MAX_LENGTH, 0,		    (struct sockaddr *) &sa, &slen);            if (enc_buf_len > 5)	{	  char src6host[NI_MAXHOST];	  int recvport = 0;	  int err;	  	  BIO *rbio;	  struct socket_tab *socket_tab_used=NULL;	  int pos;	  osip_strncpy (enc_buf + enc_buf_len, "\0", 1);	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,				  "Received message: \n%s\n", enc_buf));	  memset (src6host, 0, sizeof (src6host));	  	  if (eXtl_dtls.proto_family == AF_INET)	    recvport = ntohs (((struct sockaddr_in *) &sa)->sin_port);	  else	    recvport = ntohs (((struct sockaddr_in6 *) &sa)->sin6_port);		  #if defined(__arc__)	  {	    struct sockaddr_in *fromsa = (struct sockaddr_in *) &sa;	    char *tmp;	    tmp = inet_ntoa(fromsa->sin_addr);	    if (tmp==NULL)	      {		OSIP_TRACE (osip_trace			    (__FILE__, __LINE__, OSIP_ERROR, NULL,			     "Message received from: NULL:%i inet_ntoa failure\n",			     recvport));	      }	    else	      {		snprintf(src6host, sizeof(src6host), "%s", tmp);		OSIP_TRACE (osip_trace			    (__FILE__, __LINE__, OSIP_INFO1, NULL,			     "Message received from: %s:%i\n", src6host, recvport));	      }	  }#else	  err = getnameinfo ((struct sockaddr *) &sa, slen,			     src6host, NI_MAXHOST,			     NULL, 0, NI_NUMERICHOST);	  	  if (err != 0)	    {	      OSIP_TRACE (osip_trace			  (__FILE__, __LINE__, OSIP_ERROR, NULL,			   "Message received from: NULL:%i getnameinfo failure\n",			   recvport));	      snprintf(src6host, sizeof(src6host), "127.0.0.1");	    }	  else	    {	      OSIP_TRACE (osip_trace			  (__FILE__, __LINE__, OSIP_INFO1, NULL,			   "Message received from: %s:%i\n",			   src6host, recvport));	    }#endif	  	  OSIP_TRACE (osip_trace		      (__FILE__, __LINE__, OSIP_INFO1, NULL,		       "Message received from: %s:%i\n",		       src6host, recvport));	  for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)	    {	      if (dtls_socket_tab[pos].ssl_conn != NULL)		{		  if (dtls_socket_tab[pos].remote_port == recvport &&		      (strcmp (dtls_socket_tab[pos].remote_ip, src6host) == 0))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -