ssl_server * ssl_setup_server(int fd){ ssl_ensure_initialized(); SSL_CTX * ctx = SSL_CTX_new(DTLSv1_server_method()); { // setup server SSL CTX SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!MD5:!RC4"); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM)) printf("\nERROR: no certificate found!"); if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM)) printf("\nERROR: no private key found!"); if (!SSL_CTX_check_private_key (ctx)) printf("\nERROR: invalid private key!"); /* Client has to authenticate */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback); SSL_CTX_set_read_ahead(ctx, 1); SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie); SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie); } ssl_server * srv = alloc0(sizeof(ssl_server)); srv->ctx = ctx; srv->fd = fd; return srv; }
BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int options, BOOL clientMode) #endif { tls->ctx = SSL_CTX_new(method); if (!tls->ctx) { DEBUG_WARN( "%s: SSL_CTX_new failed\n", __FUNCTION__); return FALSE; } SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_options(tls->ctx, options); SSL_CTX_set_read_ahead(tls->ctx, 1); if (tls->settings->PermittedTLSCiphers) { if(!SSL_CTX_set_cipher_list(tls->ctx, tls->settings->PermittedTLSCiphers)) { DEBUG_WARN( "SSL_CTX_set_cipher_list %s failed\n", tls->settings->PermittedTLSCiphers); return FALSE; } } tls->bio = BIO_new_rdp_tls(tls->ctx, clientMode); if (BIO_get_ssl(tls->bio, &tls->ssl) < 0) { DEBUG_WARN( "%s: unable to retrieve the SSL of the connection\n", __FUNCTION__); return FALSE; } BIO_push(tls->bio, underlying); return TRUE; }
static int _tnet_transport_ssl_init(tnet_transport_t* transport) { if(!transport){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } #if HAVE_OPENSSL { tnet_socket_type_t type = tnet_transport_get_type(transport); tsk_bool_t is_tls = (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)); tsk_bool_t is_dtls = TNET_SOCKET_TYPE_IS_DTLS(type); if(is_dtls && !tnet_dtls_is_supported()){ TSK_DEBUG_ERROR("Requesting to create DTLS transport but source code not built with support for this feature"); return -1; } if(is_tls && !tnet_tls_is_supported()){ TSK_DEBUG_ERROR("Requesting to create TLS transport but source code not built with support for this feature"); return -1; } if((transport->tls.enabled = is_tls)){ if(!transport->tls.ctx_client && !(transport->tls.ctx_client = SSL_CTX_new(SSLv23_client_method()))){ TSK_DEBUG_ERROR("Failed to create SSL client context"); return -2; } if(!transport->tls.ctx_server && !(transport->tls.ctx_server = SSL_CTX_new(SSLv23_server_method()))){ TSK_DEBUG_ERROR("Failed to create SSL server context"); return -3; } SSL_CTX_set_mode(transport->tls.ctx_client, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(transport->tls.ctx_server, SSL_MODE_AUTO_RETRY); SSL_CTX_set_verify(transport->tls.ctx_server, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs() SSL_CTX_set_verify(transport->tls.ctx_client, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs() if(SSL_CTX_set_cipher_list(transport->tls.ctx_client, TNET_CIPHER_LIST) <= 0 || SSL_CTX_set_cipher_list(transport->tls.ctx_server, TNET_CIPHER_LIST) <= 0){ TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); return -4; } } #if HAVE_OPENSSL_DTLS if((transport->dtls.enabled = is_dtls)){ if(!transport->dtls.ctx && !(transport->dtls.ctx = SSL_CTX_new(DTLSv1_method()))){ TSK_DEBUG_ERROR("Failed to create DTLSv1 context"); TSK_OBJECT_SAFE_FREE(transport); return -5; } SSL_CTX_set_read_ahead(transport->dtls.ctx, 1); // SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_ALL); // SSL_CTX_set_mode(transport->dtls.ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_verify(transport->dtls.ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, tsk_null); // to be updated by tnet_transport_tls_set_certs() if(SSL_CTX_set_cipher_list(transport->dtls.ctx, TNET_CIPHER_LIST) <= 0){ TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); return -6; } transport->dtls.activated = tsk_true; } #endif /* HAVE_OPENSSL_DTLS */ } #endif /* HAVE_OPENSSL */ return 0; }
BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int options, BOOL clientMode) #endif { tls->ctx = SSL_CTX_new(method); if (!tls->ctx) { fprintf(stderr, "%s: SSL_CTX_new failed\n", __FUNCTION__); return FALSE; } SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_options(tls->ctx, options); SSL_CTX_set_read_ahead(tls->ctx, 1); tls->bio = BIO_new_rdp_tls(tls->ctx, clientMode); if (BIO_get_ssl(tls->bio, &tls->ssl) < 0) { fprintf(stderr, "%s: unable to retrieve the SSL of the connection\n", __FUNCTION__); return FALSE; } BIO_push(tls->bio, underlying); return TRUE; }
int swSSL_server_set_cipher(SSL_CTX* ssl_context, swSSL_config *cfg) { #ifndef TLS1_2_VERSION return SW_OK; #endif SSL_CTX_set_read_ahead(ssl_context, 1); if (strlen(cfg->ciphers) > 0) { if (SSL_CTX_set_cipher_list(ssl_context, cfg->ciphers) == 0) { swWarn("SSL_CTX_set_cipher_list(\"%s\") failed", cfg->ciphers); return SW_ERR; } if (cfg->prefer_server_ciphers) { SSL_CTX_set_options(ssl_context, SSL_OP_CIPHER_SERVER_PREFERENCE); } } #ifndef LIBRESSL_VERSION_NUMBER SSL_CTX_set_tmp_rsa_callback(ssl_context, swSSL_rsa512_key_callback); #endif if (strlen(cfg->ecdh_curve) > 0) { swSSL_set_dhparam(ssl_context); swSSL_set_ecdh_curve(ssl_context); } return SW_OK; }
// memory is only valid for duration of callback; must be copied if queueing // is required DtlsSocketContext::DtlsSocketContext() { started = false; mSocket = NULL; receiver = NULL; DtlsSocketContext::Init(); ELOG_DEBUG("Creating Dtls factory, Openssl v %s", OPENSSL_VERSION_TEXT); mContext = SSL_CTX_new(DTLSv1_method()); assert(mContext); int r = SSL_CTX_use_certificate(mContext, mCert); assert(r == 1); r = SSL_CTX_use_PrivateKey(mContext, privkey); assert(r == 1); SSL_CTX_set_cipher_list(mContext, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); SSL_CTX_set_info_callback(mContext, SSLInfoCallback); SSL_CTX_set_verify(mContext, SSL_VERIFY_PEER |SSL_VERIFY_FAIL_IF_NO_PEER_CERT, SSLVerifyCallback); // SSL_CTX_set_session_cache_mode(mContext, SSL_SESS_CACHE_OFF); // SSL_CTX_set_options(mContext, SSL_OP_NO_TICKET); // Set SRTP profiles r = SSL_CTX_set_tlsext_use_srtp(mContext, DefaultSrtpProfile); assert(r == 0); SSL_CTX_set_verify_depth(mContext, 2); SSL_CTX_set_read_ahead(mContext, 1); ELOG_DEBUG("DtlsSocketContext %p created", this); }
struct dtls_context * create_dtls_context(const char *common) { if (common == NULL) return NULL; struct dtls_context *context = (struct dtls_context *)calloc(1, sizeof *context); if (context == NULL) return NULL; SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_CTX *ctx = SSL_CTX_new(DTLSv1_method()); if (ctx == NULL) goto ctx_err; context->ctx = ctx; // ALL:NULL:eNULL:aNULL if (SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1) goto ctx_err; SSL_CTX_set_read_ahead(ctx, 1); // for DTLS SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_peer_certificate_cb); EVP_PKEY *key = gen_key(); if (key == NULL) goto ctx_err; SSL_CTX_use_PrivateKey(ctx, key); X509 *cert = gen_cert(key, common, 365); if (cert == NULL) goto ctx_err; SSL_CTX_use_certificate(ctx, cert); if (SSL_CTX_check_private_key(ctx) != 1) goto ctx_err; unsigned int len; unsigned char buf[BUFFER_SIZE]; X509_digest(cert, EVP_sha256(), buf, &len); char *p = context->fingerprint; for (int i = 0; i < len; ++i) { snprintf(p, 4, "%02X:", buf[i]); p += 3; } *(p - 1) = 0; if (0) { ctx_err: SSL_CTX_free(ctx); free(context); context = NULL; } return context; }
static SSL_CTX *dtls_setup_sslclient (void) { SSL_METHOD *meth = NULL; SSL_CTX *ctx = NULL; extern char *pass; if (!dtls_bio_err) { SSL_library_init (); ERR_clear_error (); SSL_load_error_strings (); OpenSSL_add_all_algorithms (); dtls_bio_err = BIO_new_fp (stderr, BIO_NOCLOSE); } meth = DTLSv1_client_method (); // Datagam TLS v1 client - requires openSSL > v0.9.8 ctx = SSL_CTX_new (meth); // New SSL CTX object as Framework to establish new SSL connections if (!SSL_CTX_use_certificate_chain_file (ctx, DTLSC_CERT)) { dtls_destroy_ctx (ctx); dtls_report_berr ("Error loading the file \"%s\" - %s\n", DTLSC_CERT, strerror (errno)); } pass = PASSWORD; /* Enable this if u hve generated your certificates with password. If certs are generated with '-nodes' option, this is not required */ // SSL_CTX_set_default_passwd_cb (ctx, dtls_password_cb); // fprintf (stderr, "%s: %s(): Am now here @ %d\n", __FILE__, __func__, __LINE__); if (!SSL_CTX_use_PrivateKey_file (ctx, DTLSC_KEY_CERT, SSL_FILETYPE_PEM)) { dtls_destroy_ctx (ctx); dtls_report_berr ("Error loading the private key from the file \"%s\" - %s\n", DTLSC_KEY_CERT, \ strerror (errno)); } if (!SSL_CTX_load_verify_locations (ctx, DTLSC_ROOT_CACERT, 0)) { dtls_destroy_ctx (ctx); dtls_report_berr ("Error loading the CA file - %s\n", strerror (errno)); } SSL_CTX_set_verify_depth (ctx, 2); SSL_CTX_set_options (ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); #ifdef DEBUG SSL_CTX_set_info_callback (ctx, &dtls_info_callback); #endif SSL_CTX_set_read_ahead (ctx, 1); // Required for DTLS - please refer apps/s_client.c source file return ctx; }
IoSecureServer *IoSecureServer_useDTLS(IoSecureServer *self, IoObject *locals, IoMessage *msg) { #ifdef DTLS_IMPLEMENTED SSL_CTX *ctx = OCTX(self); if(SSL_CTX_set_ssl_version(ctx, DTLSv1_server_method()) != 1) { ERR_print_errors_fp(stderr); IoState_error_(IOSTATE, msg, "Error using DTLS"); return IONIL(self); } SSL_CTX_set_read_ahead(ctx, 1); return self; #else IoState_error_(IOSTATE, msg, "Addon built against OpenSSL older than 0.9.8; DTLS is not supported."); return IONIL(self); #endif }
static int init_server(dtls_listener_relay_server_type* server, const char* ifname, const char *local_address, int port, int verbose, ioa_engine_handle e, turn_turnserver *ts) { if(!server) return -1; server->dtls_ctx = e->dtls_ctx; server->ts = ts; server->children_ss = ur_addr_map_create(65535); if(ifname) STRCPY(server->ifname,ifname); if(make_ioa_addr((const u08bits*)local_address, port, &server->addr)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create a UDP/DTLS listener for address: %s\n",local_address); return -1; } server->slen0 = get_ioa_addr_len(&(server->addr)); server->verbose=verbose; server->e = e; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method: %s\n",event_base_get_method(server->e->event_base)); if(server->dtls_ctx) { #if defined(REQUEST_CLIENT_CERT) /* If client has to authenticate, then */ SSL_CTX_set_verify(server->dtls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback); #endif SSL_CTX_set_read_ahead(server->dtls_ctx, 1); #if !defined(TURN_NO_DTLS) SSL_CTX_set_cookie_generate_cb(server->dtls_ctx, generate_cookie); SSL_CTX_set_cookie_verify_cb(server->dtls_ctx, verify_cookie); #endif } return create_server_socket(server); }
SSL_CTX * sslctx_server_setup(const SSL_METHOD *method) { netsnmp_cert *id_cert; /*********************************************************************** * Set up the server context */ /* setting up for ssl */ SSL_CTX *the_ctx = SSL_CTX_new(NETSNMP_REMOVE_CONST(SSL_METHOD *, method)); if (!the_ctx) { LOGANDDIE("can't create a new context"); } id_cert = netsnmp_cert_find(NS_CERT_IDENTITY, NS_CERTKEY_DEFAULT, NULL); if (!id_cert) LOGANDDIE ("error finding server identity keys"); if (!id_cert->key || !id_cert->key->okey) LOGANDDIE("failed to load private key"); DEBUGMSGTL(("sslctx_server", "using public key: %s\n", id_cert->info.filename)); DEBUGMSGTL(("sslctx_server", "using private key: %s\n", id_cert->key->info.filename)); if (SSL_CTX_use_certificate(the_ctx, id_cert->ocert) <= 0) LOGANDDIE("failed to set the certificate to use"); if (SSL_CTX_use_PrivateKey(the_ctx, id_cert->key->okey) <= 0) LOGANDDIE("failed to set the private key to use"); if (!SSL_CTX_check_private_key(the_ctx)) LOGANDDIE("public and private keys incompatible"); SSL_CTX_set_read_ahead(the_ctx, 1); /* XXX: DTLS only? */ SSL_CTX_set_verify(the_ctx, SSL_VERIFY_PEER| SSL_VERIFY_FAIL_IF_NO_PEER_CERT| SSL_VERIFY_CLIENT_ONCE, &verify_callback); return _sslctx_common_setup(the_ctx, NULL); }
ssl_client * ssl_start_client(int fd, struct sockaddr * remote_addr){ ssl_ensure_initialized(); SSL_CTX * ctx = SSL_CTX_new(DTLSv1_client_method()); SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!MD5:!RC4"); if (!SSL_CTX_use_certificate_file(ctx, "certs/client-cert.pem", SSL_FILETYPE_PEM)) printf("\nERROR: no certificate found!"); if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/client-key.pem", SSL_FILETYPE_PEM)) printf("\nERROR: no private key found!"); if (!SSL_CTX_check_private_key (ctx)) printf("\nERROR: invalid private key!"); SSL_CTX_set_verify_depth (ctx, 2); SSL_CTX_set_read_ahead(ctx, 1); SSL * ssl = SSL_new(ctx); // Create BIO, connect and set to already connected. BIO * bio = BIO_new_dgram(fd, BIO_CLOSE); BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, remote_addr); SSL_set_bio(ssl, bio, bio); int ret = SSL_connect(ssl); if(ret < 0){ handle_ssl_error(ssl, ret); } { struct timeval timeout; timeout.tv_sec = 3; timeout.tv_usec = 0; BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); } ssl_client * cli = alloc0(sizeof(ssl_client)); cli->ssl = ssl; cli->ctx = ctx; return cli; }
BOOL tls_prepare(rdpTls* tls, BIO* underlying, const SSL_METHOD* method, int options, BOOL clientMode) #endif { rdpSettings* settings = tls->settings; tls->ctx = SSL_CTX_new(method); if (!tls->ctx) { WLog_ERR(TAG, "SSL_CTX_new failed"); return FALSE; } SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_options(tls->ctx, options); SSL_CTX_set_read_ahead(tls->ctx, 1); if (settings->AllowedTlsCiphers) { if (!SSL_CTX_set_cipher_list(tls->ctx, settings->AllowedTlsCiphers)) { WLog_ERR(TAG, "SSL_CTX_set_cipher_list %s failed", settings->AllowedTlsCiphers); return FALSE; } } tls->bio = BIO_new_rdp_tls(tls->ctx, clientMode); if (BIO_get_ssl(tls->bio, &tls->ssl) < 0) { WLog_ERR(TAG, "unable to retrieve the SSL of the connection"); return FALSE; } BIO_push(tls->bio, underlying); tls->underlying = underlying; return TRUE; }
int swSSL_server_config(SSL_CTX* ssl_context, swSSL_config *cfg) { #ifndef TLS1_2_VERSION return SW_OK; #endif SSL_CTX_set_read_ahead(ssl_context, 1); #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation SSL_CTX_set_alpn_select_cb(ssl_context, swSSL_alpn_advertised, cfg); #endif #ifdef TLSEXT_TYPE_next_proto_neg SSL_CTX_set_next_protos_advertised_cb(ssl_context, swSSL_npn_advertised, cfg); #endif if (SSL_CTX_set_cipher_list(ssl_context, cfg->ciphers) == 0) { swWarn("SSL_CTX_set_cipher_list(\"%s\") failed", SW_SSL_CIPHER_LIST); return SW_ERR; } if (cfg->prefer_server_ciphers) { SSL_CTX_set_options(ssl_context, SSL_OP_CIPHER_SERVER_PREFERENCE); } #ifndef LIBRESSL_VERSION_NUMBER SSL_CTX_set_tmp_rsa_callback(ssl_context, swSSL_rsa512_key_callback); #endif swSSL_set_dhparam(ssl_context); swSSL_set_ecdh_curve(ssl_context); if (cfg->http) { SSL_CTX_set_session_id_context(ssl_context, (const unsigned char *) "HTTP", strlen("HTTP")); SSL_CTX_set_session_cache_mode(ssl_context, SSL_SESS_CACHE_SERVER); SSL_CTX_sess_set_cache_size(ssl_context, 1); } return SW_OK; }
static int execute_test_large_message(const SSL_METHOD *smeth, const SSL_METHOD *cmeth, int read_ahead) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; int testresult = 0; int i; BIO *certbio = BIO_new_file(cert, "r"); X509 *chaincert = NULL; int certlen; if (certbio == NULL) { printf("Can't load the certificate file\n"); goto end; } chaincert = PEM_read_bio_X509(certbio, NULL, NULL, NULL); BIO_free(certbio); certbio = NULL; if (chaincert == NULL) { printf("Unable to load certificate for chain\n"); goto end; } if (!create_ssl_ctx_pair(smeth, cmeth, &sctx, &cctx, cert, privkey)) { printf("Unable to create SSL_CTX pair\n"); goto end; } if(read_ahead) { /* * Test that read_ahead works correctly when dealing with large * records */ SSL_CTX_set_read_ahead(cctx, 1); } /* * We assume the supplied certificate is big enough so that if we add * NUM_EXTRA_CERTS it will make the overall message large enough. The * default buffer size is requested to be 16k, but due to the way BUF_MEM * works, it ends up allocating a little over 21k (16 * 4/3). So, in this test * we need to have a message larger than that. */ certlen = i2d_X509(chaincert, NULL); OPENSSL_assert((certlen * NUM_EXTRA_CERTS) > ((SSL3_RT_MAX_PLAIN_LENGTH * 4) / 3)); for (i = 0; i < NUM_EXTRA_CERTS; i++) { if (!X509_up_ref(chaincert)) { printf("Unable to up ref cert\n"); goto end; } if (!SSL_CTX_add_extra_chain_cert(sctx, chaincert)) { printf("Unable to add extra chain cert %d\n", i); X509_free(chaincert); goto end; } } if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) { printf("Unable to create SSL objects\n"); goto end; } if (!create_ssl_connection(serverssl, clientssl)) { printf("Unable to create SSL connection\n"); goto end; } /* * Calling SSL_clear() first is not required but this tests that SSL_clear() * doesn't leak (when using enable-crypto-mdebug). */ if (!SSL_clear(serverssl)) { printf("Unexpected failure from SSL_clear()\n"); goto end; } testresult = 1; end: X509_free(chaincert); SSL_free(serverssl); SSL_free(clientssl); SSL_CTX_free(sctx); SSL_CTX_free(cctx); return testresult; }
long SSL_CTX_set_read_ahead_shim(SSL_CTX *ctx, long m) { return SSL_CTX_set_read_ahead(ctx, m); }
int main(int argc, char **argv) { int port = 0; int messagenumber = 5; char local_addr[256]; int c; int mclient = 1; char peer_address[129] = "\0"; int peer_port = PEER_DEFAULT_PORT; char rest_api_separator = ':'; int use_null_cipher=0; set_logfile("stdout"); set_execdir(); set_system_parameters(0); ns_bzero(local_addr, sizeof(local_addr)); while ((c = getopt(argc, argv, "d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:vsyhcxXgtTSAPDNOUHMRIGB")) != -1) { switch (c){ case 'B': random_disconnect = 1; break; case 'G': extra_requests = 1; break; case 'F': STRCPY(cipher_suite,optarg); break; case 'I': no_permissions = 1; break; case 'M': mobility = 1; break; case 'H': shatype = SHATYPE_SHA256; break; case 'E': { char* fn = find_config_file(optarg,1); if(!fn) { fprintf(stderr,"ERROR: file %s not found\n",optarg); exit(-1); } STRCPY(ca_cert_file,fn); } break; case 'O': dos = 1; break; case 'C': rest_api_separator=*optarg; break; case 'D': mandatory_channel_padding = 1; break; case 'N': negative_test = 1; break; case 'R': negative_protocol_test = 1; break; case 'z': RTP_PACKET_INTERVAL = atoi(optarg); break; case 'A': use_short_term = 1; break; case 'u': STRCPY(g_uname, optarg); break; case 'w': STRCPY(g_upwd, optarg); break; case 'g': dont_fragment = 1; break; case 'd': STRCPY(client_ifname, optarg); break; case 'x': default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; break; case 'X': default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4; break; case 'l': clmessage_length = atoi(optarg); break; case 's': do_not_use_channel = 1; break; case 'n': messagenumber = atoi(optarg); break; case 'p': port = atoi(optarg); break; case 'L': STRCPY(local_addr, optarg); break; case 'e': STRCPY(peer_address, optarg); break; case 'r': peer_port = atoi(optarg); break; case 'v': clnet_verbose = TURN_VERBOSE_NORMAL; break; case 'h': hang_on = 1; break; case 'c': no_rtcp = 1; break; case 'm': mclient = atoi(optarg); break; case 'y': c2c = 1; break; case 't': use_tcp = 1; break; case 'P': passive_tcp = 1; /* implies 'T': */ /* no break */ case 'T': relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE; break; case 'U': use_null_cipher = 1; /* implies 'S' */ /* no break */ case 'S': use_secure = 1; break; case 'W': g_use_auth_secret_with_timestamp = 1; STRCPY(g_auth_secret,optarg); break; case 'i': { char* fn = find_config_file(optarg,1); if(!fn) { fprintf(stderr,"ERROR: file %s not found\n",optarg); exit(-1); } STRCPY(cert_file,fn); free(fn); } break; case 'k': { char* fn = find_config_file(optarg,1); if(!fn) { fprintf(stderr,"ERROR: file %s not found\n",optarg); exit(-1); } STRCPY(pkey_file,fn); free(fn); } break; default: fprintf(stderr, "%s\n", Usage); exit(1); } } if(g_use_auth_secret_with_timestamp) { if(use_short_term) { fprintf(stderr,"ERROR: You cannot use authentication secret (REST API) with short-term credentials mechanism.\n"); exit(-1); } { char new_uname[1025]; const unsigned long exp_time = 3600 * 24; /* one day */ if(g_uname[0]) { snprintf(new_uname,sizeof(new_uname),"%lu%c%s",(unsigned long)time(NULL) + exp_time,rest_api_separator, (char*)g_uname); } else { snprintf(new_uname,sizeof(new_uname),"%lu", (unsigned long)time(NULL) + exp_time); } STRCPY(g_uname,new_uname); } { u08bits hmac[MAXSHASIZE]; unsigned int hmac_len; switch(shatype) { case SHATYPE_SHA256: hmac_len = SHA256SIZEBYTES; break; default: hmac_len = SHA1SIZEBYTES; }; hmac[0]=0; if(stun_calculate_hmac(g_uname, strlen((char*)g_uname), (u08bits*)g_auth_secret, strlen(g_auth_secret), hmac, &hmac_len, shatype)>=0) { size_t pwd_length = 0; char *pwd = base64_encode(hmac,hmac_len,&pwd_length); if(pwd) { if(pwd_length>0) { ns_bcopy(pwd,g_upwd,pwd_length); g_upwd[pwd_length]=0; } } free(pwd); } } } if(is_TCP_relay()) { dont_fragment = 0; no_rtcp = 1; c2c = 1; use_tcp = 1; do_not_use_channel = 1; } if(port == 0) { if(use_secure) port = DEFAULT_STUN_TLS_PORT; else port = DEFAULT_STUN_PORT; } if (clmessage_length < (int) sizeof(message_info)) clmessage_length = (int) sizeof(message_info); const int max_header = 100; if(clmessage_length > (int)(STUN_BUFFER_SIZE-max_header)) { fprintf(stderr,"Message length was corrected to %d\n",(STUN_BUFFER_SIZE-max_header)); clmessage_length = (int)(STUN_BUFFER_SIZE-max_header); } if (optind >= argc) { fprintf(stderr, "%s\n", Usage); exit(-1); } if (!c2c) { if (make_ioa_addr((const u08bits*) peer_address, peer_port, &peer_addr) < 0) return -1; if(peer_addr.ss.sa_family == AF_INET6) default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6; } /* SSL Init ==>> */ if(use_secure) { SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); const char *csuite = "ALL"; //"AES256-SHA" "DH" if(use_null_cipher) csuite = "eNULL"; else if(cipher_suite[0]) csuite=cipher_suite; if(use_tcp) { root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv3_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; #if defined(SSL_TXT_TLSV1_1) root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; #if defined(SSL_TXT_TLSV1_2) root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; #endif #endif } else { #if defined(TURN_NO_DTLS) fprintf(stderr,"ERROR: DTLS is not supported.\n"); exit(-1); #else if(OPENSSL_VERSION_NUMBER < 0x10000000L) { TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: OpenSSL version is rather old, DTLS may not be working correctly.\n"); } root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method()); SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite); root_tls_ctx_num++; #endif } int sslind = 0; for(sslind = 0; sslind<root_tls_ctx_num; sslind++) { if(cert_file[0]) { if (!SSL_CTX_use_certificate_chain_file(root_tls_ctx[sslind], cert_file)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no certificate found!\n"); exit(-1); } } if (!SSL_CTX_use_PrivateKey_file(root_tls_ctx[sslind], pkey_file, SSL_FILETYPE_PEM)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no private key found!\n"); exit(-1); } if(cert_file[0]) { if (!SSL_CTX_check_private_key(root_tls_ctx[sslind])) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: invalid private key!\n"); exit(-1); } } if (ca_cert_file[0]) { if (!SSL_CTX_load_verify_locations(root_tls_ctx[sslind], ca_cert_file, NULL )) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: cannot load CA from file: %s\n", ca_cert_file); } /* Set to require peer (client) certificate verification */ SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_PEER, NULL ); /* Set the verification depth to 9 */ SSL_CTX_set_verify_depth(root_tls_ctx[sslind], 9); } else { SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_NONE, NULL ); } if(!use_tcp) SSL_CTX_set_read_ahead(root_tls_ctx[sslind], 1); } } start_mclient(argv[optind], port, client_ifname, local_addr, messagenumber, mclient); return 0; }
int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) { STACK_OF(SSL_CIPHER) *ciphers; method_const SSL_METHOD *dtls_method; SSL_SESSION *dtls_session; SSL *dtls_ssl; BIO *dtls_bio; int dtlsver = DTLS1_BAD_VER; const char *cipher = vpninfo->dtls_cipher; #ifdef HAVE_DTLS12 if (!strcmp(cipher, "OC-DTLS1_2-AES128-GCM")) { dtlsver = DTLS1_2_VERSION; cipher = "AES128-GCM-SHA256"; } else if (!strcmp(cipher, "OC-DTLS1_2-AES256-GCM")) { dtlsver = DTLS1_2_VERSION; cipher = "AES256-GCM-SHA384"; #ifndef OPENSSL_NO_PSK } else if (!strcmp(cipher, "PSK-NEGOTIATE")) { dtlsver = 0; /* Let it negotiate */ #endif } #endif if (!vpninfo->dtls_ctx) { #ifdef HAVE_DTLS12 dtls_method = DTLS_client_method(); #endif #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) if (dtlsver == DTLS1_BAD_VER) dtls_method = DTLSv1_client_method(); #ifdef HAVE_DTLS12 else if (dtlsver == DTLS1_2_VERSION) dtls_method = DTLSv1_2_client_method(); #endif #endif vpninfo->dtls_ctx = SSL_CTX_new(dtls_method); if (!vpninfo->dtls_ctx) { vpn_progress(vpninfo, PRG_ERR, _("Initialise DTLSv1 CTX failed\n")); openconnect_report_ssl_errors(vpninfo); vpninfo->dtls_attempt_period = 0; return -EINVAL; } if (dtlsver) { #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) if (dtlsver == DTLS1_BAD_VER) SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_CISCO_ANYCONNECT); #else if (!SSL_CTX_set_min_proto_version(vpninfo->dtls_ctx, dtlsver) || !SSL_CTX_set_max_proto_version(vpninfo->dtls_ctx, dtlsver)) { vpn_progress(vpninfo, PRG_ERR, _("Set DTLS CTX version failed\n")); openconnect_report_ssl_errors(vpninfo); SSL_CTX_free(vpninfo->dtls_ctx); vpninfo->dtls_ctx = NULL; vpninfo->dtls_attempt_period = 0; return -EINVAL; } #endif #if defined (HAVE_DTLS12) && !defined(OPENSSL_NO_PSK) } else { SSL_CTX_set_psk_client_callback(vpninfo->dtls_ctx, psk_callback); /* For PSK we override the DTLS master secret with one derived * from the HTTPS session. */ if (!SSL_export_keying_material(vpninfo->https_ssl, vpninfo->dtls_secret, PSK_KEY_SIZE, PSK_LABEL, PSK_LABEL_SIZE, NULL, 0, 0)) { vpn_progress(vpninfo, PRG_ERR, _("Failed to generate DTLS key\n")); openconnect_report_ssl_errors(vpninfo); SSL_CTX_free(vpninfo->dtls_ctx); vpninfo->dtls_ctx = NULL; vpninfo->dtls_attempt_period = 0; return -EINVAL; } SSL_CTX_add_client_custom_ext(vpninfo->dtls_ctx, DTLS_APP_ID_EXT, pskident_add, pskident_free, vpninfo, pskident_parse, vpninfo); /* For SSL_CTX_set_cipher_list() */ cipher = "PSK"; #endif } /* If we don't readahead, then we do short reads and throw away the tail of data packets. */ SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1); if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, cipher)) { vpn_progress(vpninfo, PRG_ERR, _("Set DTLS cipher list failed\n")); SSL_CTX_free(vpninfo->dtls_ctx); vpninfo->dtls_ctx = NULL; vpninfo->dtls_attempt_period = 0; return -EINVAL; } } dtls_ssl = SSL_new(vpninfo->dtls_ctx); SSL_set_connect_state(dtls_ssl); SSL_set_app_data(dtls_ssl, vpninfo); if (dtlsver) { ciphers = SSL_get_ciphers(dtls_ssl); if (dtlsver != 0 && sk_SSL_CIPHER_num(ciphers) != 1) { vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n")); SSL_CTX_free(vpninfo->dtls_ctx); SSL_free(dtls_ssl); vpninfo->dtls_ctx = NULL; vpninfo->dtls_attempt_period = 0; return -EINVAL; } /* We're going to "resume" a session which never existed. Fake it... */ dtls_session = generate_dtls_session(vpninfo, dtlsver, sk_SSL_CIPHER_value(ciphers, 0)); if (!dtls_session) { SSL_CTX_free(vpninfo->dtls_ctx); SSL_free(dtls_ssl); vpninfo->dtls_ctx = NULL; vpninfo->dtls_attempt_period = 0; return -EINVAL; } /* Add the generated session to the SSL */ if (!SSL_set_session(dtls_ssl, dtls_session)) { vpn_progress(vpninfo, PRG_ERR, _("SSL_set_session() failed with old protocol version 0x%x\n" "Are you using a version of OpenSSL older than 0.9.8m?\n" "See http://rt.openssl.org/Ticket/Display.html?id=1751\n" "Use the --no-dtls command line option to avoid this message\n"), DTLS1_BAD_VER); SSL_CTX_free(vpninfo->dtls_ctx); SSL_free(dtls_ssl); vpninfo->dtls_ctx = NULL; vpninfo->dtls_attempt_period = 0; SSL_SESSION_free(dtls_session); return -EINVAL; } /* We don't need our own refcount on it any more */ SSL_SESSION_free(dtls_session); } dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE); /* Set non-blocking */ BIO_set_nbio(dtls_bio, 1); SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio); vpninfo->dtls_ssl = dtls_ssl; return 0; }
void DtlsTransport::CreateSSL_CTX() { MS_TRACE(); std::string ssl_srtp_profiles; EC_KEY* ecdh = nullptr; int ret; /* Set the global DTLS context. */ // - Both DTLS 1.0 and 1.2 (requires OpenSSL >= 1.1.0). #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) DtlsTransport::sslCtx = SSL_CTX_new(DTLS_method()); // - Just DTLS 1.0 (requires OpenSSL >= 1.0.1). #elif (OPENSSL_VERSION_NUMBER >= 0x10001000L) DtlsTransport::sslCtx = SSL_CTX_new(DTLSv1_method()); #else #error "too old OpenSSL version" #endif if (!DtlsTransport::sslCtx) { LOG_OPENSSL_ERROR("SSL_CTX_new() failed"); goto error; } ret = SSL_CTX_use_certificate(DtlsTransport::sslCtx, DtlsTransport::certificate); if (ret == 0) { LOG_OPENSSL_ERROR("SSL_CTX_use_certificate() failed"); goto error; } ret = SSL_CTX_use_PrivateKey(DtlsTransport::sslCtx, DtlsTransport::privateKey); if (ret == 0) { LOG_OPENSSL_ERROR("SSL_CTX_use_PrivateKey() failed"); goto error; } ret = SSL_CTX_check_private_key(DtlsTransport::sslCtx); if (ret == 0) { LOG_OPENSSL_ERROR("SSL_CTX_check_private_key() failed"); goto error; } // Set options. SSL_CTX_set_options(DtlsTransport::sslCtx, SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_TICKET | SSL_OP_SINGLE_ECDH_USE); // Don't use sessions cache. SSL_CTX_set_session_cache_mode(DtlsTransport::sslCtx, SSL_SESS_CACHE_OFF); // Read always as much into the buffer as possible. // NOTE: This is the default for DTLS, but a bug in non latest OpenSSL // versions makes this call required. SSL_CTX_set_read_ahead(DtlsTransport::sslCtx, 1); SSL_CTX_set_verify_depth(DtlsTransport::sslCtx, 4); // Require certificate from peer. SSL_CTX_set_verify(DtlsTransport::sslCtx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, on_ssl_certificate_verify); // Set SSL info callback. SSL_CTX_set_info_callback(DtlsTransport::sslCtx, on_ssl_info); // Set ciphers. ret = SSL_CTX_set_cipher_list(DtlsTransport::sslCtx, "ALL:!ADH:!LOW:!EXP:!MD5:!aNULL:!eNULL:@STRENGTH"); if (ret == 0) { LOG_OPENSSL_ERROR("SSL_CTX_set_cipher_list() failed"); goto error; } // Enable ECDH ciphers. // DOC: http://en.wikibooks.org/wiki/OpenSSL/Diffie-Hellman_parameters // NOTE: https://code.google.com/p/chromium/issues/detail?id=406458 // For OpenSSL >= 1.0.2: #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) SSL_CTX_set_ecdh_auto(DtlsTransport::sslCtx, 1); #else ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (!ecdh) { LOG_OPENSSL_ERROR("EC_KEY_new_by_curve_name() failed"); goto error; } if (SSL_CTX_set_tmp_ecdh(DtlsTransport::sslCtx, ecdh) != 1) { LOG_OPENSSL_ERROR("SSL_CTX_set_tmp_ecdh() failed"); goto error; } EC_KEY_free(ecdh); ecdh = nullptr; #endif // Set the "use_srtp" DTLS extension. for (auto it = DtlsTransport::srtpProfiles.begin(); it != DtlsTransport::srtpProfiles.end(); ++it) { if (it != DtlsTransport::srtpProfiles.begin()) ssl_srtp_profiles += ":"; SrtpProfileMapEntry* profile_entry = &(*it); ssl_srtp_profiles += profile_entry->name; } MS_DEBUG("setting SRTP profiles for DTLS: %s", ssl_srtp_profiles.c_str()); // NOTE: This function returns 0 on success. ret = SSL_CTX_set_tlsext_use_srtp(DtlsTransport::sslCtx, ssl_srtp_profiles.c_str()); if (ret != 0) { MS_ERROR("SSL_CTX_set_tlsext_use_srtp() failed when entering '%s'", ssl_srtp_profiles.c_str()); LOG_OPENSSL_ERROR("SSL_CTX_set_tlsext_use_srtp() failed"); goto error; } return; error: if (DtlsTransport::sslCtx) { SSL_CTX_free(DtlsTransport::sslCtx); DtlsTransport::sslCtx = nullptr; } if (ecdh) EC_KEY_free(ecdh); MS_THROW_ERROR("SSL context creation failed"); }
static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) { SSL_CTX *ctx = NULL; unsigned long error; switch (type) { #ifdef RADPROT_TLS case RAD_TLS: ctx = SSL_CTX_new(TLSv1_method()); break; #endif #ifdef RADPROT_DTLS case RAD_DTLS: ctx = SSL_CTX_new(DTLSv1_method()); SSL_CTX_set_read_ahead(ctx, 1); break; #endif } if (!ctx) { debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name); while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); return NULL; } #ifdef DEBUG SSL_CTX_set_info_callback(ctx, ssl_info_callback); #endif if (conf->certkeypwd) { SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->certkeypwd); SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb); } if (conf->certfile || conf->certkeyfile) { if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile) || !SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) || !SSL_CTX_check_private_key(ctx)) { while ((error = ERR_get_error())) debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL)); debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS (certfile issues) in TLS context %s", conf->name); SSL_CTX_free(ctx); return NULL; } } if (conf->policyoids) { if (!conf->vpm) { conf->vpm = createverifyparams(conf->policyoids); if (!conf->vpm) { debug(DBG_ERR, "tlscreatectx: Failed to add policyOIDs in TLS context %s", conf->name); SSL_CTX_free(ctx); return NULL; } } } if (conf->cacertfile != NULL || conf->cacertpath != NULL) if (!tlsaddcacrl(ctx, conf)) { if (conf->vpm) { X509_VERIFY_PARAM_free(conf->vpm); conf->vpm = NULL; } SSL_CTX_free(ctx); return NULL; } debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name); return ctx; }
/* DTLS-SRTP initialization */ gint janus_dtls_srtp_init(const char* server_pem, const char* server_key) { /* FIXME First of all make OpenSSL thread safe (see note above on issue #316) */ janus_dtls_locks = g_malloc0(sizeof(*janus_dtls_locks) * CRYPTO_num_locks()); int l=0; for(l = 0; l < CRYPTO_num_locks(); l++) { janus_mutex_init(&janus_dtls_locks[l]); } CRYPTO_THREADID_set_callback(janus_dtls_cb_openssl_threadid); CRYPTO_set_locking_callback(janus_dtls_cb_openssl_lock); /* Go on and create the DTLS context */ ssl_ctx = SSL_CTX_new(DTLSv1_method()); if(!ssl_ctx) { JANUS_LOG(LOG_FATAL, "Ops, error creating DTLS context?\n"); return -1; } SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, janus_dtls_verify_callback); SSL_CTX_set_tlsext_use_srtp(ssl_ctx, "SRTP_AES128_CM_SHA1_80"); /* FIXME Should we support something else as well? */ if (!server_pem && !server_key) { JANUS_LOG(LOG_WARN, "No cert/key specified, autogenerating some...\n"); if (janus_dtls_generate_keys(&ssl_cert, &ssl_key) != 0) { JANUS_LOG(LOG_FATAL, "Error generating DTLS key/certificate\n"); return -2; } } else if (!server_pem || !server_key) { JANUS_LOG(LOG_FATAL, "DTLS certificate and key must be specified\n"); return -2; } else if (janus_dtls_load_keys(server_pem, server_key, &ssl_cert, &ssl_key) != 0) { return -3; } if(!SSL_CTX_use_certificate(ssl_ctx, ssl_cert)) { JANUS_LOG(LOG_FATAL, "Certificate error (%s)\n", ERR_reason_error_string(ERR_get_error())); return -4; } if(!SSL_CTX_use_PrivateKey(ssl_ctx, ssl_key)) { JANUS_LOG(LOG_FATAL, "Certificate key error (%s)\n", ERR_reason_error_string(ERR_get_error())); return -5; } if(!SSL_CTX_check_private_key(ssl_ctx)) { JANUS_LOG(LOG_FATAL, "Certificate check error (%s)\n", ERR_reason_error_string(ERR_get_error())); return -6; } SSL_CTX_set_read_ahead(ssl_ctx,1); unsigned int size; unsigned char fingerprint[EVP_MAX_MD_SIZE]; if(X509_digest(ssl_cert, EVP_sha256(), (unsigned char *)fingerprint, &size) == 0) { JANUS_LOG(LOG_FATAL, "Error converting X509 structure (%s)\n", ERR_reason_error_string(ERR_get_error())); return -7; } char *lfp = (char *)&local_fingerprint; unsigned int i = 0; for(i = 0; i < size; i++) { g_snprintf(lfp, 4, "%.2X:", fingerprint[i]); lfp += 3; } *(lfp-1) = 0; JANUS_LOG(LOG_INFO, "Fingerprint of our certificate: %s\n", local_fingerprint); SSL_CTX_set_cipher_list(ssl_ctx, DTLS_CIPHERS); /* Initialize libsrtp */ if(srtp_init() != err_status_ok) { JANUS_LOG(LOG_FATAL, "Ops, error setting up libsrtp?\n"); return 5; } return 0; }
SSL_CTX *sslctx_client_setup (const SSL_METHOD * method, _netsnmpTLSBaseData * tlsbase) { netsnmp_cert *id_cert, *peer_cert; SSL_CTX *the_ctx; /*********************************************************************** * Set up the client context */ the_ctx = SSL_CTX_new (NETSNMP_REMOVE_CONST (SSL_METHOD *, method)); if (!the_ctx) { snmp_log (LOG_ERR, "ack: %p\n", the_ctx); LOGANDDIE ("can't create a new context"); } SSL_CTX_set_read_ahead (the_ctx, 1); /* Required for DTLS */ SSL_CTX_set_verify (the_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, &verify_callback); if (tlsbase->our_identity) { DEBUGMSGTL (("sslctx_client", "looking for local id: %s\n", tlsbase->our_identity)); id_cert = netsnmp_cert_find (NS_CERT_IDENTITY, NS_CERTKEY_MULTIPLE, tlsbase->our_identity); } else { DEBUGMSGTL (("sslctx_client", "looking for default local id: %s\n", tlsbase->our_identity)); id_cert = netsnmp_cert_find (NS_CERT_IDENTITY, NS_CERTKEY_DEFAULT, NULL); } if (!id_cert) LOGANDDIE ("error finding client identity keys"); if (!id_cert->key || !id_cert->key->okey) LOGANDDIE ("failed to load private key"); DEBUGMSGTL (("sslctx_client", "using public key: %s\n", id_cert->info.filename)); DEBUGMSGTL (("sslctx_client", "using private key: %s\n", id_cert->key->info.filename)); if (SSL_CTX_use_certificate (the_ctx, id_cert->ocert) <= 0) LOGANDDIE ("failed to set the certificate to use"); if (SSL_CTX_use_PrivateKey (the_ctx, id_cert->key->okey) <= 0) LOGANDDIE ("failed to set the private key to use"); if (!SSL_CTX_check_private_key (the_ctx)) LOGANDDIE ("public and private keys incompatible"); if (tlsbase->their_identity) peer_cert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_MULTIPLE, tlsbase->their_identity); else peer_cert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_DEFAULT, NULL); if (peer_cert) { DEBUGMSGTL (("sslctx_client", "server's expected public key: %s\n", peer_cert ? peer_cert->info.filename : "none")); /* Trust the expected certificate */ if (netsnmp_cert_trust_ca (the_ctx, peer_cert) != SNMPERR_SUCCESS) LOGANDDIE ("failed to set verify paths"); } /* trust a certificate (possibly a CA) aspecifically passed in */ if (tlsbase->trust_cert) { if (!_trust_this_cert (the_ctx, tlsbase->trust_cert)) return 0; } return _sslctx_common_setup (the_ctx, tlsbase); }
int s_client_main(int argc, char **argv) { unsigned int off = 0, clr = 0; SSL *con = NULL; int s, k, width, state = 0, af = AF_UNSPEC; char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL; int cbuf_len, cbuf_off; int sbuf_len, sbuf_off; fd_set readfds, writefds; char *port = PORT_STR; int full_log = 1; char *host = SSL_HOST_NAME; char *cert_file = NULL, *key_file = NULL; int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; char *passarg = NULL, *pass = NULL; X509 *cert = NULL; EVP_PKEY *key = NULL; char *CApath = NULL, *CAfile = NULL, *cipher = NULL; int reconnect = 0, badop = 0, verify = SSL_VERIFY_NONE, bugs = 0; int crlf = 0; int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; SSL_CTX *ctx = NULL; int ret = 1, in_init = 1, i, nbio_test = 0; int starttls_proto = PROTO_OFF; int prexit = 0; X509_VERIFY_PARAM *vpm = NULL; int badarg = 0; const SSL_METHOD *meth = NULL; int socket_type = SOCK_STREAM; BIO *sbio; int mbuf_len = 0; struct timeval timeout, *timeoutp; const char *errstr = NULL; #ifndef OPENSSL_NO_ENGINE char *engine_id = NULL; char *ssl_client_engine_id = NULL; ENGINE *ssl_client_engine = NULL; #endif ENGINE *e = NULL; #ifndef OPENSSL_NO_TLSEXT char *servername = NULL; tlsextctx tlsextcbp = {NULL, 0}; #ifndef OPENSSL_NO_NEXTPROTONEG const char *next_proto_neg_in = NULL; #endif #endif char *sess_in = NULL; char *sess_out = NULL; struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0; long socket_mtu = 0; meth = SSLv23_client_method(); c_Pause = 0; c_quiet = 0; c_ign_eof = 0; c_debug = 0; c_msg = 0; c_showcerts = 0; if (((cbuf = malloc(BUFSIZZ)) == NULL) || ((sbuf = malloc(BUFSIZZ)) == NULL) || ((mbuf = malloc(BUFSIZZ + 1)) == NULL)) { /* NUL byte */ BIO_printf(bio_err, "out of memory\n"); goto end; } verify_depth = 0; verify_error = X509_V_OK; c_nbio = 0; argc--; argv++; while (argc >= 1) { if (strcmp(*argv, "-host") == 0) { if (--argc < 1) goto bad; host = *(++argv); } else if (strcmp(*argv, "-port") == 0) { if (--argc < 1) goto bad; port = *(++argv); if (port == NULL || *port == '\0') goto bad; } else if (strcmp(*argv, "-connect") == 0) { if (--argc < 1) goto bad; if (!extract_host_port(*(++argv), &host, NULL, &port)) goto bad; } else if (strcmp(*argv, "-verify") == 0) { verify = SSL_VERIFY_PEER; if (--argc < 1) goto bad; verify_depth = strtonum(*(++argv), 0, INT_MAX, &errstr); if (errstr) goto bad; BIO_printf(bio_err, "verify depth is %d\n", verify_depth); } else if (strcmp(*argv, "-cert") == 0) { if (--argc < 1) goto bad; cert_file = *(++argv); } else if (strcmp(*argv, "-sess_out") == 0) { if (--argc < 1) goto bad; sess_out = *(++argv); } else if (strcmp(*argv, "-sess_in") == 0) { if (--argc < 1) goto bad; sess_in = *(++argv); } else if (strcmp(*argv, "-certform") == 0) { if (--argc < 1) goto bad; cert_format = str2fmt(*(++argv)); } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { if (badarg) goto bad; continue; } else if (strcmp(*argv, "-verify_return_error") == 0) verify_return_error = 1; else if (strcmp(*argv, "-prexit") == 0) prexit = 1; else if (strcmp(*argv, "-crlf") == 0) crlf = 1; else if (strcmp(*argv, "-quiet") == 0) { c_quiet = 1; c_ign_eof = 1; } else if (strcmp(*argv, "-ign_eof") == 0) c_ign_eof = 1; else if (strcmp(*argv, "-no_ign_eof") == 0) c_ign_eof = 0; else if (strcmp(*argv, "-pause") == 0) c_Pause = 1; else if (strcmp(*argv, "-debug") == 0) c_debug = 1; #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv, "-tlsextdebug") == 0) c_tlsextdebug = 1; else if (strcmp(*argv, "-status") == 0) c_status_req = 1; #endif else if (strcmp(*argv, "-msg") == 0) c_msg = 1; else if (strcmp(*argv, "-showcerts") == 0) c_showcerts = 1; else if (strcmp(*argv, "-nbio_test") == 0) nbio_test = 1; else if (strcmp(*argv, "-state") == 0) state = 1; else if (strcmp(*argv, "-ssl3") == 0) meth = SSLv3_client_method(); else if (strcmp(*argv, "-tls1_2") == 0) meth = TLSv1_2_client_method(); else if (strcmp(*argv, "-tls1_1") == 0) meth = TLSv1_1_client_method(); else if (strcmp(*argv, "-tls1") == 0) meth = TLSv1_client_method(); #ifndef OPENSSL_NO_DTLS1 else if (strcmp(*argv, "-dtls1") == 0) { meth = DTLSv1_client_method(); socket_type = SOCK_DGRAM; } else if (strcmp(*argv, "-timeout") == 0) enable_timeouts = 1; else if (strcmp(*argv, "-mtu") == 0) { if (--argc < 1) goto bad; socket_mtu = strtonum(*(++argv), 0, LONG_MAX, &errstr); if (errstr) goto bad; } #endif else if (strcmp(*argv, "-bugs") == 0) bugs = 1; else if (strcmp(*argv, "-keyform") == 0) { if (--argc < 1) goto bad; key_format = str2fmt(*(++argv)); } else if (strcmp(*argv, "-pass") == 0) { if (--argc < 1) goto bad; passarg = *(++argv); } else if (strcmp(*argv, "-key") == 0) { if (--argc < 1) goto bad; key_file = *(++argv); } else if (strcmp(*argv, "-reconnect") == 0) { reconnect = 5; } else if (strcmp(*argv, "-CApath") == 0) { if (--argc < 1) goto bad; CApath = *(++argv); } else if (strcmp(*argv, "-CAfile") == 0) { if (--argc < 1) goto bad; CAfile = *(++argv); } else if (strcmp(*argv, "-no_tls1_2") == 0) off |= SSL_OP_NO_TLSv1_2; else if (strcmp(*argv, "-no_tls1_1") == 0) off |= SSL_OP_NO_TLSv1_1; else if (strcmp(*argv, "-no_tls1") == 0) off |= SSL_OP_NO_TLSv1; else if (strcmp(*argv, "-no_ssl3") == 0) off |= SSL_OP_NO_SSLv3; else if (strcmp(*argv, "-no_ssl2") == 0) off |= SSL_OP_NO_SSLv2; else if (strcmp(*argv, "-no_comp") == 0) { off |= SSL_OP_NO_COMPRESSION; } #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv, "-no_ticket") == 0) { off |= SSL_OP_NO_TICKET; } #ifndef OPENSSL_NO_NEXTPROTONEG else if (strcmp(*argv, "-nextprotoneg") == 0) { if (--argc < 1) goto bad; next_proto_neg_in = *(++argv); } #endif #endif else if (strcmp(*argv, "-serverpref") == 0) off |= SSL_OP_CIPHER_SERVER_PREFERENCE; else if (strcmp(*argv, "-legacy_renegotiation") == 0) ; /* no-op */ else if (strcmp(*argv, "-legacy_server_connect") == 0) { off |= SSL_OP_LEGACY_SERVER_CONNECT; } else if (strcmp(*argv, "-no_legacy_server_connect") == 0) { clr |= SSL_OP_LEGACY_SERVER_CONNECT; } else if (strcmp(*argv, "-cipher") == 0) { if (--argc < 1) goto bad; cipher = *(++argv); } else if (strcmp(*argv, "-nbio") == 0) { c_nbio = 1; } else if (strcmp(*argv, "-starttls") == 0) { if (--argc < 1) goto bad; ++argv; if (strcmp(*argv, "smtp") == 0) starttls_proto = PROTO_SMTP; else if (strcmp(*argv, "lmtp") == 0) starttls_proto = PROTO_LMTP; else if (strcmp(*argv, "pop3") == 0) starttls_proto = PROTO_POP3; else if (strcmp(*argv, "imap") == 0) starttls_proto = PROTO_IMAP; else if (strcmp(*argv, "ftp") == 0) starttls_proto = PROTO_FTP; else if (strcmp(*argv, "xmpp") == 0) starttls_proto = PROTO_XMPP; else goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv, "-engine") == 0) { if (--argc < 1) goto bad; engine_id = *(++argv); } else if (strcmp(*argv, "-ssl_client_engine") == 0) { if (--argc < 1) goto bad; ssl_client_engine_id = *(++argv); } #endif else if (strcmp(*argv, "-4") == 0) { af = AF_INET; } else if (strcmp(*argv, "-6") == 0) { af = AF_INET6; } #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv, "-servername") == 0) { if (--argc < 1) goto bad; servername = *(++argv); /* meth=TLSv1_client_method(); */ } #endif #ifndef OPENSSL_NO_SRTP else if (strcmp(*argv, "-use_srtp") == 0) { if (--argc < 1) goto bad; srtp_profiles = *(++argv); } #endif else if (strcmp(*argv, "-keymatexport") == 0) { if (--argc < 1) goto bad; keymatexportlabel = *(++argv); } else if (strcmp(*argv, "-keymatexportlen") == 0) { const char *errstr; if (--argc < 1) goto bad; keymatexportlen = strtonum(*(++argv), 1, INT_MAX, &errstr); if (errstr) goto bad; } else { BIO_printf(bio_err, "unknown option %s\n", *argv); badop = 1; break; } argc--; argv++; } if (badop) { bad: if (errstr) BIO_printf(bio_err, "invalid argument %s: %s\n", *argv, errstr); else sc_usage(); goto end; } #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) next_proto.status = -1; if (next_proto_neg_in) { next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in); if (next_proto.data == NULL) { BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n"); goto end; } } else next_proto.data = NULL; #endif #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine_id, 1); if (ssl_client_engine_id) { ssl_client_engine = ENGINE_by_id(ssl_client_engine_id); if (!ssl_client_engine) { BIO_printf(bio_err, "Error getting client auth engine\n"); goto end; } } #endif if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (key_file == NULL) key_file = cert_file; if (key_file) { key = load_key(bio_err, key_file, key_format, 0, pass, e, "client certificate private key file"); if (!key) { ERR_print_errors(bio_err); goto end; } } if (cert_file) { cert = load_cert(bio_err, cert_file, cert_format, NULL, e, "client certificate file"); if (!cert) { ERR_print_errors(bio_err); goto end; } } if (bio_c_out == NULL) { if (c_quiet && !c_debug && !c_msg) { bio_c_out = BIO_new(BIO_s_null()); } else { if (bio_c_out == NULL) bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE); } } ctx = SSL_CTX_new(meth); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; } if (vpm) SSL_CTX_set1_param(ctx, vpm); #ifndef OPENSSL_NO_ENGINE if (ssl_client_engine) { if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) { BIO_puts(bio_err, "Error setting client auth engine\n"); ERR_print_errors(bio_err); ENGINE_free(ssl_client_engine); goto end; } ENGINE_free(ssl_client_engine); } #endif #ifndef OPENSSL_NO_SRTP if (srtp_profiles != NULL) SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles); #endif if (bugs) SSL_CTX_set_options(ctx, SSL_OP_ALL | off); else SSL_CTX_set_options(ctx, off); if (clr) SSL_CTX_clear_options(ctx, clr); /* * DTLS: partial reads end up discarding unread UDP bytes :-( Setting * read ahead solves this problem. */ if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) if (next_proto.data) SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto); #endif if (state) SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); if (cipher != NULL) if (!SSL_CTX_set_cipher_list(ctx, cipher)) { BIO_printf(bio_err, "error setting cipher list\n"); ERR_print_errors(bio_err); goto end; } SSL_CTX_set_verify(ctx, verify, verify_callback); if (!set_cert_key_stuff(ctx, cert, key)) goto end; if ((!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { /* * BIO_printf(bio_err,"error setting default verify * locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } #ifndef OPENSSL_NO_TLSEXT if (servername != NULL) { tlsextcbp.biodebug = bio_err; SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); } #endif con = SSL_new(ctx); if (sess_in) { SSL_SESSION *sess; BIO *stmp = BIO_new_file(sess_in, "r"); if (!stmp) { BIO_printf(bio_err, "Can't open session file %s\n", sess_in); ERR_print_errors(bio_err); goto end; } sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); BIO_free(stmp); if (!sess) { BIO_printf(bio_err, "Can't open session file %s\n", sess_in); ERR_print_errors(bio_err); goto end; } SSL_set_session(con, sess); SSL_SESSION_free(sess); } #ifndef OPENSSL_NO_TLSEXT if (servername != NULL) { if (!SSL_set_tlsext_host_name(con, servername)) { BIO_printf(bio_err, "Unable to set TLS servername extension.\n"); ERR_print_errors(bio_err); goto end; } } #endif /* SSL_set_cipher_list(con,"RC4-MD5"); */ re_start: if (init_client(&s, host, port, socket_type, af) == 0) { BIO_printf(bio_err, "connect:errno=%d\n", errno); shutdown(s, SHUT_RD); close(s); goto end; } BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); if (c_nbio) { unsigned long l = 1; BIO_printf(bio_c_out, "turning on non blocking io\n"); if (BIO_socket_ioctl(s, FIONBIO, &l) < 0) { ERR_print_errors(bio_err); goto end; } } if (c_Pause & 0x01) SSL_set_debug(con, 1); if (SSL_version(con) == DTLS1_VERSION) { sbio = BIO_new_dgram(s, BIO_NOCLOSE); if (getsockname(s, &peer, (void *) &peerlen) < 0) { BIO_printf(bio_err, "getsockname:errno=%d\n", errno); shutdown(s, SHUT_RD); close(s); goto end; } (void) BIO_ctrl_set_connected(sbio, 1, &peer); if (enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); timeout.tv_sec = 0; timeout.tv_usec = DGRAM_SND_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } if (socket_mtu > 28) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); SSL_set_mtu(con, socket_mtu - 28); } else /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); } else sbio = BIO_new_socket(s, BIO_NOCLOSE); if (nbio_test) { BIO *test; test = BIO_new(BIO_f_nbio_test()); sbio = BIO_push(test, sbio); } if (c_debug) { SSL_set_debug(con, 1); BIO_set_callback(sbio, bio_dump_callback); BIO_set_callback_arg(sbio, (char *) bio_c_out); } if (c_msg) { SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_c_out); } #ifndef OPENSSL_NO_TLSEXT if (c_tlsextdebug) { SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_c_out); } if (c_status_req) { SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp); SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb); SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out); } #endif SSL_set_bio(con, sbio, sbio); SSL_set_connect_state(con); /* ok, lets connect */ width = SSL_get_fd(con) + 1; read_tty = 1; write_tty = 0; tty_on = 0; read_ssl = 1; write_ssl = 1; cbuf_len = 0; cbuf_off = 0; sbuf_len = 0; sbuf_off = 0; /* This is an ugly hack that does a lot of assumptions */ /* * We do have to handle multi-line responses which may come in a * single packet or not. We therefore have to use BIO_gets() which * does need a buffering BIO. So during the initial chitchat we do * push a buffering BIO into the chain that is removed again later on * to not disturb the rest of the s_client operation. */ if (starttls_proto == PROTO_SMTP || starttls_proto == PROTO_LMTP) { int foundit = 0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from SMTP */ do { mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); } while (mbuf_len > 3 && mbuf[3] == '-'); /* STARTTLS command requires EHLO... */ BIO_printf(fbio, "%cHLO openssl.client.net\r\n", starttls_proto == PROTO_SMTP ? 'E' : 'L'); (void) BIO_flush(fbio); /* wait for multi-line response to end EHLO SMTP response */ do { mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); if (strstr(mbuf, "STARTTLS")) foundit = 1; } while (mbuf_len > 3 && mbuf[3] == '-'); (void) BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found starttls in server response," " try anyway...\n"); BIO_printf(sbio, "STARTTLS\r\n"); BIO_read(sbio, sbuf, BUFSIZZ); } else if (starttls_proto == PROTO_POP3) { mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); if (mbuf_len == -1) { BIO_printf(bio_err, "BIO_read failed\n"); goto end; } BIO_printf(sbio, "STLS\r\n"); BIO_read(sbio, sbuf, BUFSIZZ); } else if (starttls_proto == PROTO_IMAP) { int foundit = 0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); BIO_gets(fbio, mbuf, BUFSIZZ); /* STARTTLS command requires CAPABILITY... */ BIO_printf(fbio, ". CAPABILITY\r\n"); (void) BIO_flush(fbio); /* wait for multi-line CAPABILITY response */ do { mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); if (strstr(mbuf, "STARTTLS")) foundit = 1; } while (mbuf_len > 3 && mbuf[0] != '.'); (void) BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found STARTTLS in server response," " try anyway...\n"); BIO_printf(sbio, ". STARTTLS\r\n"); BIO_read(sbio, sbuf, BUFSIZZ); } else if (starttls_proto == PROTO_FTP) { BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from FTP */ do { mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); } while (mbuf_len > 3 && mbuf[3] == '-'); (void) BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); BIO_printf(sbio, "AUTH TLS\r\n"); BIO_read(sbio, sbuf, BUFSIZZ); } if (starttls_proto == PROTO_XMPP) { int seen = 0; BIO_printf(sbio, "<stream:stream " "xmlns:stream='http://etherx.jabber.org/streams' " "xmlns='jabber:client' to='%s' version='1.0'>", host); seen = BIO_read(sbio, mbuf, BUFSIZZ); mbuf[seen] = 0; while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")) { if (strstr(mbuf, "/stream:features>")) goto shut; seen = BIO_read(sbio, mbuf, BUFSIZZ); mbuf[seen] = 0; } BIO_printf(sbio, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); seen = BIO_read(sbio, sbuf, BUFSIZZ); sbuf[seen] = 0; if (!strstr(sbuf, "<proceed")) goto shut; mbuf[0] = 0; } for (;;) { FD_ZERO(&readfds); FD_ZERO(&writefds); if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_get_timeout(con, &timeout)) timeoutp = &timeout; else timeoutp = NULL; if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { in_init = 1; tty_on = 0; } else { tty_on = 1; if (in_init) { in_init = 0; if (sess_out) { BIO *stmp = BIO_new_file(sess_out, "w"); if (stmp) { PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con)); BIO_free(stmp); } else BIO_printf(bio_err, "Error writing session file %s\n", sess_out); } print_stuff(bio_c_out, con, full_log); if (full_log > 0) full_log--; if (starttls_proto) { BIO_write(bio_err, mbuf, mbuf_len); /* We don't need to know any more */ starttls_proto = PROTO_OFF; } if (reconnect) { reconnect--; BIO_printf(bio_c_out, "drop connection and then reconnect\n"); SSL_shutdown(con); SSL_set_connect_state(con); shutdown(SSL_get_fd(con), SHUT_RD); close(SSL_get_fd(con)); goto re_start; } } } ssl_pending = read_ssl && SSL_pending(con); /* XXX should add tests for fd_set overflow */ if (!ssl_pending) { if (tty_on) { if (read_tty) FD_SET(fileno(stdin), &readfds); if (write_tty) FD_SET(fileno(stdout), &writefds); } if (read_ssl) FD_SET(SSL_get_fd(con), &readfds); if (write_ssl) FD_SET(SSL_get_fd(con), &writefds); /* printf("mode tty(%d %d%d) ssl(%d%d)\n", tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ i = select(width, &readfds, &writefds, NULL, timeoutp); if (i < 0) { BIO_printf(bio_err, "bad select %d\n", errno); goto shut; /* goto end; */ } } if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) { BIO_printf(bio_err, "TIMEOUT occured\n"); } if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) { k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int) cbuf_len); switch (SSL_get_error(con, k)) { case SSL_ERROR_NONE: cbuf_off += k; cbuf_len -= k; if (k <= 0) goto end; /* we have done a write(con,NULL,0); */ if (cbuf_len <= 0) { read_tty = 1; write_ssl = 0; } else { /* if (cbuf_len > 0) */ read_tty = 0; write_ssl = 1; } break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out, "write W BLOCK\n"); write_ssl = 1; read_tty = 0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out, "write R BLOCK\n"); write_tty = 0; read_ssl = 1; write_ssl = 0; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out, "write X BLOCK\n"); break; case SSL_ERROR_ZERO_RETURN: if (cbuf_len != 0) { BIO_printf(bio_c_out, "shutdown\n"); ret = 0; goto shut; } else { read_tty = 1; write_ssl = 0; break; } case SSL_ERROR_SYSCALL: if ((k != 0) || (cbuf_len != 0)) { BIO_printf(bio_err, "write:errno=%d\n", errno); goto shut; } else { read_tty = 1; write_ssl = 0; } break; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; } } else if (!ssl_pending && FD_ISSET(fileno(stdout), &writefds)) { i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len); if (i <= 0) { BIO_printf(bio_c_out, "DONE\n"); ret = 0; goto shut; /* goto end; */ } sbuf_len -= i; sbuf_off += i; if (sbuf_len <= 0) { read_ssl = 1; write_tty = 0; } } else if (ssl_pending || FD_ISSET(SSL_get_fd(con), &readfds)) { #ifdef RENEG { static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii = 0; } } #endif k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ ); switch (SSL_get_error(con, k)) { case SSL_ERROR_NONE: if (k <= 0) goto end; sbuf_off = 0; sbuf_len = k; read_ssl = 0; write_tty = 1; break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out, "read W BLOCK\n"); write_ssl = 1; read_tty = 0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out, "read R BLOCK\n"); write_tty = 0; read_ssl = 1; if ((read_tty == 0) && (write_ssl == 0)) write_ssl = 1; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out, "read X BLOCK\n"); break; case SSL_ERROR_SYSCALL: ret = errno; BIO_printf(bio_err, "read:errno=%d\n", ret); goto shut; case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_c_out, "closed\n"); ret = 0; goto shut; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; /* break; */ } } else if (FD_ISSET(fileno(stdin), &readfds)) { if (crlf) { int j, lf_num; i = read(fileno(stdin), cbuf, BUFSIZZ / 2); lf_num = 0; /* both loops are skipped when i <= 0 */ for (j = 0; j < i; j++) if (cbuf[j] == '\n') lf_num++; for (j = i - 1; j >= 0; j--) { cbuf[j + lf_num] = cbuf[j]; if (cbuf[j] == '\n') { lf_num--; i++; cbuf[j + lf_num] = '\r'; } } assert(lf_num == 0); } else i = read(fileno(stdin), cbuf, BUFSIZZ); if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) { BIO_printf(bio_err, "DONE\n"); ret = 0; goto shut; } if ((!c_ign_eof) && (cbuf[0] == 'R')) { BIO_printf(bio_err, "RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len = 0; } else { cbuf_len = i; cbuf_off = 0; } write_ssl = 1; read_tty = 0; } } ret = 0; shut: if (in_init) print_stuff(bio_c_out, con, full_log); SSL_shutdown(con); shutdown(SSL_get_fd(con), SHUT_RD); close(SSL_get_fd(con)); end: if (con != NULL) { if (prexit != 0) print_stuff(bio_c_out, con, 1); SSL_free(con); } #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) free(next_proto.data); #endif if (ctx != NULL) SSL_CTX_free(ctx); if (cert) X509_free(cert); if (key) EVP_PKEY_free(key); free(pass); if (vpm) X509_VERIFY_PARAM_free(vpm); if (cbuf != NULL) { OPENSSL_cleanse(cbuf, BUFSIZZ); free(cbuf); } if (sbuf != NULL) { OPENSSL_cleanse(sbuf, BUFSIZZ); free(sbuf); } if (mbuf != NULL) { OPENSSL_cleanse(mbuf, BUFSIZZ); free(mbuf); } if (bio_c_out != NULL) { BIO_free(bio_c_out); bio_c_out = NULL; } return (ret); }
LQ_EXTERN_C void* LQ_CALL LqConnSslCreate ( const void* MethodSSL, /* Example SSLv23_method()*/ const char* CertFile, /* Example: "server.pem"*/ const char* KeyFile, /*Example: "server.key"*/ const char* CipherList, int TypeCertFile, /*SSL_FILETYPE_ASN1 (The file is in abstract syntax notation 1 (ASN.1) format.) or SSL_FILETYPE_PEM (The file is in base64 privacy enhanced mail (PEM) format.)*/ const char* CAFile, const char* DhpFile ) { #ifdef HAVE_OPENSSL static const unsigned char dh1024_p[] = { 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E, 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6, 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86, 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0, 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C, 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70, 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA, 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0, 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF, 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08, 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71, }; static const unsigned char dh1024_g[] = { 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42, 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F, 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E, 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13, 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F, 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1, 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08, 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A, 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59, 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24, 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5, }; SSL_CTX* NewCtx = NULL; bool r = false; static bool IsLoaded = false; if(MethodSSL == NULL) MethodSSL = SSLv23_server_method(); do { if(!IsLoaded) { IsLoaded = true; SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); } if((NewCtx = SSL_CTX_new((const SSL_METHOD*)MethodSSL)) == NULL) break; SSL_CTX_set_read_ahead(NewCtx, 1); SSL_CTX_set_verify(NewCtx, SSL_VERIFY_NONE, NULL); if(CipherList != NULL) { if(SSL_CTX_set_cipher_list(NewCtx, CipherList) == 1) SSL_CTX_set_options(NewCtx, SSL_OP_CIPHER_SERVER_PREFERENCE); } if(CAFile != NULL) { if(!SSL_CTX_load_verify_locations(NewCtx, CAFile, NULL)) { SSL_CTX_free(NewCtx); NewCtx = NULL; break; } } if((SSL_CTX_use_certificate_file(NewCtx, CertFile, TypeCertFile) <= 0) || (SSL_CTX_use_PrivateKey_file(NewCtx, KeyFile, TypeCertFile) <= 0)) { SSL_CTX_free(NewCtx); NewCtx = NULL; break; } if(SSL_CTX_check_private_key(NewCtx) != 1) { SSL_CTX_free(NewCtx); NewCtx = NULL; break; } if(DhpFile != NULL) { BIO *bio = BIO_new_file(DhpFile, "r"); if(bio) { DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if(dh) { SSL_CTX_set_tmp_dh(NewCtx, dh); SSL_CTX_set_options(NewCtx, SSL_OP_SINGLE_DH_USE); DH_free(dh); } } } else { DH *dh = DH_new(); if(dh) { dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); dh->length = 160; if(dh->p && dh->g) { SSL_CTX_set_tmp_dh(NewCtx, dh); SSL_CTX_set_options(NewCtx, SSL_OP_SINGLE_DH_USE); } DH_free(dh); } } } while(false); return NewCtx; #else lq_errno_set(ENOSYS); return NULL; #endif }
static int init_server(dtls_listener_relay_server_type* server, const char* ifname, const char *local_address, int port, int verbose, ioa_engine_handle e, turn_turnserver *ts, int report_creation, ioa_engine_new_connection_event_handler send_socket) { if(!server) return -1; #if DTLS_SUPPORTED server->dtls_ctx = e->dtls_ctx; #if DTLSv1_2_SUPPORTED server->dtls_ctx_v1_2 = e->dtls_ctx_v1_2; #endif #endif server->ts = ts; server->connect_cb = send_socket; if(ifname) STRCPY(server->ifname,ifname); if(make_ioa_addr((const u08bits*)local_address, port, &server->addr)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create a DTLS/UDP listener for address: %s\n",local_address); return -1; } server->slen0 = get_ioa_addr_len(&(server->addr)); server->verbose=verbose; server->e = e; #if DTLS_SUPPORTED if(server->dtls_ctx) { #if defined(REQUEST_CLIENT_CERT) /* If client has to authenticate, then */ SSL_CTX_set_verify(server->dtls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback); #endif SSL_CTX_set_read_ahead(server->dtls_ctx, 1); SSL_CTX_set_cookie_generate_cb(server->dtls_ctx, generate_cookie); SSL_CTX_set_cookie_verify_cb(server->dtls_ctx, verify_cookie); } #if DTLSv1_2_SUPPORTED if(server->dtls_ctx_v1_2) { #if defined(REQUEST_CLIENT_CERT) /* If client has to authenticate, then */ SSL_CTX_set_verify(server->dtls_ctx_v1_2, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback); #endif SSL_CTX_set_read_ahead(server->dtls_ctx_v1_2, 1); SSL_CTX_set_cookie_generate_cb(server->dtls_ctx_v1_2, generate_cookie); SSL_CTX_set_cookie_verify_cb(server->dtls_ctx_v1_2, verify_cookie); } #endif #endif return create_server_socket(server, report_creation); }
int dtls_connection_init(struct packet_stream *ps, int active, struct dtls_cert *cert) { struct dtls_connection *d; unsigned long err; if (!ps || !ps->sfd) return 0; __DBG("dtls_connection_init(%i)", active); d = &ps->sfd->dtls; if (d->init) { if ((d->active && active) || (!d->active && !active)) goto done; dtls_connection_cleanup(d); } d->ssl_ctx = SSL_CTX_new(active ? DTLSv1_client_method() : DTLSv1_server_method()); if (!d->ssl_ctx) goto error; if (SSL_CTX_use_certificate(d->ssl_ctx, cert->x509) != 1) goto error; if (SSL_CTX_use_PrivateKey(d->ssl_ctx, cert->pkey) != 1) goto error; SSL_CTX_set_verify(d->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); SSL_CTX_set_verify_depth(d->ssl_ctx, 4); SSL_CTX_set_cipher_list(d->ssl_ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); if (SSL_CTX_set_tlsext_use_srtp(d->ssl_ctx, ciphers_str)) goto error; if (SSL_CTX_set_read_ahead(d->ssl_ctx, 1)) goto error; d->ssl = SSL_new(d->ssl_ctx); if (!d->ssl) goto error; d->r_bio = BIO_new(BIO_s_mem()); d->w_bio = BIO_new(BIO_s_mem()); if (!d->r_bio || !d->w_bio) goto error; SSL_set_app_data(d->ssl, ps->sfd); /* XXX obj reference here? */ SSL_set_bio(d->ssl, d->r_bio, d->w_bio); SSL_set_mode(d->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (ecdh == NULL) goto error; SSL_set_options(d->ssl, SSL_OP_SINGLE_ECDH_USE); SSL_set_tmp_ecdh(d->ssl, ecdh); EC_KEY_free(ecdh); d->init = 1; d->active = active ? -1 : 0; done: return 0; error: err = ERR_peek_last_error(); if (d->r_bio) BIO_free(d->r_bio); if (d->w_bio) BIO_free(d->w_bio); if (d->ssl) SSL_free(d->ssl); if (d->ssl_ctx) SSL_CTX_free(d->ssl_ctx); ZERO(*d); ilog(LOG_ERROR, "Failed to init DTLS connection: %s", ERR_reason_error_string(err)); return -1; }
/** * Allocate a new TLS context * * @param tlsp Pointer to allocated TLS context * @param method TLS method * @param keyfile Optional private key file * @param pwd Optional password * * @return 0 if success, otherwise errorcode */ int tls_alloc(struct tls **tlsp, enum tls_method method, const char *keyfile, const char *pwd) { struct tls *tls; int r, err; if (!tlsp) return EINVAL; tls = mem_zalloc(sizeof(*tls), destructor); if (!tls) return ENOMEM; if (!tlsg.up) { #ifdef SIGPIPE /* Set up a SIGPIPE handler */ (void)signal(SIGPIPE, sigpipe_handle); #endif SSL_library_init(); tlsg.up = true; } if (tlsg.tlsc++ == 0) { DEBUG_INFO("error strings loaded\n"); SSL_load_error_strings(); } switch (method) { case TLS_METHOD_SSLV23: tls->ctx = SSL_CTX_new(SSLv23_method()); break; #ifdef USE_OPENSSL_DTLS case TLS_METHOD_DTLSV1: tls->ctx = SSL_CTX_new(DTLSv1_method()); break; #endif default: DEBUG_WARNING("tls method %d not supported\n", method); err = ENOSYS; goto out; } if (!tls->ctx) { err = ENOMEM; goto out; } #if (OPENSSL_VERSION_NUMBER < 0x00905100L) SSL_CTX_set_verify_depth(tls->ctx, 1); #endif if (method == TLS_METHOD_DTLSV1) { SSL_CTX_set_read_ahead(tls->ctx, 1); } /* Load our keys and certificates */ if (keyfile) { if (pwd) { err = str_dup(&tls->pass, pwd); if (err) goto out; SSL_CTX_set_default_passwd_cb(tls->ctx, password_cb); SSL_CTX_set_default_passwd_cb_userdata(tls->ctx, tls); } r = SSL_CTX_use_certificate_chain_file(tls->ctx, keyfile); if (r <= 0) { DEBUG_WARNING("Can't read certificate file: %s (%d)\n", keyfile, r); err = EINVAL; goto out; } r = SSL_CTX_use_PrivateKey_file(tls->ctx, keyfile, SSL_FILETYPE_PEM); if (r <= 0) { DEBUG_WARNING("Can't read key file: %s (%d)\n", keyfile, r); err = EINVAL; goto out; } } err = 0; out: if (err) mem_deref(tls); else *tlsp = tls; return err; }
/* DTLS-SRTP initialization */ gint janus_dtls_srtp_init(gchar *server_pem, gchar *server_key) { ssl_ctx = SSL_CTX_new(DTLSv1_method()); if(!ssl_ctx) { JANUS_LOG(LOG_FATAL, "Ops, error creating DTLS context?\n"); return -1; } SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, janus_dtls_verify_callback); SSL_CTX_set_tlsext_use_srtp(ssl_ctx, "SRTP_AES128_CM_SHA1_80"); /* FIXME Should we support something else as well? */ if(!server_pem || !SSL_CTX_use_certificate_file(ssl_ctx, server_pem, SSL_FILETYPE_PEM)) { JANUS_LOG(LOG_FATAL, "Certificate error, does it exist?\n"); JANUS_LOG(LOG_FATAL, " %s\n", server_pem); return -2; } if(!server_key || !SSL_CTX_use_PrivateKey_file(ssl_ctx, server_key, SSL_FILETYPE_PEM)) { JANUS_LOG(LOG_FATAL, "Certificate key error, does it exist?\n"); JANUS_LOG(LOG_FATAL, " %s\n", server_key); return -3; } if(!SSL_CTX_check_private_key(ssl_ctx)) { JANUS_LOG(LOG_FATAL, "Certificate check error...\n"); return -4; } SSL_CTX_set_read_ahead(ssl_ctx,1); BIO *certbio = BIO_new(BIO_s_file()); if(certbio == NULL) { JANUS_LOG(LOG_FATAL, "Certificate BIO error...\n"); return -5; } if(BIO_read_filename(certbio, server_pem) == 0) { JANUS_LOG(LOG_FATAL, "Error reading certificate...\n"); BIO_free_all(certbio); return -6; } X509 *cert = PEM_read_bio_X509(certbio, NULL, 0, NULL); if(cert == NULL) { JANUS_LOG(LOG_FATAL, "Error reading certificate...\n"); BIO_free_all(certbio); return -7; } unsigned int size; unsigned char fingerprint[EVP_MAX_MD_SIZE]; if(X509_digest(cert, EVP_sha256(), (unsigned char *)fingerprint, &size) == 0) { JANUS_LOG(LOG_FATAL, "Error converting X509 structure...\n"); X509_free(cert); BIO_free_all(certbio); return -7; } char *lfp = (char *)&local_fingerprint; unsigned int i = 0; for(i = 0; i < size; i++) { g_snprintf(lfp, 4, "%.2X:", fingerprint[i]); lfp += 3; } *(lfp-1) = 0; JANUS_LOG(LOG_INFO, "Fingerprint of our certificate: %s\n", local_fingerprint); X509_free(cert); BIO_free_all(certbio); SSL_CTX_set_cipher_list(ssl_ctx, DTLS_CIPHERS); /* Initialize libsrtp */ if(srtp_init() != err_status_ok) { JANUS_LOG(LOG_FATAL, "Ops, error setting up libsrtp?\n"); return 5; } return 0; }
int MAIN(int argc, char **argv) { int off=0; SSL *con=NULL,*con2=NULL; X509_STORE *store = NULL; int s,k,width,state=0; char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; int cbuf_len,cbuf_off; int sbuf_len,sbuf_off; fd_set readfds,writefds; short port=PORT; int full_log=1; char *host=SSL_HOST_NAME; char *cert_file=NULL,*key_file=NULL; int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; char *passarg = NULL, *pass = NULL; X509 *cert = NULL; EVP_PKEY *key = NULL; char *CApath=NULL,*CAfile=NULL,*cipher=NULL; int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0; int crlf=0; int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending; SSL_CTX *ctx=NULL; int ret=1,in_init=1,i,nbio_test=0; int starttls_proto = PROTO_OFF; int prexit = 0, vflags = 0; SSL_METHOD *meth=NULL; #ifdef sock_type #undef sock_type #endif int sock_type=SOCK_STREAM; BIO *sbio; char *inrand=NULL; int mbuf_len=0; #ifndef OPENSSL_NO_ENGINE char *engine_id=NULL; ENGINE *e=NULL; #endif #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) struct timeval tv; #endif struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0 ; long mtu = 0; #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_client_method(); #elif !defined(OPENSSL_NO_SSL3) meth=SSLv3_client_method(); #elif !defined(OPENSSL_NO_SSL2) meth=SSLv2_client_method(); #endif apps_startup(); c_Pause=0; c_quiet=0; c_ign_eof=0; c_debug=0; c_msg=0; c_showcerts=0; if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; if ( ((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL)) { BIO_printf(bio_err,"out of memory\n"); goto end; } verify_depth=0; verify_error=X509_V_OK; #ifdef FIONBIO c_nbio=0; #endif argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-host") == 0) { if (--argc < 1) goto bad; host= *(++argv); } else if (strcmp(*argv,"-port") == 0) { if (--argc < 1) goto bad; port=atoi(*(++argv)); if (port == 0) goto bad; } else if (strcmp(*argv,"-connect") == 0) { if (--argc < 1) goto bad; if (!extract_host_port(*(++argv),&host,NULL,&port)) goto bad; } else if (strcmp(*argv,"-verify") == 0) { verify=SSL_VERIFY_PEER; if (--argc < 1) goto bad; verify_depth=atoi(*(++argv)); BIO_printf(bio_err,"verify depth is %d\n",verify_depth); } else if (strcmp(*argv,"-cert") == 0) { if (--argc < 1) goto bad; cert_file= *(++argv); } else if (strcmp(*argv,"-certform") == 0) { if (--argc < 1) goto bad; cert_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-crl_check") == 0) vflags |= X509_V_FLAG_CRL_CHECK; else if (strcmp(*argv,"-crl_check_all") == 0) vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; else if (strcmp(*argv,"-prexit") == 0) prexit=1; else if (strcmp(*argv,"-crlf") == 0) crlf=1; else if (strcmp(*argv,"-quiet") == 0) { c_quiet=1; c_ign_eof=1; } else if (strcmp(*argv,"-ign_eof") == 0) c_ign_eof=1; else if (strcmp(*argv,"-pause") == 0) c_Pause=1; else if (strcmp(*argv,"-debug") == 0) c_debug=1; #ifdef WATT32 else if (strcmp(*argv,"-wdebug") == 0) dbug_init(); #endif else if (strcmp(*argv,"-msg") == 0) c_msg=1; else if (strcmp(*argv,"-showcerts") == 0) c_showcerts=1; else if (strcmp(*argv,"-nbio_test") == 0) nbio_test=1; else if (strcmp(*argv,"-state") == 0) state=1; #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv,"-ssl2") == 0) meth=SSLv2_client_method(); #endif #ifndef OPENSSL_NO_SSL3 else if (strcmp(*argv,"-ssl3") == 0) meth=SSLv3_client_method(); #endif #ifndef OPENSSL_NO_TLS1 else if (strcmp(*argv,"-tls1") == 0) meth=TLSv1_client_method(); #endif #ifndef OPENSSL_NO_DTLS1 else if (strcmp(*argv,"-dtls1") == 0) { meth=DTLSv1_client_method(); sock_type=SOCK_DGRAM; } else if (strcmp(*argv,"-timeout") == 0) enable_timeouts=1; else if (strcmp(*argv,"-mtu") == 0) { if (--argc < 1) goto bad; mtu = atol(*(++argv)); } #endif else if (strcmp(*argv,"-bugs") == 0) bugs=1; else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) goto bad; key_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-pass") == 0) { if (--argc < 1) goto bad; passarg = *(++argv); } else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; key_file= *(++argv); } else if (strcmp(*argv,"-reconnect") == 0) { reconnect=5; } else if (strcmp(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath= *(++argv); } else if (strcmp(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); } else if (strcmp(*argv,"-no_tls1") == 0) off|=SSL_OP_NO_TLSv1; else if (strcmp(*argv,"-no_ssl3") == 0) off|=SSL_OP_NO_SSLv3; else if (strcmp(*argv,"-no_ssl2") == 0) off|=SSL_OP_NO_SSLv2; else if (strcmp(*argv,"-serverpref") == 0) off|=SSL_OP_CIPHER_SERVER_PREFERENCE; else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; cipher= *(++argv); } #ifdef FIONBIO else if (strcmp(*argv,"-nbio") == 0) { c_nbio=1; } #endif else if (strcmp(*argv,"-starttls") == 0) { if (--argc < 1) goto bad; ++argv; if (strcmp(*argv,"smtp") == 0) starttls_proto = PROTO_SMTP; else if (strcmp(*argv,"pop3") == 0) starttls_proto = PROTO_POP3; else if (strcmp(*argv,"imap") == 0) starttls_proto = PROTO_IMAP; else if (strcmp(*argv,"ftp") == 0) starttls_proto = PROTO_FTP; else goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine_id = *(++argv); } #endif else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) goto bad; inrand= *(++argv); } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badop=1; break; } argc--; argv++; } if (badop) { bad: sc_usage(); goto end; } OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine_id, 1); #endif if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (key_file == NULL) key_file = cert_file; if (key_file) { key = load_key(bio_err, key_file, key_format, 0, pass, e, "client certificate private key file"); if (!key) { ERR_print_errors(bio_err); goto end; } } if (cert_file) { cert = load_cert(bio_err,cert_file,cert_format, NULL, e, "client certificate file"); if (!cert) { ERR_print_errors(bio_err); goto end; } } if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL && !RAND_status()) { BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); if (bio_c_out == NULL) { if (c_quiet && !c_debug && !c_msg) { bio_c_out=BIO_new(BIO_s_null()); } else { if (bio_c_out == NULL) bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE); } } ctx=SSL_CTX_new(meth); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; } if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL|off); else SSL_CTX_set_options(ctx,off); /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); if (cipher != NULL) if(!SSL_CTX_set_cipher_list(ctx,cipher)) { BIO_printf(bio_err,"error setting cipher list\n"); ERR_print_errors(bio_err); goto end; } #if 0 else SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER")); #endif SSL_CTX_set_verify(ctx,verify,verify_callback); if (!set_cert_key_stuff(ctx,cert,key)) goto end; if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { /* BIO_printf(bio_err,"error setting default verify locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } store = SSL_CTX_get_cert_store(ctx); X509_STORE_set_flags(store, vflags); con=SSL_new(ctx); #ifndef OPENSSL_NO_KRB5 if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) { kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host); } #endif /* OPENSSL_NO_KRB5 */ /* SSL_set_cipher_list(con,"RC4-MD5"); */ re_start: if (init_client(&s,host,port,sock_type) == 0) { BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); SHUTDOWN(s); goto end; } BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s); #ifdef FIONBIO if (c_nbio) { unsigned long l=1; BIO_printf(bio_c_out,"turning on non blocking io\n"); if (BIO_socket_ioctl(s,FIONBIO,&l) < 0) { ERR_print_errors(bio_err); goto end; } } #endif if (c_Pause & 0x01) con->debug=1; if ( SSL_version(con) == DTLS1_VERSION) { struct timeval timeout; sbio=BIO_new_dgram(s,BIO_NOCLOSE); if (getsockname(s, &peer, (void *)&peerlen) < 0) { BIO_printf(bio_err, "getsockname:errno=%d\n", get_last_socket_error()); SHUTDOWN(s); goto end; } (void)BIO_ctrl_set_connected(sbio, 1, &peer); if ( enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); timeout.tv_sec = 0; timeout.tv_usec = DGRAM_SND_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } if ( mtu > 0) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); SSL_set_mtu(con, mtu); } else /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); } else sbio=BIO_new_socket(s,BIO_NOCLOSE); if (nbio_test) { BIO *test; test=BIO_new(BIO_f_nbio_test()); sbio=BIO_push(test,sbio); } if (c_debug) { con->debug=1; BIO_set_callback(sbio,bio_dump_callback); BIO_set_callback_arg(sbio,(char *)bio_c_out); } if (c_msg) { SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_c_out); } SSL_set_bio(con,sbio,sbio); SSL_set_connect_state(con); /* ok, lets connect */ width=SSL_get_fd(con)+1; read_tty=1; write_tty=0; tty_on=0; read_ssl=1; write_ssl=1; cbuf_len=0; cbuf_off=0; sbuf_len=0; sbuf_off=0; /* This is an ugly hack that does a lot of assumptions */ /* We do have to handle multi-line responses which may come in a single packet or not. We therefore have to use BIO_gets() which does need a buffering BIO. So during the initial chitchat we do push a buffering BIO into the chain that is removed again later on to not disturb the rest of the s_client operation. */ if (starttls_proto == PROTO_SMTP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from SMTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); /* STARTTLS command requires EHLO... */ BIO_printf(fbio,"EHLO openssl.client.net\r\n"); (void)BIO_flush(fbio); /* wait for multi-line response to end EHLO SMTP response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found starttls in server response," " try anyway...\n"); BIO_printf(sbio,"STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_POP3) { BIO_read(sbio,mbuf,BUFSIZZ); BIO_printf(sbio,"STLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_IMAP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); BIO_gets(fbio,mbuf,BUFSIZZ); /* STARTTLS command requires CAPABILITY... */ BIO_printf(fbio,". CAPABILITY\r\n"); (void)BIO_flush(fbio); /* wait for multi-line CAPABILITY response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[0]!='.'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found STARTTLS in server response," " try anyway...\n"); BIO_printf(sbio,". STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_FTP) { BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from FTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); BIO_printf(sbio,"AUTH TLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } for (;;) { FD_ZERO(&readfds); FD_ZERO(&writefds); if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { in_init=1; tty_on=0; } else { tty_on=1; if (in_init) { in_init=0; print_stuff(bio_c_out,con,full_log); if (full_log > 0) full_log--; if (starttls_proto) { BIO_printf(bio_err,"%s",mbuf); /* We don't need to know any more */ starttls_proto = PROTO_OFF; } if (reconnect) { reconnect--; BIO_printf(bio_c_out,"drop connection and then reconnect\n"); SSL_shutdown(con); SSL_set_connect_state(con); SHUTDOWN(SSL_get_fd(con)); goto re_start; } } } ssl_pending = read_ssl && SSL_pending(con); if (!ssl_pending) { #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) if (tty_on) { if (read_tty) FD_SET(fileno(stdin),&readfds); if (write_tty) FD_SET(fileno(stdout),&writefds); } if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); #else if(!tty_on || !write_tty) { if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); } #endif /* printf("mode tty(%d %d%d) ssl(%d%d)\n", tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ /* Note: under VMS with SOCKETSHR the second parameter * is currently of type (int *) whereas under other * systems it is (void *) if you don't have a cast it * will choke the compiler: if you do have a cast then * you can either go for (int *) or (void *). */ #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) /* Under Windows/DOS we make the assumption that we can * always write to the tty: therefore if we need to * write to the tty we just fall through. Otherwise * we timeout the select every second and see if there * are any keypresses. Note: this is a hack, in a proper * Windows application we wouldn't do this. */ i=0; if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) if(!i && (!_kbhit() || !read_tty) ) continue; #else if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue; #endif } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); } #elif defined(OPENSSL_SYS_NETWARE) if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); } #else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); #endif if ( i < 0) { BIO_printf(bio_err,"bad select %d\n", get_last_socket_error()); goto shut; /* goto end; */ } } if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds)) { k=SSL_write(con,&(cbuf[cbuf_off]), (unsigned int)cbuf_len); switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: cbuf_off+=k; cbuf_len-=k; if (k <= 0) goto end; /* we have done a write(con,NULL,0); */ if (cbuf_len <= 0) { read_tty=1; write_ssl=0; } else /* if (cbuf_len > 0) */ { read_tty=0; write_ssl=1; } break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"write W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"write R BLOCK\n"); write_tty=0; read_ssl=1; write_ssl=0; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"write X BLOCK\n"); break; case SSL_ERROR_ZERO_RETURN: if (cbuf_len != 0) { BIO_printf(bio_c_out,"shutdown\n"); goto shut; } else { read_tty=1; write_ssl=0; break; } case SSL_ERROR_SYSCALL: if ((k != 0) || (cbuf_len != 0)) { BIO_printf(bio_err,"write:errno=%d\n", get_last_socket_error()); goto shut; } else { read_tty=1; write_ssl=0; } break; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) /* Assume Windows/DOS can always write */ else if (!ssl_pending && write_tty) #else else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds)) #endif { #ifdef CHARSET_EBCDIC ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len); #endif i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len); if (i <= 0) { BIO_printf(bio_c_out,"DONE\n"); goto shut; /* goto end; */ } sbuf_len-=i;; sbuf_off+=i; if (sbuf_len <= 0) { read_ssl=1; write_tty=0; } } else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds)) { #ifdef RENEG { static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } } #endif #if 1 k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ ); #else /* Demo for pending and peek :-) */ k=SSL_read(con,sbuf,16); { char zbuf[10240]; printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240)); } #endif switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: if (k <= 0) goto end; sbuf_off=0; sbuf_len=k; read_ssl=0; write_tty=1; break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"read W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"read R BLOCK\n"); write_tty=0; read_ssl=1; if ((read_tty == 0) && (write_ssl == 0)) write_ssl=1; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"read X BLOCK\n"); break; case SSL_ERROR_SYSCALL: BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error()); goto shut; case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_c_out,"closed\n"); goto shut; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; /* break; */ } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) else if (_kbhit()) #else else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) #endif #elif defined (OPENSSL_SYS_NETWARE) else if (_kbhit()) #else else if (FD_ISSET(fileno(stdin),&readfds)) #endif { if (crlf) { int j, lf_num; i=read(fileno(stdin),cbuf,BUFSIZZ/2); lf_num = 0; /* both loops are skipped when i <= 0 */ for (j = 0; j < i; j++) if (cbuf[j] == '\n') lf_num++; for (j = i-1; j >= 0; j--) { cbuf[j+lf_num] = cbuf[j]; if (cbuf[j] == '\n') { lf_num--; i++; cbuf[j+lf_num] = '\r'; } } assert(lf_num == 0); } else i=read(fileno(stdin),cbuf,BUFSIZZ); if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) { BIO_printf(bio_err,"DONE\n"); goto shut; } if ((!c_ign_eof) && (cbuf[0] == 'R')) { BIO_printf(bio_err,"RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len=0; } else { cbuf_len=i; cbuf_off=0; #ifdef CHARSET_EBCDIC ebcdic2ascii(cbuf, cbuf, i); #endif } write_ssl=1; read_tty=0; } } shut: SSL_shutdown(con); SHUTDOWN(SSL_get_fd(con)); ret=0; end: if(prexit) print_stuff(bio_c_out,con,1); if (con != NULL) SSL_free(con); if (con2 != NULL) SSL_free(con2); if (ctx != NULL) SSL_CTX_free(ctx); if (cert) X509_free(cert); if (key) EVP_PKEY_free(key); if (pass) OPENSSL_free(pass); if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); } if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); } if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); } if (bio_c_out != NULL) { BIO_free(bio_c_out); bio_c_out=NULL; } apps_shutdown(); OPENSSL_EXIT(ret); }
static int dtls_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket) { int len = 0; size_t length = 0; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; char *message; char ipbuf[INET6_ADDRSTRLEN]; int i; int pos; struct socket_tab *socket_tab_used=NULL; BIO *sbio=NULL; if (dtls_socket <= 0) return -1; if (host == NULL) { host = sip->req_uri->host; if (sip->req_uri->port != NULL) port = osip_atoi (sip->req_uri->port); else port = 5061; } if (port == 5060) port = 5061; if (MSG_IS_REQUEST(sip)) { if (MSG_IS_REGISTER(sip) ||MSG_IS_INVITE(sip) ||MSG_IS_SUBSCRIBE(sip) || MSG_IS_NOTIFY(sip)) eXtl_update_local_target(sip); } i=-1; #ifndef MINISIZE if (tr!=NULL && tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0') { /* always choose the first here. if a network error occur, remove first entry and replace with next entries. */ osip_srv_entry_t *srv; int n=0; for (srv = &tr->record.srventry[0]; n<10 && tr->record.srventry[0].srv[0]; srv = &tr->record.srventry[0]) { i = eXosip_get_addrinfo (&addrinfo, srv->srv, srv->port, IPPROTO_UDP); if (i == 0) { host = srv->srv; port = srv->port; break; } memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t)); memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t)); i=-1; /* copy next element */ n++; } } #endif /* if SRV was used, distination may be already found */ if (i != 0) { i = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_UDP); } if (i != 0) { return -1; } memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); len = addrinfo->ai_addrlen; eXosip_freeaddrinfo (addrinfo); /* remove preloaded route if there is no tag in the To header */ { osip_route_t *route=NULL; osip_generic_param_t *tag=NULL; osip_message_get_route (sip, 0, &route); osip_to_get_tag (sip->to, &tag); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_remove(&sip->routes, 0); } i = osip_message_to_str (sip, &message, &length); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_add(&sip->routes, route, 0); } } if (i != 0 || length <= 0) { return -1; } switch ( ((struct sockaddr *)&addr)->sa_family ) { case AF_INET: inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in *) &addr)->sin_addr), ipbuf, sizeof (ipbuf)); break; case AF_INET6: inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf, sizeof (ipbuf)); break; default: strncpy (ipbuf, "(unknown)", sizeof (ipbuf)); break; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message sent: \n%s (to dest=%s:%i)\n", message, ipbuf, port)); for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn != NULL && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_SERVER) { if (dtls_socket_tab[pos].remote_port == port && (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0)) { BIO *rbio; socket_tab_used = &dtls_socket_tab[pos]; rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); dtls_socket_tab[pos].ssl_conn->rbio = rbio; break; } } } if (socket_tab_used==NULL) { for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn != NULL && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_CLIENT) { if (dtls_socket_tab[pos].remote_port == port && (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0)) { BIO *rbio; socket_tab_used = &dtls_socket_tab[pos]; rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); dtls_socket_tab[pos].ssl_conn->rbio = rbio; break; } } } } if (socket_tab_used==NULL) { /* delete an old one! */ pos=0; if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); } if (dtls_socket_tab[pos].ssl_conn == NULL) { /* create a new one */ SSL_CTX_set_read_ahead (client_ctx, 1); dtls_socket_tab[pos].ssl_conn = SSL_new (client_ctx); if (dtls_socket_tab[pos].ssl_conn == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS SSL_new error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); osip_free (message); return -1; } if (connect (dtls_socket, (struct sockaddr *) &addr, sizeof (addr)) == -1) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS connect error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); osip_free (message); return -1; } SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_NO_QUERY_MTU); SSL_set_mtu (dtls_socket_tab[pos].ssl_conn, 2000); SSL_set_connect_state (dtls_socket_tab[pos].ssl_conn); sbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_ctrl_set_connected (sbio, 1, (struct sockaddr *) &addr); SSL_set_bio (dtls_socket_tab[pos].ssl_conn, sbio, sbio); dtls_socket_tab[pos].ssl_type = 2; dtls_socket_tab[pos].ssl_state = 2; osip_strncpy (dtls_socket_tab[pos].remote_ip, ipbuf, sizeof (dtls_socket_tab[pos].remote_ip)); dtls_socket_tab[pos].remote_port = port; } i = SSL_write (dtls_socket_tab[pos].ssl_conn, message, length); if (i<0) { i = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i); print_ssl_error (i); if (i==SSL_ERROR_SSL || i==SSL_ERROR_SYSCALL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS SSL_write error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); } #ifndef MINISIZE /* delete first SRV entry that is not reachable */ if (tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0') { memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t)); memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t)); osip_free (message); return 0; /* retry for next retransmission! */ } #endif /* SIP_NETWORK_ERROR; */ osip_free (message); return -1; } if (eXosip.keep_alive > 0) { if (MSG_IS_REGISTER (sip)) { eXosip_reg_t *reg = NULL; if (_eXosip_reg_find (®, tr) == 0) { memcpy (&(reg->addr), &addr, len); reg->len = len; } } } osip_free (message); return 0; }