📄 extl_tls.c
字号:
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; } SSL_CTX_set_default_passwd_cb_userdata (ctx, (void *) password); 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, eXosip_tls_ctx_params.root_ca_cert, 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 OSIP_SUCCESS; } 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_dh_params (ctx, eXosip_tls_ctx_params.dh_param); generate_eph_rsa_key (ctx); SSL_CTX_set_session_id_context (ctx, (void *) &s_server_session_id_context, sizeof s_server_session_id_context); return ctx;}/*** @brief Initializes the OpenSSL lib and the client/server contexts.* Depending on the previously initialized eXosip TLS context (see eXosip_set_tls_ctx() ), only the necessary contexts will be initialized.* The client context will be ALWAYS initialized, the server context only if certificates are available. The following chart should illustrate* the behaviour.** possible certificates | Client initialized | Server initialized* -------------------------------------------------------------------------------------* no certificate | yes, no cert used | not initialized* only client cert | yes, own cert (client) used | yes, client cert used* only server cert | yes, server cert used | yes, own cert (server) used* server and client cert | yes, own cert (client) used | yes, own cert (server) used** The file for seeding the PRNG is only needed on Windows machines. If you compile under a Windows environment, please set W32 oder _WINDOWS as* Preprocessor directives.*@return < 0 if an error occured**/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; // initialization (outside initialize_server_ctx) SSL_library_init (); SSL_load_error_strings (); if (eXosip_tls_ctx_params.server.cert[0] != '\0') { ssl_ctx = initialize_server_ctx (eXosip_tls_ctx_params.server.priv_key, eXosip_tls_ctx_params.server.cert, eXosip_tls_ctx_params.server.priv_key_pw, IPPROTO_TCP); } //always initialize the client client_ctx = initialize_client_ctx (eXosip_tls_ctx_params.client.priv_key, eXosip_tls_ctx_params.client.cert, eXosip_tls_ctx_params.server.priv_key_pw, IPPROTO_TCP);//only necessary under Windows-based OS, unix-like systems use /dev/random or /dev/urandom#if defined(WIN32) || defined(_WINDOWS)#if 0 //check if a file with random data is present --> will be verified when random file is needed if (eXosip_tls_ctx_params.random_file[0] == '\0') { return TLS_ERR_NO_RAND; }#endif /* Load randomness */ if (!(RAND_load_file (eXosip_tls_ctx_params.random_file, 1024 * 1024))) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Couldn't load randomness\n"));#endif 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; } 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_tls.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_tls.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_tls.proto_port)); return -1; } tls_socket = sock; if (eXtl_tls.proto_port == 0) { /* get port number from socket */ if (eXtl_tls.proto_family == AF_INET) eXtl_tls.proto_port = ntohs (((struct sockaddr_in *) &ai_addr)->sin_port); else eXtl_tls.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_tls.proto_port)); } snprintf (tls_firewall_port, sizeof (tls_firewall_port), "%i", eXtl_tls.proto_port); return OSIP_SUCCESS;}static inttls_tl_set_fdset (fd_set * osip_fdset, int *fd_max){ int pos; if (tls_socket <= 0) return -1; eXFD_SET (tls_socket, osip_fdset); if (tls_socket > *fd_max) *fd_max = tls_socket; for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (tls_socket_tab[pos].socket > 0) { eXFD_SET (tls_socket_tab[pos].socket, osip_fdset); if (tls_socket_tab[pos].socket > *fd_max) *fd_max = tls_socket_tab[pos].socket; } } return OSIP_SUCCESS;}int staticprint_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 OSIP_SUCCESS;}static inttls_tl_read_message (fd_set * osip_fdset){ int pos = 0; char *buf; if (FD_ISSET (tls_socket, osip_fdset)) { /* accept incoming connection */ char src6host[NI_MAXHOST]; int recvport = 0; struct sockaddr_storage sa; int sock; int i;#ifdef __linux socklen_t slen;#else int slen;#endif SSL *ssl = NULL; BIO *sbio; if (eXtl_tls.proto_family == AF_INET) slen = sizeof (struct sockaddr_in); else slen = sizeof (struct sockaddr_in6); for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (tls_socket_tab[pos].socket <= 0) break; } if (pos < 0) { /* delete an old one! */ pos = 0; 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[pos], 0, sizeof (struct socket_tab)); } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "creating TLS socket at index: %i\n", pos)); sock = accept (tls_socket, (struct sockaddr *) &sa, &slen); if (sock < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Error accepting TLS socket\n")); } else { if (ssl_ctx != NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "TLS connection rejected\n")); close (sock); return -1; } if (!SSL_CTX_check_private_key (ssl_ctx)) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SSL CTX private key check error\n")); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -