BOOL tls_accept(rdpTls* tls, BIO *underlying, const char* cert_file, const char* privatekey_file) { long options = 0; /** * 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; if (!tls_prepare(tls, underlying, SSLv23_server_method(), options, FALSE)) return FALSE; if (SSL_use_RSAPrivateKey_file(tls->ssl, privatekey_file, SSL_FILETYPE_PEM) <= 0) { DEBUG_WARN( "%s: SSL_CTX_use_RSAPrivateKey_file failed\n", __FUNCTION__); DEBUG_WARN( "PrivateKeyFile: %s\n", privatekey_file); return FALSE; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { DEBUG_WARN( "%s: SSL_use_certificate_file failed\n", __FUNCTION__); return FALSE; } return tls_do_handshake(tls, FALSE) > 0; }
static void tls_exec_server(const char *user, int startfd, const char *privkey, const char *cert, int debuglevel) { SSL_CTX *sslctx; SSL *ssl; int sockfd, tcpfd, ret; pjdlog_debug_set(debuglevel); pjdlog_prefix_set("[TLS sandbox] (server) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (server) "); #endif sockfd = startfd; tcpfd = startfd + 1; SSL_load_error_strings(); SSL_library_init(); sslctx = SSL_CTX_new(TLSv1_server_method()); if (sslctx == NULL) pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed."); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); ssl = SSL_new(sslctx); if (ssl == NULL) pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed."); if (SSL_use_RSAPrivateKey_file(ssl, privkey, SSL_FILETYPE_PEM) != 1) { ssl_log_errors(); pjdlog_exitx(EX_CONFIG, "SSL_use_RSAPrivateKey_file(%s) failed.", privkey); } if (SSL_use_certificate_file(ssl, cert, SSL_FILETYPE_PEM) != 1) { ssl_log_errors(); pjdlog_exitx(EX_CONFIG, "SSL_use_certificate_file(%s) failed.", cert); } if (sandbox(user, true, "proto_tls server") != 0) pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS server."); pjdlog_debug(1, "Privileges successfully dropped."); nonblock(sockfd); nonblock(tcpfd); if (SSL_set_fd(ssl, tcpfd) != 1) pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed."); ret = SSL_accept(ssl); ssl_check_error(ssl, ret); tls_loop(sockfd, ssl); }
boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file) { int connection_status; tls->ctx = SSL_CTX_new(SSLv23_server_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } /* * We only want SSLv3 and TLSv1, so disable SSLv2. * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. */ SSL_CTX_set_options(tls->ctx, SSL_OP_NO_SSLv2); if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); return false; } tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_use_certificate_file failed\n"); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_accept(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_accept", tls->ssl, connection_status)) return false; } printf("TLS connection accepted\n"); return true; }
int tls_connection_client_cert(void *ssl_ctx, struct tls_connection *conn, const char *client_cert) { if (client_cert == NULL) return 0; if (conn == NULL) return -1; if (SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_ASN1) != 1 && SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_PEM) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to load client " "certificate: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } return 0; }
static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value) { int rv = 1; if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) return -2; if (cctx->ctx) rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value); if (cctx->ssl) rv = SSL_use_certificate_file(cctx->ssl, value, SSL_FILETYPE_PEM); return rv > 0; }
tbool tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file) { int connection_status; tls->ctx = SSL_CTX_new(TLSv1_server_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); return false; } tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_use_certificate_file failed\n"); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_accept(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_accept", tls->ssl, connection_status)) return false; } printf("TLS connection accepted\n"); return true; }
static int conn_init_client_ssl(Connection *ret, Octstr *certkeyfile) { ret->ssl = SSL_new(global_ssl_context); /* * 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. */ ERR_clear_error(); if (certkeyfile != NULL) { SSL_use_certificate_file(ret->ssl, octstr_get_cstr(certkeyfile), SSL_FILETYPE_PEM); SSL_use_PrivateKey_file(ret->ssl, octstr_get_cstr(certkeyfile), SSL_FILETYPE_PEM); if (SSL_check_private_key(ret->ssl) != 1) { error(0, "conn_open_ssl: private key isn't consistent with the " "certificate from file %s (or failed reading the file)", octstr_get_cstr(certkeyfile)); return -1; } } /* SSL_set_fd can fail, so check it */ if (SSL_set_fd(ret->ssl, ret->fd) == 0) { /* SSL_set_fd failed, log error */ error(errno, "SSL: OpenSSL: %.256s", ERR_error_string(ERR_get_error(), NULL)); return -1; } /* * make sure the socket is non-blocking while we do SSL_connect */ if (socket_set_blocking(ret->fd, 0) < 0) { return -1; } BIO_set_nbio(SSL_get_rbio(ret->ssl), 1); BIO_set_nbio(SSL_get_wbio(ret->ssl), 1); SSL_set_connect_state(ret->ssl); return 0; }
DSCRPTR nbr_ssl_accept(DSCRPTR fd, void *addr, int *alen, SKCONF *cfg) { int r, ret; sslfd_t *sfd = nbr_array_alloc(g_ssl.socks), *afd = (sslfd_t *)fd; if (!sfd) { SSL_ERROUT(ERROR,EXPIRE,"sfd alloc fail"); goto bad; } if ((sfd->fd = nbr_osdep_tcp_accept(afd->fd, addr, alen, cfg)) == INVALID_FD) { SSL_ERROUT(ERROR,ACCEPT,"ssl accept fail"); goto bad; } if (!(sfd->ssl = SSL_new(g_ssl.server))) { SSL_ERROUT(ERROR,EXPIRE,"ssl new fail"); goto bad; } #if defined(_DEBUG) sfd->ssl->info_callback = (void (*)())ssl_info_callback; #endif if (!g_ssl.pubkey || SSL_use_certificate_file(sfd->ssl, g_ssl.pubkey, SSL_FILETYPE_PEM) < 0) { SSL_ERROUT(ERROR,EXPIRE,"ssl SSL_use_certificate_file fail"); goto bad; } if (!g_ssl.privkey || SSL_use_PrivateKey_file(sfd->ssl, g_ssl.privkey, SSL_FILETYPE_PEM) < 0) { SSL_ERROUT(ERROR,EXPIRE,"ssl SSL_use_PrivateKey_file fail"); goto bad; } SSL_set_fd(sfd->ssl, sfd->fd); if ((r = SSL_accept(sfd->ssl)) <= 0) { ret = SSL_get_error(sfd->ssl, ret); if (ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_WANT_WRITE) { return 0; /* connection pending */ } ERR_print_errors_fp(stderr); SSL_ERROUT(ERROR,ACCEPT,"ssl_accept fail (%d/%d)", r, ret); goto bad; } return (DSCRPTR)sfd; bad: ssl_free_fd(sfd); return INVALID_FD; }
/* Load certificate and private key */ static void tls_certkey(SSL *_tls) { int ret, ret2; if(!_tls) { TLSERROR("Certificate cannot be loaded."); return; } if((!_key) || (!_cert) || (!_callback)) { printf("WARNING: certificates are disabled!\n"); return; } SSL_CTX_set_default_passwd_cb(_tlsctx, _callback); /*ret = SSL_CTX_load_verify_locations(_tlsctx, "/usr/lib/ssl/cacert.pem", NULL); if(ret != 1) { TLSERROR("Couldn't load root CA file!"); ret2 = ERR_get_error(); printf("EXT: %s\n%s\n%s\n%s\n%s\n", tls_exterror(_tls, ret), ERR_error_string(ret2, NULL), ERR_lib_error_string(ret2), ERR_func_error_string(ret2), ERR_reason_error_string(ret2)); }*/ ret = SSL_use_RSAPrivateKey_file(_tls, _key, SSL_FILETYPE_PEM); if(ret != 1) { TLSERROR("Error loading TLS PEM private key."); ret2 = ERR_get_error(); printf("EXT: %s\n%s\n%s\n%s\n%s\n", tls_exterror(_tls, ret), ERR_error_string(ret2, NULL), ERR_lib_error_string(ret2), ERR_func_error_string(ret2), ERR_reason_error_string(ret2)); } ret = SSL_use_certificate_file(_tls, _cert, SSL_FILETYPE_PEM); if(ret != 1) TLSERROR("Error loading TLS PEM certificate."); ret = SSL_check_private_key(_tls); if(!ret) TLSERROR("Private key doesn't match certificate public key."); printf("*** certificate loaded ***\n"); }
/// loads one PEM file with one certificate, no chain, no CA int Certificate::loadCertificateFromFile( void ) { const int certificateFileCheckResult = validateCertificateFilename(m_certfn); if(certificateFileCheckResult < 0) return certificateFileCheckResult; m_ssl = SSL_new( SSL_CTX_new( SSLv23_method() ) ); SSL_use_certificate_file( m_ssl, m_certfn.c_str(), m_type); // or like this, including a CA // SSL_CTX_use_certificate_chain_file( _ssl_ctx, fname.c_str() ); X509 *x509crt = SSL_get_certificate( m_ssl ); // validity format is here: // https://github.com/openssl/openssl/commit/f48b83b4fb7d6689584cf25f61ca63a4891f5b11 // in fact these are strings in UTC format, need to convert them into time_t to become useful m_time_end = _timeASN1toTIME_T( x509crt->cert_info->validity->notAfter ); remainingValidityTime(); LOG(Log::INF) << " certificate remaining time= " << remainingDays() << "days " << remainingHours() << ":" << remainingMins() << ":" << remainingSecs(); return( 0 ); }
boolean 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) { printf("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) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); return false; } tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_use_certificate_file failed\n"); return false; } cert = tls_get_certificate(tls, false); if (cert == NULL) { printf("tls_connect: tls_get_certificate failed to return the server certificate.\n"); return false; } if (!crypto_cert_get_public_key(cert, &tls->public_key)) { printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n"); tls_free_certificate(cert); return false; } xfree(cert); if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("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; } } printf("TLS connection accepted\n"); return true; }
int main( int argc, char *argv[]) { int port = 10001; int n; int s; if (argc > 1) { sscanf( argv[1], "%d", &port); } SSL_library_init(); SSL_load_error_strings(); s = socket( PF_INET, SOCK_STREAM, 0); if (s != -1) { int cs; char buf[1024]; struct sockaddr_in sa; int on; on = 1; setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof( on)); memset( &sa, 0, sizeof( sa)); sa.sin_family = AF_INET; sa.sin_port = htons( port); sa.sin_addr.s_addr = INADDR_ANY; bind( s, (struct sockaddr *)&sa, sizeof( sa)); listen( s, 1); while (1) { printf( "accepting on port %d..\n", port); cs = accept( s, NULL, NULL); if (cs != -1) { SSL *ssl = 0; SSL_CTX *ssl_ctx = 0; ssl_ctx = SSL_CTX_new( SSLv23_server_method()); if (ssl_ctx) { ssl = SSL_new( ssl_ctx); if (ssl) { n = SSL_use_PrivateKey_file( ssl, key_file, 1); if (n != 1) printf( "failed to SSL use key (%d, %d)\n", n, SSL_get_error( ssl, n)); n = SSL_use_certificate_file( ssl, certificate_file, 1); if (n != 1) printf( "failed to SSL use cert (%d, %d)\n", n, SSL_get_error( ssl, n)); if (SSL_set_fd( ssl, cs)) { printf( "SSL accepting..\n"); n = SSL_accept( ssl); if (n == 1) { printf( "ssl initiated\n"); if ((n = SSL_read( ssl, buf, sizeof( buf))) > 0) { if (n > (sizeof( buf) - 1)) n = sizeof( buf) - 1; buf[n] = 0; printf( "SSL_read %d bytes [%s]\n", n, buf); } else printf( "failed to SSL read\n"); } else { #ifdef WIN32 unsigned long err = ERR_get_error(); printf( "failed to SSL accept (%d, %d) (%ld, %s)\n", n, SSL_get_error( ssl, n), err, ERR_error_string( err, NULL)); #else printf( "failed to SSL accept (%d)\n", n); #endif } } else printf( "failed to SSL set fd\n"); SSL_shutdown( ssl); } else printf( "couldn't create server ssl\n"); SSL_CTX_free( ssl_ctx); } else printf( "couldn't create server ctx\n"); close( cs); } else perror( "accept"); } } else perror( "socket"); return 0; }
int schannel_openssl_server_init(SCHANNEL_OPENSSL* context) { int status; long options = 0; //context->ctx = SSL_CTX_new(SSLv23_server_method()); context->ctx = SSL_CTX_new(TLSv1_server_method()); if (!context->ctx) { WLog_ERR(TAG, "SSL_CTX_new failed"); return -1; } /* * 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(context->ctx, options); if (SSL_CTX_use_RSAPrivateKey_file(context->ctx, "/tmp/localhost.key", SSL_FILETYPE_PEM) <= 0) { WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed"); return -1; } context->ssl = SSL_new(context->ctx); if (!context->ssl) { WLog_ERR(TAG, "SSL_new failed"); return -1; } if (SSL_use_certificate_file(context->ssl, "/tmp/localhost.crt", SSL_FILETYPE_PEM) <= 0) { WLog_ERR(TAG, "SSL_use_certificate_file failed"); return -1; } context->bioRead = BIO_new(BIO_s_mem()); if (!context->bioRead) { WLog_ERR(TAG, "BIO_new failed"); return -1; } status = BIO_set_write_buf_size(context->bioRead, SCHANNEL_CB_MAX_TOKEN); context->bioWrite = BIO_new(BIO_s_mem()); if (!context->bioWrite) { WLog_ERR(TAG, "BIO_new failed"); return -1; } status = BIO_set_write_buf_size(context->bioWrite, SCHANNEL_CB_MAX_TOKEN); status = BIO_make_bio_pair(context->bioRead, context->bioWrite); SSL_set_bio(context->ssl, context->bioRead, context->bioWrite); context->ReadBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); context->WriteBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); return 0; }
/** 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; }
BOOL tls_accept(rdpTls* tls, BIO* underlying, const char* cert_file, const char* privatekey_file) { long options = 0; /** * 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; if (!tls_prepare(tls, underlying, SSLv23_server_method(), options, FALSE)) return FALSE; if (SSL_use_RSAPrivateKey_file(tls->ssl, privatekey_file, SSL_FILETYPE_PEM) <= 0) { WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed"); WLog_ERR(TAG, "PrivateKeyFile: %s", privatekey_file); return FALSE; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { WLog_ERR(TAG, "SSL_use_certificate_file failed"); return FALSE; } #ifndef OPENSSL_NO_TLSEXT /** * The Microsoft iOS clients eventually send a null or even double null * terminated hostname in the SNI TLS extension! * If the length indicator does not equal the hostname strlen OpenSSL * will abort (see openssl:ssl/t1_lib.c). * Here is a tcpdump segment of Microsoft Remote Desktop Client Version * 8.1.7 running on an iPhone 4 with iOS 7.1.2 showing the transmitted * SNI hostname TLV blob when connection to server "abcd": * 00 name_type 0x00 (host_name) * 00 06 length_in_bytes 0x0006 * 61 62 63 64 00 00 host_name "abcd\0\0" * * Currently the only (runtime) workaround is setting an openssl tls * extension debug callback that sets the SSL context's servername_done * to 1 which effectively disables the parsing of that extension type. */ SSL_set_tlsext_debug_callback(tls->ssl, tls_openssl_tlsext_debug_callback); #endif return tls_do_handshake(tls, FALSE) > 0; }
int APP_CC xrdp_tls_accept(struct xrdp_tls *self) { int connection_status; long options = 0; /** * 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; #if defined(SSL_OP_NO_COMPRESSION) /** * 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. */ 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; self->ctx = SSL_CTX_new(SSLv23_server_method()); /* set context options */ SSL_CTX_set_mode(self->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_options(self->ctx, options); SSL_CTX_set_read_ahead(self->ctx, 1); if (self->ctx == NULL) { g_writeln("xrdp_tls_accept: SSL_CTX_new failed"); return 1; } if (SSL_CTX_use_RSAPrivateKey_file(self->ctx, self->key, SSL_FILETYPE_PEM) <= 0) { g_writeln("xrdp_tls_accept: SSL_CTX_use_RSAPrivateKey_file failed"); return 1; } self->ssl = SSL_new(self->ctx); if (self->ssl == NULL) { g_writeln("xrdp_tls_accept: SSL_new failed"); return 1; } if (SSL_use_certificate_file(self->ssl, self->cert, SSL_FILETYPE_PEM) <= 0) { g_writeln("xrdp_tls_accept: SSL_use_certificate_file failed"); return 1; } if (SSL_set_fd(self->ssl, self->trans->sck) < 1) { g_writeln("xrdp_tls_accept: SSL_set_fd failed"); return 1; } connection_status = SSL_accept(self->ssl); if (connection_status <= 0) { if (xrdp_tls_print_error("SSL_accept", self->ssl, connection_status)) { return 1; } } g_writeln("xrdp_tls_accept: TLS connection accepted"); return 0; }