SSL_Connection *ssl_connect(const char *host, int port, const char *certfile, const char *keyfile, const char *capath) { int err; SSL_Connection *sslcon = NULL; sslcon = (SSL_Connection *)malloc(sizeof(SSL_Connection)); if(sslcon == NULL) { log_error("Could not allocate memory for SSL Connection"); return NULL; } /* Load encryption & hashing algorithms for the SSL program */ SSL_library_init(); /* Load the error strings for SSL & CRYPTO APIs */ SSL_load_error_strings(); /* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */ sslcon->meth = SSLv3_method(); /* Create an SSL_CTX structure */ sslcon->ctx = SSL_CTX_new(sslcon->meth); if(!sslcon->ctx) { log_error("Could not get SSL Context\n"); return NULL; } /* Load the CA from the Path */ if(SSL_CTX_load_verify_locations(sslcon->ctx, NULL, capath) <= 0) { /* Handle failed load here */ log_error("Failed to set CA location...\n"); ERR_print_errors_fp(stderr); return NULL; } /* Load the client certificate into the SSL_CTX structure */ if (SSL_CTX_use_certificate_file(sslcon->ctx, certfile, SSL_FILETYPE_PEM) <= 0) { log_error("Cannot use Certificate File\n"); ERR_print_errors_fp(stderr); return NULL; } /* Load the private-key corresponding to the client certificate */ if (SSL_CTX_use_PrivateKey_file(sslcon->ctx, keyfile, SSL_FILETYPE_PEM) <= 0) { log_error("Cannot use Private Key\n"); ERR_print_errors_fp(stderr); return NULL; } /* Check if the client certificate and private-key matches */ if (!SSL_CTX_check_private_key(sslcon->ctx)) { log_error("Private key does not match the certificate public key\n"); return NULL; } /* Set up a TCP socket */ sslcon->sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if(sslcon->sock == -1) { log_error("Could not get Socket\n"); return NULL; } memset (&sslcon->server_addr, '\0', sizeof(sslcon->server_addr)); sslcon->server_addr.sin_family = AF_INET; sslcon->server_addr.sin_port = htons(port); /* Server Port number */ sslcon->host_info = gethostbyname(host); if(sslcon->host_info) { /* Take the first IP */ struct in_addr *address = (struct in_addr*)sslcon->host_info->h_addr_list[0]; sslcon->server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*address)); /* Server IP */ } else { log_error("Could not resolve hostname %s\n", host); return NULL; } /* Establish a TCP/IP connection to the SSL client */ err = connect(sslcon->sock, (struct sockaddr*) &sslcon->server_addr, sizeof(sslcon->server_addr)); if(err == -1) { log_error("Could not connect\n"); return NULL; } /* An SSL structure is created */ sslcon->ssl = SSL_new(sslcon->ctx); if(!sslcon->ssl) { log_error("Could not get SSL Socket\n"); return NULL; } /* Assign the socket into the SSL structure (SSL and socket without BIO) */ SSL_set_fd(sslcon->ssl, sslcon->sock); /* Perform SSL Handshake on the SSL client */ err = SSL_connect(sslcon->ssl); if(err <= 0) { log_error("Could not connect to SSL Server\n"); return NULL; } return sslcon; }
HybridSslConnection* hybrid_ssl_connect_with_fd(gint sk, ssl_callback func, gpointer user_data) { gint l; SSL *ssl; BIO *sbio; BIO *buf_io; BIO *ssl_bio; SSL_CTX *ssl_ctx; HybridSslConnection *ssl_conn; SSL_load_error_strings(); SSL_library_init(); if (!(ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) { hybrid_debug_error("ssl", "initialize SSL CTX: %s", ERR_reason_error_string(ERR_get_error())); return NULL; } if (!(ssl = ssl_new_with_certs(ssl_ctx))) { return NULL; } if (!SSL_set_fd(ssl, sk)) { hybrid_debug_error("ssl", "add ssl to tcp socket:%s", ERR_reason_error_string(ERR_get_error())); return NULL; } sbio = BIO_new(BIO_s_socket()); BIO_set_fd(sbio, sk, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); SSL_set_connect_state(ssl); reconnect: l = SSL_connect(ssl); switch (SSL_get_error(ssl, l)) { case SSL_ERROR_NONE: goto ssl_conn_sk_ok; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: usleep(100); goto reconnect; case SSL_ERROR_SYSCALL: case SSL_ERROR_WANT_X509_LOOKUP: case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_SSL: default: hybrid_debug_error("ssl", "ssl hand-shake error:%s", ERR_reason_error_string(ERR_get_error())); return NULL; } ssl_conn_sk_ok: if (HYBRID_OK != ssl_verify_certs(ssl)) { return NULL; } SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); buf_io = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio, ssl, BIO_NOCLOSE); BIO_push(buf_io, ssl_bio); ssl_conn = g_new0(HybridSslConnection, 1); ssl_conn->sk = sk; ssl_conn->ssl = ssl; ssl_conn->ssl_ctx = ssl_ctx; ssl_conn->conn_cb = func; ssl_conn->conn_data = user_data; ssl_conn->rbio = buf_io; ssl_conn->wbio = sbio; if (func) { func(ssl_conn, user_data); } return ssl_conn; }
status_t SSO::SSLSend(const char *host, HTTPFormatter *send, HTTPFormatter **recv) { int err = B_OK; int sd; struct sockaddr_in sa; struct hostent *hp; SSL_CTX *ctx; SSL *ssl; char buffer[1024]; SSL_METHOD *meth; SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); meth = SSLv23_client_method(); ctx = SSL_CTX_new (meth); CHK_NULL(ctx); SSL_CTX_set_options(ctx, SSL_OP_ALL); /* ----------------------------------------------- */ /* Create a socket and connect to server using normal socket calls. */ sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(sd, "socket"); // clear sa memset (&sa, '\0', sizeof(sa)); // get address if ((hp= gethostbyname(host)) == NULL) { sa.sin_addr.s_addr = inet_addr (host); /* Server IP */ } else { memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length); /* set address */ }; sa.sin_family = AF_INET; sa.sin_port = htons(443); /* Server Port number */ err = connect(sd, (struct sockaddr*) &sa, sizeof(sa)); CHK_ERR(err, "connect"); /* ----------------------------------------------- */ /* Now we have TCP conncetion. Start SSL negotiation. */ ssl = SSL_new (ctx); CHK_NULL(ssl); if (SSL_set_fd(ssl, sd) == 0) { LOG(kProtocolName, liDebug, "C %lX: SSL Error setting fd", this); return -1; }; SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); SSL_set_connect_state(ssl); err = SSL_connect (ssl); CHK_SSL(err); /* --------------------------------------------------- */ /* DATA EXCHANGE - Send a message and receive a reply. */ err = SSL_write(ssl, send->Flatten(), send->Length()); CHK_SSL(err); if (err <= 0) { LOG(kProtocolName, liDebug, "C %lX: SSL Error writing. Err: %ld", this, SSL_get_error(ssl, err)); }; BString data; int received = 0; while (err > 0) { err = SSL_read(ssl, buffer, sizeof(buffer)); CHK_SSL(err); if (err > 0) { received += err; data.Append(buffer, err); memset(buffer, 0, sizeof(buffer)); }; }; *recv = new HTTPFormatter(data.String(), data.Length()); LOG(kProtocolName, liDebug, "C %lX: Got %d chars", this, received); SSL_shutdown (ssl); /* send SSL/TLS close_notify */ /* Clean up. */ close (sd); SSL_free (ssl); SSL_CTX_free (ctx); return received; };
static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify) { #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) const SSL_METHOD *meth; #else SSL_METHOD *meth; #endif SSL_CTX *ctx; int ret; X509 *cert; SSL_library_init(); SSL_load_error_strings(); if (use_tls_only) meth = TLSv1_method(); else meth = SSLv23_method(); if (!meth) { ssl_socket_perror("SSLv23_method"); return -1; } ctx = SSL_CTX_new(meth); if (verify) SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); if (!SSL_CTX_set_default_verify_paths(ctx)) { ssl_socket_perror("SSL_CTX_set_default_verify_paths"); return -1; } sock->ssl = SSL_new(ctx); if (!sock->ssl) { ssl_socket_perror("SSL_new"); return -1; } if (!SSL_set_rfd(sock->ssl, sock->fd[0])) { ssl_socket_perror("SSL_set_rfd"); return -1; } if (!SSL_set_wfd(sock->ssl, sock->fd[1])) { ssl_socket_perror("SSL_set_wfd"); return -1; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME /* * SNI (RFC4366) * OpenSSL does not document this function, but the implementation * returns 1 on success, 0 on failure after calling SSLerr(). */ ret = SSL_set_tlsext_host_name(sock->ssl, server.host); if (ret != 1) warning("SSL_set_tlsext_host_name(%s) failed.", server.host); #endif ret = SSL_connect(sock->ssl); if (ret <= 0) { socket_perror("SSL_connect", sock, ret); return -1; } if (verify) { /* make sure the hostname matches that of the certificate */ cert = SSL_get_peer_certificate(sock->ssl); if (!cert) return error("unable to get peer certificate."); if (verify_hostname(cert, server.host) < 0) return -1; } return 0; }
/* Create a socket and connect it to 'ip' on port 'port'. * Returns -1 on failure (ip is NULL, socket creation/connection error) * Returns sock number on success. */ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port) { int sock = INVALID_SOCKET; #ifndef WIN32 int opt; #endif struct addrinfo hints; struct addrinfo *ainfo, *rp; int s; #ifdef WIN32 uint32_t val = 1; #endif #ifdef WITH_TLS int ret; BIO *bio; #endif if(!mosq || !host || !port) return MOSQ_ERR_INVAL; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; s = getaddrinfo(host, NULL, &hints, &ainfo); if(s) return MOSQ_ERR_UNKNOWN; for(rp = ainfo; rp != NULL; rp = rp->ai_next){ sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(sock == INVALID_SOCKET) continue; if(rp->ai_family == PF_INET){ ((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port); }else if(rp->ai_family == PF_INET6){ ((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port); }else{ continue; } if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1){ break; } #ifdef WIN32 errno = WSAGetLastError(); #endif COMPAT_CLOSE(sock); } freeaddrinfo(ainfo); if(!rp){ return MOSQ_ERR_ERRNO; } /* Set non-blocking */ #ifndef WIN32 opt = fcntl(sock, F_GETFL, 0); if(opt == -1 || fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1){ #ifdef WITH_TLS if(mosq->ssl){ SSL_shutdown(mosq->ssl); SSL_free(mosq->ssl); mosq->ssl = NULL; } if(mosq->ssl_ctx){ SSL_CTX_free(mosq->ssl_ctx); mosq->ssl_ctx = NULL; } #endif COMPAT_CLOSE(sock); return MOSQ_ERR_ERRNO; } #else if(ioctlsocket(sock, FIONBIO, &val)){ errno = WSAGetLastError(); #ifdef WITH_TLS if(mosq->ssl){ SSL_shutdown(mosq->ssl); SSL_free(mosq->ssl); mosq->ssl = NULL; } if(mosq->ssl_ctx){ SSL_CTX_free(mosq->ssl_ctx); mosq->ssl_ctx = NULL; } #endif COMPAT_CLOSE(sock); return MOSQ_ERR_ERRNO; } #endif #ifdef WITH_TLS if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1")){ mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); if(!mosq->ssl_ctx){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context."); COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } }else{ COMPAT_CLOSE(sock); return MOSQ_ERR_INVAL; } #if OPENSSL_VERSION_NUMBER >= 0x10000000 /* Disable compression */ SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_COMPRESSION); #endif #ifdef SSL_MODE_RELEASE_BUFFERS /* Use even less memory per SSL connection. */ SSL_CTX_set_mode(mosq->ssl_ctx, SSL_MODE_RELEASE_BUFFERS); #endif if(mosq->tls_ciphers){ ret = SSL_CTX_set_cipher_list(mosq->ssl_ctx, mosq->tls_ciphers); if(ret == 0){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", mosq->tls_ciphers); COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } } if(mosq->tls_cafile || mosq->tls_capath){ ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath); if(ret == 0){ #ifdef WITH_BROKER if(mosq->tls_cafile && mosq->tls_capath){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath); }else if(mosq->tls_cafile){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile); }else{ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath); } #else if(mosq->tls_cafile && mosq->tls_capath){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath); }else if(mosq->tls_cafile){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile); }else{ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath); } #endif COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } if(mosq->tls_cert_reqs == 0){ SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_NONE, NULL); }else{ SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_PEER, NULL); } if(mosq->tls_pw_callback){ SSL_CTX_set_default_passwd_cb(mosq->ssl_ctx, mosq->tls_pw_callback); SSL_CTX_set_default_passwd_cb_userdata(mosq->ssl_ctx, mosq); } if(mosq->tls_certfile){ ret = SSL_CTX_use_certificate_file(mosq->ssl_ctx, mosq->tls_certfile, SSL_FILETYPE_PEM); if(ret != 1){ #ifdef WITH_BROKER _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate, check bridge_certfile \"%s\".", mosq->tls_certfile); #else _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate \"%s\".", mosq->tls_certfile); #endif COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } } if(mosq->tls_keyfile){ ret = SSL_CTX_use_PrivateKey_file(mosq->ssl_ctx, mosq->tls_keyfile, SSL_FILETYPE_PEM); if(ret != 1){ #ifdef WITH_BROKER _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file, check bridge_keyfile \"%s\".", mosq->tls_keyfile); #else _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file \"%s\".", mosq->tls_keyfile); #endif COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } ret = SSL_CTX_check_private_key(mosq->ssl_ctx); if(ret != 1){ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Client certificate/key are inconsistent."); COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } } #ifdef WITH_TLS_PSK }else if(mosq->tls_psk){ SSL_CTX_set_psk_client_callback(mosq->ssl_ctx, psk_client_callback); #endif } mosq->ssl = SSL_new(mosq->ssl_ctx); if(!mosq->ssl){ COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq); bio = BIO_new_socket(sock, BIO_NOCLOSE); if(!bio){ COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } SSL_set_bio(mosq->ssl, bio, bio); ret = SSL_connect(mosq->ssl); if(ret != 1){ ret = SSL_get_error(mosq->ssl, ret); if(ret == SSL_ERROR_WANT_READ){ mosq->want_read = true; }else if(ret == SSL_ERROR_WANT_WRITE){ mosq->want_write = true; }else{ COMPAT_CLOSE(sock); return MOSQ_ERR_TLS; } } } #endif mosq->sock = sock; return MOSQ_ERR_SUCCESS; }
BOOL CSSLTcpSocket::SSLConnect(LPCSTR pszTargetIP,USHORT nTargetPort) { BOOL bRes = Connect(pszTargetIP,nTargetPort); int nRet = SSL_connect (m_ssl); return FALSE; }
int main(int argc, char **argv) { int c, test_config = 0; #ifndef WIN32 int gid = 0; #endif int sock = 0, port = 1515, ret = 0; char *dir = DEFAULTDIR; char *user = USER; char *group = GROUPGLOBAL; char *cfg = DEFAULTCPATH; char *manager = NULL; char *agentname = NULL; char lhostname[512 + 1]; char buf[2048 +1]; SSL_CTX *ctx; SSL *ssl; BIO *sbio; bio_err = 0; buf[2048] = '\0'; /* Setting the name */ OS_SetName(ARGV0); while((c = getopt(argc, argv, "Vdhu:g:D:c:m:p:A:")) != -1) { switch(c) { case 'V': print_version(); break; case 'h': report_help(); break; case 'd': nowDebug(); break; case 'u': if(!optarg) ErrorExit("%s: -u needs an argument",ARGV0); user=optarg; break; case 'g': if(!optarg) ErrorExit("%s: -g needs an argument",ARGV0); group=optarg; break; case 'D': if(!optarg) ErrorExit("%s: -D needs an argument",ARGV0); dir=optarg; break; case 'c': if(!optarg) ErrorExit("%s: -c needs an argument",ARGV0); cfg = optarg; break; case 't': test_config = 1; break; case 'm': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); manager = optarg; break; case 'A': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); agentname = optarg; break; case 'p': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); port = atoi(optarg); if(port <= 0 || port >= 65536) { ErrorExit("%s: Invalid port: %s", ARGV0, optarg); } break; default: report_help(); break; } } /* Starting daemon */ debug1(STARTED_MSG,ARGV0); #ifndef WIN32 /* Check if the user/group given are valid */ gid = Privsep_GetGroup(group); if(gid < 0) ErrorExit(USER_ERROR,ARGV0,user,group); /* Privilege separation */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR,ARGV0,group); /* Signal manipulation */ StartSIG(ARGV0); /* Creating PID files */ if(CreatePID(ARGV0, getpid()) < 0) ErrorExit(PID_ERROR,ARGV0); #endif /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); if(agentname == NULL) { lhostname[512] = '\0'; if(gethostname(lhostname, 512 -1) != 0) { merror("%s: ERROR: Unable to extract hostname. Custom agent name not set.", ARGV0); exit(1); } agentname = lhostname; } /* Starting SSL */ ctx = os_ssl_keys(1, NULL); if(!ctx) { merror("%s: ERROR: SSL error. Exiting.", ARGV0); exit(1); } if(!manager) { merror("%s: ERROR: Manager IP not set.", ARGV0); exit(1); } /* Check to see if manager is an IP */ int is_ip = 1; struct sockaddr_in iptest; memset(&iptest, 0, sizeof(iptest)); if(inet_pton(AF_INET, manager, &iptest.sin_addr) != 1) is_ip = 0; /* This is not an IPv4 address */ /* Not IPv4, IPv6 maybe? */ if(is_ip == 0) { struct sockaddr_in6 iptest6; memset(&iptest6, 0, sizeof(iptest6)); if(inet_pton(AF_INET6, manager, &iptest6.sin6_addr) != 1) is_ip = 0; else is_ip = 1; /* This is an IPv6 address */ } /* If it isn't an ip, try to resolve the IP */ if(is_ip == 0) { char *ipaddress; ipaddress = OS_GetHost(manager, 3); if(ipaddress != NULL) strncpy(manager, ipaddress, 16); else { printf("Could not resolve hostname: %s\n", manager); return(1); } } /* Connecting via TCP */ sock = OS_ConnectTCP(port, manager, 0); if(sock <= 0) { merror("%s: Unable to connect to %s:%d", ARGV0, manager, port); exit(1); } /* Connecting the SSL socket */ ssl = SSL_new(ctx); sbio = BIO_new_socket(sock, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); ret = SSL_connect(ssl); if(ret <= 0) { ERR_print_errors_fp(stderr); merror("%s: ERROR: SSL error (%d). Exiting.", ARGV0, ret); exit(1); } printf("INFO: Connected to %s:%d\n", manager, port); printf("INFO: Using agent name as: %s\n", agentname); snprintf(buf, 2048, "OSSEC A:'%s'\n", agentname); ret = SSL_write(ssl, buf, strlen(buf)); if(ret < 0) { printf("SSL write error (unable to send message.)\n"); ERR_print_errors_fp(stderr); exit(1); } printf("INFO: Send request to manager. Waiting for reply.\n"); while(1) { ret = SSL_read(ssl,buf,sizeof(buf) -1); switch(SSL_get_error(ssl,ret)) { case SSL_ERROR_NONE: buf[ret] = '\0'; if(strncmp(buf, "ERROR", 5) == 0) { char *tmpstr; tmpstr = strchr(buf, '\n'); if(tmpstr) *tmpstr = '\0'; printf("%s (from manager)\n", buf); } else if(strncmp(buf, "OSSEC K:'",9) == 0) { char *key; char *tmpstr; char **entry; printf("INFO: Received response with agent key\n"); key = buf; key += 9; tmpstr = strchr(key, '\''); if(!tmpstr) { printf("ERROR: Invalid key received. Closing connection.\n"); exit(1); } *tmpstr = '\0'; entry = OS_StrBreak(' ', key, 4); if(!OS_IsValidID(entry[0]) || !OS_IsValidName(entry[1]) || !OS_IsValidName(entry[2]) || !OS_IsValidName(entry[3])) { printf("ERROR: Invalid key received (2). Closing connection.\n"); exit(1); } { FILE *fp; fp = fopen(KEYSFILE_PATH,"w"); if(!fp) { printf("ERROR: Unable to open key file: %s", KEYSFILE_PATH); exit(1); } fprintf(fp, "%s\n", key); fclose(fp); } printf("INFO: Valid key created. Finished.\n"); } break; case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_SYSCALL: printf("INFO: Connection closed.\n"); exit(0); break; default: printf("ERROR: SSL read (unable to receive message)\n"); exit(1); break; } } /* Shutdown the socket */ SSL_CTX_free(ctx); close(sock); exit(0); }
/* handle_connect_results assumes that select or poll have already shown the * descriptor to be active */ void handle_connect_result(struct npool *ms, struct nevent *nse, enum nse_status status) { int optval; socklen_t optlen = sizeof(int); struct niod *iod = nse->iod; #if HAVE_OPENSSL int sslerr; int rc = 0; int sslconnect_inprogress = nse->type == NSE_TYPE_CONNECT_SSL && nse->iod && (nse->sslinfo.ssl_desire == SSL_ERROR_WANT_READ || nse->sslinfo.ssl_desire == SSL_ERROR_WANT_WRITE); #else int sslconnect_inprogress = 0; #endif if (status == NSE_STATUS_TIMEOUT || status == NSE_STATUS_CANCELLED) { nse->status = status; nse->event_done = 1; } else if (sslconnect_inprogress) { /* Do nothing */ } else if (status == NSE_STATUS_SUCCESS) { /* First we want to determine whether the socket really is connected */ if (getsockopt(iod->sd, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen) != 0) optval = socket_errno(); /* Stupid Solaris */ switch (optval) { case 0: nse->status = NSE_STATUS_SUCCESS; break; /* EACCES can be caused by ICMPv6 dest-unreach-admin, or when a port is blocked by Windows Firewall (WSAEACCES). */ case EACCES: case ECONNREFUSED: case EHOSTUNREACH: case ENETDOWN: case ENETUNREACH: case ENETRESET: case ECONNABORTED: case ETIMEDOUT: case EHOSTDOWN: case ECONNRESET: #ifdef WIN32 case WSAEADDRINUSE: case WSAEADDRNOTAVAIL: #endif #ifndef WIN32 case EPIPE: /* Has been seen after connect on Linux. */ case ENOPROTOOPT: /* Also seen on Linux, perhaps in response to protocol unreachable. */ #endif nse->status = NSE_STATUS_ERROR; nse->errnum = optval; break; default: /* I'd like for someone to report it */ fatal("Strange connect error from %s (%d): %s", inet_ntop_ez(&iod->peer, iod->peerlen), optval, socket_strerror(optval)); } /* Now special code for the SSL case where the TCP connection was successful. */ if (nse->type == NSE_TYPE_CONNECT_SSL && nse->status == NSE_STATUS_SUCCESS) { #if HAVE_OPENSSL assert(ms->sslctx != NULL); /* Reuse iod->ssl if present. If set, this is the second try at connection without the SSL_OP_NO_SSLv2 option set. */ if (iod->ssl == NULL) { iod->ssl = SSL_new(ms->sslctx); if (!iod->ssl) fatal("SSL_new failed: %s", ERR_error_string(ERR_get_error(), NULL)); } #if HAVE_SSL_SET_TLSEXT_HOST_NAME if (iod->hostname != NULL) { if (SSL_set_tlsext_host_name(iod->ssl, iod->hostname) != 1) fatal("SSL_set_tlsext_host_name failed: %s", ERR_error_string(ERR_get_error(), NULL)); } #endif /* Associate our new SSL with the connected socket. It will inherit the * non-blocking nature of the sd */ if (SSL_set_fd(iod->ssl, iod->sd) != 1) fatal("SSL_set_fd failed: %s", ERR_error_string(ERR_get_error(), NULL)); /* Event not done -- need to do SSL connect below */ nse->sslinfo.ssl_desire = SSL_ERROR_WANT_CONNECT; #endif } else { /* This is not an SSL connect (in which case we are always done), or the * TCP connect() underlying the SSL failed (in which case we are also done */ nse->event_done = 1; } } else { fatal("Unknown status (%d)", status); } /* At this point the TCP connection is done, whether successful or not. * Therefore decrease the read/write listen counts that were incremented in * nsp_add_event. In the SSL case, we may increase one of the counts depending * on whether SSL_connect returns an error of SSL_ERROR_WANT_READ or * SSL_ERROR_WANT_WRITE. In that case we will re-enter this function, but we * don't want to execute this block again. */ if (iod->sd != -1 && !sslconnect_inprogress) { int ev = EV_NONE; ev |= socket_count_read_dec(iod); ev |= socket_count_write_dec(iod); ev |= EV_EXCEPT; update_events(iod, ms, EV_NONE, ev); } #if HAVE_OPENSSL if (nse->type == NSE_TYPE_CONNECT_SSL && !nse->event_done) { /* Lets now start/continue/finish the connect! */ if (iod->ssl_session) { rc = SSL_set_session(iod->ssl, iod->ssl_session); if (rc == 0) nsock_log_error(ms, "Uh-oh: SSL_set_session() failed - please tell [email protected]"); iod->ssl_session = NULL; /* No need for this any more */ } /* If this is a reinvocation of handle_connect_result, clear out the listen * bits that caused it, based on the previous SSL desire. */ if (sslconnect_inprogress) { int ev; ev = socket_count_dec_ssl_desire(nse); update_events(iod, ms, EV_NONE, ev); } rc = SSL_connect(iod->ssl); if (rc == 1) { /* Woop! Connect is done! */ nse->event_done = 1; /* Check that certificate verification was okay, if requested. */ if (nsi_ssl_post_connect_verify(iod)) { nse->status = NSE_STATUS_SUCCESS; } else { nsock_log_error(ms, "certificate verification error for EID %li: %s", nse->id, ERR_error_string(ERR_get_error(), NULL)); nse->status = NSE_STATUS_ERROR; } } else { long options = SSL_get_options(iod->ssl); sslerr = SSL_get_error(iod->ssl, rc); if (rc == -1 && sslerr == SSL_ERROR_WANT_READ) { nse->sslinfo.ssl_desire = sslerr; socket_count_read_inc(iod); update_events(iod, ms, EV_READ, EV_NONE); } else if (rc == -1 && sslerr == SSL_ERROR_WANT_WRITE) { nse->sslinfo.ssl_desire = sslerr; socket_count_write_inc(iod); update_events(iod, ms, EV_WRITE, EV_NONE); } else if (!(options & SSL_OP_NO_SSLv2)) { int saved_ev; /* SSLv3-only and TLSv1-only servers can't be connected to when the * SSL_OP_NO_SSLv2 option is not set, which is the case when the pool * was initialized with nsp_ssl_init_max_speed. Try reconnecting with * SSL_OP_NO_SSLv2. Never downgrade a NO_SSLv2 connection to one that * might use SSLv2. */ nsock_log_info(ms, "EID %li reconnecting with SSL_OP_NO_SSLv2", nse->id); saved_ev = iod->watched_events; nsock_engine_iod_unregister(ms, iod); close(iod->sd); nsock_connect_internal(ms, nse, SOCK_STREAM, iod->lastproto, &iod->peer, iod->peerlen, nsi_peerport(iod)); nsock_engine_iod_register(ms, iod, saved_ev); SSL_clear(iod->ssl); if(!SSL_clear(iod->ssl)) fatal("SSL_clear failed: %s", ERR_error_string(ERR_get_error(), NULL)); SSL_set_options(iod->ssl, options | SSL_OP_NO_SSLv2); socket_count_read_inc(nse->iod); socket_count_write_inc(nse->iod); update_events(iod, ms, EV_READ|EV_WRITE, EV_NONE); nse->sslinfo.ssl_desire = SSL_ERROR_WANT_CONNECT; } else { nsock_log_info(ms, "EID %li %s", nse->id, ERR_error_string(ERR_get_error(), NULL)); nse->event_done = 1; nse->status = NSE_STATUS_ERROR; nse->errnum = EIO; } } } #endif }
int main(int argc, char **argv) { int c; int sock = 0, portnum, ret = 0; char *host = NULL, *port = "443"; SSL_CTX *ctx; SSL *ssl; SSL_METHOD *sslmeth; BIO *sbio; BIO *bio_err = 0; while ((c = getopt(argc, argv, "h:p:")) != -1) { switch (c) { case 'h': host = optarg; break; case 'p': portnum = atoi(optarg); if (portnum <= 0 || portnum >= 65536) { exit(1); } port = optarg; break; default: exit(1); break; } } if (!bio_err) { SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); } sslmeth = SSLv23_method(); ctx = SSL_CTX_new(sslmeth); if (!ctx) { printf("CTX ERROR\n"); exit(1); } if (!host) { printf("ERROR - host not set.\n"); exit(1); } /* Connect via TCP */ sock = OS_ConnectTCP(port, host); if (sock <= 0) { printf("connect error\n"); exit(1); } /* Connect the SSL socket */ ssl = SSL_new(ctx); sbio = BIO_new_socket(sock, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); ret = SSL_connect(ssl); if (ret <= 0) { printf("SSL connect error\n"); ERR_print_errors_fp(stderr); exit(1); } printf("Connected!\n"); ret = SSL_write(ssl, TEST, sizeof(TEST)); if (ret < 0) { printf("SSL write error\n"); ERR_print_errors_fp(stderr); exit(1); } while (1) { char buf[2048]; ret = SSL_read(ssl, buf, sizeof(buf) - 1); printf("ret: %d\n", ret); switch (SSL_get_error(ssl, ret)) { case SSL_ERROR_NONE: buf[ret] = '\0'; printf("no error: %s\n", buf); break; case SSL_ERROR_ZERO_RETURN: printf("no return\n"); exit(1); break; case SSL_ERROR_SYSCALL: fprintf(stderr, "SSL Error: Premature close\n"); exit(1); break; default: printf("default error\n"); exit(1); break; } } exit(0); }
bool SSLSocket::enableCrypto(bool activate /* = true */) { if (activate && !m_data->m_ssl_active) { double timeout = m_data->m_connect_timeout; bool blocked = m_data->m_is_blocked; if (!m_data->m_state_set) { if (m_data->m_client) { SSL_set_connect_state(m_data->m_handle); } else { SSL_set_accept_state(m_data->m_handle); } m_data->m_state_set = true; } if (m_data->m_client && setBlocking(false)) { m_data->m_is_blocked = false; } int n; bool retry = true; do { if (m_data->m_client) { struct timeval tvs, tve; struct timezone tz; gettimeofday(&tvs, &tz); n = SSL_connect(m_data->m_handle); gettimeofday(&tve, &tz); timeout -= (tve.tv_sec + (double) tve.tv_usec / 1000000) - (tvs.tv_sec + (double) tvs.tv_usec / 1000000); if (timeout < 0) { raise_warning("SSL: connection timeout"); return false; } } else { n = SSL_accept(m_data->m_handle); } if (n <= 0) { retry = handleError(n, true); } else { break; } } while (retry); if (m_data->m_client && m_data->m_is_blocked != blocked && setBlocking(blocked)) { m_data->m_is_blocked = blocked; } if (n == 1) { X509 *peer_cert = SSL_get_peer_certificate(m_data->m_handle); if (!applyVerificationPolicy(peer_cert)) { SSL_shutdown(m_data->m_handle); } else { m_data->m_ssl_active = true; /* allow the script to capture the peer cert * and/or the certificate chain */ if (m_context[s_capture_peer_cert].toBoolean()) { m_context.set(s_peer_certificate, Variant(req::make<Certificate>(peer_cert))); peer_cert = nullptr; } if (m_context[s_capture_peer_cert_chain].toBoolean()) { Array arr; STACK_OF(X509) *chain = SSL_get_peer_cert_chain(m_data->m_handle); if (chain) { for (int i = 0; i < sk_X509_num(chain); i++) { X509 *mycert = X509_dup(sk_X509_value(chain, i)); arr.append(Variant(req::make<Certificate>(mycert))); } } m_context.set(s_peer_certificate_chain, arr); } } if (peer_cert) { X509_free(peer_cert); } } else { n = errno == EAGAIN ? 0 : -1; } return n >= 0; } else if (!activate && m_data->m_ssl_active) { /* deactivate - common for server/client */ SSL_shutdown(m_data->m_handle); m_data->m_ssl_active = false; } return true; }
void _socket_handle(int fd, int type) { sock *sock = fds[fd]; if (sock == NULL) { return; } sock->flags |= SOCKET_INUSE; #ifdef HAVE_SSL switch (sock->sslstate) { case SSL_OFF: case SSL_IDLE: #endif if ((type & MONITOR_READ) && sock->read_handler) { sock->read_handler(sock); } if ((type & MONITOR_WRITE) && sock->write_handler) { sock->write_handler(sock); } #ifdef HAVE_SSL break; case SSL_ACCEPT: if (_socket_checkssl(sock, SSL_accept(sock->ssl)) < 0) { type |= MONITOR_ERROR; } break; case SSL_CONNECT: if (_socket_checkssl(sock, SSL_connect(sock->ssl)) < 0) { type |= MONITOR_ERROR; } break; case SSL_READ: if (sock->read_handler) { sock->read_handler(sock); } break; case SSL_WRITE: if (sock->write_handler) { sock->write_handler(sock); } break; } #endif if ((type & MONITOR_ERROR) && sock->error_handler) { sock->error_handler(sock); } if (sock->flags & SOCKET_CLOSE) { _socket_free(sock); } else { sock->flags &= ~SOCKET_INUSE; } }
int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int version, char *cert, char *privkey) { SSL_METHOD *method = NULL; switch (version) { case 0: /* Deafult to auto negotiation */ method = SSLv23_client_method(); break; case 1: /* TLSv1 protocol */ method = TLSv1_client_method(); break; case 2: /* SSLv2 protocol */ #if defined(USE_GNUTLS) || defined(OPENSSL_NO_SSL2) printf(("%s\n", _("CRITICAL - SSL protocol version 2 is not supported by your SSL library."))); return STATE_CRITICAL; #else method = SSLv2_client_method(); #endif break; case 3: /* SSLv3 protocol */ method = SSLv3_client_method(); break; default: /* Unsupported */ printf("%s\n", _("CRITICAL - Unsupported SSL protocol version.")); return STATE_CRITICAL; } if (!initialized) { /* Initialize SSL context */ SSLeay_add_ssl_algorithms(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); initialized = 1; } if ((c = SSL_CTX_new(method)) == NULL) { printf("%s\n", _("CRITICAL - Cannot create SSL context.")); return STATE_CRITICAL; } if (cert && privkey) { SSL_CTX_use_certificate_file(c, cert, SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(c, privkey, SSL_FILETYPE_PEM); if (!SSL_CTX_check_private_key(c)) { printf ("%s\n", _("CRITICAL - Private key does not seem to match certificate!\n")); return STATE_CRITICAL; } } #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(c, SSL_OP_NO_TICKET); #endif SSL_CTX_set_mode(c, SSL_MODE_AUTO_RETRY); if ((s = SSL_new(c)) != NULL) { #ifdef SSL_set_tlsext_host_name if (host_name != NULL) SSL_set_tlsext_host_name(s, host_name); #endif SSL_set_fd(s, sd); if (SSL_connect(s) == 1) { return OK; } else { printf("%s\n", _("CRITICAL - Cannot make SSL connection.")); # ifdef USE_OPENSSL /* XXX look into ERR_error_string */ ERR_print_errors_fp(stdout); # endif /* USE_OPENSSL */ } } else { printf("%s\n", _("CRITICAL - Cannot initiate SSL handshake.")); } return STATE_CRITICAL; }
// This test launches a gRPC server on a separate thread and then establishes a // TLS handshake via a minimal TLS client. The TLS client has configurable (via // alpn_list) ALPN settings and can probe at the supported ALPN preferences // using this (via alpn_expected). static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, const char *alpn_expected) { bool success = true; grpc_init(); int port = grpc_pick_unused_port_or_die(); gpr_event_init(&client_handshake_complete); // Launch the gRPC server thread. gpr_thd_options thdopt = gpr_thd_options_default(); gpr_thd_id thdid; gpr_thd_options_set_joinable(&thdopt); GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt)); SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); const SSL_METHOD *method = TLSv1_2_client_method(); SSL_CTX *ctx = SSL_CTX_new(method); if (!ctx) { perror("Unable to create SSL context"); ERR_print_errors_fp(stderr); abort(); } // Load key pair. if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { ERR_print_errors_fp(stderr); abort(); } if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { ERR_print_errors_fp(stderr); abort(); } // Set the cipher list to match the one expressed in // src/core/lib/tsi/ssl_transport_security.c. const char *cipher_list = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { ERR_print_errors_fp(stderr); gpr_log(GPR_ERROR, "Couldn't set server cipher list."); abort(); } // Configure ALPN list the client will send to the server. This must match the // wire format, see documentation for SSL_CTX_set_alpn_protos. unsigned int alpn_protos_len = alpn_list_len; for (unsigned int i = 0; i < alpn_list_len; ++i) { alpn_protos_len += (unsigned int)strlen(alpn_list[i]); } unsigned char *alpn_protos = gpr_malloc(alpn_protos_len); unsigned char *p = alpn_protos; for (unsigned int i = 0; i < alpn_list_len; ++i) { const uint8_t len = (uint8_t)strlen(alpn_list[i]); *p++ = len; memcpy(p, alpn_list[i], len); p += len; } GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0); // Try and connect to server. We allow a bounded number of retries as we might // be racing with the server setup on its separate thread. int retries = 10; int sock = -1; while (sock == -1 && retries-- > 0) { sock = create_socket(port); if (sock < 0) { sleep(1); } } GPR_ASSERT(sock > 0); gpr_log(GPR_INFO, "Connected to server on port %d", port); // Establish a SSL* and connect at SSL layer. SSL *ssl = SSL_new(ctx); GPR_ASSERT(ssl); SSL_set_fd(ssl, sock); if (SSL_connect(ssl) <= 0) { ERR_print_errors_fp(stderr); gpr_log(GPR_ERROR, "Handshake failed."); success = false; } else { gpr_log(GPR_INFO, "Handshake successful."); // Validate ALPN preferred by server matches alpn_expected. const unsigned char *alpn_selected; unsigned int alpn_selected_len; SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len); if (strlen(alpn_expected) != alpn_selected_len || strncmp((const char *)alpn_selected, alpn_expected, alpn_selected_len) != 0) { gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference"); success = false; } } gpr_event_set(&client_handshake_complete, &client_handshake_complete); SSL_free(ssl); gpr_free(alpn_protos); SSL_CTX_free(ctx); EVP_cleanup(); close(sock); gpr_thd_join(thdid); grpc_shutdown(); return success; }
static int ssl23_get_server_hello(SSL *s) { char buf[8]; unsigned char *p; int i; int n; n = ssl23_read_bytes(s, 7); if (n != 7) return (n); p = s->packet; memcpy(buf, p, n); /* Old unsupported sslv2 handshake */ if ((p[0] & 0x80) && (p[2] == SSL2_MT_SERVER_HELLO) && (p[5] == 0x00) && (p[6] == 0x02)) { SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_R_UNSUPPORTED_PROTOCOL); goto err; } if (p[1] == SSL3_VERSION_MAJOR && p[2] <= TLS1_2_VERSION_MINOR && ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) || (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2))) { /* we have sslv3 or tls1 (server hello or alert) */ if ((p[2] == SSL3_VERSION_MINOR) && !(s->options & SSL_OP_NO_SSLv3)) { s->version = SSL3_VERSION; s->method = SSLv3_client_method(); } else if ((p[2] == TLS1_VERSION_MINOR) && !(s->options & SSL_OP_NO_TLSv1)) { s->version = TLS1_VERSION; s->method = TLSv1_client_method(); } else if ((p[2] == TLS1_1_VERSION_MINOR) && !(s->options & SSL_OP_NO_TLSv1_1)) { s->version = TLS1_1_VERSION; s->method = TLSv1_1_client_method(); } else if ((p[2] == TLS1_2_VERSION_MINOR) && !(s->options & SSL_OP_NO_TLSv1_2)) { s->version = TLS1_2_VERSION; s->method = TLSv1_2_client_method(); } else { SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_R_UNSUPPORTED_PROTOCOL); goto err; } if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING) { /* fatal alert */ void (*cb)(const SSL *ssl, int type, int val) = NULL; int j; if (s->info_callback != NULL) cb = s->info_callback; else if (s->ctx->info_callback != NULL) cb = s->ctx->info_callback; i = p[5]; if (cb != NULL) { j = (i << 8) | p[6]; cb(s, SSL_CB_READ_ALERT, j); } if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_ALERT, p + 5, 2, s, s->msg_callback_arg); s->rwstate = SSL_NOTHING; SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_AD_REASON_OFFSET + p[6]); goto err; } if (!ssl_init_wbio_buffer(s, 1)) goto err; /* we are in this state */ s->state = SSL3_ST_CR_SRVR_HELLO_A; /* put the 7 bytes we have read into the input buffer * for SSLv3 */ s->rstate = SSL_ST_READ_HEADER; s->packet_length = n; if (s->s3->rbuf.buf == NULL) if (!ssl3_setup_read_buffer(s)) goto err; s->packet = &(s->s3->rbuf.buf[0]); memcpy(s->packet, buf, n); s->s3->rbuf.left = n; s->s3->rbuf.offset = 0; s->handshake_func = s->method->ssl_connect; } else { SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_R_UNKNOWN_PROTOCOL); goto err; } s->init_num = 0; /* * Since, if we are sending a ssl23 client hello, we are not * reusing a session-id */ if (!ssl_get_new_session(s, 0)) goto err; return (SSL_connect(s)); err: return (-1); }
int OpenSSLClient::handshakeFunction() { return SSL_connect( m_ssl ); }
R_API int r_socket_connect (RSocket *s, const char *host, const char *port, int proto, int timeout) { #if __WINDOWS__ struct sockaddr_in sa; struct hostent *he; WSADATA wsadata; if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) { eprintf ("Error creating socket."); return R_FALSE; } s->fd = socket (AF_INET, SOCK_STREAM, 0); if (s->fd == -1) return R_FALSE; memset (&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; he = (struct hostent *)gethostbyname (host); if (he == (struct hostent*)0) { close (s->fd); return R_FALSE; } sa.sin_addr = *((struct in_addr *)he->h_addr); s->port = r_socket_port_by_name (port); sa.sin_port = htons (s->port); #warning TODO: implement connect timeout on w32 if (connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) { close (s->fd); return R_FALSE; } return R_TRUE; #elif __UNIX__ if (!proto) proto = R_SOCKET_PROTO_TCP; int gai, ret; struct addrinfo hints, *res, *rp; signal (SIGPIPE, SIG_IGN); if (proto == R_SOCKET_PROTO_UNIX) { if (!r_socket_unix_connect (s, host)) return R_FALSE; } else { memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_protocol = proto; gai = getaddrinfo (host, port, &hints, &res); if (gai != 0) { //eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai)); return R_FALSE; } for (rp = res; rp != NULL; rp = rp->ai_next) { s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s->fd == -1) continue; if (timeout>0) r_socket_block_time (s, 1, timeout); //fcntl (s->fd, F_SETFL, O_NONBLOCK, 1); ret = connect (s->fd, rp->ai_addr, rp->ai_addrlen); if (ret<0) { close (s->fd); s->fd = -1; continue; } if (timeout<1) { if (ret == -1) { close (s->fd); s->fd = -1; return R_FALSE; } return R_TRUE; } if (timeout>0) { struct timeval tv; fd_set fdset, errset; FD_ZERO (&fdset); FD_SET (s->fd, &fdset); tv.tv_sec = 1; //timeout; tv.tv_usec = 0; if (r_socket_is_connected (s)) return R_TRUE; if (select (s->fd + 1, NULL, NULL, &errset, &tv) == 1) { int so_error; socklen_t len = sizeof so_error; ret = getsockopt (s->fd, SOL_SOCKET, SO_ERROR, &so_error, &len); // fcntl (s->fd, F_SETFL, O_NONBLOCK, 0); // r_socket_block_time (s, 0, 0); freeaddrinfo (res); return R_TRUE; } else { // freeaddrinfo (res); close (s->fd); s->fd = -1; continue; // return R_FALSE; } } close (s->fd); s->fd = -1; } freeaddrinfo (res); if (rp == NULL) { eprintf ("Could not resolve address '%s'\n", host); return R_FALSE; } } #endif #if HAVE_LIB_SSL if (s->is_ssl) { s->ctx = SSL_CTX_new (SSLv23_client_method ()); if (s->ctx == NULL) { r_socket_free (s); return R_FALSE; } s->sfd = SSL_new (s->ctx); SSL_set_fd (s->sfd, s->fd); if (SSL_connect (s->sfd) != 1) { r_socket_free (s); return R_FALSE; } } #endif return R_TRUE; }
/* OS dependent */ Boolean rocs_socket_connect( iOSocket inst ) { #ifdef __ROCS_SOCKET__ iOSocketData o = Data(inst); struct sockaddr_in srvaddr; struct in_addr* addr = o->hostaddr; int rc = 0; if( o->sh == 0 ) rocs_socket_create( o ); if( o->sh == 0 ) return False; if( !rocs_socket_resolveHost( o ) ) return False; addr = o->hostaddr; memset( &srvaddr,0, sizeof( struct sockaddr_in ) ); srvaddr.sin_family = AF_INET; srvaddr.sin_port = htons( (u_short)o->port ); srvaddr.sin_addr = *addr; rc = connect( o->sh, (struct sockaddr *)&srvaddr, sizeof( struct sockaddr_in ) ); if( rc == -1 ) { o->rc = WSAGetLastError(); TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "connect(%s:%d) failed [%d]", o->host, o->port , WSAGetLastError() ); o->connected = False; return False; } o->connected = True; TraceOp.trc( name, TRCLEVEL_DEBUG, __LINE__, 9999, "socket connected." ); if( o->ssl ) { #ifdef __OPENSSL__ SSL_METHOD* meth; X509* server_cert; o->openssl_support = True; SSLeay_add_ssl_algorithms(); meth = SSLv3_client_method(); SSL_load_error_strings(); o->ssl_ctx = SSL_CTX_new (meth); TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "OpenSSL support.(v%d)", meth->version ); o->ssl_sh = SSL_new( o->ssl_ctx ); if( o->ssl_sh != NULL ) { SSL_set_fd( o->ssl_sh, o->sh ); rc = SSL_connect( o->ssl_sh ); if( rc <= 0 ) { char err[256] = {'\0'}; rc = ERR_peek_error(); ERR_error_string_n( (unsigned long) rc, err, sizeof(err) ); TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "SSL_connect() failed [%d] %s", rc, err ); o->connected = False; o->openssl_support = False; return False; } /* Trace some info. */ TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "SSL connection using %s", SSL_get_cipher( o->ssl_sh ) ); server_cert = SSL_get_peer_certificate( o->ssl_sh ); if( server_cert != NULL ) { char* sub = NULL; char* iss = NULL; sub = X509_NAME_oneline( X509_get_subject_name( server_cert ), 0, 0 ); iss = X509_NAME_oneline( X509_get_issuer_name ( server_cert ), 0, 0 ); TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "SSL Server certificate subject = %s, issuer = %s", sub, iss ); free( sub ); free( iss ); } } #else TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "SSL requested but not supported! Compile with __OPENSSL__ defined." ); return False; #endif } #endif return True; }
void echoclient_test(void* args) { SOCKET_T sockfd = 0; FILE* fin = stdin; FILE* fout = stdout; int inCreated = 0; int outCreated = 0; char send[1024]; char reply[1024]; SSL_METHOD* method = 0; SSL_CTX* ctx = 0; SSL* ssl = 0; int doDTLS = 0; int sendSz; int argc = 0; char** argv = 0; ((func_args*)args)->return_code = -1; /* error state */ argc = ((func_args*)args)->argc; argv = ((func_args*)args)->argv; if (argc >= 2) { fin = fopen(argv[1], "r"); inCreated = 1; } if (argc >= 3) { fout = fopen(argv[2], "w"); outCreated = 1; } if (!fin) err_sys("can't open input file"); if (!fout) err_sys("can't open output file"); #ifdef CYASSL_DTLS doDTLS = 1; #endif tcp_connect(&sockfd, yasslIP, yasslPort, doDTLS); #if defined(CYASSL_DTLS) method = DTLSv1_client_method(); #elif !defined(NO_TLS) method = CyaSSLv23_client_method(); #else method = SSLv3_client_method(); #endif ctx = SSL_CTX_new(method); #ifndef NO_FILESYSTEM if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from CyaSSL home dir"); #ifdef HAVE_ECC if (SSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from CyaSSL home dir"); #endif #else load_buffer(ctx, caCert, CYASSL_CA); #endif #if defined(CYASSL_SNIFFER) && !defined(HAVE_NTRU) && !defined(HAVE_ECC) /* don't use EDH, can't sniff tmp keys */ SSL_CTX_set_cipher_list(ctx, "AES256-SHA"); #endif #ifdef OPENSSL_EXTRA SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); #if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER) /* let echoserver bind first, TODO: add Windows signal like pthreads does */ Sleep(100); #endif if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed"); while (fgets(send, sizeof(send), fin)) { sendSz = (int)strlen(send); if (SSL_write(ssl, send, sendSz) != sendSz) err_sys("SSL_write failed"); if (strncmp(send, "quit", 4) == 0) { fputs("sending server shutdown command: quit!\n", fout); break; } if (strncmp(send, "break", 5) == 0) { fputs("sending server session close: break!\n", fout); break; } while (sendSz) { int got; if ( (got = SSL_read(ssl, reply, sizeof(reply))) > 0) { reply[got] = 0; fputs(reply, fout); sendSz -= got; } else break; } } #ifdef CYASSL_DTLS strncpy(send, "break", 6); sendSz = (int)strlen(send); /* try to tell server done */ SSL_write(ssl, send, sendSz); #else SSL_shutdown(ssl); #endif SSL_free(ssl); SSL_CTX_free(ctx); fflush(fout); if (inCreated) fclose(fin); if (outCreated) fclose(fout); CloseSocket(sockfd); ((func_args*)args)->return_code = 0; }
static void handle_connect(int cnum, struct timeval* nowP, int double_check) { int url_num; char buf[600]; int bytes, r; url_num = connections[cnum].url_num; if (double_check) { /* Check to make sure the non-blocking connect succeeded. */ int err, errlen; if (connect(connections[cnum].conn_fd, (struct sockaddr*)&connections[cnum].sa, connections[cnum].sa_len) < 0) { switch(errno) { case EISCONN: /* Ok! */ break; case EINVAL: errlen = sizeof(err); if ( getsockopt( connections[cnum].conn_fd, SOL_SOCKET, SO_ERROR, (void*) &err, (socklen_t*)&errlen ) < 0 ) { (void) fprintf(stderr, "%s: unknown connect error\n", urls[url_num].url_str ); } else { (void) fprintf(stderr, "%s: %s\n", urls[url_num].url_str, strerror( err )); } close_connection( cnum ); return; default: perror( urls[url_num].url_str ); close_connection( cnum ); return; } } } #ifdef USE_SSL if ( urls[url_num].protocol == PROTO_HTTPS ) { int flags; /* Make SSL connection. */ if ( ssl_ctx == (SSL_CTX*) 0 ) { SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); ssl_ctx = SSL_CTX_new( SSLv23_client_method() ); if ( cipher != (char*) 0 ) { if ( ! SSL_CTX_set_cipher_list( ssl_ctx, cipher ) ) { (void) fprintf( stderr, "%s: cannot set cipher list\n", argv0 ); ERR_print_errors_fp( stderr ); close_connection( cnum ); return; } } } if ( ! RAND_status() ) { unsigned char bytes[1024]; int i; for ( i = 0; i < sizeof(bytes); ++i ) bytes[i] = random() % 0xff; RAND_seed( bytes, sizeof(bytes) ); } flags = fcntl( connections[cnum].conn_fd, F_GETFL, 0 ); if ( flags != -1 ) (void) fcntl( connections[cnum].conn_fd, F_SETFL, flags & ~ (int) O_NDELAY ); connections[cnum].ssl = SSL_new( ssl_ctx ); SSL_set_fd( connections[cnum].ssl, connections[cnum].conn_fd ); r = SSL_connect( connections[cnum].ssl ); if ( r <= 0 ) { (void) fprintf( stderr, "%s: SSL connection failed - %d\n", argv0, r ); ERR_print_errors_fp( stderr ); close_connection( cnum ); return; } } #endif connections[cnum].did_connect = 1; /* Format the request. */ if (do_proxy) { #ifdef USE_SSL bytes = snprintf( buf, sizeof(buf), "GET %s://%.500s:%d%.500s HTTP/1.0\r\n", urls[url_num].protocol == PROTO_HTTPS ? "https" : "http", urls[url_num].hostname, (int) urls[url_num].port, urls[url_num].filename ); #else bytes = snprintf(buf, sizeof(buf), "GET http://%.500s:%d%.500s HTTP/1.0\r\n", urls[url_num].hostname, (int)urls[url_num].port, urls[url_num].filename); #endif } else { bytes = snprintf(buf, sizeof(buf), "GET %.500s HTTP/1.0\r\n", urls[url_num].filename); } bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "Host: %s\r\n", urls[url_num].hostname); bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "User-Agent: %s\r\n", VERSION); bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "\r\n"); /* Send the request. */ connections[cnum].request_at = *nowP; #ifdef USE_SSL if ( urls[url_num].protocol == PROTO_HTTPS ) r = SSL_write( connections[cnum].ssl, buf, bytes ); else r = write( connections[cnum].conn_fd, buf, bytes ); #else r = write(connections[cnum].conn_fd, buf, bytes); #endif if (r < 0) { perror(urls[url_num].url_str); close_connection(cnum); return; } connections[cnum].conn_state = CNST_HEADERS; connections[cnum].header_state = HDST_LINE1_PROTOCOL; }
tcpcon_t * tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize, int timeout, int ssl) { struct hostent *hp; char *tmphstbuf; int fd, val, r, err, herr; const char *errtxt; #if !defined(__APPLE__) struct hostent hostbuf; size_t hstbuflen; int res; #endif struct sockaddr_in6 in6; struct sockaddr_in in; socklen_t errlen = sizeof(int); if(!strcmp(hostname, "localhost")) { if((fd = getstreamsocket(AF_INET, errbuf, errbufsize)) == -1) return NULL; memset(&in, 0, sizeof(in)); in.sin_family = AF_INET; in.sin_port = htons(port); in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in)); } else { #if defined(__APPLE__) herr = 0; tmphstbuf = NULL; /* free NULL is a nop */ /* TODO: AF_INET6 */ hp = gethostbyname(hostname); if(hp == NULL) herr = h_errno; #else hstbuflen = 1024; tmphstbuf = malloc(hstbuflen); while((res = gethostbyname_r(hostname, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr)) == ERANGE) { hstbuflen *= 2; tmphstbuf = realloc(tmphstbuf, hstbuflen); } #endif if(herr != 0) { switch(herr) { case HOST_NOT_FOUND: errtxt = "Unknown host"; break; case NO_ADDRESS: errtxt = "The requested name is valid but does not have an IP address"; break; case NO_RECOVERY: errtxt = "A non-recoverable name server error occurred"; break; case TRY_AGAIN: errtxt = "A temporary error occurred on an authoritative name server"; break; default: errtxt = "Unknown error"; break; } snprintf(errbuf, errbufsize, "%s", errtxt); free(tmphstbuf); return NULL; } else if(hp == NULL) { snprintf(errbuf, errbufsize, "Resolver internal error"); free(tmphstbuf); return NULL; } if((fd = getstreamsocket(hp->h_addrtype, errbuf, errbufsize)) == -1) { free(tmphstbuf); return NULL; } switch(hp->h_addrtype) { case AF_INET: memset(&in, 0, sizeof(in)); in.sin_family = AF_INET; in.sin_port = htons(port); memcpy(&in.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in)); break; case AF_INET6: memset(&in6, 0, sizeof(in6)); in6.sin6_family = AF_INET6; in6.sin6_port = htons(port); memcpy(&in6.sin6_addr, hp->h_addr_list[0], sizeof(struct in6_addr)); r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in6)); break; default: snprintf(errbuf, errbufsize, "Invalid protocol family"); free(tmphstbuf); return NULL; } free(tmphstbuf); } if(r == -1) { if(errno == EINPROGRESS) { struct pollfd pfd; pfd.fd = fd; pfd.events = POLLOUT; pfd.revents = 0; r = poll(&pfd, 1, timeout); if(r == 0) { /* Timeout */ snprintf(errbuf, errbufsize, "Connection attempt timed out"); close(fd); return NULL; } if(r == -1) { snprintf(errbuf, errbufsize, "poll() error: %s", strerror(errno)); close(fd); return NULL; } getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen); } else { err = errno; } } else { err = 0; } if(err != 0) { snprintf(errbuf, errbufsize, "%s", strerror(err)); close(fd); return NULL; } fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK); val = 1; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); tcpcon_t *tc = calloc(1, sizeof(tcpcon_t)); tc->fd = fd; htsbuf_queue_init(&tc->spill, 0); if(ssl) { #if ENABLE_OPENSSL if(showtime_ssl_ctx != NULL) { char errmsg[120]; if((tc->ssl = SSL_new(showtime_ssl_ctx)) == NULL) { ERR_error_string(ERR_get_error(), errmsg); snprintf(errbuf, errlen, "SSL: %s", errmsg); tcp_close(tc); return NULL; } if(SSL_set_fd(tc->ssl, tc->fd) == 0) { ERR_error_string(ERR_get_error(), errmsg); snprintf(errbuf, errlen, "SSL fd: %s", errmsg); tcp_close(tc); return NULL; } if(SSL_connect(tc->ssl) <= 0) { ERR_error_string(ERR_get_error(), errmsg); snprintf(errbuf, errlen, "SSL connect: %s", errmsg); tcp_close(tc); return NULL; } SSL_set_mode(tc->ssl, SSL_MODE_AUTO_RETRY); tc->read = ssl_read; tc->write = ssl_write; } else #elif ENABLE_POLARSSL if(1) { tc->ssl = malloc(sizeof(ssl_context)); if(ssl_init(tc->ssl)) { snprintf(errbuf, errlen, "SSL failed to initialize"); close(fd); free(tc->ssl); free(tc); return NULL; } tc->ssn = malloc(sizeof(ssl_session)); tc->hs = malloc(sizeof(havege_state)); havege_init(tc->hs); memset(tc->ssn, 0, sizeof(ssl_session)); ssl_set_endpoint(tc->ssl, SSL_IS_CLIENT ); ssl_set_authmode(tc->ssl, SSL_VERIFY_NONE ); ssl_set_rng(tc->ssl, havege_rand, tc->hs ); ssl_set_bio(tc->ssl, net_recv, &tc->fd, net_send, &tc->fd); ssl_set_ciphers(tc->ssl, ssl_default_ciphers ); ssl_set_session(tc->ssl, 1, 600, tc->ssn ); tc->read = polarssl_read; tc->write = polarssl_write; } else #endif { snprintf(errbuf, errlen, "SSL not supported"); tcp_close(tc); return NULL; } } else { tc->read = tcp_read; tc->write = tcp_write; } return tc; }
/* * Create an SSL connection, but does not ready any post-handshake * NewSessionTicket messages. * If |read| is set and we're using DTLS then we will attempt to SSL_read on * the connection once we've completed one half of it, to ensure any retransmits * get triggered. */ int create_bare_ssl_connection(SSL *serverssl, SSL *clientssl, int want, int read) { int retc = -1, rets = -1, err, abortctr = 0; int clienterr = 0, servererr = 0; int isdtls = SSL_is_dtls(serverssl); do { err = SSL_ERROR_WANT_WRITE; while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) { retc = SSL_connect(clientssl); if (retc <= 0) err = SSL_get_error(clientssl, retc); } if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) { TEST_info("SSL_connect() failed %d, %d", retc, err); clienterr = 1; } if (want != SSL_ERROR_NONE && err == want) return 0; err = SSL_ERROR_WANT_WRITE; while (!servererr && rets <= 0 && err == SSL_ERROR_WANT_WRITE) { rets = SSL_accept(serverssl); if (rets <= 0) err = SSL_get_error(serverssl, rets); } if (!servererr && rets <= 0 && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_X509_LOOKUP) { TEST_info("SSL_accept() failed %d, %d", rets, err); servererr = 1; } if (want != SSL_ERROR_NONE && err == want) return 0; if (clienterr && servererr) return 0; if (isdtls && read) { unsigned char buf[20]; /* Trigger any retransmits that may be appropriate */ if (rets > 0 && retc <= 0) { if (SSL_read(serverssl, buf, sizeof(buf)) > 0) { /* We don't expect this to succeed! */ TEST_info("Unexpected SSL_read() success!"); return 0; } } if (retc > 0 && rets <= 0) { if (SSL_read(clientssl, buf, sizeof(buf)) > 0) { /* We don't expect this to succeed! */ TEST_info("Unexpected SSL_read() success!"); return 0; } } } if (++abortctr == MAXLOOPS) { TEST_info("No progress made"); return 0; } if (isdtls && abortctr <= 50 && (abortctr % 10) == 0) { /* * It looks like we're just spinning. Pause for a short period to * give the DTLS timer a chance to do something. We only do this for * the first few times to prevent hangs. */ ossl_sleep(50); } } while (retc <=0 || rets <= 0); return 1; }
gboolean _lm_ssl_begin (LmSSL *ssl, gint fd, const gchar *server, GError **error) { gint ssl_ret; GIOStatus status; LmSSLBase *base; base = LM_SSL_BASE(ssl); if (!ssl->ssl_ctx) { g_set_error (error, LM_ERROR, LM_ERROR_CONNECTION_OPEN, "No SSL Context for OpenSSL"); return FALSE; } if (base->cipher_list) { SSL_CTX_set_cipher_list(ssl->ssl_ctx, base->cipher_list); } if (base->ca_path) { _lm_ssl_set_ca (ssl, base->ca_path); } else { SSL_CTX_set_default_verify_paths (ssl->ssl_ctx); } ssl->ssl = SSL_new(ssl->ssl_ctx); if (ssl->ssl == NULL) { g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "SSL_new() == NULL"); g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN, "SSL_new()"); return FALSE; } if (!SSL_set_fd (ssl->ssl, fd)) { g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "SSL_set_fd() failed"); g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN, "SSL_set_fd()"); return FALSE; } /*ssl->bio = BIO_new_socket (fd, BIO_NOCLOSE); if (ssl->bio == NULL) { g_warning("BIO_new_socket() failed"); g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN, "BIO_new_socket()"); return FALSE; } SSL_set_bio(ssl->ssl, ssl->bio, ssl->bio);*/ do { ssl_ret = SSL_connect(ssl->ssl); if (ssl_ret <= 0) { status = ssl_io_status_from_return(ssl, ssl_ret); if (status != G_IO_STATUS_AGAIN) { ssl_print_state(ssl, "SSL_connect", ssl_ret); g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN, "SSL_connect()"); return FALSE; } } } while (ssl_ret <= 0); if (!ssl_verify_certificate (ssl, server)) { g_set_error (error, LM_ERROR, LM_ERROR_CONNECTION_OPEN, "*** SSL certificate verification failed"); return FALSE; } return TRUE; }
int lws_ssl_client_connect2(struct lws *wsi) { struct lws_context *context = wsi->context; struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; char *p = (char *)&pt->serv_buf[0]; char *sb = p; int n; if (wsi->mode == LWSCM_WSCL_WAITING_SSL) { lws_latency_pre(context, wsi); n = SSL_connect(wsi->ssl); lws_latency(context, wsi, "SSL_connect LWSCM_WSCL_WAITING_SSL", n, n > 0); if (n < 0) { n = SSL_get_error(wsi->ssl, n); if (n == SSL_ERROR_WANT_READ) { wsi->mode = LWSCM_WSCL_WAITING_SSL; return 0; /* no error */ } if (n == SSL_ERROR_WANT_WRITE) { /* * wants us to retry connect due to * state of the underlying ssl layer... * but since it may be stalled on * blocked write, no incoming data may * arrive to trigger the retry. * Force (possibly many times if the SSL * state persists in returning the * condition code, but other sockets * are getting serviced inbetweentimes) * us to get called back when writable. */ lwsl_info("SSL_connect WANT_WRITE... retrying\n"); lws_callback_on_writable(wsi); wsi->mode = LWSCM_WSCL_WAITING_SSL; return 0; /* no error */ } n = -1; } if (n <= 0) { /* * retry if new data comes until we * run into the connection timeout or win */ n = ERR_get_error(); if (n != SSL_ERROR_NONE) { lwsl_err("SSL connect error %lu: %s\n", n, ERR_error_string(n, sb)); return 0; } } } #ifndef USE_WOLFSSL /* * See comment above about wolfSSL certificate * verification */ lws_latency_pre(context, wsi); n = SSL_get_verify_result(wsi->ssl); lws_latency(context, wsi, "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE", n, n > 0); if (n != X509_V_OK) { if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && wsi->use_ssl == 2) { lwsl_notice("accepting self-signed certificate\n"); } else { lwsl_err("server's cert didn't look good, X509_V_ERR = %d: %s, x509: %s\n", n, ERR_error_string(n, sb), X509_verify_cert_error_string(n)); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; } } #endif /* USE_WOLFSSL */ return 1; }
netsnmp_transport * netsnmp_tlstcp_open(netsnmp_transport *t) { _netsnmpTLSBaseData *tlsdata; BIO *bio; SSL_CTX *ctx; SSL *ssl; int rc = 0; _netsnmp_verify_info *verify_info; netsnmp_assert_or_return(t != NULL, NULL); netsnmp_assert_or_return(t->data != NULL, NULL); netsnmp_assert_or_return(sizeof(_netsnmpTLSBaseData) == t->data_length, NULL); tlsdata = t->data; if (tlsdata->flags & NETSNMP_TLSBASE_IS_CLIENT) { /* Is the client */ /* RFC5953 Section 5.3.1: Establishing a Session as a Client * 1) The snmpTlstmSessionOpens counter is incremented. */ snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENS); /* RFC5953 Section 5.3.1: Establishing a Session as a Client 2) The client selects the appropriate certificate and cipher_suites for the key agreement based on the tmSecurityName and the tmRequestedSecurityLevel for the session. For sessions being established as a result of a SNMP-TARGET-MIB based operation, the certificate will potentially have been identified via the snmpTlstmParamsTable mapping and the cipher_suites will have to be taken from system-wide or implementation-specific configuration. If no row in the snmpTlstmParamsTable exists then implementations MAY choose to establish the connection using a default client certificate available to the application. Otherwise, the certificate and appropriate cipher_suites will need to be passed to the openSession() ASI as supplemental information or configured through an implementation-dependent mechanism. It is also implementation-dependent and possibly policy-dependent how tmRequestedSecurityLevel will be used to influence the security capabilities provided by the (D)TLS connection. However this is done, the security capabilities provided by (D)TLS MUST be at least as high as the level of security indicated by the tmRequestedSecurityLevel parameter. The actual security level of the session is reported in the tmStateReference cache as tmSecurityLevel. For (D)TLS to provide strong authentication, each principal acting as a command generator SHOULD have its own certificate. */ /* Implementation notes: we do most of this in the sslctx_client_setup The transport should have been f_config()ed with the proper fingerprints to use (which is stored in tlsdata), or we'll use the default identity fingerprint if that can be found. */ /* XXX: check securityLevel and ensure no NULL fingerprints are used */ /* set up the needed SSL context */ tlsdata->ssl_context = ctx = sslctx_client_setup(TLSv1_method(), tlsdata); if (!ctx) { snmp_log(LOG_ERR, "failed to create TLS context\n"); return NULL; } /* RFC5953 Section 5.3.1: Establishing a Session as a Client 3) Using the destTransportDomain and destTransportAddress values, the client will initiate the (D)TLS handshake protocol to establish session keys for message integrity and encryption. */ /* Implementation note: The transport domain and address are pre-processed by this point */ /* Create a BIO connection for it */ DEBUGMSGTL(("tlstcp", "connecting to tlstcp %s\n", tlsdata->addr_string)); t->remote = (void *) strdup(tlsdata->addr_string); t->remote_length = strlen(tlsdata->addr_string) + 1; bio = BIO_new_connect(tlsdata->addr_string); /* RFC5953 Section 5.3.1: Establishing a Session as a Client 3) continued: If the attempt to establish a session is unsuccessful, then snmpTlstmSessionOpenErrors is incremented, an error indication is returned, and processing stops. */ if (NULL == bio) { snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS); snmp_log(LOG_ERR, "tlstcp: failed to create bio\n"); _openssl_log_error(rc, NULL, "BIO creation"); SNMP_FREE(tlsdata); SNMP_FREE(t); return NULL; } /* Tell the BIO to actually do the connection */ if ((rc = BIO_do_connect(bio)) <= 0) { snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS); snmp_log(LOG_ERR, "tlstcp: failed to connect to %s\n", tlsdata->addr_string); _openssl_log_error(rc, NULL, "BIO_do_connect"); BIO_free(bio); SNMP_FREE(tlsdata); SNMP_FREE(t); return NULL; } /* Create the SSL layer on top of the socket bio */ ssl = tlsdata->ssl = SSL_new(ctx); if (NULL == ssl) { snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS); snmp_log(LOG_ERR, "tlstcp: failed to create a SSL connection\n"); BIO_free(bio); SNMP_FREE(tlsdata); SNMP_FREE(t); return NULL; } /* Bind the SSL layer to the BIO */ SSL_set_bio(ssl, bio, bio); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); verify_info = SNMP_MALLOC_TYPEDEF(_netsnmp_verify_info); if (NULL == verify_info) { snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS); snmp_log(LOG_ERR, "tlstcp: failed to create a SSL connection\n"); SSL_shutdown(ssl); BIO_free(bio); SNMP_FREE(tlsdata); SNMP_FREE(t); return NULL; } SSL_set_ex_data(ssl, tls_get_verify_info_index(), verify_info); /* Then have SSL do it's connection over the BIO */ if ((rc = SSL_connect(ssl)) <= 0) { snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS); snmp_log(LOG_ERR, "tlstcp: failed to ssl_connect\n"); BIO_free(bio); SNMP_FREE(tlsdata); SNMP_FREE(t); return NULL; } /* RFC5953 Section 5.3.1: Establishing a Session as a Client 3) continued: If the session failed to open because the presented server certificate was unknown or invalid then the snmpTlstmSessionUnknownServerCertificate or snmpTlstmSessionInvalidServerCertificates MUST be incremented and a snmpTlstmServerCertificateUnknown or snmpTlstmServerInvalidCertificate notification SHOULD be sent as appropriate. Reasons for server certificate invalidation includes, but is not limited to, cryptographic validation failures and an unexpected presented certificate identity. */ /* RFC5953 Section 5.3.1: Establishing a Session as a Client 4) The (D)TLS client MUST then verify that the (D)TLS server's presented certificate is the expected certificate. The (D)TLS client MUST NOT transmit SNMP messages until the server certificate has been authenticated, the client certificate has been transmitted and the TLS connection has been fully established. If the connection is being established from configuration based on SNMP-TARGET-MIB configuration, then the snmpTlstmAddrTable DESCRIPTION clause describes how the verification is done (using either a certificate fingerprint, or an identity authenticated via certification path validation). If the connection is being established for reasons other than configuration found in the SNMP-TARGET-MIB then configuration and procedures outside the scope of this document should be followed. Configuration mechanisms SHOULD be similar in nature to those defined in the snmpTlstmAddrTable to ensure consistency across management configuration systems. For example, a command-line tool for generating SNMP GETs might support specifying either the server's certificate fingerprint or the expected host name as a command line argument. */ /* Implementation notes: - All remote certificate fingerprints are expected to be stored in the transport's config information. This is true both for CLI clients and TARGET-MIB sessions. - netsnmp_tlsbase_verify_server_cert implements these checks */ if (netsnmp_tlsbase_verify_server_cert(ssl, tlsdata) != SNMPERR_SUCCESS) { /* XXX: unknown vs invalid; two counters */ snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONUNKNOWNSERVERCERTIFICATE); snmp_log(LOG_ERR, "tlstcp: failed to verify ssl certificate\n"); SSL_shutdown(ssl); BIO_free(bio); SNMP_FREE(tlsdata); SNMP_FREE(t); return NULL; } /* RFC5953 Section 5.3.1: Establishing a Session as a Client 5) (D)TLS provides assurance that the authenticated identity has been signed by a trusted configured certification authority. If verification of the server's certificate fails in any way (for example because of failures in cryptographic verification or the presented identity did not match the expected named entity) then the session establishment MUST fail, the snmpTlstmSessionInvalidServerCertificates object is incremented. If the session can not be opened for any reason at all, including cryptographic verification failures, then the snmpTlstmSessionOpenErrors counter is incremented and processing stops. */ /* XXX: add snmpTlstmSessionInvalidServerCertificates on crypto failure */ /* RFC5953 Section 5.3.1: Establishing a Session as a Client 6) The TLSTM-specific session identifier (tlstmSessionID) is set in the tmSessionID of the tmStateReference passed to the TLS Transport Model to indicate that the session has been established successfully and to point to a specific (D)TLS connection for future use. The tlstmSessionID is also stored in the LCD for later lookup during processing of incoming messages (Section 5.1.2). */ /* Implementation notes: - the tlsdata pointer is used as our session identifier, as noted in the netsnmp_tlstcp_recv() function comments. */ t->sock = BIO_get_fd(bio, NULL); } else { /* Is the server */ /* Create the socket bio */ DEBUGMSGTL(("tlstcp", "listening on tlstcp port %s\n", tlsdata->addr_string)); tlsdata->accept_bio = BIO_new_accept(tlsdata->addr_string); t->local = (void *) strdup(tlsdata->addr_string); t->local_length = strlen(tlsdata->addr_string)+1; if (NULL == tlsdata->accept_bio) { SNMP_FREE(t); SNMP_FREE(tlsdata); snmp_log(LOG_ERR, "TLSTCP: Falied to create a accept BIO\n"); return NULL; } /* openssl requires an initial accept to bind() the socket */ if (BIO_do_accept(tlsdata->accept_bio) <= 0) { _openssl_log_error(rc, tlsdata->ssl, "BIO_do__accept"); SNMP_FREE(t); SNMP_FREE(tlsdata); snmp_log(LOG_ERR, "TLSTCP: Falied to do first accept on the TLS accept BIO\n"); return NULL; } /* create the OpenSSL TLS context */ tlsdata->ssl_context = sslctx_server_setup(TLSv1_method()); t->sock = BIO_get_fd(tlsdata->accept_bio, NULL); t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN; } return t; }
int lws_client_socket_service(struct lws_context *context, struct lws *wsi, struct lws_pollfd *pollfd) { struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; char *p = (char *)&pt->serv_buf[0]; char *sb = p; unsigned char c; int n, len; switch (wsi->mode) { case LWSCM_WSCL_WAITING_CONNECT: /* * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE * timeout protection set in client-handshake.c */ if (!lws_client_connect_2(wsi)) { /* closed */ lwsl_client("closed\n"); return -1; } /* either still pending connection, or changed mode */ return 0; case LWSCM_WSCL_WAITING_PROXY_REPLY: /* handle proxy hung up on us */ if (pollfd->revents & LWS_POLLHUP) { lwsl_warn("Proxy connection %p (fd=%d) dead\n", (void *)wsi, pollfd->fd); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; } n = recv(wsi->sock, sb, LWS_MAX_SOCKET_IO_BUF, 0); if (n < 0) { if (LWS_ERRNO == LWS_EAGAIN) { lwsl_debug("Proxy read returned EAGAIN... retrying\n"); return 0; } lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); lwsl_err("ERROR reading from proxy socket\n"); return 0; } pt->serv_buf[13] = '\0'; if (strcmp(sb, "HTTP/1.0 200 ") && strcmp(sb, "HTTP/1.1 200 ")) { lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); lwsl_err("ERROR proxy: %s\n", sb); return 0; } /* clear his proxy connection timeout */ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); /* fallthru */ case LWSCM_WSCL_ISSUE_HANDSHAKE: /* * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE * timeout protection set in client-handshake.c * * take care of our lws_callback_on_writable * happening at a time when there's no real connection yet */ if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) return -1; #ifdef LWS_OPENSSL_SUPPORT /* we can retry this... just cook the SSL BIO the first time */ if (wsi->use_ssl && !wsi->ssl) { #if defined(CYASSL_SNI_HOST_NAME) || defined(WOLFSSL_SNI_HOST_NAME) || defined(SSL_CTRL_SET_TLSEXT_HOSTNAME) const char *hostname = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST); #endif wsi->ssl = SSL_new(context->ssl_client_ctx); #ifndef USE_WOLFSSL SSL_set_mode(wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #endif /* * use server name indication (SNI), if supported, * when establishing connection */ #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL #ifdef CYASSL_SNI_HOST_NAME CyaSSL_UseSNI(wsi->ssl, CYASSL_SNI_HOST_NAME, hostname, strlen(hostname)); #endif #else #ifdef WOLFSSL_SNI_HOST_NAME wolfSSL_UseSNI(wsi->ssl, WOLFSSL_SNI_HOST_NAME, hostname, strlen(hostname)); #endif #endif #else #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME SSL_set_tlsext_host_name(wsi->ssl, hostname); #endif #endif #ifdef USE_WOLFSSL /* * wolfSSL/CyaSSL does certificate verification differently * from OpenSSL. * If we should ignore the certificate, we need to set * this before SSL_new and SSL_connect is called. * Otherwise the connect will simply fail with error * code -155 */ #ifdef USE_OLD_CYASSL if (wsi->use_ssl == 2) CyaSSL_set_verify(wsi->ssl, SSL_VERIFY_NONE, NULL); #else if (wsi->use_ssl == 2) wolfSSL_set_verify(wsi->ssl, SSL_VERIFY_NONE, NULL); #endif #endif /* USE_WOLFSSL */ wsi->client_bio = BIO_new_socket(wsi->sock, BIO_NOCLOSE); SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio); #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL CyaSSL_set_using_nonblock(wsi->ssl, 1); #else wolfSSL_set_using_nonblock(wsi->ssl, 1); #endif #else BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */ #endif SSL_set_ex_data(wsi->ssl, openssl_websocket_private_data_index, context); } if (wsi->use_ssl) { lws_latency_pre(context, wsi); n = SSL_connect(wsi->ssl); lws_latency(context, wsi, "SSL_connect LWSCM_WSCL_ISSUE_HANDSHAKE", n, n > 0); if (n < 0) { n = SSL_get_error(wsi->ssl, n); if (n == SSL_ERROR_WANT_READ) goto some_wait; if (n == SSL_ERROR_WANT_WRITE) { /* * wants us to retry connect due to * state of the underlying ssl layer... * but since it may be stalled on * blocked write, no incoming data may * arrive to trigger the retry. * Force (possibly many times if the SSL * state persists in returning the * condition code, but other sockets * are getting serviced inbetweentimes) * us to get called back when writable. */ lwsl_info("%s: WANT_WRITE... retrying\n", __func__); lws_callback_on_writable(wsi); some_wait: wsi->mode = LWSCM_WSCL_WAITING_SSL; return 0; /* no error */ } n = -1; } if (n <= 0) { /* * retry if new data comes until we * run into the connection timeout or win */ n = ERR_get_error(); if (n != SSL_ERROR_NONE) { lwsl_err("SSL connect error %lu: %s\n", n, ERR_error_string(n, sb)); return 0; } } } else wsi->ssl = NULL; /* fallthru */ case LWSCM_WSCL_WAITING_SSL: if (wsi->use_ssl) { if (wsi->mode == LWSCM_WSCL_WAITING_SSL) { lws_latency_pre(context, wsi); n = SSL_connect(wsi->ssl); lws_latency(context, wsi, "SSL_connect LWSCM_WSCL_WAITING_SSL", n, n > 0); if (n < 0) { n = SSL_get_error(wsi->ssl, n); if (n == SSL_ERROR_WANT_READ) goto some_wait; if (n == SSL_ERROR_WANT_WRITE) { /* * wants us to retry connect due to * state of the underlying ssl layer... * but since it may be stalled on * blocked write, no incoming data may * arrive to trigger the retry. * Force (possibly many times if the SSL * state persists in returning the * condition code, but other sockets * are getting serviced inbetweentimes) * us to get called back when writable. */ lwsl_info("SSL_connect WANT_WRITE... retrying\n"); lws_callback_on_writable(wsi); goto some_wait; } n = -1; } if (n <= 0) { /* * retry if new data comes until we * run into the connection timeout or win */ n = ERR_get_error(); if (n != SSL_ERROR_NONE) { lwsl_err("SSL connect error %lu: %s\n", n, ERR_error_string(n, sb)); return 0; } } } #ifndef USE_WOLFSSL /* * See comment above about wolfSSL certificate * verification */ lws_latency_pre(context, wsi); n = SSL_get_verify_result(wsi->ssl); lws_latency(context, wsi, "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE", n, n > 0); if (n != X509_V_OK) { if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && wsi->use_ssl == 2) { lwsl_notice("accepting self-signed certificate\n"); } else { lwsl_err("server's cert didn't look good, X509_V_ERR = %d: %s\n", n, ERR_error_string(n, sb)); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; } } #endif /* USE_WOLFSSL */ } else wsi->ssl = NULL; #endif wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE2; lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, context->timeout_secs); /* fallthru */ case LWSCM_WSCL_ISSUE_HANDSHAKE2: p = lws_generate_client_handshake(wsi, p); if (p == NULL) { lwsl_err("Failed to generate handshake for client\n"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; } /* send our request to the server */ lws_latency_pre(context, wsi); n = lws_ssl_capable_write(wsi, (unsigned char *)sb, p - sb); lws_latency(context, wsi, "send lws_issue_raw", n, n == p - sb); switch (n) { case LWS_SSL_CAPABLE_ERROR: lwsl_debug("ERROR writing to client socket\n"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; case LWS_SSL_CAPABLE_MORE_SERVICE: lws_callback_on_writable(wsi); break; } wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; wsi->u.hdr.lextable_pos = 0; wsi->mode = LWSCM_WSCL_WAITING_SERVER_REPLY; lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, context->timeout_secs); break; case LWSCM_WSCL_WAITING_SERVER_REPLY: /* handle server hung up on us */ if (pollfd->revents & LWS_POLLHUP) { lwsl_debug("Server connection %p (fd=%d) dead\n", (void *)wsi, pollfd->fd); goto bail3; } if (!(pollfd->revents & LWS_POLLIN)) break; /* interpret the server response */ /* * HTTP/1.1 101 Switching Protocols * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo= * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC== * Sec-WebSocket-Protocol: chat */ /* * we have to take some care here to only take from the * socket bytewise. The browser may (and has been seen to * in the case that onopen() performs websocket traffic) * coalesce both handshake response and websocket traffic * in one packet, since at that point the connection is * definitively ready from browser pov. */ len = 1; while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE && len > 0) { n = lws_ssl_capable_read(wsi, &c, 1); lws_latency(context, wsi, "send lws_issue_raw", n, n == 1); switch (n) { case 0: case LWS_SSL_CAPABLE_ERROR: goto bail3; case LWS_SSL_CAPABLE_MORE_SERVICE: return 0; } if (lws_parse(wsi, c)) { lwsl_warn("problems parsing header\n"); goto bail3; } } /* * hs may also be coming in multiple packets, there is a 5-sec * libwebsocket timeout still active here too, so if parsing did * not complete just wait for next packet coming in this state */ if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE) break; /* * otherwise deal with the handshake. If there's any * packet traffic already arrived we'll trigger poll() again * right away and deal with it that way */ return lws_client_interpret_server_handshake(wsi); bail3: lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return -1; case LWSCM_WSCL_WAITING_EXTENSION_CONNECT: lwsl_ext("LWSCM_WSCL_WAITING_EXTENSION_CONNECT\n"); break; case LWSCM_WSCL_PENDING_CANDIDATE_CHILD: lwsl_ext("LWSCM_WSCL_PENDING_CANDIDATE_CHILD\n"); break; default: break; } return 0; }
int tls_start(tls_t *tls, int fd, const char *hostname, int no_certcheck, tls_cert_info_t *tci, char **errstr) { #ifdef HAVE_LIBGNUTLS int error_code; gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr_t)fd); do { error_code = gnutls_handshake(tls->session); } while (error_code < 0 && gnutls_error_is_fatal(error_code) == 0); if (error_code != 0) { *errstr = xasprintf(_("TLS handshake failed: %s"), gnutls_strerror(error_code)); gnutls_deinit(tls->session); gnutls_certificate_free_credentials(tls->cred); return TLS_EHANDSHAKE; } if (tci) { if ((error_code = tls_cert_info_get(tls, tci, errstr)) != TLS_EOK) { gnutls_deinit(tls->session); gnutls_certificate_free_credentials(tls->cred); return error_code; } } if (!no_certcheck) { if ((error_code = tls_check_cert(tls, hostname, errstr)) != TLS_EOK) { gnutls_deinit(tls->session); gnutls_certificate_free_credentials(tls->cred); return error_code; } } tls->is_active = 1; return TLS_EOK; #endif /* HAVE_LIBGNUTLS */ #ifdef HAVE_LIBSSL int error_code; if (!SSL_set_fd(tls->ssl, fd)) { *errstr = xasprintf(_("cannot set the file descriptor for TLS: %s"), ERR_error_string(ERR_get_error(), NULL)); SSL_free(tls->ssl); SSL_CTX_free(tls->ssl_ctx); return TLS_ELIBFAILED; } if ((error_code = SSL_connect(tls->ssl)) < 1) { if (errno == EINTR && (SSL_get_error(tls->ssl, error_code) == SSL_ERROR_WANT_READ || SSL_get_error(tls->ssl, error_code) == SSL_ERROR_WANT_WRITE)) { *errstr = xasprintf(_("operation aborted")); } else { *errstr = openssl_io_error(error_code, SSL_get_error(tls->ssl, error_code), _("TLS handshake failed")); } SSL_free(tls->ssl); SSL_CTX_free(tls->ssl_ctx); return TLS_EIO; } if (tci) { if ((error_code = tls_cert_info_get(tls, tci, errstr)) != TLS_EOK) { SSL_free(tls->ssl); SSL_CTX_free(tls->ssl_ctx); return error_code; } } if (!no_certcheck) { if ((error_code = tls_check_cert(tls, hostname, errstr)) != TLS_EOK) { SSL_free(tls->ssl); SSL_CTX_free(tls->ssl_ctx); return error_code; } } tls->is_active = 1; return TLS_EOK; #endif /* HAVE_LIBSSL */ }
static struct mailstream_ssl_data * ssl_data_new_full(int fd, SSL_METHOD * method, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) { struct mailstream_ssl_data * ssl_data; SSL * ssl_conn; int r; SSL_CTX * tmp_ctx; struct mailstream_cancel * cancel; struct mailstream_ssl_context * ssl_context = NULL; mailstream_ssl_init(); tmp_ctx = SSL_CTX_new(method); if (tmp_ctx == NULL) goto err; if (callback != NULL) { ssl_context = mailstream_ssl_context_new(tmp_ctx, fd); callback(ssl_context, cb_data); } SSL_CTX_set_app_data(tmp_ctx, ssl_context); SSL_CTX_set_client_cert_cb(tmp_ctx, mailstream_openssl_client_cert_cb); ssl_conn = (SSL *) SSL_new(tmp_ctx); if (ssl_conn == NULL) goto free_ctx; if (SSL_set_fd(ssl_conn, fd) == 0) goto free_ssl_conn; again: r = SSL_connect(ssl_conn); switch(SSL_get_error(ssl_conn, r)) { case SSL_ERROR_WANT_READ: r = wait_SSL_connect(fd, 1); if (r < 0) goto free_ssl_conn; else goto again; break; case SSL_ERROR_WANT_WRITE: r = wait_SSL_connect(fd, 0); if (r < 0) goto free_ssl_conn; else goto again; break; } if (r <= 0) goto free_ssl_conn; cancel = mailstream_cancel_new(); if (cancel == NULL) goto free_ssl_conn; r = mailstream_prepare_fd(fd); if (r < 0) goto free_cancel; ssl_data = malloc(sizeof(* ssl_data)); if (ssl_data == NULL) goto free_cancel; ssl_data->fd = fd; ssl_data->ssl_conn = ssl_conn; ssl_data->ssl_ctx = tmp_ctx; ssl_data->cancel = cancel; mailstream_ssl_context_free(ssl_context); return ssl_data; free_cancel: mailstream_cancel_free(cancel); free_ssl_conn: SSL_free(ssl_conn); free_ctx: SSL_CTX_free(tmp_ctx); mailstream_ssl_context_free(ssl_context); err: return NULL; }
int WebRequest::Request ( int request_type , std::string url_host , int url_port , std::string url_path , std::string data ) { bool secure = false; mMessageHeader = ""; mMessageBody.clear(); // temp fix for POST recognition data = "_start_=1&" + data + "&_end_=1"; mReadSize = 1024; mError = 0; if(request_type == HTTPS_GET || request_type == HTTPS_POST || request_type == HTTPS_PUT || request_type == HTTPS_DELETE) { secure = true; } #ifdef WIN32 WSADATA wsa; // startup winsock mError = WSAStartup(MAKEWORD(2,0),&wsa); if(mError) { printf("Error in Startup = %d\n", mError); return -1; } #endif // socket int socket = 0; // struct for socket struct sockaddr_in host_addr = {0}; // information about host struct hostent *host = {0}; // request of client std::string request; // SSL context SSL_CTX *sslContext = NULL; // SSL socket SSL *sslSocket = NULL; // get IP from name host host = gethostbyname(url_host.c_str()); if (host == NULL) { printf("Unknown Host %s\n", url_host.c_str()); return -1; } // create socket TCP socket = ::socket(PF_INET, SOCK_STREAM, 0); if (socket < 0) { printf("Socket Error\n"); return -1; } // create host struct host_addr.sin_family = AF_INET; // set IP addres host_addr.sin_addr = *((struct in_addr *)host->h_addr); // set HTTP port host_addr.sin_port = htons(url_port); // connect mError = connect(socket, (struct sockaddr *)&host_addr, sizeof(host_addr)); if (mError == -1) { CloseSocket(socket); printf("Connection Error\n"); return -1; } if(secure) { // init OpenSSL SSL_load_error_strings(); SSL_library_init(); // create context sslContext = SSL_CTX_new(SSLv23_client_method()); //create ssl socket sslSocket = SSL_new(sslContext); if(!sslSocket) { CloseSocket(socket); printf("SSL creation error\n"); return -1; } // join sslSocket and socket SSL_set_fd(sslSocket, socket); // conect sslSocket mError = SSL_connect(sslSocket); if(!mError) { CloseSocket(socket); printf("SSL connect error = %d\n", mError); mError = SSL_get_error(sslSocket, mError); printf("SSL error: %d\n", mError); //std::cin.get(); return -1; } } if(request_type == HTTP_GET || request_type == HTTPS_GET) { //create get request request = "GET " + url_path + " HTTP/1.0\nHost: " + url_host + " \r\n\r\n"; } else if(request_type == HTTP_POST || request_type == HTTPS_POST) { //create get request request = "POST " + url_path + " HTTP/1.0\nHost: " + url_host + "\nContent-Length: " + to_string(data.length()) + "\nContent-Type: application/x-www-form-urlencoded\n" + "\r\n\r\n" + data + "\r\n"; } // TODO add DELETE and PUT // send data to server if(secure) { mError = SSL_write(sslSocket, request.c_str(), strlen(request.c_str())); } else { mError = send(socket, request.c_str(), strlen(request.c_str()), 0); } // read in header and body char bufferHeader[1]; int readHeader; int lineLength; bool loop = true; bool bHeader = false; // header mMessageHeader = ""; while(loop) { if(secure) readHeader = SSL_read(sslSocket, bufferHeader, 1); else readHeader = recv(socket, bufferHeader, 1, 0); if(readHeader < 0) loop = false; if(bufferHeader[0]=='\n') { if(lineLength == 0) loop = false; lineLength = 0; if(mMessageHeader.find("200") != std::string::npos) bHeader = true; } else if(bufferHeader[0]!='\r') lineLength++; mMessageHeader += bufferHeader[0]; } // body mMessageBody.clear(); if(bHeader) { unsigned char bufferBody[1024]; if(secure) { while((readHeader = SSL_read(sslSocket, bufferBody, sizeof(bufferBody))) > 0) { mMessageBody.insert(mMessageBody.end(), bufferBody, bufferBody + readHeader); } } else { while((readHeader = recv(socket, (char*)bufferBody, sizeof(bufferBody), 0)) > 0) { mMessageBody.insert(mMessageBody.end(), bufferBody, bufferBody + readHeader); } } } if(secure) { switch(SSL_get_error( sslSocket, mReadSize )) { case SSL_ERROR_ZERO_RETURN: printf( "\n\nSSL::ZERO\n\n" ); break; case SSL_ERROR_NONE: printf( "\n\nSSL::No Error\n\n" ); break; case SSL_ERROR_SSL: printf( "\n\nSSL::SSL ERROR\n\n" ); break; } } #if WIN32 Sleep(1); #else sleep(1); #endif if(secure) { //close SSLsocket SSL_shutdown(sslSocket); //free memory SSL_free(sslSocket); // free context SSL_CTX_free(sslContext); } //close scoket CloseSocket(socket); return 0; }
BOOL tls_connect(rdpTls* tls) { CryptoCert cert; long options = 0; int connection_status; tls->ctx = SSL_CTX_new(TLSv1_client_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return FALSE; } /** * SSL_OP_NO_COMPRESSION: * * The Microsoft RDP server does not advertise support * for TLS compression, but alternative servers may support it. * This was observed between early versions of the FreeRDP server * and the FreeRDP client, and caused major performance issues, * which is why we're disabling it. */ #ifdef SSL_OP_NO_COMPRESSION options |= SSL_OP_NO_COMPRESSION; #endif /** * SSL_OP_TLS_BLOCK_PADDING_BUG: * * The Microsoft RDP server does *not* support TLS padding. * It absolutely needs to be disabled otherwise it won't work. */ options |= SSL_OP_TLS_BLOCK_PADDING_BUG; /** * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: * * Just like TLS padding, the Microsoft RDP server does not * support empty fragments. This needs to be disabled. */ options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; SSL_CTX_set_options(tls->ctx, options); tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return FALSE; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return FALSE; } connection_status = SSL_connect(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_connect", tls->ssl, connection_status)) { return FALSE; } } cert = tls_get_certificate(tls, TRUE); if (cert == NULL) { printf("tls_connect: tls_get_certificate failed to return the server certificate.\n"); return FALSE; } if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength)) { printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n"); tls_free_certificate(cert); return FALSE; } if (!tls_verify_certificate(tls, cert, tls->settings->hostname)) { printf("tls_connect: certificate not trusted, aborting.\n"); tls_disconnect(tls); tls_free_certificate(cert); return FALSE; } tls_free_certificate(cert); return TRUE; }
int openSSLConnect() { if(m_ctx == NULL) return SSL_PROBLEM; m_ssl = SSL_new (m_ctx); if(m_ssl == NULL) return SSL_PROBLEM; SSL_set_fd (m_ssl, (int)smtp_socket); SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY); int res = 0; fd_set fdwrite; fd_set fdread; int write_blocked = 0; int read_blocked = 0; timeval time; time.tv_sec = TIME_IN_SEC; time.tv_usec = 0; while(1) { FD_ZERO(&fdwrite); FD_ZERO(&fdread); if(write_blocked) FD_SET(smtp_socket, &fdwrite); if(read_blocked) FD_SET(smtp_socket, &fdread); if(write_blocked || read_blocked) { write_blocked = 0; read_blocked = 0; if((res = select(smtp_socket+1,&fdread,&fdwrite,NULL,&time)) == SOCKET_ERROR) { FD_ZERO(&fdwrite); FD_ZERO(&fdread); return WSA_SELECT; } if(!res) { //timeout FD_ZERO(&fdwrite); FD_ZERO(&fdread); return SERVER_NOT_RESPONDING; } } res = SSL_connect(m_ssl); switch(SSL_get_error(m_ssl, res)) { case SSL_ERROR_NONE: FD_ZERO(&fdwrite); FD_ZERO(&fdread); return CSMTP_NO_ERROR; break; case SSL_ERROR_WANT_WRITE: write_blocked = 1; break; case SSL_ERROR_WANT_READ: read_blocked = 1; break; default: FD_ZERO(&fdwrite); FD_ZERO(&fdread); return SSL_PROBLEM; } } return CSMTP_NO_ERROR; }