/* handles a client connection */ void handle_connection(int sock){ u_int32_t calculated_crc32; command *temp_command; packet receive_packet; packet send_packet; int bytes_to_send; int bytes_to_recv; char buffer[MAX_INPUT_BUFFER]; char raw_command[MAX_INPUT_BUFFER]; char processed_command[MAX_INPUT_BUFFER]; int result=STATE_OK; int early_timeout=FALSE; int rc; int x; #ifdef DEBUG FILE *errfp; #endif #ifdef HAVE_SSL SSL *ssl=NULL; #endif /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Handling the connection..."); #ifdef OLDSTUFF /* socket should be non-blocking */ fcntl(sock,F_SETFL,O_NONBLOCK); #endif /* set connection handler */ signal(SIGALRM,my_connection_sighandler); alarm(connection_timeout); #ifdef HAVE_SSL /* do SSL handshake */ if(result==STATE_OK && use_ssl==TRUE){ if((ssl=SSL_new(ctx))!=NULL){ SSL_set_fd(ssl,sock); /* keep attempting the request if needed */ while(((rc=SSL_accept(ssl))!=1) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ)); if(rc!=1){ syslog(LOG_ERR,"Error: Could not complete SSL handshake. %d\n",SSL_get_error(ssl,rc)); #ifdef DEBUG errfp=fopen("/tmp/err.log","w"); ERR_print_errors_fp(errfp); fclose(errfp); #endif return; } } else{ syslog(LOG_ERR,"Error: Could not create SSL connection structure.\n"); #ifdef DEBUG errfp=fopen("/tmp/err.log","w"); ERR_print_errors_fp(errfp); fclose(errfp); #endif return; } } #endif bytes_to_recv=sizeof(receive_packet); if(use_ssl==FALSE) rc=recvall(sock,(char *)&receive_packet,&bytes_to_recv,socket_timeout); #ifdef HAVE_SSL else{ while(((rc=SSL_read(ssl,&receive_packet,bytes_to_recv))<=0) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ)); } #endif /* recv() error or client disconnect */ if(rc<=0){ /* log error to syslog facility */ syslog(LOG_ERR,"Could not read request from client, bailing out..."); #ifdef HAVE_SSL if(ssl){ SSL_shutdown(ssl); SSL_free(ssl); syslog(LOG_INFO,"INFO: SSL Socket Shutdown.\n"); } #endif return; } /* we couldn't read the correct amount of data, so bail out */ else if(bytes_to_recv!=sizeof(receive_packet)){ /* log error to syslog facility */ syslog(LOG_ERR,"Data packet from client was too short, bailing out..."); #ifdef HAVE_SSL if(ssl){ SSL_shutdown(ssl); SSL_free(ssl); } #endif return; } #ifdef DEBUG fp=fopen("/tmp/packet","w"); if(fp){ fwrite(&receive_packet,1,sizeof(receive_packet),fp); fclose(fp); } #endif /* make sure the request is valid */ if(validate_request(&receive_packet)==ERROR){ /* log an error */ syslog(LOG_ERR,"Client request was invalid, bailing out..."); /* free memory */ free(command_name); command_name=NULL; for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){ free(macro_argv[x]); macro_argv[x]=NULL; } #ifdef HAVE_SSL if(ssl){ SSL_shutdown(ssl); SSL_free(ssl); } #endif return; } /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Host is asking for command '%s' to be run...",receive_packet.buffer); /* disable connection alarm - a new alarm will be setup during my_system */ alarm(0); /* if this is the version check command, just spew it out */ if(!strcmp(command_name,NRPE_HELLO_COMMAND)){ snprintf(buffer,sizeof(buffer),"NRPE v%s",PROGRAM_VERSION); buffer[sizeof(buffer)-1]='\x0'; /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Response: %s",buffer); result=STATE_OK; } /* find the command we're supposed to run */ else{ temp_command=find_command(command_name); if(temp_command==NULL){ snprintf(buffer,sizeof(buffer),"NRPE: Command '%s' not defined",command_name); buffer[sizeof(buffer)-1]='\x0'; /* log error to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"%s",buffer); result=STATE_CRITICAL; } else{ /* process command line */ if(command_prefix==NULL) strncpy(raw_command,temp_command->command_line,sizeof(raw_command)-1); else snprintf(raw_command,sizeof(raw_command)-1,"%s %s",command_prefix,temp_command->command_line); raw_command[sizeof(raw_command)-1]='\x0'; process_macros(raw_command,processed_command,sizeof(processed_command)); /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Running command: %s",processed_command); /* run the command */ strcpy(buffer,""); result=my_system(processed_command,command_timeout,&early_timeout,buffer,sizeof(buffer)); /* log debug info */ if(debug==TRUE) syslog(LOG_DEBUG,"Command completed with return code %d and output: %s",result,buffer); /* see if the command timed out */ if(early_timeout==TRUE) snprintf(buffer,sizeof(buffer)-1,"NRPE: Command timed out after %d seconds\n",command_timeout); else if(!strcmp(buffer,"")) snprintf(buffer,sizeof(buffer)-1,"NRPE: Unable to read output\n"); buffer[sizeof(buffer)-1]='\x0'; /* check return code bounds */ if((result<0) || (result>3)){ /* log error to syslog facility */ syslog(LOG_ERR,"Bad return code for [%s]: %d", buffer,result); result=STATE_UNKNOWN; } } } /* free memory */ free(command_name); command_name=NULL; for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){ free(macro_argv[x]); macro_argv[x]=NULL; } /* strip newline character from end of output buffer */ if(buffer[strlen(buffer)-1]=='\n') buffer[strlen(buffer)-1]='\x0'; /* clear the response packet buffer */ bzero(&send_packet,sizeof(send_packet)); /* fill the packet with semi-random data */ randomize_buffer((char *)&send_packet,sizeof(send_packet)); /* initialize response packet data */ send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2); send_packet.packet_type=(int16_t)htons(RESPONSE_PACKET); send_packet.result_code=(int16_t)htons(result); strncpy(&send_packet.buffer[0],buffer,MAX_PACKETBUFFER_LENGTH); send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0'; /* calculate the crc 32 value of the packet */ send_packet.crc32_value=(u_int32_t)0L; calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet)); send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32); /***** ENCRYPT RESPONSE *****/ /* send the response back to the client */ bytes_to_send=sizeof(send_packet); if(use_ssl==FALSE) sendall(sock,(char *)&send_packet,&bytes_to_send); #ifdef HAVE_SSL else SSL_write(ssl,&send_packet,bytes_to_send); #endif #ifdef HAVE_SSL if(ssl){ SSL_shutdown(ssl); SSL_free(ssl); } #endif /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Return Code: %d, Output: %s",result,buffer); return; }
/* // Name: main // In: argv, the arguments sent to the program. // argc, the number of arguments sent to the program. */ int main (int argc, char **argv) { char port[6]; char ssl_port[6]; if(!arguments(argv, argc, port, ssl_port)) { printf("Usage: chat_server [port] [ssl port]\n"); return 0; } char topic[MAXTOKENSIZE]; memset(topic, '\0', MAXTOKENSIZE); // Set the signal handler. signal(SIGINT, signal_handler); server_socket = -1; ssl_socket = -1; server_socket_fd; int epoll_fd; struct epoll_event event, ssl_event; BIO *sbio; SSL *ssl; // Initialize ssl context. ctx=init_ctx(); memset(&event, 0, sizeof event); memset(&ssl_event, 0, sizeof event); printf("Trying to create socket.\n"); server_socket_fd = create_socket("telnet", port); ssl_socket_fd = create_socket("telnet", ssl_port); printf("Created socket.\n"); // Check if sockets couldn't be created. if(server_socket_fd<0 || ssl_socket_fd<0) { fprintf(stderr, "Socket could not be created!\n"); return -1; } // Set the socket to be non-blocking. server_socket = unblock_socket(server_socket_fd); ssl_socket = unblock_socket(ssl_socket_fd); if(server_socket<0 || ssl_socket<0) { fprintf(stderr, "Could not make socket non blocking.\n"); return -1; } printf("Listening...\n"); // Listen for incoming connections. server_socket = listen(server_socket_fd, NUMBER_PENDING_CONNECTIONS); ssl_socket = listen(ssl_socket_fd, NUMBER_PENDING_CONNECTIONS); if(server_socket < 0 || ssl_socket<0) { fprintf(stderr, "Could not listen to incoming connections.\n"); return -1; } epoll_fd = epoll_create1(0); event.data.fd = server_socket_fd; // Run as edge-triggered, meaning that epoll_wait will return only on // new events. event.events = EPOLLIN | EPOLLET; // Create epoll control interface for the unsecure socket. server_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_socket_fd, &event); ssl_event.data.fd=ssl_socket_fd; ssl_event.events = EPOLLIN | EPOLLET; // Create epoll control interface for the secure socket. ssl_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ssl_socket_fd, &ssl_event); if(server_socket<0 || ssl_socket<0) { fprintf(stderr, "Could not create control interface for polling.\n"); return -1; } events = calloc(MAXEVENTS, sizeof event); // Create hash map for storing connected clients. clients = hash_empty(MAXCLIENTS); struct sockaddr client_addr; socklen_t client_len; int insocket_fd; int client_socket; char host[MAXHOST_LEN], serv[MAXSERV_LEN]; client_len = sizeof client_addr; // Main loop listening from events generated by epoll. while(1) { int n,i; // Wait for new events. n = epoll_wait(epoll_fd, events, MAXEVENTS, -1); for(i=0;i<n;i++) { if((events[i].events & EPOLLERR) || events[i].events & EPOLLHUP || (!(events[i].events & EPOLLIN))) { fprintf(stderr, "An error occured at an event.\n"); clientconn_t *c; // If the an error-event occured at a connected client. if((c = hash_get(events[i].data.fd, clients))!=NULL) { client_close(c); hash_remove(c, clients); } close(events[i].data.fd); continue; } // If an a connection is made on the unsecure socket. else if(server_socket_fd == events[i].data.fd) { while(1) { // Accept connection. insocket_fd = accept(server_socket_fd, &client_addr, &client_len); if(insocket_fd<0) { if(!(errno == EAGAIN || errno == EWOULDBLOCK)) { fprintf(stderr, "Could not accept " "input connection"); break; } else { // If the whole handshake could not be made, // keep trying to accept. break; } } // The address information. server_socket = getnameinfo(&client_addr, client_len, host, sizeof host, serv, sizeof serv, NI_NUMERICHOST|NI_NUMERICSERV); if(server_socket==0) { printf("Connection accepted!\n"); } // Make client socket non-blocking. server_socket = unblock_socket(insocket_fd); if(server_socket <0) { fprintf(stderr, "Could not make client socket " "non-blocking\n"); return -1; } // Create an epoll interface for the client socket. event.data.fd = insocket_fd; event.events = EPOLLIN|EPOLLET; server_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, insocket_fd, &event); if(server_socket<0) { fprintf(stderr, "Could not create epoll " "interface for client\n"); return -1; } printf("Added client(%d)!\n", insocket_fd); // Store client in the hash map. c = create_client(insocket_fd, &client_addr); hash_insert(c, clients); } continue; } // If a connection is made on the secure socket. else if(ssl_socket_fd == events[i].data.fd) { printf("Someone connected through ssl!\n"); while(1) { // Accept in the same way as the unsecure socket. insocket_fd = accept(ssl_socket_fd, &client_addr, &client_len); if(insocket_fd<0) { if(!(errno == EAGAIN || errno == EWOULDBLOCK)) { fprintf(stderr, "Could not accept input " "connection\n"); break; } else { break; } } ssl_socket = getnameinfo(&client_addr, client_len, host, sizeof host, serv, sizeof serv, NI_NUMERICHOST|NI_NUMERICSERV); if(ssl_socket==0) { printf("Connection accepted!\n"); } // Make socket non-blocking ssl_socket = unblock_socket(insocket_fd); if(ssl_socket<0){ fprintf(stderr, "Could not make secure client " "socket non-blocking.\n"); return -1; } // Create epoll interface for the secure client connection ssl_event.data.fd = insocket_fd; ssl_event.events = EPOLLIN; ssl_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, insocket_fd, &ssl_event); if(ssl_socket<0) { fprintf(stderr, "Could not create " "epoll interface for client.\n"); return -1; } printf("Added client!(%d)\n", insocket_fd); c = create_client(insocket_fd, &client_addr); // Set up ssl. c->ssl_status=STATUS_HANDSHAKE; c->ssl = SSL_new(ctx); SSL_set_fd(c->ssl, insocket_fd); SSL_set_mode(c->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); hash_insert(c, clients); } continue; } // If an incoming message has caused an event. else { int done = 0; while (1) { ssize_t count; char buf[MAXBUFSIZE]; memset(buf, '\0', MAXBUFSIZE); clientconn_t *c = hash_get(events[i].data.fd, clients); // If the client is trying to make an ssl handshake. if(c->ssl_status==STATUS_HANDSHAKE) { int r=1; r=SSL_accept(c->ssl); if (r<0) { if(SSL_get_error(c->ssl, r)!=SSL_ERROR_WANT_READ && SSL_get_error(c->ssl, r)!=SSL_ERROR_WANT_WRITE ){ done=1; printf("Could not accept ssl " "connection\n"); break; } } else { // Handshake is done. c->ssl_status=STATUS_ACCEPTED; } } else { // Read data from client. int count = client_read(c, buf, sizeof buf); if(count<0) { if(errno!=EAGAIN) { fprintf(stderr, "Could not read" " from socket!\n"); done=1; } break; } if(buf[MAXBUFSIZE-1] != '\0') { write(events[i].data.fd, "* BAD Buffer will " "overflow\r\n", 28); break; } else if (count==0) { done=1; break; } if (handle_input(events[i].data.fd, buf, count, clients, topic)==CLIENTCLOSED) { done=1; break; } if(server_socket<0) { fprintf(stderr, "Could get input.\n"); return -1; } } } // Client connection is done, wants to disconnect. if(done) { printf("Closed connection!\n"); clientconn_t *closeclient = hash_get(events[i].data.fd, clients); if(closeclient != NULL) { hash_remove(closeclient, clients); client_close(closeclient); } close(events[i].data.fd); } } } } free(events); close(server_socket_fd); return 0; }
static void init_ssl(CLI *c) { int i, err; SSL_SESSION *old_session; int unsafe_openssl; c->ssl=SSL_new(c->opt->ctx); if(!c->ssl) { sslerror("SSL_new"); longjmp(c->err, 1); } SSL_set_ex_data(c->ssl, cli_index, c); /* for callbacks */ if(c->opt->option.client) { #ifndef OPENSSL_NO_TLSEXT if(c->opt->sni) { s_log(LOG_DEBUG, "SNI: host name: %s", c->opt->sni); if(!SSL_set_tlsext_host_name(c->ssl, c->opt->sni)) { sslerror("SSL_set_tlsext_host_name"); longjmp(c->err, 1); } } #endif if(c->opt->session) { enter_critical_section(CRIT_SESSION); SSL_set_session(c->ssl, c->opt->session); leave_critical_section(CRIT_SESSION); } SSL_set_fd(c->ssl, c->remote_fd.fd); SSL_set_connect_state(c->ssl); } else { if(c->local_rfd.fd==c->local_wfd.fd) SSL_set_fd(c->ssl, c->local_rfd.fd); else { /* does it make sense to have SSL on STDIN/STDOUT? */ SSL_set_rfd(c->ssl, c->local_rfd.fd); SSL_set_wfd(c->ssl, c->local_wfd.fd); } SSL_set_accept_state(c->ssl); } /* setup some values for transfer() function */ if(c->opt->option.client) { c->sock_rfd=&(c->local_rfd); c->sock_wfd=&(c->local_wfd); c->ssl_rfd=c->ssl_wfd=&(c->remote_fd); } else { c->sock_rfd=c->sock_wfd=&(c->remote_fd); c->ssl_rfd=&(c->local_rfd); c->ssl_wfd=&(c->local_wfd); } unsafe_openssl=SSLeay()<0x0090810fL || (SSLeay()>=0x10000000L && SSLeay()<0x1000002fL); while(1) { /* critical section for OpenSSL version < 0.9.8p or 1.x.x < 1.0.0b * * this critical section is a crude workaround for CVE-2010-3864 * * see http://www.securityfocus.com/bid/44884 for details * * alternative solution is to disable internal session caching * * NOTE: this critical section also covers callbacks (e.g. OCSP) */ if(unsafe_openssl) enter_critical_section(CRIT_SSL); if(c->opt->option.client) i=SSL_connect(c->ssl); else i=SSL_accept(c->ssl); if(unsafe_openssl) leave_critical_section(CRIT_SSL); err=SSL_get_error(c->ssl, i); if(err==SSL_ERROR_NONE) break; /* ok -> done */ if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) { s_poll_init(c->fds); s_poll_add(c->fds, c->ssl_rfd->fd, err==SSL_ERROR_WANT_READ, err==SSL_ERROR_WANT_WRITE); switch(s_poll_wait(c->fds, c->opt->timeout_busy, 0)) { case -1: sockerror("init_ssl: s_poll_wait"); longjmp(c->err, 1); case 0: s_log(LOG_INFO, "init_ssl: s_poll_wait:" " TIMEOUTbusy exceeded: sending reset"); longjmp(c->err, 1); case 1: break; /* OK */ default: s_log(LOG_ERR, "init_ssl: s_poll_wait: unknown result"); longjmp(c->err, 1); } continue; /* ok -> retry */ } if(err==SSL_ERROR_SYSCALL) { switch(get_last_socket_error()) { case S_EINTR: case S_EWOULDBLOCK: #if S_EAGAIN!=S_EWOULDBLOCK case S_EAGAIN: #endif continue; } } if(c->opt->option.client) sslerror("SSL_connect"); else sslerror("SSL_accept"); longjmp(c->err, 1); } if(SSL_session_reused(c->ssl)) { s_log(LOG_INFO, "SSL %s: previous session reused", c->opt->option.client ? "connected" : "accepted"); } else { /* a new session was negotiated */ #ifdef USE_WIN32 win_new_chain(c); #endif if(c->opt->option.client) { s_log(LOG_INFO, "SSL connected: new session negotiated"); enter_critical_section(CRIT_SESSION); old_session=c->opt->session; c->opt->session=SSL_get1_session(c->ssl); /* store it */ if(old_session) SSL_SESSION_free(old_session); /* release the old one */ leave_critical_section(CRIT_SESSION); } else s_log(LOG_INFO, "SSL accepted: new session negotiated"); print_cipher(c); } }
/** * @brief Accept a TLS connection and authenticate and identify. * @note Various fields in #conn are set, like username and keyhash. */ int ServerTLSSessionEstablish(ServerConnectionState *conn) { int ret; if (ConnectionInfoConnectionStatus(conn->conn_info) != CF_CONNECTION_ESTABLISHED) { assert(ConnectionInfoSSL(conn->conn_info) == NULL); SSL *ssl = SSL_new(SSLSERVERCONTEXT); if (ssl == NULL) { Log(LOG_LEVEL_ERR, "SSL_new: %s", TLSErrorString(ERR_get_error())); return -1; } ConnectionInfoSetSSL(conn->conn_info, ssl); /* Pass conn_info inside the ssl struct for TLSVerifyCallback(). */ SSL_set_ex_data(ssl, CONNECTIONINFO_SSL_IDX, conn->conn_info); /* Now we are letting OpenSSL take over the open socket. */ SSL_set_fd(ssl, ConnectionInfoSocket(conn->conn_info)); ret = SSL_accept(ssl); if (ret <= 0) { TLSLogError(ssl, LOG_LEVEL_ERR, "Failed to accept TLS connection", ret); return -1; } Log(LOG_LEVEL_VERBOSE, "TLS cipher negotiated: %s, %s", SSL_get_cipher_name(ssl), SSL_get_cipher_version(ssl)); Log(LOG_LEVEL_VERBOSE, "TLS session established, checking trust..."); /* Send/Receive "CFE_v%d" version string, agree on version, receive identity (username) of peer. */ char username[sizeof(conn->username)] = ""; bool b = ServerIdentificationDialog(conn->conn_info, username, sizeof(username)); if (b != true) { return -1; } /* We *now* (maybe a bit late) verify the key that the client sent us in * the TLS handshake, since we need the username to do so. TODO in the * future store keys irrelevant of username, so that we can match them * before IDENTIFY. */ ret = TLSVerifyPeer(conn->conn_info, conn->ipaddr, username); if (ret == -1) /* error */ { return -1; } if (ret == 1) /* trusted key */ { Log(LOG_LEVEL_VERBOSE, "%s: Client is TRUSTED, public key MATCHES stored one.", KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); } if (ret == 0) /* untrusted key */ { if ((SV.trustkeylist != NULL) && (IsMatchItemIn(SV.trustkeylist, conn->ipaddr))) { Log(LOG_LEVEL_VERBOSE, "Peer was found in \"trustkeysfrom\" list"); Log(LOG_LEVEL_NOTICE, "Trusting new key: %s", KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); SavePublicKey(username, KeyPrintableHash(conn->conn_info->remote_key), KeyRSA(ConnectionInfoKey(conn->conn_info))); } else { Log(LOG_LEVEL_NOTICE, "TRUST FAILED, peer presented an untrusted key, dropping connection!"); Log(LOG_LEVEL_VERBOSE, "Add peer to \"trustkeysfrom\" if you really want to start trusting this new key."); return -1; } } /* All checks succeeded, set conn->uid (conn->sid for Windows) * according to the received USERNAME identity. */ SetConnIdentity(conn, username); /* No CAUTH, SAUTH in non-classic protocol. */ conn->user_data_set = 1; conn->rsa_auth = 1; LastSaw1(conn->ipaddr, KeyPrintableHash(ConnectionInfoKey(conn->conn_info)), LAST_SEEN_ROLE_ACCEPT); ServerSendWelcome(conn); } return 1; }
LWS_VISIBLE int lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) { struct lws_context *context = wsi->context; struct lws_vhost *vh; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; int n, m; #if !defined(USE_WOLFSSL) && !defined(LWS_WITH_MBEDTLS) BIO *bio; #endif char buf[256]; (void)buf; if (!LWS_SSL_ENABLED(wsi->vhost)) return 0; switch (wsi->mode) { case LWSCM_SSL_INIT: case LWSCM_SSL_INIT_RAW: if (wsi->ssl) lwsl_err("%s: leaking ssl\n", __func__); if (accept_fd == LWS_SOCK_INVALID) assert(0); if (context->simultaneous_ssl_restriction && context->simultaneous_ssl >= context->simultaneous_ssl_restriction) { lwsl_notice("unable to deal with SSL connection\n"); return 1; } errno = 0; wsi->ssl = SSL_new(wsi->vhost->ssl_ctx); if (wsi->ssl == NULL) { lwsl_err("SSL_new failed: %d (errno %d)\n", lws_ssl_get_error(wsi, 0), errno); lws_ssl_elaborate_error(); if (accept_fd != LWS_SOCK_INVALID) compatible_close(accept_fd); goto fail; } #if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK) if (wsi->vhost->ssl_info_event_mask) SSL_set_info_callback(wsi->ssl, lws_ssl_info_callback); #endif if (context->simultaneous_ssl_restriction && ++context->simultaneous_ssl == context->simultaneous_ssl_restriction) /* that was the last allowed SSL connection */ lws_gate_accepts(context, 0); #if defined(LWS_WITH_STATS) context->updated = 1; #endif #if !defined(LWS_WITH_MBEDTLS) SSL_set_ex_data(wsi->ssl, openssl_websocket_private_data_index, wsi); #endif SSL_set_fd(wsi->ssl, accept_fd); #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL CyaSSL_set_using_nonblock(wsi->ssl, 1); #else wolfSSL_set_using_nonblock(wsi->ssl, 1); #endif #else #if defined(LWS_WITH_MBEDTLS) lws_plat_set_socket_options(wsi->vhost, accept_fd); #else SSL_set_mode(wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); bio = SSL_get_rbio(wsi->ssl); if (bio) BIO_set_nbio(bio, 1); /* nonblocking */ else lwsl_notice("NULL rbio\n"); bio = SSL_get_wbio(wsi->ssl); if (bio) BIO_set_nbio(bio, 1); /* nonblocking */ else lwsl_notice("NULL rbio\n"); #endif #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 */ if (wsi->mode == LWSCM_SSL_INIT) wsi->mode = LWSCM_SSL_ACK_PENDING; else wsi->mode = LWSCM_SSL_ACK_PENDING_RAW; if (insert_wsi_socket_into_fds(context, wsi)) { lwsl_err("%s: failed to insert into fds\n", __func__); goto fail; } lws_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT, context->timeout_secs); lwsl_debug("inserted SSL accept into fds, trying SSL_accept\n"); /* fallthru */ case LWSCM_SSL_ACK_PENDING: case LWSCM_SSL_ACK_PENDING_RAW: if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { lwsl_err("%s: lws_change_pollfd failed\n", __func__); goto fail; } lws_latency_pre(context, wsi); if (wsi->vhost->allow_non_ssl_on_ssl_port) { n = recv(wsi->desc.sockfd, (char *)pt->serv_buf, context->pt_serv_buf_size, 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 (n >= 1 && pt->serv_buf[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; if (lws_check_opt(context->options, LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS)) wsi->redirect_to_https = 1; 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 */ #if defined(LWS_WITH_STATS) if (!wsi->accept_start_us) wsi->accept_start_us = time_in_microseconds(); #endif errno = 0; lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNECTIONS_ACCEPT_SPIN, 1); n = SSL_accept(wsi->ssl); lws_latency(context, wsi, "SSL_accept LWSCM_SSL_ACK_PENDING\n", n, n == 1); lwsl_info("SSL_accept says %d\n", n); if (n == 1) goto accepted; m = lws_ssl_get_error(wsi, n); #if defined(LWS_WITH_MBEDTLS) if (m == SSL_ERROR_SYSCALL && errno == 11) m = SSL_ERROR_WANT_READ; #endif if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL) goto failed; go_again: if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) { if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { lwsl_info("%s: WANT_READ change_pollfd failed\n", __func__); goto fail; } lwsl_info("SSL_ERROR_WANT_READ\n"); break; } if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) { lwsl_debug("%s: WANT_WRITE\n", __func__); if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) { lwsl_info("%s: WANT_WRITE change_pollfd failed\n", __func__); goto fail; } break; } failed: lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNECTIONS_FAILED, 1); wsi->socket_is_permanently_unusable = 1; lwsl_info("SSL_accept failed socket %u: %s\n", wsi->desc.sockfd, lws_ssl_get_error_string(m, n, buf, sizeof(buf))); lws_ssl_elaborate_error(); goto fail; accepted: lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED, 1); #if defined(LWS_WITH_STATS) lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY, time_in_microseconds() - wsi->accept_start_us); wsi->accept_start_us = time_in_microseconds(); #endif /* adapt our vhost to match the SNI SSL_CTX that was chosen */ vh = context->vhost_list; while (vh) { if (!vh->being_destroyed && wsi->ssl && vh->ssl_ctx == SSL_get_SSL_CTX(wsi->ssl)) { lwsl_info("setting wsi to vh %s\n", vh->name); wsi->vhost = vh; break; } vh = vh->vhost_next; } /* OK, we are accepted... give him some time to negotiate */ lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER, context->timeout_secs); if (wsi->mode == LWSCM_SSL_ACK_PENDING_RAW) wsi->mode = LWSCM_RAW; else wsi->mode = LWSCM_HTTP_SERVING; #if defined(LWS_WITH_HTTP2) if (lws_h2_configure_if_upgraded(wsi)) goto fail; #endif lwsl_debug("accepted new SSL conn\n"); break; } return 0; fail: return 1; }
void server(int protocol) { int sock,s; BIO *sbio; SSL_CTX *ctx; SSL *ssl; int r; pid_t pid; /* Build our SSL context*/ ctx=initialize_ctx(KEYFILE,PASSWORD); load_dh_params(ctx,DHFILE); SSL_CTX_set_cipher_list(ctx,"ALL"); long options = SSL_OP_NO_TICKET | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; int port; switch (protocol) { case SSL2_VERSION: options |= SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; port = 4434; break; case SSL3_VERSION: options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; port = 4435; break; case TLS1_VERSION: options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; port = 4436; break; case TLS1_1_VERSION: options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2; port = 4437; break; case TLS1_2_VERSION: options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1; port = 4438; break; default: err_exit("Unexpected protocol value"); } SSL_CTX_set_options(ctx, options); sock=tcp_listen(port); while(1){ if((s=accept(sock,0,0))<0) err_exit("Problem accepting"); if((pid=fork())){ close(s); } else { sbio=BIO_new_socket(s,BIO_NOCLOSE); ssl=SSL_new(ctx); SSL_set_bio(ssl,sbio,sbio); if((r=SSL_accept(ssl)<=0)) berr_exit("SSL accept error"); http_serve(ssl,s); exit(0); } } destroy_ctx(ctx); }
int main(int argc , char *argv[]) { int sfd; char *P_num; SSL_CTX * ctx; struct sockaddr_in cli_addr; socklen_t len ; int cli; pid_t pid; struct sigaction sa; //Innitiliaze Server if (checkFileStruct() == -1){ printf("Server: Problem With OldTrusty File Structure\n"); exit(1); } //Initialize the Vouch Structure initVouchStruct(); //Initialize SSL if (argc != 2) { printf("Usage %s <portNUMBER> \n" , argv[0]); exit(1); } P_num = argv[1]; //Set Port ctx = InitSSL(); load_Certs(ctx, "OldTrusty/ServerCerts/server.crt", "OldTrusty/ServerCerts/server.key"); //ALL IN ONE ? //Get A regular tcp socket. already bound and listening. sfd = sock_setup(P_num); sa.sa_handler = sigchld_handler; // reap all dead processes sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } printf("Server: OldTrusty Awaiting Connections on Port: %s\n" , P_num); //***********************************MAIN ACCEPT LOOP STARTS HERE *****************************/ for(;;) { len = sizeof(cli_addr); cli = accept(sfd, (struct sockaddr *)&cli_addr, &len); if (cli == -1) { perror("accept"); continue; } printf("Server: OLDTRUSTY recieved A Connection from: %s:%d\n",inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)); SSL *ssl; if ( ( pid = fork()) == 0 ){ //WE ARE THE CHILD close(sfd); //Child doesnt need listner //Layer SSL Over Client Socket ssl = SSL_new(ctx); SSL_set_fd(ssl, cli); //HANDSHAKE.. if ( SSL_accept(ssl) == -1) ERR_print_errors_fp(stderr); //Show Client Certs (If any) // CAN ADDif require client auth then //for now jsut show client certs if has any ShowCerts(ssl); // Here is a connection to the client do_clients_bidding(ssl); SSL_free(ssl); close(cli); exit(0); // kill child. } close(cli); //Parent closes connected socket (Being Handled in child) } ///***END MAIN ACCEPT LOOP *****// SSL_CTX_free(ctx); //release context TODO never get hear?? graceful shutdown of server? return 0; }
bool SSLSocket::enableCrypto(bool activate /* = true */) { if (activate && !m_data->m_ssl_active) { double timeout = m_data->m_connect_timeout; bool blocked = m_data->m_is_blocked; if (!m_data->m_state_set) { if (m_data->m_client) { SSL_set_connect_state(m_data->m_handle); } else { SSL_set_accept_state(m_data->m_handle); } m_data->m_state_set = true; } if (m_data->m_client && setBlocking(false)) { m_data->m_is_blocked = false; } int n; bool retry = true; do { if (m_data->m_client) { struct timeval tvs, tve; struct timezone tz; gettimeofday(&tvs, &tz); n = SSL_connect(m_data->m_handle); gettimeofday(&tve, &tz); timeout -= (tve.tv_sec + (double) tve.tv_usec / 1000000) - (tvs.tv_sec + (double) tvs.tv_usec / 1000000); if (timeout < 0) { raise_warning("SSL: connection timeout"); return false; } } else { n = SSL_accept(m_data->m_handle); } if (n <= 0) { retry = handleError(n, true); } else { break; } } while (retry); if (m_data->m_client && m_data->m_is_blocked != blocked && setBlocking(blocked)) { m_data->m_is_blocked = blocked; } if (n == 1) { X509 *peer_cert = SSL_get_peer_certificate(m_data->m_handle); if (!applyVerificationPolicy(peer_cert)) { SSL_shutdown(m_data->m_handle); } else { m_data->m_ssl_active = true; /* allow the script to capture the peer cert * and/or the certificate chain */ if (m_context[s_capture_peer_cert].toBoolean()) { m_context.set(s_peer_certificate, Variant(req::make<Certificate>(peer_cert))); peer_cert = nullptr; } if (m_context[s_capture_peer_cert_chain].toBoolean()) { Array arr; STACK_OF(X509) *chain = SSL_get_peer_cert_chain(m_data->m_handle); if (chain) { for (int i = 0; i < sk_X509_num(chain); i++) { X509 *mycert = X509_dup(sk_X509_value(chain, i)); arr.append(Variant(req::make<Certificate>(mycert))); } } m_context.set(s_peer_certificate_chain, arr); } } if (peer_cert) { X509_free(peer_cert); } } else { n = errno == EAGAIN ? 0 : -1; } return n >= 0; } else if (!activate && m_data->m_ssl_active) { /* deactivate - common for server/client */ SSL_shutdown(m_data->m_handle); m_data->m_ssl_active = false; } return true; }
THREAD_RETURN YASSL_API echoserver_test(void* args) { #ifdef _WIN32 WSADATA wsd; WSAStartup(0x0002, &wsd); #endif SOCKET_T sockfd = 0; int argc = 0; char** argv = 0; set_args(argc, argv, *static_cast<func_args*>(args)); #ifdef ECHO_OUT FILE* fout = stdout; if (argc >= 2) fout = fopen(argv[1], "w"); if (!fout) err_sys("can't open output file"); #endif tcp_listen(sockfd); SSL_METHOD* method = SSLv23_server_method(); SSL_CTX* ctx = SSL_CTX_new(method); set_serverCerts(ctx); DH* dh = set_tmpDH(ctx); bool shutdown(false); #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) // signal ready to tcp_accept func_args& server_args = *((func_args*)args); tcp_ready& ready = *server_args.signal_; pthread_mutex_lock(&ready.mutex_); ready.ready_ = true; pthread_cond_signal(&ready.cond_); pthread_mutex_unlock(&ready.mutex_); #endif while (!shutdown) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); SOCKET_T clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); if (clientfd == (SOCKET_T) -1) { SSL_CTX_free(ctx); tcp_close(sockfd); err_sys("tcp accept failed"); } SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); if (SSL_accept(ssl) != SSL_SUCCESS) { printf("SSL_accept failed\n"); SSL_free(ssl); tcp_close(clientfd); continue; } char command[1024]; int echoSz(0); while ( (echoSz = SSL_read(ssl, command, sizeof(command))) > 0) { if ( strncmp(command, "quit", 4) == 0) { printf("client sent quit command: shutting down!\n"); shutdown = true; break; } else if ( strncmp(command, "GET", 3) == 0) { char type[] = "HTTP/1.0 200 ok\r\nContent-type:" " text/html\r\n\r\n"; char header[] = "<html><body BGCOLOR=\"#ffffff\">\n<pre>\n"; char body[] = "greetings from yaSSL\n"; char footer[] = "</body></html>\r\n\r\n"; strncpy(command, type, sizeof(type)); echoSz = sizeof(type) - 1; strncpy(&command[echoSz], header, sizeof(header)); echoSz += sizeof(header) - 1; strncpy(&command[echoSz], body, sizeof(body)); echoSz += sizeof(body) - 1; strncpy(&command[echoSz], footer, sizeof(footer)); echoSz += sizeof(footer); if (SSL_write(ssl, command, echoSz) != echoSz) EchoError(ctx, ssl, sockfd, clientfd, "SSL_write failed"); break; } command[echoSz] = 0; #ifdef ECHO_OUT fputs(command, fout); #endif if (SSL_write(ssl, command, echoSz) != echoSz) EchoError(ctx, ssl, sockfd, clientfd, "SSL_write failed"); } SSL_shutdown(ssl); SSL_free(ssl); tcp_close(clientfd); } tcp_close(sockfd); DH_free(dh); SSL_CTX_free(ctx); ((func_args*)args)->return_code = 0; return 0; }
fprintf(stderr, "SSL_set_fd failed\n"); goto err; } return conn; err: ssl_display_errors(); return NULL; } void ssl_setup_accept(SSL_CTX *ctx __attribute__ ((unused)), SSL *conn){ int sslaccept = 0; X509 *cert; char *line; sslaccept = SSL_accept(conn); if(sslaccept < 0){ ssl_display_errors(); fprintf(stderr, "SSL_accept failed with error %d\n", SSL_get_error(conn, sslaccept)); cleanup_ssl(); exit(EXIT_FAILURE); } printf("SSL connection using %s\n", SSL_get_cipher (conn)); /* if present, get certs and display some info about them */ if ( (cert = SSL_get_peer_certificate(conn)) ) { printf("Server certs:\n"); line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); printf("Subject: %s\n", line);
int main() { struct sockaddr_in server; struct sockaddr_in dest; int socket_fd, client_fd,num; socklen_t size; SSL_CTX *ctx; /******* START SSL ***************/ /* http://mooon.blog.51cto.com/1246491/909932 */ /* SSL Libraries Init */ SSL_library_init(); /* add all SSL algorithms */ OpenSSL_add_all_algorithms(); /* add all SSL ciphers */ OpenSSL_add_all_ciphers(); /* add all digests */ OpenSSL_add_all_digests(); /* load all SSL errors */ SSL_load_error_strings(); /* Build SSL_CTX -> SSL Content Text * SSLv2_server_method() or SSLv3_server_method() relative to SSL V2 * and SSL V3 */ ctx = SSL_CTX_new(SSLv23_server_method()); if(ctx == NULL){ ERR_print_errors_fp(stdout); exit(EXIT_FAILURE); } /* Load the server certificate into the SSL_CTX structure */ if(SSL_CTX_use_certificate_file(ctx,RSA_SERVER_CERT,SSL_FILETYPE_PEM) <= 0){ ERR_print_errors_fp(stdout); exit(EXIT_FAILURE); } /* Load the private-key corresponding to the server certificate */ if(SSL_CTX_use_PrivateKey_file(ctx,RSA_SERVER_KEY,SSL_FILETYPE_PEM) <= 0){ ERR_print_errors_fp(stdout); exit(EXIT_FAILURE); } /* Check if the server certificate and private-key matches */ if(!SSL_CTX_check_private_key(ctx)){ ERR_print_errors_fp(stdout); exit(EXIT_FAILURE); } /*********** END SSL ****************/ int yes =1; /* Open a socket to listen */ if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) { fprintf(stderr, "Socket failure!!\n"); exit(EXIT_FAILURE); } if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(EXIT_FAILURE); } /* init memory for server and dest */ memset(&server, 0, sizeof(server)); memset(&dest,0,sizeof(dest)); server.sin_family = AF_INET; //same to PF_INET server.sin_port = htons(PORT); server.sin_addr.s_addr = INADDR_ANY; /* BIND SOCKET */ if ((bind(socket_fd, (struct sockaddr *)&server, sizeof(struct sockaddr )))== -1) { //sizeof(struct sockaddr) fprintf(stderr, "Binding Failure\n"); exit(EXIT_FAILURE); } /* START LISTENING */ if ((listen(socket_fd, BACKLOG))== -1){ fprintf(stderr, "Listening Failure\n"); exit(EXIT_FAILURE); } while(1) { SSL *ssl; size = sizeof(struct sockaddr_in); /* Waiting for client to connect */ if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size))==-1 ) { perror("accept"); continue; //exit(EXIT_FAILURE); } else{ printf("Server got connection from client %s, port %d, socket %d\n", inet_ntoa(dest.sin_addr),ntohs(dest.sin_port),client_fd); } /* /connection complete */ /* create a new ssl based on ctx */ ssl = SSL_new(ctx); /* add socket : client_fd to SSL */ SSL_set_fd(ssl,client_fd); /* Build up SSL connection */ if(SSL_accept(ssl) == -1){ perror("accept"); SSL_shutdown(ssl); SSL_free(ssl); close(client_fd); continue; //exit(EXIT_FAILURE); } /******* START PROCESSING DATA *************/ /* read header - then do action based on header parsing */ char header_buf[HEADER_SIZE]; int len = HEADER_SIZE; if ((num = recv_all(ssl, (unsigned char *)header_buf, &len))== -1) { printf("Read header failed\n"); perror("recv"); SSL_shutdown(ssl); SSL_free(ssl); close(client_fd); continue; //exit(EXIT_FAILURE); } char *hr = NULL; hr = malloc(3); SSL_read(ssl, hr, sizeof(hr)); if(strcmp("100",hr)){ printf("Header receiving failed\n"); SSL_write(ssl,"-1",strlen("-1")); /* Close SSL Connection */ SSL_shutdown(ssl); /* Release SSL */ SSL_free(ssl); //Close Connection Socket close(client_fd); continue; } else{ printf("Header received successfully\n"); } /* unpack header string */ header h; if (unpack_header_string(header_buf, &h) == -1) { fprintf(stderr, "[SERVER] Could not unpack header information from client\n"); h.action = FAIL_ERROR; //exit(EXIT_FAILURE); } if (h.action == FAIL_ERROR) { printf("Header action is FAIL ERROR\n"); SSL_write(ssl,"-1",strlen("-1")); /* Close SSL Connection */ SSL_shutdown(ssl); /* Release SSL */ SSL_free(ssl); //Close Connection Socket close(client_fd); continue; } //inform client header unpacked successfully SSL_write(ssl,"100",strlen("100")); printf("Header unpacked successfully\n"); // header part end // if client requests to uplaod file if (h.action == ADD_FILE) { char *target = NULL; target = malloc(BLOCK_SIZE); sprintf(target, "%s/%s", SERVER_FILE_DIR, h.file_name); printf("[SERVER] Adding file %s\n", target); receive_file(ssl, target, h.file_size); free(target); } else if (h.action == FETCH_FILE) { char *target = NULL; target = malloc(BLOCK_SIZE); sprintf(target, "%s/%s", SERVER_FILE_DIR, h.file_name); printf("[SERVER] Fetching file %s\n", target); FILE *fp; if (!(fp = fopen(target, "r"))) { perror("fopen"); /* Close SSL Connection */ SSL_shutdown(ssl); /* Release SSL */ SSL_free(ssl); //Close Connection Socket close(client_fd); continue; //exit(EXIT_FAILURE); } free(target); // get file's protection rating to compare to // client's requested circumference int protectionRating = getProtectionRating(h.file_name); header h_send; if (protectionRating >= h.circ) { h_send.action = ADD_FILE; } else { h_send.action = FAIL_ERROR; // client will fail out } h_send.file_size = get_file_size(fp); h_send.file_name = h.file_name; h_send.certificate = " "; send_header(ssl, h_send); if (protectionRating >= h.circ) send_file(ssl, fp); fclose(fp); } else if (h.action == UPLOAD_CERT) { char target[MAXSIZE]; sprintf(target, "%s/%s_crt.pem", SERVER_CERT_DIR, h.file_name); printf("Receiving cert and storing: %s\n", target); receive_file(ssl, target, h.file_size); }// if client requests to list files else if (h.action == LIST_FILE) { char **files; size_t count; unsigned int i; count = file_list(SERVER_FILE_DIR, &files); for (i = 0; i < count; i++) { char *send_str = NULL; send_str = malloc(MAXSIZE); int protectionRating = getProtectionRating(files[i]); if (protectionRating >= h.circ) { sprintf(send_str, "Protected (c = %i): %s",protectionRating,files[i]); } else { sprintf(send_str, "Unprotected (c = %i): %s",protectionRating,files[i]); } send_message(ssl, send_str); free(send_str); } printf("File list transmitting completed.\n"); close(client_fd); printf("Client connection closed.\n"); } /* if client requires to vouch a file * https://gitorious.org/random_play/random_play/source/b9f19d4d9e8d4a9ba0ef55a6b0e2113d1c6a5587:openssl_sign.c */ else if (h.action == VOUCH_FILE){ // vouch for this file const char *clearTextFileName = h.file_name; int isCertFile = isNameCertFile(clearTextFileName); // vouch using this certificate char *certificate_file_name = h.certificate; char *cert_loc = NULL; cert_loc = malloc(MAXSIZE); sprintf(cert_loc, "%s/%s", SERVER_CERT_DIR, certificate_file_name); if (!check_if_file_exists(cert_loc)) { char *message = NULL; message = malloc(MAXSIZE); sprintf(message, "Unable to locate %s certificate on the server. Please upload using -a\n", cert_loc); SSL_write(ssl, message,strlen(message)); free(message); /* Close SSL Connection */ SSL_shutdown(ssl); /* Release SSL */ SSL_free(ssl); //Close Connection Socket close(client_fd); continue; // should notify client here somehow } else{ char *message = NULL; message = malloc(MAXSIZE); sprintf(message, "Located %s certificate on the server. \n", cert_loc); SSL_write(ssl, message,strlen(message)); free(message); } free(cert_loc); char *target = NULL; target = malloc(MAXSIZE); if (isCertFile) { sprintf(target, "%s/%s", SERVER_CERT_DIR, h.file_name); } else { sprintf(target, "%s/%s", SERVER_FILE_DIR, h.file_name); } unsigned char *md5Value = NULL; md5Value = malloc(MD5_DIGEST_LENGTH); if(hashFile(md5Value, (const char *)target)!=0){ printf("Couldn't open file"); free(target); /* Close SSL Connection */ SSL_shutdown(ssl); /* Release SSL */ SSL_free(ssl); //Close Connection Socket close(client_fd); continue; } free(target); send_message(ssl, (char *)md5Value); unsigned char signature[MAXSIZE]; SSL_read(ssl, signature, 128); char *sig_name = NULL; sig_name = malloc(MAXSIZE); // keep certificate signatures with certificates if (isCertFile) { sprintf(sig_name, "%s/%s_%s.sig", SERVER_CERT_DIR, clearTextFileName, certificate_file_name); } else { sprintf(sig_name, "%s/%s_%s.sig", SERVER_SIG_DIR, clearTextFileName, certificate_file_name); } if (writeSig(signature, sig_name) != 0) { fprintf(stderr, "Could not save signature file\n"); free(sig_name); SSL_write(ssl,"-1",strlen("-1")); /* Close SSL Connection */ SSL_shutdown(ssl); /* Release SSL */ SSL_free(ssl); //Close Connection Socket close(client_fd); continue; //exit(EXIT_FAILURE); } else{ printf("Sig loc: %s\n", sig_name); SSL_write(ssl,"100",strlen("100")); } free(sig_name); } else if (h.action == VERIFY_FILE){ // test verification of signature files char signatoryCertName[MAXSIZE]; sprintf( signatoryCertName, "%s_crt.pem", h.certificate ); const char *clearText = h.file_name; if(!verifySig(signatoryCertName,clearText)){ printf("Verify failed\n"); } } else if (h.action == FIND_ISSUER){ char certPath[MAXSIZE]; sprintf( certPath, "%s", h.certificate ); } else if (h.action == TEST_RINGOFTRUST) { ringOfTrust(h.file_name); } /********** END DATA PROCESSING **************/ free(h.certificate); free(h.file_name); /* Close SSL Connection */ SSL_shutdown(ssl); /* Release SSL */ SSL_free(ssl); //Close Connection Socket close(client_fd); } //Outer While /* Close listening socket */ close(socket_fd); /* Release CTX */ SSL_CTX_free(ctx); return 0; } //End of main
THREAD_RETURN CYASSL_API echoserver_test(void* args) { SOCKET_T sockfd = 0; SSL_METHOD* method = 0; SSL_CTX* ctx = 0; int shutdown = 0; int argc = 0; char** argv = 0; #ifdef ECHO_OUT FILE* fout = stdout; if (argc >= 2) fout = fopen(argv[1], "w"); if (!fout) err_sys("can't open output file"); #endif ((func_args*)args)->return_code = -1; /* error state */ argc = ((func_args*)args)->argc; argv = ((func_args*)args)->argv; tcp_listen(&sockfd); #if defined(CYASSL_DTLS) method = DTLSv1_server_method(); #elif !defined(NO_TLS) method = TLSv1_server_method(); #else method = SSLv3_server_method(); #endif ctx = SSL_CTX_new(method); /* SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); */ if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) err_sys("can't load ca file"); if (SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server cert file"); if (SSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server key file"); SignalReady(args); while (!shutdown) { SSL* ssl = 0; char command[1024]; int echoSz = 0; int clientfd; #ifndef CYASSL_DTLS SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); #else clientfd = udp_read_connect(sockfd); #endif if (clientfd == -1) err_sys("tcp accept failed"); ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); if (SSL_accept(ssl) != SSL_SUCCESS) { printf("SSL_accept failed"); SSL_free(ssl); CloseSocket(clientfd); continue; } while ( (echoSz = SSL_read(ssl, command, sizeof(command))) > 0) { if ( strncmp(command, "quit", 4) == 0) { printf("client sent quit command: shutting down!\n"); shutdown = 1; break; } if ( strncmp(command, "break", 5) == 0) { printf("client sent break command: closing session!\n"); break; } else if ( strncmp(command, "GET", 3) == 0) { char type[] = "HTTP/1.0 200 ok\r\nContent-type:" " text/html\r\n\r\n"; char header[] = "<html><body BGCOLOR=\"#ffffff\">\n<pre>\n"; char body[] = "greetings from CyaSSL\n"; char footer[] = "</body></html>\r\n\r\n"; strncpy(command, type, sizeof(type)); echoSz = sizeof(type) - 1; strncpy(&command[echoSz], header, sizeof(header)); echoSz += sizeof(header) - 1; strncpy(&command[echoSz], body, sizeof(body)); echoSz += sizeof(body) - 1; strncpy(&command[echoSz], footer, sizeof(footer)); echoSz += sizeof(footer); if (SSL_write(ssl, command, echoSz) != echoSz) err_sys("SSL_write failed"); break; } command[echoSz] = 0; #ifdef ECHO_OUT fputs(command, fout); #endif if (SSL_write(ssl, command, echoSz) != echoSz) err_sys("SSL_write failed"); } SSL_shutdown(ssl); SSL_free(ssl); CloseSocket(clientfd); #ifdef CYASSL_DTLS tcp_listen(&sockfd); SignalReady(args); #endif } CloseSocket(sockfd); SSL_CTX_free(ctx); ((func_args*)args)->return_code = 0; return 0; }
int lws_server_socket_service(struct libwebsocket_context *context, struct libwebsocket *wsi, struct pollfd *pollfd) { struct libwebsocket *new_wsi; int accept_fd; socklen_t clilen; struct sockaddr_in cli_addr; int n; ssize_t len; #ifdef LWS_OPENSSL_SUPPORT int m; #ifndef USE_CYASSL BIO *bio; #endif #endif switch (wsi->mode) { case LWS_CONNMODE_HTTP_SERVING: case LWS_CONNMODE_HTTP_SERVING_ACCEPTED: /* handle http headers coming in */ /* pending truncated sends have uber priority */ if (wsi->truncated_send_malloc) { if (pollfd->revents & POLLOUT) lws_issue_raw(wsi, wsi->truncated_send_malloc + wsi->truncated_send_offset, wsi->truncated_send_len); /* * we can't afford to allow input processing send * something new, so spin around he event loop until * he doesn't have any partials */ break; } /* any incoming data ready? */ if (pollfd->revents & POLLIN) { #ifdef LWS_OPENSSL_SUPPORT if (wsi->ssl) len = SSL_read(wsi->ssl, context->service_buffer, sizeof(context->service_buffer)); else #endif len = recv(pollfd->fd, context->service_buffer, sizeof(context->service_buffer), 0); if (len < 0) { lwsl_debug("Socket read returned %d\n", len); if (errno != EINTR && errno != EAGAIN) libwebsocket_close_and_free_session( context, wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; } if (!len) { lwsl_info("lws_server_skt_srv: read 0 len\n"); /* lwsl_info(" state=%d\n", wsi->state); */ if (!wsi->hdr_parsing_completed) free(wsi->u.hdr.ah); libwebsocket_close_and_free_session( context, wsi, LWS_CLOSE_STATUS_NOSTATUS); return 0; } /* hm this may want to send (via HTTP callback for example) */ n = libwebsocket_read(context, wsi, context->service_buffer, len); if (n < 0) /* we closed wsi */ return 0; /* hum he may have used up the writability above */ break; } /* this handles POLLOUT for http serving fragments */ if (!(pollfd->revents & POLLOUT)) break; /* one shot */ lws_change_pollfd(wsi, POLLOUT, 0); if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) { n = user_callback_handle_rxflow( wsi->protocol->callback, wsi->protocol->owning_server, wsi, LWS_CALLBACK_HTTP_WRITEABLE, wsi->user_space, NULL, 0); if (n < 0) libwebsocket_close_and_free_session( context, wsi, LWS_CLOSE_STATUS_NOSTATUS); break; } /* nonzero for completion or error */ if (libwebsockets_serve_http_file_fragment(context, wsi)) libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); break; case LWS_CONNMODE_SERVER_LISTENER: /* pollin means a client has connected to us then */ if (!(pollfd->revents & POLLIN)) break; /* listen socket got an unencrypted connection... */ clilen = sizeof(cli_addr); lws_latency_pre(context, wsi); accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr, &clilen); lws_latency(context, wsi, "unencrypted accept LWS_CONNMODE_SERVER_LISTENER", accept_fd, accept_fd >= 0); if (accept_fd < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { lwsl_debug("accept asks to try again\n"); break; } lwsl_warn("ERROR on accept: %s\n", strerror(errno)); break; } lws_set_socket_options(context, accept_fd); /* * look at who we connected to and give user code a chance * to reject based on client IP. There's no protocol selected * yet so we issue this to protocols[0] */ if ((context->protocols[0].callback)(context, wsi, LWS_CALLBACK_FILTER_NETWORK_CONNECTION, NULL, (void *)(long)accept_fd, 0)) { lwsl_debug("Callback denied network connection\n"); compatible_close(accept_fd); break; } new_wsi = libwebsocket_create_new_server_wsi(context); if (new_wsi == NULL) { compatible_close(accept_fd); break; } new_wsi->sock = accept_fd; #ifdef LWS_OPENSSL_SUPPORT new_wsi->ssl = NULL; if (!context->use_ssl) { #endif lwsl_debug("accepted new conn port %u on fd=%d\n", ntohs(cli_addr.sin_port), accept_fd); insert_wsi_socket_into_fds(context, new_wsi); break; #ifdef LWS_OPENSSL_SUPPORT } 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(); free(new_wsi); compatible_close(accept_fd); break; } SSL_set_ex_data(new_wsi->ssl, openssl_websocket_private_data_index, context); SSL_set_fd(new_wsi->ssl, accept_fd); #ifdef USE_CYASSL CyaSSL_set_using_nonblock(new_wsi->ssl, 1); #else 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 */ wsi = new_wsi; wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING; insert_wsi_socket_into_fds(context, wsi); 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: lws_change_pollfd(wsi, POLLOUT, 0); lws_latency_pre(context, wsi); n = recv(wsi->sock, 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 && n >= 1 && context->service_buffer[0] >= ' ') { /* * TLS content-type for Handshake is 0x16 * TLS content-type for ChangeCipherSpec Record is 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; } /* 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) { m = SSL_get_error(wsi->ssl, n); lwsl_debug("SSL_accept failed %d / %s\n", m, ERR_error_string(m, NULL)); if (m == SSL_ERROR_WANT_READ) { lws_change_pollfd(wsi, 0, POLLIN); lwsl_info("SSL_ERROR_WANT_READ\n"); break; } if (m == SSL_ERROR_WANT_WRITE) { lws_change_pollfd(wsi, 0, POLLOUT); break; } lwsl_debug("SSL_accept failed skt %u: %s\n", pollfd->fd, ERR_error_string(m, NULL)); libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); break; } accepted: /* OK, we are accepted */ libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); wsi->mode = LWS_CONNMODE_HTTP_SERVING; lwsl_debug("accepted new SSL conn\n"); break; #endif default: break; } return 0; }
//pki server void doPKIServer(pid_t cpid, int* pipefd,char* newkeyiv, int port, int PORT, char* ip)//(int argc, char* argv[]) { int i; int err; int listen_sd; int sd; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; size_t client_len; SSL_CTX* ctx; SSL* ssl; X509* client_cert; char* str; char buf [4096]; SSL_METHOD *meth; /* SSL preliminaries. We keep the certificate and key with the context. */ SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); meth = SSLv23_server_method(); ctx = SSL_CTX_new (meth); if (!ctx) { ERR_print_errors_fp(stderr); exit(2); } SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); /* whether verify the certificate */ SSL_CTX_load_verify_locations(ctx,SCACERT,NULL); if (SSL_CTX_use_certificate_file(ctx, SCERTF, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(3); } if (SSL_CTX_use_PrivateKey_file(ctx, SKEYF, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(4); } if (!SSL_CTX_check_private_key(ctx)) { fprintf(stderr,"Private key does not match the certificate public key\n"); exit(5); } /* ----------------------------------------------- */ /* Prepare TCP socket for receiving connections */ listen_sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(listen_sd, "socket"); memset (&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons (PORT); /* Server Port number */ err = bind(listen_sd, (struct sockaddr*) &sa_serv, sizeof (sa_serv)); CHK_ERR(err, "bind"); /* Receive a TCP connection. */ err = listen (listen_sd, 5); CHK_ERR(err, "listen"); client_len = sizeof(sa_cli); sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); CHK_ERR(sd, "accept"); close (listen_sd); printf ("Connection from %lx, port %x\n", (long unsigned int)sa_cli.sin_addr.s_addr, sa_cli.sin_port); /* ----------------------------------------------- */ /* TCP connection is ready. Do server side SSL. */ ssl = SSL_new (ctx); CHK_NULL(ssl); SSL_set_fd (ssl, sd); err = SSL_accept (ssl); CHK_SSL(err); /* Get the cipher - opt */ printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); /* Get client's certificate (note: beware of dynamic allocation) - opt */ client_cert = SSL_get_peer_certificate (ssl); if (client_cert != NULL) { printf ("Client certificate:\n"); //blx verify the common name char commonName[512]; X509_NAME *name=X509_get_subject_name (client_cert); X509_NAME_get_text_by_NID(name,NID_commonName,commonName,512); //printf("%s\n",commonName); if(strcmp(commonName,ClientCN)!=0) { printf("wrong CN\n"); exit(-1); } printf("right CN\n"); str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); CHK_NULL(str); printf ("\t subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); CHK_NULL(str); printf ("\t issuer: %s\n", str); OPENSSL_free (str); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free (client_cert); } else printf ("Client does not have certificate.\n"); /* DATA EXCHANGE - Receive message and send reply. */ while(1){//key read new key and iv err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err); if(err ==0){continue;} buf[err] = '\0'; //printf ("Got %d chars:'%s'\n", err, buf); for(i=0;i<32;i++) { newkeyiv[i] = buf[i]; } write(pipefd[1], newkeyiv, 32);//write the new key and iv to tunnel process err = SSL_write (ssl, "server recieved new key or iv.", strlen("server recieved new key or iv.")); CHK_SSL(err);//write reply to client } /* Clean up. */ close (sd); SSL_free (ssl); SSL_CTX_free (ctx); }
void Test_OpenSSL_ClientServerAuth() { LCD_Clear(); lcd_printf("Testing SSL Client/Server negotiations...\n"); int err; int client_numbytes, server_numbytes; int listen_sd; int server_sd; int client_sd; struct TINYCLR_SSL_SOCKADDR_IN sa_serv; struct TINYCLR_SSL_SOCKADDR_IN sa_cli; size_t client_len; SSL_CTX* server_ctx = NULL; SSL* server_ssl = NULL; X509* server_cert = NULL; SSL_CTX* client_ctx = NULL; SSL* client_ssl = NULL; X509* client_cert = NULL; char* str = NULL; char client_buf [256]; char server_buf [256]; SSL_METHOD *server_meth = NULL; SSL_METHOD *client_meth = NULL; BIO *cert = NULL; X509 *x = NULL; EVP_PKEY *pkey = NULL; // SSL preliminaries. // create client ssl client_meth = (SSL_METHOD*)SSLv3_client_method(); client_ctx = SSL_CTX_new (client_meth); if (!client_ctx) goto cleanup; server_meth = (SSL_METHOD*)SSLv3_server_method(); server_ctx = SSL_CTX_new (server_meth); if (!server_ctx) goto cleanup; if ((cert=BIO_new(BIO_s_mem())) == NULL) { TINYCLR_SSL_PRINTF("Unable to create new BIO"); goto cleanup; } BIO_puts(cert,server_pem); x=PEM_read_bio_X509_AUX(cert, NULL, 0, NULL); pkey=PEM_read_bio_PrivateKey(cert,NULL, server_ctx->default_passwd_callback,server_ctx->default_passwd_callback_userdata); //if (SSL_CTX_use_certificate_file(server_ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { if (SSL_CTX_use_certificate(server_ctx, x) <= 0) { TINYCLR_SSL_PRINTF("Use certifcate chain file failed"); goto cleanup; } if (SSL_CTX_use_PrivateKey(server_ctx, pkey) <= 0) { TINYCLR_SSL_PRINTF("Unable to use Private Key"); goto cleanup; } if (!SSL_CTX_check_private_key(server_ctx)) { TINYCLR_SSL_PRINTF("Private key does not match the certificate public key\n"); goto cleanup; } //if (SSL_CTX_set_cipher_list(server_ctx, ); // ----------------------------------------------- // Prepare TCP socket for receiving connections listen_sd = TINYCLR_SSL_SOCKET (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_sd < 0) goto cleanup; // set it to non-blocking int nonblock = 1; err = TINYCLR_SSL_IOCTL(listen_sd,SOCK_FIONBIO,&nonblock); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Nonblocking call failed for server: %d.\n", wsa); goto cleanup; } TINYCLR_SSL_MEMSET(&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); sa_serv.sin_port = TINYCLR_SSL_HTONS (1111); /* Server Port number */ TINYCLR_SSL_PRINTF("Binding to %d...\n", TINYCLR_SSL_NTOHS(sa_serv.sin_port)); err = TINYCLR_SSL_BIND(listen_sd, (struct TINYCLR_SSL_SOCKADDR*) &sa_serv, sizeof (sa_serv)); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Bind Socket error %d\n", wsa); goto cleanup; } TINYCLR_SSL_PRINTF("Listening...\n"); /* Receive a TCP connection. */ err = TINYCLR_SSL_LISTEN (listen_sd, 5); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Listen Socket error %d\n", wsa); goto cleanup; } // create a client socket client_sd = TINYCLR_SSL_SOCKET (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (client_sd < 0) goto cleanup; // set it to non-blocking err = TINYCLR_SSL_IOCTL(client_sd,SOCK_FIONBIO,&nonblock); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Nonblocking call failed for client: %d.\n", wsa); goto cleanup; } // Set up a tcp connection for client: Bind, Connect err == TINYCLR_SSL_CONNECT( client_sd, (const struct TINYCLR_SSL_SOCKADDR*)&sa_serv, sizeof(sa_serv)); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Client connect failed with: %d.\n", wsa); } client_len = sizeof(sa_cli); char nodename[128] = ""; char servname[128] = ""; SOCK_addrinfo hints; SOCK_addrinfo *res = NULL; TINYCLR_SSL_MEMSET(&hints, '\0', sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; SOCK_getaddrinfo(nodename,servname,&hints,&res); SOCK_addrinfo *ptr = NULL; for (ptr=res; ptr!=NULL; ptr=ptr->ai_next) { struct sockaddr_in *ip = (struct sockaddr_in*) ptr->ai_addr; TINYCLR_SSL_PRINTF("Accepting connections on...%s:%d\n", inet_ntoa(ip->sin_addr), 1111 ); } int counter=0; do { server_sd = TINYCLR_SSL_ACCEPT (listen_sd, (struct TINYCLR_SSL_SOCKADDR*) &sa_cli, (int*)&client_len); Events_WaitForEvents(0,2000); TINYCLR_SSL_PRINTF("Accept again %d:%d\n", TINYCLR_SSL_GETLASTSOCKETERROR(), counter++); } while (server_sd == -1); TINYCLR_SSL_CLOSESOCKET (listen_sd); TINYCLR_SSL_PRINTF ("Connection from %lx, port %x\n", sa_cli.sin_addr.S_un.S_addr, sa_cli.sin_port); // connections are completed between server & client // now lets do the SSL negotiations // create server ssl server_ssl = SSL_new(server_ctx); if (server_ssl == NULL) goto cleanup; SSL_set_fd (server_ssl, server_sd); //Create server bio and set as non-blocking BIO* server_bio = BIO_new(BIO_s_socket()); if (server_bio == NULL) goto cleanup; //CHK_NULL(bio); BIO_set_nbio(server_bio,1); BIO_set_fd(server_bio, server_sd, BIO_NOCLOSE); SSL_set_bio(server_ssl,server_bio,server_bio); // create client ssl & connect client_ssl = SSL_new(client_ctx); if (client_ssl == NULL) goto cleanup; SSL_set_fd(client_ssl, client_sd); //Create client bio and set as non-blocking BIO* client_bio = BIO_new(BIO_s_socket()); if (client_bio == NULL) goto cleanup; BIO_set_nbio(client_bio,1); BIO_set_fd(client_bio, client_sd, BIO_NOCLOSE); SSL_set_bio(client_ssl,client_bio,client_bio); // loop until server accepts ssl client connect int ssl_err =0; do { err = SSL_connect(client_ssl); if (err <= 0) { ssl_err = SSL_get_error(client_ssl,err); TINYCLR_SSL_PRINTF("SSL_Connect error: %d\n", ssl_err); } Events_WaitForEvents(0,1000); err = SSL_accept (server_ssl); if (err <= 0) { ssl_err = SSL_get_error(server_ssl, err); TINYCLR_SSL_PRINTF("SSL_Accept error: %d\n", ssl_err); } Events_WaitForEvents(0,1000); } while (err != 1); //Get the cipher - opt TINYCLR_SSL_PRINTF("SSL connection using %s\n", SSL_get_cipher (server_ssl)); //Get client's certificate (note: beware of dynamic allocation) - opt client_cert = SSL_get_peer_certificate (server_ssl); if (client_cert != NULL) { TINYCLR_SSL_PRINTF("Client certificate:\n"); str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("issuer: %s\n", str); OPENSSL_free (str); //We could do all sorts of certificate verification stuff here before // deallocating the certificate. X509_free (client_cert); } else TINYCLR_SSL_PRINTF("Client does not have certificate.\n"); //Get server's certificate (note: beware of dynamic allocation) - opt server_cert = SSL_get_peer_certificate (client_ssl); if (server_cert != NULL) { TINYCLR_SSL_PRINTF("Server certificate:\n"); str = X509_NAME_oneline (X509_get_subject_name (server_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (server_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("issuer: %s\n", str); OPENSSL_free (str); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free (server_cert); } else TINYCLR_SSL_PRINTF("Server with no certificate?!?!?.\n"); do { // DATA EXCHANGE - Receive message and send reply. err = SSL_write(client_ssl,"Hello World!",TINYCLR_SSL_STRLEN("Hello World!")); if (err <= 0) ssl_err = SSL_get_error(client_ssl, err); Events_WaitForEvents(0,1000); server_numbytes= SSL_read (server_ssl, server_buf, sizeof(server_buf) - 1); if (server_numbytes <= 0) ssl_err = SSL_get_error(server_ssl, server_numbytes); else server_buf[server_numbytes] = '\0'; Events_WaitForEvents(0,1000); err = SSL_write (server_ssl, "I hear you.", TINYCLR_SSL_STRLEN("I hear you.")); if (err <= 0) ssl_err = SSL_get_error(server_ssl, err); Events_WaitForEvents(0,1000); client_numbytes= SSL_read(client_ssl, client_buf, sizeof(client_buf) -1); if (client_numbytes <= 0) ssl_err = SSL_get_error(client_ssl, client_numbytes); else client_buf[client_numbytes] = '\0'; Events_WaitForEvents(0,1000); } while (err <= 0); TINYCLR_SSL_PRINTF("Server got %d chars:'%s'\n", server_numbytes, server_buf); TINYCLR_SSL_PRINTF("Client go %d chars:'%s'\n", client_numbytes, client_buf); /* Clean up. */ cleanup: if (pkey) EVP_PKEY_free(pkey); if (cert) BIO_free(cert); if (x) X509_free(x); TINYCLR_SSL_CLOSESOCKET(server_sd); if (server_ssl) SSL_shutdown(server_ssl); if (server_ssl) SSL_free (server_ssl); server_ssl = NULL; if (server_ctx) SSL_CTX_free(server_ctx); server_ctx = NULL; TINYCLR_SSL_CLOSESOCKET(client_sd); if (client_ssl) SSL_shutdown(client_ssl); if (client_ssl) SSL_free (client_ssl); client_ssl = NULL; if (client_ctx) SSL_CTX_free(client_ctx); client_ctx = NULL; }
int main(int argc , char *argv[]) { int socket_desc , client_sock , read_size; socklen_t c; struct sockaddr_in server , client; char client_message[0xFFFF]; const char msg[] = "HTTP/1.1 200 OK\r\nContent-length: 31\r\nContent-type: text/plain\r\n\r\nHello world from TLSe (TLS 1.2)"; #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); #else signal(SIGPIPE, SIG_IGN); #endif socket_desc = socket(AF_INET , SOCK_STREAM , 0); if (socket_desc == -1) { printf("Could not create socket"); return 0; } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(2000); int enable = 1; setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) { perror("bind failed. Error"); return 1; } listen(socket_desc , 3); c = sizeof(struct sockaddr_in); unsigned int size; SSL *server_ctx = SSL_CTX_new(SSLv3_server_method()); if (!server_ctx) { fprintf(stderr, "Error creating server context\n"); return -1; } SSL_CTX_use_certificate_file(server_ctx, "testcert/fullchain.pem", SSL_SERVER_RSA_CERT); SSL_CTX_use_PrivateKey_file(server_ctx, "testcert/privkey.pem", SSL_SERVER_RSA_KEY); if (!SSL_CTX_check_private_key(server_ctx)) { fprintf(stderr, "Private key not loaded\n"); return -2; } while (1) { client_sock = accept(socket_desc, (struct sockaddr *)&client, &c); if (client_sock < 0) { fprintf(stderr, "Accept failed\n"); return -3; } SSL *client = SSL_new(server_ctx); if (!client) { fprintf(stderr, "Error creating SSL client\n"); return -4; } SSL_set_fd(client, client_sock); if (SSL_accept(client)) { fprintf(stderr, "Cipher %s\n", tls_cipher_name(client)); while ((read_size = SSL_read(client, client_message, sizeof(client_message))) >= 0) { fwrite(client_message, read_size, 1, stdout); if (SSL_write(client, msg, strlen(msg)) < 0) fprintf(stderr, "Error in SSL write\n"); break; } } else fprintf(stderr, "Error in handshake\n"); SSL_shutdown(client); #ifdef __WIN32 shutdown(client_sock, SD_BOTH); closesocket(client_sock); #else shutdown(client_sock, SHUT_RDWR); close(client_sock); #endif SSL_free(client); } SSL_CTX_free(server_ctx); return 0; }
/* * Wrapper around SSL_accept, returns -1 on error, 0 on success */ static int tls_accept(struct tcp_connection *c, short *poll_events) { int ret, err; SSL *ssl; X509* cert; if ( (c->proto_flags&F_TLS_DO_ACCEPT)==0 ) { LM_BUG("invalid connection state (bug in TLS code)\n"); return -1; } ssl = (SSL *) c->extra_data; #ifndef OPENSSL_NO_KRB5 if ( ssl->kssl_ctx==NULL ) ssl->kssl_ctx = kssl_ctx_new( ); #endif ret = SSL_accept(ssl); #ifndef OPENSSL_NO_KRB5 if ( ssl->kssl_ctx ) { kssl_ctx_free( ssl->kssl_ctx ); ssl->kssl_ctx = 0; } #endif if (ret > 0) { LM_INFO("New TLS connection from %s:%d accepted\n", ip_addr2a(&c->rcv.src_ip), c->rcv.src_port); /* TLS accept done, reset the flag */ c->proto_flags &= ~F_TLS_DO_ACCEPT; LM_DBG("new TLS connection from %s:%d using %s %s %d\n", ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl), SSL_get_cipher_bits(ssl, 0) ); LM_DBG("local socket: %s:%d\n", ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port ); cert = SSL_get_peer_certificate(ssl); if (cert != 0) { tls_dump_cert_info("tls_accept: client TLS certificate", cert); if (SSL_get_verify_result(ssl) != X509_V_OK) { LM_WARN("TLS client certificate verification failed\n"); tls_dump_verification_failure(SSL_get_verify_result(ssl)); } X509_free(cert); } else { LM_INFO("Client did not present a TLS certificate\n"); } cert = SSL_get_certificate(ssl); if (cert != 0) { tls_dump_cert_info("tls_accept: local TLS server certificate", cert); } else { /* this should not happen, servers always present a cert */ LM_ERR("local TLS server domain has no certificate\n"); } return 0; } else { err = SSL_get_error(ssl, ret); switch (err) { case SSL_ERROR_ZERO_RETURN: LM_INFO("TLS connection from %s:%d accept failed cleanly\n", ip_addr2a(&c->rcv.src_ip), c->rcv.src_port); c->state = S_CONN_BAD; return -1; case SSL_ERROR_WANT_READ: if (poll_events) *poll_events = POLLIN; return 0; case SSL_ERROR_WANT_WRITE: if (poll_events) *poll_events = POLLOUT; return 0; default: c->state = S_CONN_BAD; if (errno == 0) { LM_ERR("New TLS connection from %s:%d failed to accept:" " rejected by client\n", ip_addr2a(&c->rcv.src_ip), c->rcv.src_port); } else { LM_ERR("New TLS connection from %s:%d failed to accept\n", ip_addr2a(&c->rcv.src_ip), c->rcv.src_port); LM_ERR("TLS error: (ret=%d, err=%d, errno=%d/%s):\n", ret, err, errno, strerror(errno)); tls_print_errstack(); } return -1; } } LM_BUG("bug\n"); return -1; }
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; } 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; } } 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); fprintf(stderr, "TLS connection accepted\n"); return TRUE; }
/** * Embeds an accepted server socket in an existing ssl connection. * @param ssl ssl connection * @param socket the socket to be used. * @return TRUE, or FALSE if an error has occured. */ int embed_accepted_ssl_socket(ssl_connection *ssl, int socket) { int ssl_error; time_t ssl_time; ASSERT(ssl); ssl->socket = socket; if (!ssl_initialized) start_ssl(); if (!(ssl->handler = SSL_new(ssl->ctx))) { LogError("%s: Cannot initialize the SSL handler -- %s\n", prog, SSLERROR); return FALSE; } if (socket < 0) { LogError("%s: Socket error!\n", prog); return FALSE; } set_noblock(ssl->socket); if (!(ssl->socket_bio = BIO_new_socket(ssl->socket, BIO_NOCLOSE))) { LogError("%s: Cannot generate IO buffer -- %s\n", prog, SSLERROR); return FALSE; } SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio); ssl_time = time(NULL); while ((ssl_error = SSL_accept(ssl->handler)) < 0) { if ((time(NULL) - ssl_time) > SSL_TIMEOUT) { LogError("%s: SSL service timeout!\n", prog); return FALSE; } if (!handle_error(ssl_error, ssl)) return FALSE; if (!BIO_should_retry(ssl->socket_bio)) return FALSE; } ssl->cipher = (char *)SSL_get_cipher(ssl->handler); if (!update_ssl_cert_data(ssl) && ssl->clientpemfile) { LogError("%s: The client did not supply a required client certificate!\n", prog); return FALSE; } if (SSL_get_verify_result(ssl->handler) > 0) { LogError("%s: Verification of the certificate has failed!\n", prog); return FALSE; } return TRUE; }
static int ssl_connect(struct stream *stream) { struct ssl_stream *sslv = ssl_stream_cast(stream); int retval; switch (sslv->state) { case STATE_TCP_CONNECTING: retval = check_connection_completion(sslv->fd); if (retval) { return retval; } sslv->state = STATE_SSL_CONNECTING; /* Fall through. */ case STATE_SSL_CONNECTING: /* Capture the first few bytes of received data so that we can guess * what kind of funny data we've been sent if SSL negotation fails. */ if (sslv->n_head <= 0) { sslv->n_head = recv(sslv->fd, sslv->head, sizeof sslv->head, MSG_PEEK); } retval = (sslv->type == CLIENT ? SSL_connect(sslv->ssl) : SSL_accept(sslv->ssl)); if (retval != 1) { int error = SSL_get_error(sslv->ssl, retval); if (retval < 0 && ssl_wants_io(error)) { return EAGAIN; } else { int unused; interpret_ssl_error((sslv->type == CLIENT ? "SSL_connect" : "SSL_accept"), retval, error, &unused); shutdown(sslv->fd, SHUT_RDWR); stream_report_content(sslv->head, sslv->n_head, STREAM_SSL, THIS_MODULE, stream_get_name(stream)); return EPROTO; } } else if (bootstrap_ca_cert) { return do_ca_cert_bootstrap(stream); } else if (verify_peer_cert && ((SSL_get_verify_mode(sslv->ssl) & (SSL_VERIFY_NONE | SSL_VERIFY_PEER)) != SSL_VERIFY_PEER)) { /* Two or more SSL connections completed at the same time while we * were in bootstrap mode. Only one of these can finish the * bootstrap successfully. The other one(s) must be rejected * because they were not verified against the bootstrapped CA * certificate. (Alternatively we could verify them against the CA * certificate, but that's more trouble than it's worth. These * connections will succeed the next time they retry, assuming that * they have a certificate against the correct CA.) */ VLOG_INFO("rejecting SSL connection during bootstrap race window"); return EPROTO; } else { return 0; } } NOT_REACHED(); }
MONO_API int mono_btls_ssl_accept (MonoBtlsSsl *ptr) { return SSL_accept (ptr->ssl); }
// Minimal TLS server. This is largely based on the example at // https://wiki.openssl.org/index.php/Simple_TLS_Server and the gRPC core // internals in src/core/lib/tsi/ssl_transport_security.c. static void server_thread(void *arg) { const server_args *args = (server_args *)arg; SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); const SSL_METHOD *method = TLSv1_2_server_method(); SSL_CTX *ctx = SSL_CTX_new(method); if (!ctx) { perror("Unable to create SSL context"); ERR_print_errors_fp(stderr); abort(); } // Load key pair. if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { ERR_print_errors_fp(stderr); abort(); } if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { ERR_print_errors_fp(stderr); abort(); } // Set the cipher list to match the one expressed in // src/core/lib/tsi/ssl_transport_security.c. const char *cipher_list = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { ERR_print_errors_fp(stderr); gpr_log(GPR_ERROR, "Couldn't set server cipher list."); abort(); } // Register the ALPN selection callback. SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, args->alpn_preferred); // bind/listen/accept at TCP layer. const int sock = args->socket; gpr_log(GPR_INFO, "Server listening"); struct sockaddr_in addr; socklen_t len = sizeof(addr); const int client = accept(sock, (struct sockaddr *)&addr, &len); if (client < 0) { perror("Unable to accept"); abort(); } // Establish a SSL* and accept at SSL layer. SSL *ssl = SSL_new(ctx); GPR_ASSERT(ssl); SSL_set_fd(ssl, client); if (SSL_accept(ssl) <= 0) { ERR_print_errors_fp(stderr); gpr_log(GPR_ERROR, "Handshake failed."); } else { gpr_log(GPR_INFO, "Handshake successful."); } // Wait until the client drops its connection. char buf; while (SSL_read(ssl, &buf, sizeof(buf)) > 0) ; SSL_free(ssl); close(client); close(sock); SSL_CTX_free(ctx); EVP_cleanup(); }
void* sqlhandler(void *arg) { char sql[MAX_MSG]; int ret, err; SSL *ssl; sqlite4_stmt *pStmt; struct conn_ctx *conn = (struct conn_ctx *)arg; struct freeq_ctx *freeqctx = conn->srvctx->freeqctx; BIO *client = conn->client; if (!(ssl = freeq_ssl_new(freeqctx))) { err(freeqctx, "couldn't allocate new ssl instance"); BIO_free_all(client); free(conn); pthread_exit(NULL); } SSL_set_bio(ssl, client, client); if (SSL_accept(ssl) <= 0) { int_error("Error accepting SSL connection"); BIO_free_all(client); free(conn); pthread_exit(NULL); } if ((err = post_connection_check(freeqctx, ssl, "localhost")) != X509_V_OK) { err(freeqctx, "error: peer certificate: %s\n", X509_verify_cert_error_string(err)); BIO_free_all(client); free(conn); pthread_exit(NULL); } BIO *b, *ssl_bio; b = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE); BIO_push(b, ssl_bio); memset(sql, 0, MAX_MSG); ret = BIO_gets(b, sql, MAX_MSG); ret = sqlite4_prepare(pDb, sql, strlen(sql), &pStmt, 0); if (ret != SQLITE4_OK) { dbg(freeqctx, "prepare failed for %s sending error, ret was %d\n", sql, ret); //freeq_error_write_sock(freeqctx, sqlite4_errmsg(pDb), b); dbg(freeqctx, sqlite4_errmsg(pDb)); //BIO_printf(b, "error: %s\n", sqlite4_errmsg(pDb)); sqlite4_finalize(pStmt); //pthread_exit(FREEQ_ERR); } freeq_sqlite_to_bio(freeqctx, b, pStmt); SSL_shutdown(ssl); SSL_free(ssl); BIO_free_all(client); free(conn); pthread_exit(FREEQ_OK); }
/* * Attempt to negotiate SSL connection. */ static int open_server_SSL(Port *port) { int r; int err; 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()))); close_SSL(port); return -1; } if (!my_SSL_set_fd(port->ssl, port->sock)) { ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("could not set SSL socket: %s", SSLerrmessage()))); close_SSL(port); return -1; } aloop: r = SSL_accept(port->ssl); if (r <= 0) { err = SSL_get_error(port->ssl, r); switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: #ifdef WIN32 pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl), (err == SSL_ERROR_WANT_READ) ? FD_READ | FD_CLOSE | FD_ACCEPT : FD_WRITE | FD_CLOSE, INFINITE); #endif 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()))); 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; } close_SSL(port); return -1; } port->count = 0; /* Get client certificate, if available. */ port->peer = SSL_get_peer_certificate(port->ssl); /* and extract the Common Name from it. */ port->peer_cn = NULL; 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); close_SSL(port); 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); close_SSL(port); return -1; } port->peer_cn = peer_cn; } } 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; }
int ssl23_get_client_hello(SSL *s) { char buf_space[11]; /* Request this many bytes in initial read. * We can detect SSL 3.0/TLS 1.0 Client Hellos * ('type == 3') correctly only when the following * is in a single record, which is not guaranteed by * the protocol specification: * Byte Content * 0 type \ * 1/2 version > record header * 3/4 length / * 5 msg_type \ * 6-8 length > Client Hello message * 9/10 client_version / */ char *buf= &(buf_space[0]); unsigned char *p,*d,*d_len,*dd; unsigned int i; unsigned int csl,sil,cl; int n=0,j; int type=0; int v[2]; if (s->state == SSL23_ST_SR_CLNT_HELLO_A) { /* read the initial header */ v[0]=v[1]=0; if (!ssl3_setup_buffers(s)) goto err; n=ssl23_read_bytes(s, sizeof buf_space); if (n != sizeof buf_space) return(n); /* n == -1 || n == 0 */ p=s->packet; memcpy(buf,p,n); if ((p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) { /* * SSLv2 header */ if ((p[3] == 0x00) && (p[4] == 0x02)) { v[0]=p[3]; v[1]=p[4]; /* SSLv2 */ if (!(s->options & SSL_OP_NO_SSLv2)) type=1; } else if (p[3] == SSL3_VERSION_MAJOR) { v[0]=p[3]; v[1]=p[4]; /* SSLv3/TLSv1 */ if (p[4] >= TLS1_VERSION_MINOR) { if (p[4] >= TLS1_2_VERSION_MINOR && !(s->options & SSL_OP_NO_TLSv1_2)) { s->version=TLS1_2_VERSION; s->state=SSL23_ST_SR_CLNT_HELLO_B; } else if (p[4] >= TLS1_1_VERSION_MINOR && !(s->options & SSL_OP_NO_TLSv1_1)) { s->version=TLS1_1_VERSION; /* type=2; */ /* done later to survive restarts */ s->state=SSL23_ST_SR_CLNT_HELLO_B; } else if (!(s->options & SSL_OP_NO_TLSv1)) { s->version=TLS1_VERSION; /* type=2; */ /* done later to survive restarts */ s->state=SSL23_ST_SR_CLNT_HELLO_B; } else if (!(s->options & SSL_OP_NO_SSLv3)) { s->version=SSL3_VERSION; /* type=2; */ s->state=SSL23_ST_SR_CLNT_HELLO_B; } else if (!(s->options & SSL_OP_NO_SSLv2)) { type=1; } } else if (!(s->options & SSL_OP_NO_SSLv3)) { s->version=SSL3_VERSION; /* type=2; */ s->state=SSL23_ST_SR_CLNT_HELLO_B; } else if (!(s->options & SSL_OP_NO_SSLv2)) type=1; } } else if ((p[0] == SSL3_RT_HANDSHAKE) && (p[1] == SSL3_VERSION_MAJOR) && (p[5] == SSL3_MT_CLIENT_HELLO) && ((p[3] == 0 && p[4] < 5 /* silly record length? */) || (p[9] >= p[1]))) { /* * SSLv3 or tls1 header */ v[0]=p[1]; /* major version (= SSL3_VERSION_MAJOR) */ /* We must look at client_version inside the Client Hello message * to get the correct minor version. * However if we have only a pathologically small fragment of the * Client Hello message, this would be difficult, and we'd have * to read more records to find out. * No known SSL 3.0 client fragments ClientHello like this, * so we simply assume TLS 1.0 to avoid protocol version downgrade * attacks. */ if (p[3] == 0 && p[4] < 6) { #if 0 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL); goto err; #else v[1] = TLS1_VERSION_MINOR; #endif } /* if major version number > 3 set minor to a value * which will use the highest version 3 we support. * If TLS 2.0 ever appears we will need to revise * this.... */ else if (p[9] > SSL3_VERSION_MAJOR) v[1]=0xff; else v[1]=p[10]; /* minor version according to client_version */ if (v[1] >= TLS1_VERSION_MINOR) { if (v[1] >= TLS1_2_VERSION_MINOR && !(s->options & SSL_OP_NO_TLSv1_2)) { s->version=TLS1_2_VERSION; type=3; } else if (v[1] >= TLS1_1_VERSION_MINOR && !(s->options & SSL_OP_NO_TLSv1_1)) { s->version=TLS1_1_VERSION; type=3; } else if (!(s->options & SSL_OP_NO_TLSv1)) { s->version=TLS1_VERSION; type=3; } else if (!(s->options & SSL_OP_NO_SSLv3)) { s->version=SSL3_VERSION; type=3; } } else { /* client requests SSL 3.0 */ if (!(s->options & SSL_OP_NO_SSLv3)) { s->version=SSL3_VERSION; type=3; } else if (!(s->options & SSL_OP_NO_TLSv1)) { /* we won't be able to use TLS of course, * but this will send an appropriate alert */ s->version=TLS1_VERSION; type=3; } } } else if ((strncmp("GET ", (char *)p,4) == 0) || (strncmp("POST ",(char *)p,5) == 0) || (strncmp("HEAD ",(char *)p,5) == 0) || (strncmp("PUT ", (char *)p,4) == 0)) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTP_REQUEST); goto err; } else if (strncmp("CONNECT",(char *)p,7) == 0) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTPS_PROXY_REQUEST); goto err; } } /* ensure that TLS_MAX_VERSION is up-to-date */ OPENSSL_assert(s->version <= TLS_MAX_VERSION); #ifdef OPENSSL_FIPS if (FIPS_mode() && (s->version < TLS1_VERSION)) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); goto err; } #endif if (s->state == SSL23_ST_SR_CLNT_HELLO_B) { /* we have SSLv3/TLSv1 in an SSLv2 header * (other cases skip this state) */ type=2; p=s->packet; v[0] = p[3]; /* == SSL3_VERSION_MAJOR */ v[1] = p[4]; n=((p[0]&0x7f)<<8)|p[1]; if (n > (1024*4)) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE); goto err; } j=ssl23_read_bytes(s,n+2); if (j <= 0) return(j); ssl3_finish_mac(s, s->packet+2, s->packet_length-2); if (s->msg_callback) s->msg_callback(0, SSL2_VERSION, 0, s->packet+2, s->packet_length-2, s, s->msg_callback_arg); /* CLIENT-HELLO */ p=s->packet; p+=5; n2s(p,csl); n2s(p,sil); n2s(p,cl); d=(unsigned char *)s->init_buf->data; if ((csl+sil+cl+11) != s->packet_length) /* We can't have TLS extensions in SSL 2.0 format * Client Hello, can we? Error condition should be * '>' otherweise */ { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH); goto err; } /* record header: msg_type ... */ *(d++) = SSL3_MT_CLIENT_HELLO; /* ... and length (actual value will be written later) */ d_len = d; d += 3; /* client_version */ *(d++) = SSL3_VERSION_MAJOR; /* == v[0] */ *(d++) = v[1]; /* lets populate the random area */ /* get the challenge_length */ i=(cl > SSL3_RANDOM_SIZE)?SSL3_RANDOM_SIZE:cl; memset(d,0,SSL3_RANDOM_SIZE); memcpy(&(d[SSL3_RANDOM_SIZE-i]),&(p[csl+sil]),i); d+=SSL3_RANDOM_SIZE; /* no session-id reuse */ *(d++)=0; /* ciphers */ j=0; dd=d; d+=2; for (i=0; i<csl; i+=3) { if (p[i] != 0) continue; *(d++)=p[i+1]; *(d++)=p[i+2]; j+=2; } s2n(j,dd); /* COMPRESSION */ *(d++)=1; *(d++)=0; #if 0 /* copy any remaining data with may be extensions */ p = p+csl+sil+cl; while (p < s->packet+s->packet_length) { *(d++)=*(p++); } #endif i = (d-(unsigned char *)s->init_buf->data) - 4; l2n3((long)i, d_len); /* get the data reused from the init_buf */ s->s3->tmp.reuse_message=1; s->s3->tmp.message_type=SSL3_MT_CLIENT_HELLO; s->s3->tmp.message_size=i; } /* imaginary new state (for program structure): */ /* s->state = SSL23_SR_CLNT_HELLO_C */ if (type == 1) { #ifdef OPENSSL_NO_SSL2 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); goto err; #else /* we are talking sslv2 */ /* we need to clean up the SSLv3/TLSv1 setup and put in the * sslv2 stuff. */ if (s->s2 == NULL) { if (!ssl2_new(s)) goto err; } else ssl2_clear(s); if (s->s3 != NULL) ssl3_free(s); if (!BUF_MEM_grow_clean(s->init_buf, SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)) { goto err; } s->state=SSL2_ST_GET_CLIENT_HELLO_A; if (s->options & SSL_OP_NO_TLSv1 && s->options & SSL_OP_NO_SSLv3) s->s2->ssl2_rollback=0; else /* reject SSL 2.0 session if client supports SSL 3.0 or TLS 1.0 * (SSL 3.0 draft/RFC 2246, App. E.2) */ s->s2->ssl2_rollback=1; /* setup the n bytes we have read so we get them from * the sslv2 buffer */ s->rstate=SSL_ST_READ_HEADER; s->packet_length=n; s->packet= &(s->s2->rbuf[0]); memcpy(s->packet,buf,n); s->s2->rbuf_left=n; s->s2->rbuf_offs=0; s->method=SSLv2_server_method(); s->handshake_func=s->method->ssl_accept; #endif } if ((type == 2) || (type == 3)) { /* we have SSLv3/TLSv1 (type 2: SSL2 style, type 3: SSL3/TLS style) */ s->method = ssl23_get_server_method(s->version); if (s->method == NULL) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); goto err; } if (!ssl_init_wbio_buffer(s,1)) goto err; /* we are in this state */ s->state=SSL3_ST_SR_CLNT_HELLO_A; if (type == 3) { /* put the 'n' bytes we have read into the input buffer * for SSLv3 */ s->rstate=SSL_ST_READ_HEADER; s->packet_length=n; if (s->s3->rbuf.buf == NULL) if (!ssl3_setup_read_buffer(s)) goto err; s->packet= &(s->s3->rbuf.buf[0]); memcpy(s->packet,buf,n); s->s3->rbuf.left=n; s->s3->rbuf.offset=0; } else { s->packet_length=0; s->s3->rbuf.left=0; s->s3->rbuf.offset=0; } #if 0 /* ssl3_get_client_hello does this */ s->client_version=(v[0]<<8)|v[1]; #endif s->handshake_func=s->method->ssl_accept; } if ((type < 1) || (type > 3)) { /* bad, very bad */ SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNKNOWN_PROTOCOL); goto err; } s->init_num=0; if (buf != buf_space) OPENSSL_free(buf); return(SSL_accept(s)); err: if (buf != buf_space) OPENSSL_free(buf); return(-1); }
/* * 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); 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; } port->count = 0; /* 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; }
int kore_connection_handle(struct connection *c) { int r; u_int32_t len; const u_char *data; kore_debug("kore_connection_handle(%p)", c); kore_connection_stop_idletimer(c); switch (c->state) { case CONN_STATE_SSL_SHAKE: if (c->ssl == NULL) { c->ssl = SSL_new(primary_dom->ssl_ctx); if (c->ssl == NULL) { kore_debug("SSL_new(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } SSL_set_fd(c->ssl, c->fd); SSL_set_accept_state(c->ssl); } r = SSL_accept(c->ssl); if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: return (KORE_RESULT_OK); default: kore_debug("SSL_accept(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } } r = SSL_get_verify_result(c->ssl); if (r != X509_V_OK) { kore_debug("SSL_get_verify_result(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } SSL_get0_next_proto_negotiated(c->ssl, &data, &len); if (data) { if (!memcmp(data, "spdy/3", MIN(6, len))) { c->proto = CONN_PROTO_SPDY; c->idle_timer.length = spdy_idle_time; net_recv_queue(c, SPDY_FRAME_SIZE, 0, NULL, spdy_frame_recv); } else if (!memcmp(data, "http/1.1", MIN(8, len))) { c->proto = CONN_PROTO_HTTP; net_recv_queue(c, HTTP_HEADER_MAX_LEN, NETBUF_CALL_CB_ALWAYS, NULL, http_header_recv); } else { kore_debug("npn: received unknown protocol"); } } else { c->proto = CONN_PROTO_HTTP; net_recv_queue(c, HTTP_HEADER_MAX_LEN, NETBUF_CALL_CB_ALWAYS, NULL, http_header_recv); } c->state = CONN_STATE_ESTABLISHED; /* FALLTHROUGH */ case CONN_STATE_ESTABLISHED: if (c->flags & CONN_READ_POSSIBLE) { if (!net_recv_flush(c)) return (KORE_RESULT_ERROR); } if (c->flags & CONN_WRITE_POSSIBLE) { if (!net_send_flush(c)) return (KORE_RESULT_ERROR); } break; case CONN_STATE_DISCONNECTING: break; default: kore_debug("unknown state on %d (%d)", c->fd, c->state); break; } kore_connection_start_idletimer(c); return (KORE_RESULT_OK); }
int main(int argc, char **argv) { FILE *fp; // Bucket to keep pids in. int process_pool[POOL_SIZE]; // Count of pids we are wait()ing on. int c = 0, test_config = 0, use_ip_address = 0, pid = 0, status, i = 0, active_processes = 0; int gid = 0, client_sock = 0, sock = 0, port = DEFAULT_PORT, ret = 0; char *dir = DEFAULTDIR; char *group = GROUPGLOBAL; char *server_cert = NULL; char *server_key = NULL; char *ca_cert = NULL; char buf[4096 +1]; SSL_CTX *ctx; SSL *ssl; char srcip[IPSIZE +1]; struct sockaddr_in _nc; socklen_t _ncl; /* Initializing some variables */ memset(srcip, '\0', IPSIZE + 1); memset(process_pool, 0x0, POOL_SIZE); bio_err = 0; /* Setting the name */ OS_SetName(ARGV0); /* add an option to use the ip on the socket to tie the name to a specific address */ while((c = getopt(argc, argv, "Vdhtig:D:m:p:v:x:k:")) != -1) { switch(c){ case 'V': print_version(); break; case 'h': help_authd(); break; case 'd': nowDebug(); break; case 'i': use_ip_address = 1; break; case 'g': if(!optarg) ErrorExit("%s: -g needs an argument",ARGV0); group = optarg; break; case 'D': if(!optarg) ErrorExit("%s: -D needs an argument",ARGV0); dir = optarg; break; case 't': test_config = 1; break; case 'p': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); port = atoi(optarg); if(port <= 0 || port >= 65536) { ErrorExit("%s: Invalid port: %s", ARGV0, optarg); } break; case 'v': if (!optarg) ErrorExit("%s: -%c needs an argument", ARGV0, c); ca_cert = optarg; break; case 'x': if (!optarg) ErrorExit("%s: -%c needs an argument", ARGV0, c); server_cert = optarg; break; case 'k': if (!optarg) ErrorExit("%s: -%c needs an argument", ARGV0, c); server_key = optarg; break; default: help_authd(); break; } } /* Starting daemon -- NB: need to double fork and setsid */ debug1(STARTED_MSG,ARGV0); /* Check if the user/group given are valid */ gid = Privsep_GetGroup(group); if(gid < 0) ErrorExit(USER_ERROR,ARGV0,"",group); /* Exit here if test config is set */ if(test_config) exit(0); /* Privilege separation */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR,ARGV0,group); /* chrooting -- TODO: this isn't a chroot. Should also close unneeded open file descriptors (like stdin/stdout)*/ if(chdir(dir) == -1) { ErrorExit(CHDIR_ERROR, ARGV0, dir); } /* Signal manipulation */ StartSIG(ARGV0); /* Creating PID files */ if(CreatePID(ARGV0, getpid()) < 0) ErrorExit(PID_ERROR,ARGV0); /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); fp = fopen(KEYSFILE_PATH,"a"); if(!fp) { merror("%s: ERROR: Unable to open %s (key file)", ARGV0, KEYSFILE_PATH); exit(1); } /* Starting SSL */ ctx = os_ssl_keys(1, dir, server_cert, server_key, ca_cert); if(!ctx) { merror("%s: ERROR: SSL error. Exiting.", ARGV0); exit(1); } /* Connecting via TCP */ sock = OS_Bindporttcp(port, NULL, 0); if(sock <= 0) { merror("%s: Unable to bind to port %d", ARGV0, port); exit(1); } fcntl(sock, F_SETFL, O_NONBLOCK); debug1("%s: DEBUG: Going into listening mode.", ARGV0); while(1) { // no need to completely pin the cpu, 100ms should be fast enough usleep(100*1000); // Only check process-pool if we have active processes if(active_processes > 0){ for (i = 0; i < POOL_SIZE; i++) { int rv = 0; status = 0; if (process_pool[i]) { rv = waitpid(process_pool[i], &status, WNOHANG); if (rv != 0){ debug1("%s: DEBUG: Process %d exited", ARGV0, process_pool[i]); process_pool[i] = 0; active_processes = active_processes - 1; } } } } memset(&_nc, 0, sizeof(_nc)); _ncl = sizeof(_nc); if((client_sock = accept(sock, (struct sockaddr *) &_nc, &_ncl)) > 0){ if (active_processes >= POOL_SIZE) { merror("%s: Error: Max concurrency reached. Unable to fork", ARGV0); break; } pid = fork(); if(pid) { active_processes = active_processes + 1; close(client_sock); for (i = 0; i < POOL_SIZE; i++) { if (! process_pool[i]) { process_pool[i] = pid; break; } } } else { strncpy(srcip, inet_ntoa(_nc.sin_addr),IPSIZE -1); char *agentname = NULL; ssl = SSL_new(ctx); SSL_set_fd(ssl, client_sock); do { ret = SSL_accept(ssl); if (ssl_error(ssl, ret)) clean_exit(ctx, client_sock); } while (ret <= 0); verbose("%s: INFO: New connection from %s", ARGV0, srcip); do { ret = SSL_read(ssl, buf, sizeof(buf)); if (ssl_error(ssl, ret)) clean_exit(ctx, client_sock); } while (ret <= 0); int parseok = 0; if(strncmp(buf, "OSSEC A:'", 9) == 0) { char *tmpstr = buf; agentname = tmpstr + 9; tmpstr += 9; while(*tmpstr != '\0') { if(*tmpstr == '\'') { *tmpstr = '\0'; verbose("%s: INFO: Received request for a new agent (%s) from: %s", ARGV0, agentname, srcip); parseok = 1; break; } tmpstr++; } } if(parseok == 0) { merror("%s: ERROR: Invalid request for new agent from: %s", ARGV0, srcip); } else { int acount = 2; char fname[2048 +1]; char response[2048 +1]; char *finalkey = NULL; response[2048] = '\0'; fname[2048] = '\0'; if(!OS_IsValidName(agentname)) { merror("%s: ERROR: Invalid agent name: %s from %s", ARGV0, agentname, srcip); snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname); ret = SSL_write(ssl, response, strlen(response)); snprintf(response, 2048, "ERROR: Unable to add agent.\n\n"); ret = SSL_write(ssl, response, strlen(response)); sleep(1); exit(0); } /* Checking for a duplicated names. */ strncpy(fname, agentname, 2048); while(NameExist(fname)) { snprintf(fname, 2048, "%s%d", agentname, acount); acount++; if(acount > 256) { merror("%s: ERROR: Invalid agent name %s (duplicated)", ARGV0, agentname); snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname); ret = SSL_write(ssl, response, strlen(response)); snprintf(response, 2048, "ERROR: Unable to add agent.\n\n"); ret = SSL_write(ssl, response, strlen(response)); sleep(1); exit(0); } } agentname = fname; /* Adding the new agent. */ if (use_ip_address) { finalkey = OS_AddNewAgent(agentname, srcip, NULL); } else { finalkey = OS_AddNewAgent(agentname, NULL, NULL); } if(!finalkey) { merror("%s: ERROR: Unable to add agent: %s (internal error)", ARGV0, agentname); snprintf(response, 2048, "ERROR: Internal manager error adding agent: %s\n\n", agentname); ret = SSL_write(ssl, response, strlen(response)); snprintf(response, 2048, "ERROR: Unable to add agent.\n\n"); ret = SSL_write(ssl, response, strlen(response)); sleep(1); exit(0); } snprintf(response, 2048,"OSSEC K:'%s'\n\n", finalkey); verbose("%s: INFO: Agent key generated for %s (requested by %s)", ARGV0, agentname, srcip); ret = SSL_write(ssl, response, strlen(response)); if(ret < 0) { merror("%s: ERROR: SSL write error (%d)", ARGV0, ret); merror("%s: ERROR: Agen key not saved for %s", ARGV0, agentname); ERR_print_errors_fp(stderr); } else { verbose("%s: INFO: Agent key created for %s (requested by %s)", ARGV0, agentname, srcip); } } clean_exit(ctx, client_sock); } } } /* Shutdown the socket */ clean_exit(ctx, sock); return (0); }
/* * Attempt to negotiate SSL connection. */ static int open_server_SSL(Port *port) { int r; int err; 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()))); close_SSL(port); return -1; } if (!my_SSL_set_fd(port->ssl, port->sock)) { ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("could not set SSL socket: %s", SSLerrmessage()))); close_SSL(port); return -1; } aloop: r = SSL_accept(port->ssl); if (r <= 0) { err = SSL_get_error(port->ssl, r); switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: #ifdef WIN32 pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl), (err == SSL_ERROR_WANT_READ) ? FD_READ | FD_CLOSE | FD_ACCEPT : FD_WRITE | FD_CLOSE, INFINITE); #endif 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()))); 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; } close_SSL(port); return -1; } port->count = 0; /* get client certificate, if available. */ port->peer = SSL_get_peer_certificate(port->ssl); if (port->peer == NULL) { strlcpy(port->peer_dn, "(anonymous)", sizeof(port->peer_dn)); strlcpy(port->peer_cn, "(anonymous)", sizeof(port->peer_cn)); } else { X509_NAME_oneline(X509_get_subject_name(port->peer), port->peer_dn, sizeof(port->peer_dn)); port->peer_dn[sizeof(port->peer_dn) - 1] = '\0'; r = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer), NID_commonName, port->peer_cn, sizeof(port->peer_cn)); port->peer_cn[sizeof(port->peer_cn) - 1] = '\0'; if (r == -1) { /* Unable to get the CN, set it to blank so it can't be used */ port->peer_cn[0] = '\0'; } else { /* * Reject embedded NULLs in certificate common name to prevent * attacks like CVE-2009-4034. */ if (r != strlen(port->peer_cn)) { ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("SSL certificate's common name contains embedded null"))); close_SSL(port); return -1; } } } ereport(DEBUG2, (errmsg("SSL connection from \"%s\"", port->peer_cn))); /* set up debugging/info callback */ SSL_CTX_set_info_callback(SSL_context, info_cb); return 0; }
static void http_server_handler(int c) { int code; struct socket_buffer sock; struct http_request request; char *buf; socket_buffer_init(&sock, c); #if HAVE_OPENSSL if (o.ssl) { sock.fdn.ssl = new_ssl(sock.fdn.fd); if (SSL_accept(sock.fdn.ssl) != 1) { loguser("Failed SSL connection: %s\n", ERR_error_string(ERR_get_error(), NULL)); fdinfo_close(&sock.fdn); return; } } #endif code = http_read_request_line(&sock, &buf); if (code != 0) { if (o.verbose) logdebug("Error reading Request-Line.\n"); send_string(&sock.fdn, http_code2str(code)); fdinfo_close(&sock.fdn); return; } if (o.debug > 1) logdebug("Request-Line: %s", buf); code = http_parse_request_line(buf, &request); free(buf); if (code != 0) { if (o.verbose) logdebug("Error parsing Request-Line.\n"); send_string(&sock.fdn, http_code2str(code)); fdinfo_close(&sock.fdn); return; } if (!method_is_known(request.method)) { if (o.debug > 1) logdebug("Bad method: %s.\n", request.method); http_request_free(&request); send_string(&sock.fdn, http_code2str(405)); fdinfo_close(&sock.fdn); return; } code = http_read_header(&sock, &buf); if (code != 0) { if (o.verbose) logdebug("Error reading header.\n"); http_request_free(&request); send_string(&sock.fdn, http_code2str(code)); fdinfo_close(&sock.fdn); return; } if (o.debug > 1) logdebug("Header:\n%s", buf); code = http_request_parse_header(&request, buf); free(buf); if (code != 0) { if (o.verbose) logdebug("Error parsing header.\n"); http_request_free(&request); send_string(&sock.fdn, http_code2str(code)); fdinfo_close(&sock.fdn); return; } /* Check authentication. */ if (o.proxy_auth) { struct http_credentials credentials; int ret, stale; if (http_header_get_proxy_credentials(request.header, &credentials) == NULL) { /* No credentials or a parsing error. */ send_proxy_authenticate(&sock.fdn, 0); http_request_free(&request); fdinfo_close(&sock.fdn); return; } ret = check_auth(&request, &credentials, &stale); http_credentials_free(&credentials); if (!ret) { /* Password doesn't match. */ /* RFC 2617, section 1.2: "If a proxy does not accept the credentials sent with a request, it SHOULD return a 407 (Proxy Authentication Required). */ send_proxy_authenticate(&sock.fdn, stale); http_request_free(&request); fdinfo_close(&sock.fdn); return; } } if (strcmp(request.method, "CONNECT") == 0) { code = handle_connect(&sock, &request); } else if (strcmp(request.method, "GET") == 0 || strcmp(request.method, "HEAD") == 0 || strcmp(request.method, "POST") == 0) { code = handle_method(&sock, &request); } else { code = 500; } http_request_free(&request); if (code != 0) { send_string(&sock.fdn, http_code2str(code)); fdinfo_close(&sock.fdn); return; } fdinfo_close(&sock.fdn); }