Example #1
1
int network_init(server *srv) {
	buffer *b;
	size_t i;
	network_backend_t backend;

	struct nb_map {
		network_backend_t nb;
		const char *name;
	} network_backends[] = {
		/* lowest id wins */
#if defined USE_LINUX_SENDFILE
		{ NETWORK_BACKEND_LINUX_SENDFILE,       "linux-sendfile" },
#endif
#if defined USE_FREEBSD_SENDFILE
		{ NETWORK_BACKEND_FREEBSD_SENDFILE,     "freebsd-sendfile" },
#endif
#if defined USE_SOLARIS_SENDFILEV
		{ NETWORK_BACKEND_SOLARIS_SENDFILEV,	"solaris-sendfilev" },
#endif
#if defined USE_WRITEV
		{ NETWORK_BACKEND_WRITEV,		"writev" },
#endif
		{ NETWORK_BACKEND_WRITE,		"write" },
		{ NETWORK_BACKEND_UNSET,        	NULL }
	};

#ifdef USE_OPENSSL
	/* load SSL certificates */
	for (i = 0; i < srv->config_context->used; i++) {
		specific_config *s = srv->config_storage[i];

		if (buffer_is_empty(s->ssl_pemfile)) continue;

#ifdef OPENSSL_NO_TLSEXT
		{
			data_config *dc = (data_config *)srv->config_context->data[i];
			if (COMP_HTTP_HOST == dc->comp) {
			    log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
					    "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
			    return -1;
			}
		}
#endif

		if (srv->ssl_is_init == 0) {
			SSL_load_error_strings();
			SSL_library_init();
			srv->ssl_is_init = 1;

			if (0 == RAND_status()) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						"not enough entropy in the pool");
				return -1;
			}
		}

		if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
					ERR_error_string(ERR_get_error(), NULL));
			return -1;
		}

		if (!s->ssl_use_sslv2) {
			/* disable SSLv2 */
			if (SSL_OP_NO_SSLv2 != SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}
		}

		if (!buffer_is_empty(s->ssl_cipher_list)) {
			/* Disable support for low encryption ciphers */
			if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}
		}

		if (!buffer_is_empty(s->ssl_ca_file)) {
			if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
				log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
						ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
				return -1;
			}
			if (s->ssl_verifyclient) {
				STACK_OF(X509_NAME) *certs = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
				if (!certs) {
					log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
							ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
				}
				if (SSL_CTX_set_session_id_context(s->ssl_ctx, (void*) &srv, sizeof(srv)) != 1) {
					log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
					return -1;
				}
				SSL_CTX_set_client_CA_list(s->ssl_ctx, certs);
				SSL_CTX_set_verify(
					s->ssl_ctx,
					SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
					NULL
				);
				SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
			}
		} else if (s->ssl_verifyclient) {
			log_error_write(
				srv, __FILE__, __LINE__, "s",
				"SSL: You specified ssl.verifyclient.activate but no ca_file"
			);
		}

		if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
			return -1;
		}

		if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
			return -1;
		}

		if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
			log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
					"Private key does not match the certificate public key, reason:",
					ERR_error_string(ERR_get_error(), NULL),
					s->ssl_pemfile);
			return -1;
		}
		SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1);
		SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

# ifndef OPENSSL_NO_TLSEXT
		if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) ||
		    !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
					"failed to initialize TLS servername callback, openssl library does not support TLS servername extension");
			return -1;
		}
# endif
	}
#endif

	b = buffer_init();

	buffer_copy_string_buffer(b, srv->srvconf.bindhost);
	buffer_append_string_len(b, CONST_STR_LEN(":"));
	buffer_append_long(b, srv->srvconf.port);

	if (0 != network_server_init(srv, b, srv->config_storage[0])) {
		return -1;
	}
	buffer_free(b);

#ifdef USE_OPENSSL
	srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
#endif

	/* get a usefull default */
	backend = network_backends[0].nb;

	/* match name against known types */
	if (!buffer_is_empty(srv->srvconf.network_backend)) {
		for (i = 0; network_backends[i].name; i++) {
			/**/
			if (buffer_is_equal_string(srv->srvconf.network_backend, network_backends[i].name, strlen(network_backends[i].name))) {
				backend = network_backends[i].nb;
				break;
			}
		}
		if (NULL == network_backends[i].name) {
			/* we don't know it */

			log_error_write(srv, __FILE__, __LINE__, "sb",
					"server.network-backend has a unknown value:",
					srv->srvconf.network_backend);

			return -1;
		}
	}

	switch(backend) {
	case NETWORK_BACKEND_WRITE:
		srv->network_backend_write = network_write_chunkqueue_write;
		break;
#ifdef USE_WRITEV
	case NETWORK_BACKEND_WRITEV:
		srv->network_backend_write = network_write_chunkqueue_writev;
		break;
#endif
#ifdef USE_LINUX_SENDFILE
	case NETWORK_BACKEND_LINUX_SENDFILE:
		srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
		break;
#endif
#ifdef USE_FREEBSD_SENDFILE
	case NETWORK_BACKEND_FREEBSD_SENDFILE:
		srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
		break;
#endif
#ifdef USE_SOLARIS_SENDFILEV
	case NETWORK_BACKEND_SOLARIS_SENDFILEV:
		srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
		break;
#endif
	default:
		return -1;
	}

	/* check for $SERVER["socket"] */
	for (i = 1; i < srv->config_context->used; i++) {
		data_config *dc = (data_config *)srv->config_context->data[i];
		specific_config *s = srv->config_storage[i];
		size_t j;

		/* not our stage */
		if (COMP_SERVER_SOCKET != dc->comp) continue;

		if (dc->cond != CONFIG_COND_EQ) continue;

		/* check if we already know this socket,
		 * if yes, don't init it */
		for (j = 0; j < srv->srv_sockets.used; j++) {
			if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
				break;
			}
		}

		if (j == srv->srv_sockets.used) {
			if (0 != network_server_init(srv, dc->string, s)) return -1;
		}
	}

	return 0;
}
Example #2
0
// This test launches a gRPC server on a separate thread and then establishes a
// TLS handshake via a minimal TLS client. The TLS client has configurable (via
// alpn_list) ALPN settings and can probe at the supported ALPN preferences
// using this (via alpn_expected).
static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len,
                            const char *alpn_expected) {
  bool success = true;

  grpc_init();
  int port = grpc_pick_unused_port_or_die();
  gpr_event_init(&client_handshake_complete);

  // Launch the gRPC server thread.
  gpr_thd_options thdopt = gpr_thd_options_default();
  gpr_thd_id thdid;
  gpr_thd_options_set_joinable(&thdopt);
  GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt));

  SSL_load_error_strings();
  OpenSSL_add_ssl_algorithms();

  const SSL_METHOD *method = TLSv1_2_client_method();
  SSL_CTX *ctx = SSL_CTX_new(method);
  if (!ctx) {
    perror("Unable to create SSL context");
    ERR_print_errors_fp(stderr);
    abort();
  }

  // Load key pair.
  if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) {
    ERR_print_errors_fp(stderr);
    abort();
  }
  if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) {
    ERR_print_errors_fp(stderr);
    abort();
  }

  // Set the cipher list to match the one expressed in
  // src/core/lib/tsi/ssl_transport_security.c.
  const char *cipher_list =
      "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-"
      "SHA384:ECDHE-RSA-AES256-GCM-SHA384";
  if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
    ERR_print_errors_fp(stderr);
    gpr_log(GPR_ERROR, "Couldn't set server cipher list.");
    abort();
  }

  // Configure ALPN list the client will send to the server. This must match the
  // wire format, see documentation for SSL_CTX_set_alpn_protos.
  unsigned int alpn_protos_len = alpn_list_len;
  for (unsigned int i = 0; i < alpn_list_len; ++i) {
    alpn_protos_len += (unsigned int)strlen(alpn_list[i]);
  }
  unsigned char *alpn_protos = gpr_malloc(alpn_protos_len);
  unsigned char *p = alpn_protos;
  for (unsigned int i = 0; i < alpn_list_len; ++i) {
    const uint8_t len = (uint8_t)strlen(alpn_list[i]);
    *p++ = len;
    memcpy(p, alpn_list[i], len);
    p += len;
  }
  GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0);

  // Try and connect to server. We allow a bounded number of retries as we might
  // be racing with the server setup on its separate thread.
  int retries = 10;
  int sock = -1;
  while (sock == -1 && retries-- > 0) {
    sock = create_socket(port);
    if (sock < 0) {
      sleep(1);
    }
  }
  GPR_ASSERT(sock > 0);
  gpr_log(GPR_INFO, "Connected to server on port %d", port);

  // Establish a SSL* and connect at SSL layer.
  SSL *ssl = SSL_new(ctx);
  GPR_ASSERT(ssl);
  SSL_set_fd(ssl, sock);
  if (SSL_connect(ssl) <= 0) {
    ERR_print_errors_fp(stderr);
    gpr_log(GPR_ERROR, "Handshake failed.");
    success = false;
  } else {
    gpr_log(GPR_INFO, "Handshake successful.");
    // Validate ALPN preferred by server matches alpn_expected.
    const unsigned char *alpn_selected;
    unsigned int alpn_selected_len;
    SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len);
    if (strlen(alpn_expected) != alpn_selected_len ||
        strncmp((const char *)alpn_selected, alpn_expected,
                alpn_selected_len) != 0) {
      gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference");
      success = false;
    }
  }
  gpr_event_set(&client_handshake_complete, &client_handshake_complete);

  SSL_free(ssl);
  gpr_free(alpn_protos);
  SSL_CTX_free(ctx);
  EVP_cleanup();
  close(sock);

  gpr_thd_join(thdid);

  grpc_shutdown();

  return success;
}
Example #3
0
int main(int argc, char **argv){
	int result=OK;
	int x;
	char buffer[MAX_INPUT_BUFFER];
	char *env_string=NULL;
#ifdef HAVE_SSL
	DH *dh;
	char seedfile[FILENAME_MAX];
	int i,c;
#endif

	/* set some environment variables */
	asprintf(&env_string,"NRPE_MULTILINESUPPORT=1");
	putenv(env_string);
	asprintf(&env_string,"NRPE_PROGRAMVERSION=%s",PROGRAM_VERSION);
	putenv(env_string);

	/* process command-line args */
	result=process_arguments(argc,argv);

        if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){

		printf("\n");
		printf("NRPE - Nagios Remote Plugin Executor\n");
		printf("Copyright (c) 1999-2008 Ethan Galstad ([email protected])\n");
		printf("Version: %s\n",PROGRAM_VERSION);
		printf("Last Modified: %s\n",MODIFICATION_DATE);
		printf("License: GPL v2 with exemptions (-l for more info)\n");
#ifdef HAVE_SSL
		printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n");
#endif
#ifdef HAVE_LIBWRAP
		printf("TCP Wrappers Available\n");
#endif
		printf("\n");
#ifdef ENABLE_COMMAND_ARGUMENTS
		printf("***************************************************************\n");
		printf("** POSSIBLE SECURITY RISK - COMMAND ARGUMENTS ARE SUPPORTED! **\n");
		printf("**      Read the NRPE SECURITY file for more information     **\n");
		printf("***************************************************************\n");
		printf("\n");
#endif
#ifndef HAVE_LIBWRAP
		printf("***************************************************************\n");
		printf("** POSSIBLE SECURITY RISK - TCP WRAPPERS ARE NOT AVAILABLE!  **\n");
		printf("**      Read the NRPE SECURITY file for more information     **\n");
		printf("***************************************************************\n");
		printf("\n");
#endif
	        }

	if(show_license==TRUE)
		display_license();

	else if(result!=OK || show_help==TRUE){

		printf("Usage: nrpe [-n] -c <config_file> <mode>\n");
		printf("\n");
		printf("Options:\n");
		printf(" -n            = Do not use SSL\n");
		printf(" <config_file> = Name of config file to use\n");
		printf(" <mode>        = One of the following operating modes:\n");  
		printf("   -i          =    Run as a service under inetd or xinetd\n");
		printf("   -d          =    Run as a standalone daemon\n");
		/* Updates help section to indicate how to start under SRC on AIX */
		printf("   -d -s       =    Run as a subsystem under AIX\n");        
		printf("\n");
		printf("Notes:\n");
		printf("This program is designed to process requests from the check_nrpe\n");
		printf("plugin on the host(s) running Nagios.  It can run as a service\n");
		printf("under inetd or xinetd (read the docs for info on this), or as a\n");
		printf("standalone daemon. Once a request is received from an authorized\n");
		printf("host, NRPE will execute the command/plugin (as defined in the\n");
		printf("config file) and return the plugin output and return code to the\n");
		printf("check_nrpe plugin.\n");
		printf("\n");
		}

        if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE)
		exit(STATE_UNKNOWN);


	/* open a connection to the syslog facility */
	/* facility name may be overridden later */
	get_log_facility(NRPE_LOG_FACILITY);
        openlog("nrpe",LOG_PID,log_facility); 

	/* make sure the config file uses an absolute path */
	if(config_file[0]!='/'){

		/* save the name of the config file */
		strncpy(buffer,config_file,sizeof(buffer));
		buffer[sizeof(buffer)-1]='\x0';

		/* get absolute path of current working directory */
		strcpy(config_file,"");
		getcwd(config_file,sizeof(config_file));

		/* append a forward slash */
		strncat(config_file,"/",sizeof(config_file)-2);
		config_file[sizeof(config_file)-1]='\x0';

		/* append the config file to the path */
		strncat(config_file,buffer,sizeof(config_file)-strlen(config_file)-1);
		config_file[sizeof(config_file)-1]='\x0';
	        }

	/* read the config file */
	result=read_config_file(config_file);	

	/* exit if there are errors... */
	if(result==ERROR){
		syslog(LOG_ERR,"Config file '%s' contained errors, aborting...",config_file);
		return STATE_CRITICAL;
		}

        /* generate the CRC 32 table */
        generate_crc32_table();

	/* initialize macros */
	for(x=0;x<MAX_COMMAND_ARGUMENTS;x++)
		macro_argv[x]=NULL;

#ifdef HAVE_SSL
	/* initialize SSL */
	if(use_ssl==TRUE){
		SSL_library_init();
		SSLeay_add_ssl_algorithms();
		meth=SSLv23_server_method();
		SSL_load_error_strings();

		/* use week random seed if necessary */
		if(allow_weak_random_seed && (RAND_status()==0)){

			if(RAND_file_name(seedfile,sizeof(seedfile)-1))
				if(RAND_load_file(seedfile,-1))
					RAND_write_file(seedfile);

			if(RAND_status()==0){
				syslog(LOG_ERR,"Warning: SSL/TLS uses a weak random seed which is highly discouraged");
				srand(time(NULL));
				for(i=0;i<500 && RAND_status()==0;i++){
					for(c=0;c<sizeof(seedfile);c+=sizeof(int)){
						*((int *)(seedfile+c))=rand();
					        }
					RAND_seed(seedfile,sizeof(seedfile));
					}
				}
			}

		if((ctx=SSL_CTX_new(meth))==NULL){
			syslog(LOG_ERR,"Error: could not create SSL context.\n");
			exit(STATE_CRITICAL);
		        }

		/* ADDED 01/19/2004 */
		/* use only TLSv1 protocol */
		SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

		/* use anonymous DH ciphers */
		SSL_CTX_set_cipher_list(ctx,"ADH");
		dh=get_dh512();
		SSL_CTX_set_tmp_dh(ctx,dh);
		DH_free(dh);
		if(debug==TRUE)
			syslog(LOG_INFO,"INFO: SSL/TLS initialized. All network traffic will be encrypted.");
	        }
	else{
		if(debug==TRUE)
			syslog(LOG_INFO,"INFO: SSL/TLS NOT initialized. Network encryption DISABLED.");
	        }
#endif

	/* if we're running under inetd... */
	if(use_inetd==TRUE){

		/* make sure we're not root */
		check_privileges();

		/* redirect STDERR to /dev/null */
		close(2);
		open("/dev/null",O_WRONLY);

		/* handle the connection */
		handle_connection(0);
	        }

	/* if we're running under SRC... 
	   we don't fork but does drop-privileges*/
	else if (use_src==TRUE){

		/* close standard file descriptors */
		close(0);
		close(1);
		close(2);

		/* redirect standard descriptors to /dev/null */
		open("/dev/null",O_RDONLY);
		open("/dev/null",O_WRONLY);
		open("/dev/null",O_WRONLY);

		chdir("/");
		/*umask(0);*/

		/* handle signals */
		signal(SIGQUIT,sighandler);
		signal(SIGTERM,sighandler);
		signal(SIGHUP,sighandler);

		/* log info to syslog facility */
		syslog(LOG_NOTICE,"Starting up daemon");

		/* write pid file */
		if(write_pid_file()==ERROR)
			return STATE_CRITICAL;

		/* drop privileges */
		drop_privileges(nrpe_user,nrpe_group);

		/* make sure we're not root */
		check_privileges();

		do{

			/* reset flags */
			sigrestart=FALSE;
			sigshutdown=FALSE;

			/* wait for connections */
			wait_for_connections();

			/* free all memory we allocated */
			free_memory();
			
			if(sigrestart==TRUE){

				/* read the config file */
				result=read_config_file(config_file);	

				/* exit if there are errors... */
				if(result==ERROR){
					syslog(LOG_ERR,"Config file '%s' contained errors, bailing out...",config_file);
					return STATE_CRITICAL;
				        }
			        }

		        }while(sigrestart==TRUE && sigshutdown==FALSE);

		/* remove pid file */
		remove_pid_file();

		syslog(LOG_NOTICE,"Daemon shutdown\n");
	        }            


	/* else daemonize and start listening for requests... */
	else if(fork()==0){
		
		/* we're a daemon - set up a new process group */
		setsid();

		/* close standard file descriptors */
		close(0);
		close(1);
		close(2);

		/* redirect standard descriptors to /dev/null */
		open("/dev/null",O_RDONLY);
		open("/dev/null",O_WRONLY);
		open("/dev/null",O_WRONLY);

		chdir("/");
		/*umask(0);*/

		/* handle signals */
		signal(SIGQUIT,sighandler);
		signal(SIGTERM,sighandler);
		signal(SIGHUP,sighandler);

		/* log info to syslog facility */
		syslog(LOG_NOTICE,"Starting up daemon");

		/* write pid file */
		if(write_pid_file()==ERROR)
			return STATE_CRITICAL;
		
		/* drop privileges */
		drop_privileges(nrpe_user,nrpe_group);

		/* make sure we're not root */
		check_privileges();

		do{

			/* reset flags */
			sigrestart=FALSE;
			sigshutdown=FALSE;

			/* wait for connections */
			wait_for_connections();

			/* free all memory we allocated */
			free_memory();

			if(sigrestart==TRUE){

				/* read the config file */
				result=read_config_file(config_file);	

				/* exit if there are errors... */
				if(result==ERROR){
					syslog(LOG_ERR,"Config file '%s' contained errors, bailing out...",config_file);
					return STATE_CRITICAL;
				        }
			        }
	
		        }while(sigrestart==TRUE && sigshutdown==FALSE);

		/* remove pid file */
		remove_pid_file();

		syslog(LOG_NOTICE,"Daemon shutdown\n");
	        }

#ifdef HAVE_SSL
	if(use_ssl==TRUE)
		SSL_CTX_free(ctx);
#endif

	/* We are now running in daemon mode, or the connection handed over by inetd has
	   been completed, so the parent process exits */
        return STATE_OK;
	}
Example #4
0
void echoclient_test(void* args)
{
    SOCKET_T sockfd = 0;

    FILE* fin   = stdin  ;
    FILE* fout = stdout;

    int inCreated  = 0;
    int outCreated = 0;

    char msg[1024];
    char reply[1024+1];

    SSL_METHOD* method = 0;
    SSL_CTX*    ctx    = 0;
    SSL*        ssl    = 0;

    int doDTLS = 0;
    int doPSK = 0;
    int sendSz;
    int argc    = 0;
    char** argv = 0;
    int port = yasslPort;

    ((func_args*)args)->return_code = -1; /* error state */
    
#ifndef CYASSL_MDK_SHELL
    argc = ((func_args*)args)->argc;
    argv = ((func_args*)args)->argv;
#endif

    if (argc >= 2) {
        fin  = fopen(argv[1], "r"); 
        inCreated = 1;
    }
    if (argc >= 3) {
        fout = fopen(argv[2], "w");
        outCreated = 1;
    }

    if (!fin)  err_sys("can't open input file");
    if (!fout) err_sys("can't open output file");

#ifdef CYASSL_DTLS
    doDTLS  = 1;
#endif

#ifdef CYASSL_LEANPSK 
    doPSK = 1;
#endif

#if defined(NO_RSA) && !defined(HAVE_ECC)
    doPSK = 1;
#endif

#if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API) && !defined(CYASSL_MDK_SHELL)
    port = ((func_args*)args)->signal->port;
#endif

#if defined(CYASSL_DTLS)
    method  = DTLSv1_client_method();
#elif  !defined(NO_TLS)
    method = CyaSSLv23_client_method();
#else
    method = SSLv3_client_method();
#endif
    ctx    = SSL_CTX_new(method);

#ifndef NO_FILESYSTEM
    #ifndef NO_RSA
    if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS)
        err_sys("can't load ca file, Please run from CyaSSL home dir");
    #endif
    #ifdef HAVE_ECC
        if (SSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS)
            err_sys("can't load ca file, Please run from CyaSSL home dir");
    #endif
#elif !defined(NO_CERTS)
    if (!doPSK)
        load_buffer(ctx, caCert, CYASSL_CA);
#endif

#if defined(CYASSL_SNIFFER) && !defined(HAVE_NTRU) && !defined(HAVE_ECC)
    /* don't use EDH, can't sniff tmp keys */
    SSL_CTX_set_cipher_list(ctx, "AES256-SHA");
#endif
    if (doPSK) {
#ifndef NO_PSK
        const char *defaultCipherList;

        CyaSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
        #ifdef HAVE_NULL_CIPHER
            defaultCipherList = "PSK-NULL-SHA256";
        #else
            defaultCipherList = "PSK-AES128-CBC-SHA256";
        #endif
        if (CyaSSL_CTX_set_cipher_list(ctx,defaultCipherList) !=SSL_SUCCESS)
            err_sys("client can't set cipher list 2");
#endif
    }

#ifdef OPENSSL_EXTRA
    SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif

    #if defined(CYASSL_MDK_ARM)
    CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
    #endif

    ssl = SSL_new(ctx);
        

    if (doDTLS) {
        SOCKADDR_IN_T addr;
        build_addr(&addr, yasslIP, port, 1);
        CyaSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
        tcp_socket(&sockfd, 1);
    }
    else {
        tcp_connect(&sockfd, yasslIP, port, 0);
    }
        
    SSL_set_fd(ssl, sockfd);
#if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER)
    /* let echoserver bind first, TODO: add Windows signal like pthreads does */
    Sleep(100);
#endif

    if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed");

    while (fgets(msg, sizeof(msg), fin) != 0) {
     
        sendSz = (int)strlen(msg);

        if (SSL_write(ssl, msg, sendSz) != sendSz)
            err_sys("SSL_write failed");

        if (strncmp(msg, "quit", 4) == 0) {
            fputs("sending server shutdown command: quit!\n", fout);
            break;
        }

        if (strncmp(msg, "break", 5) == 0) {
            fputs("sending server session close: break!\n", fout);
            break;
        }

        #ifndef CYASSL_MDK_SHELL
        while (sendSz) {
            int got;
            if ( (got = SSL_read(ssl, reply, sizeof(reply)-1)) > 0) {
                reply[got] = 0;
                fputs(reply, fout);
                fflush(fout) ;
                sendSz -= got;
            }
            else
                break;
        }
        #else
        {
            int got;
            if ( (got = SSL_read(ssl, reply, sizeof(reply)-1)) > 0) {
                reply[got] = 0;
                fputs(reply, fout);
                fflush(fout) ;
                sendSz -= got;
            }
        }
        #endif
    }


#ifdef CYASSL_DTLS
    strncpy(msg, "break", 6);
    sendSz = (int)strlen(msg);
    /* try to tell server done */
    SSL_write(ssl, msg, sendSz);
#else
    SSL_shutdown(ssl);
#endif

    SSL_free(ssl);
    SSL_CTX_free(ctx);

    fflush(fout);
    if (inCreated)  fclose(fin);
    if (outCreated) fclose(fout);

    CloseSocket(sockfd);
    ((func_args*)args)->return_code = 0; 
}
Example #5
0
/* ====================================================== */
CURLcode
Curl_ossl_connect(struct connectdata *conn,
                  int sockindex)
{
  CURLcode retcode = CURLE_OK;

  struct SessionHandle *data = conn->data;
  int err;
  long lerr;
  int what;
  char * str;
  SSL_METHOD_QUAL SSL_METHOD *req_method=NULL;
  void *ssl_sessionid=NULL;
  ASN1_TIME *certdate;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  if(!ssl_seeded || data->set.ssl.random_file || data->set.ssl.egdsocket) {
    /* Make funny stuff to get random input */
    random_the_seed(data);

    ssl_seeded = TRUE;
  }

  /* check to see if we've been told to use an explicit SSL/TLS version */
  switch(data->set.ssl.version) {
  default:
  case CURL_SSLVERSION_DEFAULT:
    /* we try to figure out version */
    req_method = SSLv23_client_method();
    break;
  case CURL_SSLVERSION_TLSv1:
    req_method = TLSv1_client_method();
    break;
  case CURL_SSLVERSION_SSLv2:
    req_method = SSLv2_client_method();
    break;
  case CURL_SSLVERSION_SSLv3:
    req_method = SSLv3_client_method();
    break;
  }

  connssl->ctx = SSL_CTX_new(req_method);

  if(!connssl->ctx) {
    failf(data, "SSL: couldn't create a context!");
    return CURLE_OUT_OF_MEMORY;
  }

#ifdef SSL_CTRL_SET_MSG_CALLBACK
  if (data->set.fdebug) {
    if (!SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK,
                               (void (*)(void))ssl_tls_trace)) {
      failf(data, "SSL: couldn't set callback!");
      return CURLE_SSL_CONNECT_ERROR;
    }

    if (!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, conn)) {
      failf(data, "SSL: couldn't set callback argument!");
      return CURLE_SSL_CONNECT_ERROR;
    }
  }
#endif

  /* OpenSSL contains code to work-around lots of bugs and flaws in various
     SSL-implementations. SSL_CTX_set_options() is used to enabled those
     work-arounds. The man page for this option states that SSL_OP_ALL enables
     ll the work-arounds and that "It is usually safe to use SSL_OP_ALL to
     enable the bug workaround options if compatibility with somewhat broken
     implementations is desired."

  */
  SSL_CTX_set_options(connssl->ctx, SSL_OP_ALL);

#if 0
  /*
   * Not sure it's needed to tell SSL_connect() that socket is
   * non-blocking. It doesn't seem to care, but just return with
   * SSL_ERROR_WANT_x.
   */
  if (data->state.used_interface == Curl_if_multi)
    SSL_CTX_ctrl(connssl->ctx, BIO_C_SET_NBIO, 1, NULL);
#endif

  if(data->set.cert) {
    if(!cert_stuff(conn,
                   connssl->ctx,
                   data->set.cert,
                   data->set.cert_type,
                   data->set.key,
                   data->set.key_type)) {
      /* failf() is already done in cert_stuff() */
      return CURLE_SSL_CERTPROBLEM;
    }
  }

  if(data->set.ssl.cipher_list) {
    if(!SSL_CTX_set_cipher_list(connssl->ctx,
                                data->set.ssl.cipher_list)) {
      failf(data, "failed setting cipher list");
      return CURLE_SSL_CIPHER;
    }
  }

  if (data->set.ssl.CAfile || data->set.ssl.CApath) {
    /* tell SSL where to find CA certificates that are used to verify
       the servers certificate. */
    if (!SSL_CTX_load_verify_locations(connssl->ctx, data->set.ssl.CAfile,
                                       data->set.ssl.CApath)) {
      if (data->set.ssl.verifypeer) {
        /* Fail if we insist on successfully verifying the server. */
        failf(data,"error setting certificate verify locations:\n"
              "  CAfile: %s\n  CApath: %s\n",
              data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
              data->set.ssl.CApath ? data->set.ssl.CApath : "none");
        return CURLE_SSL_CACERT;
      }
      else {
        /* Just continue with a warning if no strict  certificate verification
           is required. */
        infof(data, "error setting certificate verify locations,"
              " continuing anyway:\n");
      }
    }
    else {
      /* Everything is fine. */
      infof(data, "successfully set certificate verify locations:\n");
    }
    infof(data,
          "  CAfile: %s\n"
          "  CApath: %s\n",
          data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
          data->set.ssl.CApath ? data->set.ssl.CApath : "none");
  }
  /* SSL always tries to verify the peer, this only says whether it should
   * fail to connect if the verification fails, or if it should continue
   * anyway. In the latter case the result of the verification is checked with
   * SSL_get_verify_result() below. */
  SSL_CTX_set_verify(connssl->ctx,
                     data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
                     cert_verify_callback);

  /* give application a chance to interfere with SSL set up. */
  if(data->set.ssl.fsslctx) {
    retcode = (*data->set.ssl.fsslctx)(data, connssl->ctx,
                                       data->set.ssl.fsslctxp);
    if(retcode) {
      failf(data,"error signaled by ssl ctx callback");
      return retcode;
    }
  }

  /* Lets make an SSL structure */
  connssl->handle = SSL_new(connssl->ctx);
  if (!connssl->handle) {
    failf(data, "SSL: couldn't create a context (handle)!");
    return CURLE_OUT_OF_MEMORY;
  }
  SSL_set_connect_state(connssl->handle);

  connssl->server_cert = 0x0;

  /* Check if there's a cached ID we can/should use here! */
  if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
    /* we got a session id, use it! */
    if (!SSL_set_session(connssl->handle, ssl_sessionid)) {
      failf(data, "SSL: SSL_set_session failed: %s",
            ERR_error_string(ERR_get_error(),NULL));
      return CURLE_SSL_CONNECT_ERROR;
    }
    /* Informational message */
    infof (data, "SSL re-using session ID\n");
  }

  /* pass the raw socket into the SSL layers */
  if (!SSL_set_fd(connssl->handle, sockfd)) {
     failf(data, "SSL: SSL_set_fd failed: %s",
           ERR_error_string(ERR_get_error(),NULL));
     return CURLE_SSL_CONNECT_ERROR;
  }

  while(1) {
    int writefd;
    int readfd;
    long timeout_ms;
    long has_passed;

    /* Find out if any timeout is set. If not, use 300 seconds.
       Otherwise, figure out the most strict timeout of the two possible one
       and then how much time that has elapsed to know how much time we
       allow for the connect call */
    if(data->set.timeout || data->set.connecttimeout) {

      /* get the most strict timeout of the ones converted to milliseconds */
      if(data->set.timeout &&
         (data->set.timeout>data->set.connecttimeout))
        timeout_ms = data->set.timeout*1000;
      else
        timeout_ms = data->set.connecttimeout*1000;
    }
    else
      /* no particular time-out has been set */
      timeout_ms= DEFAULT_CONNECT_TIMEOUT;

    /* Evaluate in milliseconds how much time that has passed */
    has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);

    /* subtract the passed time */
    timeout_ms -= has_passed;

    if(timeout_ms < 0) {
      /* a precaution, no need to continue if time already is up */
      failf(data, "SSL connection timeout");
      return CURLE_OPERATION_TIMEOUTED;
    }

    readfd = CURL_SOCKET_BAD;
    writefd = CURL_SOCKET_BAD;

    err = SSL_connect(connssl->handle);

    /* 1  is fine
       0  is "not successful but was shut down controlled"
       <0 is "handshake was not successful, because a fatal error occurred" */
    if(1 != err) {
      int detail = SSL_get_error(connssl->handle, err);

      if(SSL_ERROR_WANT_READ == detail)
        readfd = sockfd;
      else if(SSL_ERROR_WANT_WRITE == detail)
        writefd = sockfd;
      else {
        /* untreated error */
        unsigned long errdetail;
        char error_buffer[120]; /* OpenSSL documents that this must be at least
                                   120 bytes long. */
        CURLcode rc;
        const char *cert_problem = NULL;

        errdetail = ERR_get_error(); /* Gets the earliest error code from the
                                        thread's error queue and removes the
                                        entry. */

        switch(errdetail) {
        case 0x1407E086:
          /* 1407E086:
             SSL routines:
             SSL2_SET_CERTIFICATE:
             certificate verify failed */
          /* fall-through */
        case 0x14090086:
          /* 14090086:
             SSL routines:
             SSL3_GET_SERVER_CERTIFICATE:
             certificate verify failed */
          cert_problem = "SSL certificate problem, verify that the CA cert is"
                         " OK. Details:\n";
          rc = CURLE_SSL_CACERT;
          break;
        default:
          rc = CURLE_SSL_CONNECT_ERROR;
          break;
        }

          /* detail is already set to the SSL error above */

        /* If we e.g. use SSLv2 request-method and the server doesn't like us
         * (RST connection etc.), OpenSSL gives no explanation whatsoever and
         * the SO_ERROR is also lost.
         */
        if (CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
          failf(data, "Unknown SSL protocol error in connection to %s:%d ",
                conn->host.name, conn->port);
          return rc;
        }
        /* Could be a CERT problem */

        SSL_strerror(errdetail, error_buffer, sizeof(error_buffer));
        failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer);
        return rc;
      }
    }
    else
      /* we have been connected fine, get out of the connect loop */
      break;

    while(1) {
      what = Curl_select(readfd, writefd, (int)timeout_ms);
      if(what > 0)
        /* reabable or writable, go loop in the outer loop */
        break;
      else if(0 == what) {
        /* timeout */
        failf(data, "SSL connection timeout");
        return CURLE_OPERATION_TIMEDOUT;
      }
      else {
        /* anything that gets here is fatally bad */
        failf(data, "select on SSL socket, errno: %d", Curl_ourerrno());
        return CURLE_SSL_CONNECT_ERROR;
      }
    } /* while()-loop for the select() */
  } /* while()-loop for the SSL_connect() */

  /* Informational message */
  infof (data, "SSL connection using %s\n",
         SSL_get_cipher(connssl->handle));

  if(!ssl_sessionid) {
    /* Since this is not a cached session ID, then we want to stach this one
       in the cache! */
    SSL_SESSION *ssl_sessionid;
#ifdef HAVE_SSL_GET1_SESSION
    ssl_sessionid = SSL_get1_session(connssl->handle);

    /* SSL_get1_session() will increment the reference
       count and the session will stay in memory until explicitly freed with
       SSL_SESSION_free(3), regardless of its state.
       This function was introduced in openssl 0.9.5a. */
#else
    ssl_sessionid = SSL_get_session(connssl->handle);

    /* if SSL_get1_session() is unavailable, use SSL_get_session().
       This is an inferior option because the session can be flushed
       at any time by openssl. It is included only so curl compiles
       under versions of openssl < 0.9.5a.

       WARNING: How curl behaves if it's session is flushed is
       untested.
    */
#endif
    retcode = Curl_ssl_addsessionid(conn, ssl_sessionid,
                                    0 /* unknown size */);
    if(retcode) {
      failf(data, "failed to store ssl session");
      return retcode;
    }
  }


  /* Get server's certificate (note: beware of dynamic allocation) - opt */
  /* major serious hack alert -- we should check certificates
   * to authenticate the server; otherwise we risk man-in-the-middle
   * attack
   */

  connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
  if(!connssl->server_cert) {
    failf(data, "SSL: couldn't get peer certificate!");
    return CURLE_SSL_PEER_CERTIFICATE;
  }
  infof (data, "Server certificate:\n");

  str = X509_NAME_oneline(X509_get_subject_name(connssl->server_cert),
                          NULL, 0);
  if(!str) {
    failf(data, "SSL: couldn't get X509-subject!");
    X509_free(connssl->server_cert);
    connssl->server_cert = NULL;
    return CURLE_SSL_CONNECT_ERROR;
  }
  infof(data, "\t subject: %s\n", str);
  CRYPTO_free(str);

  certdate = X509_get_notBefore(connssl->server_cert);
  Curl_ASN1_UTCTIME_output(conn, "\t start date: ", certdate);

  certdate = X509_get_notAfter(connssl->server_cert);
  Curl_ASN1_UTCTIME_output(conn, "\t expire date: ", certdate);

  if(data->set.ssl.verifyhost) {
    retcode = verifyhost(conn, connssl->server_cert);
    if(retcode) {
      X509_free(connssl->server_cert);
      connssl->server_cert = NULL;
      return retcode;
    }
  }

  str = X509_NAME_oneline(X509_get_issuer_name(connssl->server_cert),
                          NULL, 0);
  if(!str) {
    failf(data, "SSL: couldn't get X509-issuer name!");
    retcode = CURLE_SSL_CONNECT_ERROR;
  }
  else {
    infof(data, "\t issuer: %s\n", str);
    CRYPTO_free(str);

    /* We could do all sorts of certificate verification stuff here before
       deallocating the certificate. */

    lerr = data->set.ssl.certverifyresult=
      SSL_get_verify_result(connssl->handle);
    if(data->set.ssl.certverifyresult != X509_V_OK) {
      if(data->set.ssl.verifypeer) {
        /* We probably never reach this, because SSL_connect() will fail
           and we return earlyer if verifypeer is set? */
        failf(data, "SSL certificate verify result: %s (%ld)",
              X509_verify_cert_error_string(lerr), lerr);
        retcode = CURLE_SSL_PEER_CERTIFICATE;
      }
      else
        infof(data, "SSL certificate verify result: %s (%ld),"
              " continuing anyway.\n",
              X509_verify_cert_error_string(err), lerr);
    }
    else
      infof(data, "SSL certificate verify ok.\n");
  }

  X509_free(connssl->server_cert);
  connssl->server_cert = NULL;
  return retcode;
}
Example #6
0
void DataPlaneServer::start() {
    server_addr.s6.sin6_family = AF_INET6;
    // we listen on public IP, which is the one stored in the DB.
    struct in6_addr servIp;
    inet_pton(AF_INET6, qSql->getLocalIP().toUtf8().data(), &servIp);
    server_addr.s6.sin6_addr = servIp; //in6addr_any;
    server_addr.s6.sin6_port = htons(DATAPLANEPORT);

    const int on = 1, off = 0;

    OpenSSL_add_ssl_algorithms();

    SSL_load_error_strings();
    ctx = SSL_CTX_new(DTLSv1_server_method());

    SSL_CTX_set_cipher_list(ctx, DTLS_ENCRYPT);
    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);

    // get certificate and key from SQL & use them
    ConnectionInitiator* i = ConnectionInitiator::getInstance();
    QSslCertificate cert = i->getLocalCertificate();
    QByteArray certBytesPEM = cert.toPem();
    char* x509buffer = certBytesPEM.data();

    BIO *bi;
    bi = BIO_new_mem_buf(x509buffer, certBytesPEM.length());
    X509 *x;
    x = PEM_read_bio_X509(bi, NULL, NULL, NULL);

    if (!SSL_CTX_use_certificate(ctx,x)) {
        qWarning() << "ERROR: no certificate found!";
        UnixSignalHandler::termSignalHandler(0);
    }

    if (x != NULL) X509_free(x);
    if (bi != NULL) BIO_free(bi);

    QSslKey key = i->getPrivateKey();
    QByteArray keyBytesPEM = key.toPem();
    char* keyBuffer = keyBytesPEM.data();

    bi = BIO_new_mem_buf(keyBuffer, keyBytesPEM.length());
    EVP_PKEY *pkey;
    pkey = PEM_read_bio_PrivateKey(bi, NULL, NULL, NULL);

    if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
        qWarning() << "ERROR: no private key found!";
        UnixSignalHandler::termSignalHandler(0);
    }

    if (pkey != NULL) EVP_PKEY_free(pkey);
    if (bi != NULL) BIO_free(bi);

    if (!SSL_CTX_check_private_key (ctx)) {
        qWarning() << "ERROR: invalid private key!";
        UnixSignalHandler::termSignalHandler(0);
    }
    /* Client has to authenticate */
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, dtls_verify_callback);

    SSL_CTX_set_read_ahead(ctx, 1);
    SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie);
    SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie);

    fd = socket(server_addr.ss.ss_family, SOCK_DGRAM, 0);
    if (fd < 0) {
        qWarning() << "Could not open SOCK_DGRAM";
        UnixSignalHandler::termSignalHandler(0);
    }

#ifdef WIN32
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, (socklen_t) sizeof(on));
#else
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
#ifdef SO_REUSEPORT
    setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &on, (socklen_t) sizeof(on));
#endif
#endif

    setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off));
    bind(fd, (const struct sockaddr *) &server_addr, sizeof(struct sockaddr_in6));

    notif = new QSocketNotifier(fd, QSocketNotifier::Read);
    connect(notif, SIGNAL(activated(int)), this, SLOT(readyRead(int)));
}
Example #7
0
THREAD_RETURN CYASSL_THREAD server_test(void* args)
{
    SOCKET_T sockfd   = 0;
    SOCKET_T clientfd = 0;

    SSL_METHOD* method = 0;
    SSL_CTX*    ctx    = 0;
    SSL*        ssl    = 0;

    char   msg[] = "I hear you fa shizzle!";
    char   input[80];
    int    idx;
    int    ch;
    int    version = SERVER_DEFAULT_VERSION;
    int    doCliCertCheck = 1;
    int    useAnyAddr = 0;
    int    port = yasslPort;
    int    usePsk = 0;
    int    doDTLS = 0;
    int    useNtruKey   = 0;
    int    nonBlocking  = 0;
    int    trackMemory  = 0;
    int    fewerPackets = 0;
    char*  cipherList = NULL;
    char*  verifyCert = (char*)cliCert;
    char*  ourCert    = (char*)svrCert;
    char*  ourKey     = (char*)svrKey;
    int    argc = ((func_args*)args)->argc;
    char** argv = ((func_args*)args)->argv;

#ifdef HAVE_SNI
    char*  sniHostName = NULL;
#endif

    ((func_args*)args)->return_code = -1; /* error state */

#ifdef NO_RSA
    verifyCert = (char*)cliEccCert;
    ourCert    = (char*)eccCert;
    ourKey     = (char*)eccKey;
#endif
    (void)trackMemory;

    while ((ch = mygetopt(argc, argv, "?dbstnNufp:v:l:A:c:k:S:")) != -1) {
        switch (ch) {
            case '?' :
                Usage();
                exit(EXIT_SUCCESS);

            case 'd' :
                doCliCertCheck = 0;
                break;

            case 'b' :
                useAnyAddr = 1;
                break;

            case 's' :
                usePsk = 1;
                break;

            case 't' :
            #ifdef USE_CYASSL_MEMORY
                trackMemory = 1;
            #endif
                break;

            case 'n' :
                useNtruKey = 1;
                break;

            case 'u' :
                doDTLS  = 1;
                break;

            case 'f' :
                fewerPackets = 1;
                break;

            case 'p' :
                port = atoi(myoptarg);
                #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
                    if (port == 0)
                        err_sys("port number cannot be 0");
                #endif
                break;

            case 'v' :
                version = atoi(myoptarg);
                if (version < 0 || version > 3) {
                    Usage();
                    exit(MY_EX_USAGE);
                }
                break;

            case 'l' :
                cipherList = myoptarg;
                break;

            case 'A' :
                verifyCert = myoptarg;
                break;

            case 'c' :
                ourCert = myoptarg;
                break;

            case 'k' :
                ourKey = myoptarg;
                break;

            case 'N':
                nonBlocking = 1;
                break;

            case 'S' :
                #ifdef HAVE_SNI
                    sniHostName = myoptarg;
                #endif
                break;

            default:
                Usage();
                exit(MY_EX_USAGE);
        }
    }

    myoptind = 0;      /* reset for test cases */

    /* sort out DTLS versus TLS versions */
    if (version == CLIENT_INVALID_VERSION) {
        if (doDTLS)
            version = CLIENT_DTLS_DEFAULT_VERSION;
        else
            version = CLIENT_DEFAULT_VERSION;
    }
    else {
        if (doDTLS) {
            if (version == 3)
                version = -2;
            else
                version = -1;
        }
    }

#ifdef USE_CYASSL_MEMORY
    if (trackMemory)
        InitMemoryTracker(); 
#endif

    switch (version) {
#ifndef NO_OLD_TLS
        case 0:
            method = SSLv3_server_method();
            break;

    #ifndef NO_TLS
        case 1:
            method = TLSv1_server_method();
            break;


        case 2:
            method = TLSv1_1_server_method();
            break;

        #endif
#endif

#ifndef NO_TLS
        case 3:
            method = TLSv1_2_server_method();
            break;
#endif
                
#ifdef CYASSL_DTLS
        case -1:
            method = DTLSv1_server_method();
            break;

        case -2:
            method = DTLSv1_2_server_method();
            break;
#endif

        default:
            err_sys("Bad SSL version");
    }

    if (method == NULL)
        err_sys("unable to get method");

    ctx = SSL_CTX_new(method);
    if (ctx == NULL)
        err_sys("unable to get ctx");

    if (cipherList)
        if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
            err_sys("server can't set cipher list 1");

#ifdef CYASSL_LEANPSK
    usePsk = 1;
#endif

#if defined(NO_RSA) && !defined(HAVE_ECC)
    usePsk = 1;
#endif

    if (fewerPackets)
        CyaSSL_CTX_set_group_messages(ctx);

#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
    if (!usePsk) {
        if (SSL_CTX_use_certificate_file(ctx, ourCert, SSL_FILETYPE_PEM)
                                         != SSL_SUCCESS)
            err_sys("can't load server cert file, check file and run from"
                    " CyaSSL home dir");
    }
#endif

#ifdef HAVE_NTRU
    if (useNtruKey) {
        if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey)
                                               != SSL_SUCCESS)
            err_sys("can't load ntru key file, "
                    "Please run from CyaSSL home dir");
    }
#endif

#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
    if (!useNtruKey && !usePsk) {
        if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM)
                                         != SSL_SUCCESS)
            err_sys("can't load server cert file, check file and run from"
                " CyaSSL home dir");
    }
#endif

    if (usePsk) {
#ifndef NO_PSK
        SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb);
        SSL_CTX_use_psk_identity_hint(ctx, "cyassl server");
        if (cipherList == NULL) {
            const char *defaultCipherList;
            #ifdef HAVE_NULL_CIPHER
                defaultCipherList = "PSK-NULL-SHA256";
            #else
                defaultCipherList = "PSK-AES128-CBC-SHA256";
            #endif
            if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS)
                err_sys("server can't set cipher list 2");
        }
#endif
    }

#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
    /* if not using PSK, verify peer with certs */
    if (doCliCertCheck && usePsk == 0) {
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER |
                                SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);
        if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS)
            err_sys("can't load ca file, Please run from CyaSSL home dir");
    }
#endif

#ifdef OPENSSL_EXTRA
    SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif

#if defined(CYASSL_SNIFFER) && !defined(HAVE_NTRU) && !defined(HAVE_ECC)
    /* don't use EDH, can't sniff tmp keys */
    if (cipherList == NULL) {
        if (SSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != SSL_SUCCESS)
            err_sys("server can't set cipher list 3");
    }
#endif

#ifdef HAVE_SNI
    if (sniHostName) {
        if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName,
                                                          XSTRLEN(sniHostName)))
            err_sys("UseSNI failed");
        else
            CyaSSL_CTX_SNI_SetOptions(ctx, CYASSL_SNI_HOST_NAME,
                                                  CYASSL_SNI_ABORT_ON_MISMATCH);
    }
#endif

    ssl = SSL_new(ctx);
    if (ssl == NULL)
        err_sys("unable to get SSL");
    CyaSSL_set_quiet_shutdown(ssl, 1) ;
#ifdef HAVE_CRL
    CyaSSL_EnableCRL(ssl, 0);
    CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, CYASSL_CRL_MONITOR |
                                                     CYASSL_CRL_START_MON);
    CyaSSL_SetCRL_Cb(ssl, CRL_CallBack);
#endif
        osDelay(5000) ;
    tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, doDTLS);
    if (!doDTLS) 
        CloseSocket(sockfd);

    SSL_set_fd(ssl, clientfd);
    if (usePsk == 0) {
        #if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA)
            CyaSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM);
        #elif !defined(NO_CERTS)
            SetDH(ssl);  /* repick suites with DHE, higher priority than PSK */
        #endif
    }
        osDelay(5000) ;
#ifndef CYASSL_CALLBACKS
    if (nonBlocking) {
        CyaSSL_set_using_nonblock(ssl, 1);
        tcp_set_nonblocking(&clientfd);
        NonBlockingSSL_Accept(ssl);
    } else if (SSL_accept(ssl) != SSL_SUCCESS) {
        int err = SSL_get_error(ssl, 0);
        char buffer[80];
        printf("error = %d, %s\n", err, ERR_error_string(err, buffer));
        err_sys("SSL_accept failed");
    }
#else
    NonBlockingSSL_Accept(ssl);
#endif
    showPeer(ssl);
        osDelay(5000) ;
    idx = SSL_read(ssl, input, sizeof(input)-1);
    if (idx > 0) {
        input[idx] = 0;
        printf("Client message: %s\n", input);

    }
    else if (idx < 0) {
        int readErr = SSL_get_error(ssl, 0);
        if (readErr != SSL_ERROR_WANT_READ)
            err_sys("SSL_read failed");
    }

    if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg))
        err_sys("SSL_write failed");
        
    SSL_shutdown(ssl);
    SSL_free(ssl);
    SSL_CTX_free(ctx);
    
    CloseSocket(clientfd);
    ((func_args*)args)->return_code = 0;

#ifdef USE_CYASSL_MEMORY
    if (trackMemory)
        ShowMemoryTracker();
#endif /* USE_CYASSL_MEMORY */

    return 0;
}
Example #8
0
static int tport_ws_init_primary_secure(tport_primary_t *pri,
				 tp_name_t tpn[1],
				 su_addrinfo_t *ai,
				 tagi_t const *tags,
				 char const **return_culprit)
{
  tport_ws_primary_t *wspri = (tport_ws_primary_t *)pri;
  const char *cert = "/ssl.pem";
  const char *key = "/ssl.pem";
  char *homedir;
  char *tbf = NULL;
  su_home_t autohome[SU_HOME_AUTO_SIZE(1024)];
  char const *path = NULL;
  int ret = -1;

  su_home_auto(autohome, sizeof autohome);

  tl_gets(tags,
	  TPTAG_CERTIFICATE_REF(path),
	  TAG_END());

  if (!path) {
    homedir = getenv("HOME");
    if (!homedir)
      homedir = "";
    path = tbf = su_sprintf(autohome, "%s/.sip/auth", homedir);
  }

  if (path) {
    key  = su_sprintf(autohome, "%s/%s", path, "wss.key");
	if (access(key, R_OK) != 0) key = NULL;
	cert = su_sprintf(autohome, "%s/%s", path, "wss.crt");
	if (access(cert, R_OK) != 0) cert = NULL;
	if ( !key )  key  = su_sprintf(autohome, "%s/%s", path, "wss.pem");
	if ( !cert ) cert = su_sprintf(autohome, "%s/%s", path, "wss.pem");
	if (access(key, R_OK) != 0) key = NULL;
	if (access(cert, R_OK) != 0) cert = NULL;
  }

  init_ssl();

  //  OpenSSL_add_all_algorithms();   /* load & register cryptos */                                                                                       
  //  SSL_load_error_strings();     /* load all error messages */                                                                                         
  wspri->ssl_method = SSLv23_server_method();   /* create server instance */
  wspri->ssl_ctx = SSL_CTX_new((SSL_METHOD *)wspri->ssl_method);         /* create context */
  SSL_CTX_sess_set_remove_cb(wspri->ssl_ctx, NULL);
  wspri->ws_secure = 1;

  if ( !wspri->ssl_ctx ) goto done;

  /* set the local certificate from CertFile */
  SSL_CTX_use_certificate_file(wspri->ssl_ctx, cert, SSL_FILETYPE_PEM);
  /* set the private key from KeyFile */
  SSL_CTX_use_PrivateKey_file(wspri->ssl_ctx, key, SSL_FILETYPE_PEM);
  /* verify private key */
  if ( !SSL_CTX_check_private_key(wspri->ssl_ctx) ) {
	  goto done;
  }

  SSL_CTX_set_cipher_list(wspri->ssl_ctx, "HIGH:!DSS:!aNULL@STRENGTH");

  ret = tport_ws_init_primary(pri, tpn, ai, tags, return_culprit);

 done:
  su_home_zap(autohome);
  return ret;
}
Example #9
0
static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
{
	STACK_OF(SSL_CIPHER) *ciphers;
	method_const SSL_METHOD *dtls_method;
	SSL_CIPHER *dtls_cipher;
	SSL *dtls_ssl;
	BIO *dtls_bio;

	if (!vpninfo->dtls_ctx) {
		dtls_method = DTLSv1_client_method();
		vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
		if (!vpninfo->dtls_ctx) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Initialise DTLSv1 CTX failed\n"));
			openconnect_report_ssl_errors(vpninfo);
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}

		/* If we don't readahead, then we do short reads and throw
		   away the tail of data packets. */
		SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);

		if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, vpninfo->dtls_cipher)) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Set DTLS cipher list failed\n"));
			SSL_CTX_free(vpninfo->dtls_ctx);
			vpninfo->dtls_ctx = NULL;
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}
	}

	if (!vpninfo->dtls_session) {
		/* We're going to "resume" a session which never existed. Fake it... */
		vpninfo->dtls_session = SSL_SESSION_new();
		if (!vpninfo->dtls_session) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Initialise DTLSv1 session failed\n"));
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}
		vpninfo->dtls_session->ssl_version = 0x0100; /* DTLS1_BAD_VER */
	}

	/* Do this every time; it may have changed due to a rekey */
	vpninfo->dtls_session->master_key_length = sizeof(vpninfo->dtls_secret);
	memcpy(vpninfo->dtls_session->master_key, vpninfo->dtls_secret,
	       sizeof(vpninfo->dtls_secret));

	vpninfo->dtls_session->session_id_length = sizeof(vpninfo->dtls_session_id);
	memcpy(vpninfo->dtls_session->session_id, vpninfo->dtls_session_id,
	       sizeof(vpninfo->dtls_session_id));

	dtls_ssl = SSL_new(vpninfo->dtls_ctx);
	SSL_set_connect_state(dtls_ssl);

	ciphers = SSL_get_ciphers(dtls_ssl);
	if (sk_SSL_CIPHER_num(ciphers) != 1) {
		vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n"));
		SSL_CTX_free(vpninfo->dtls_ctx);
		SSL_free(dtls_ssl);
		SSL_SESSION_free(vpninfo->dtls_session);
		vpninfo->dtls_ctx = NULL;
		vpninfo->dtls_session = NULL;
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}
	dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);

	/* Set the appropriate cipher on our session to be resumed */
	vpninfo->dtls_session->cipher = dtls_cipher;
	vpninfo->dtls_session->cipher_id = dtls_cipher->id;

	/* Add the generated session to the SSL */
	if (!SSL_set_session(dtls_ssl, vpninfo->dtls_session)) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("SSL_set_session() failed with old protocol version 0x%x\n"
			       "Are you using a version of OpenSSL older than 0.9.8m?\n"
			       "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
			       "Use the --no-dtls command line option to avoid this message\n"),
			     vpninfo->dtls_session->ssl_version);
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}

	dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
	/* Set non-blocking */
	BIO_set_nbio(dtls_bio, 1);
	SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);

	SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);

	vpninfo->new_dtls_ssl = dtls_ssl;

	return 0;
}
Example #10
0
/* DTLS-SRTP initialization */
gint janus_dtls_srtp_init(const char *server_pem, const char *server_key, const char *password) {
	const char *crypto_lib = NULL;
#if JANUS_USE_OPENSSL_PRE_1_1_API
#if defined(LIBRESSL_VERSION_NUMBER)
	crypto_lib = "LibreSSL";
#else
	crypto_lib = "OpenSSL pre-1.1.0";
#endif
	/* First of all make OpenSSL thread safe (see note above on issue #316) */
	janus_dtls_locks = g_malloc0(sizeof(*janus_dtls_locks) * CRYPTO_num_locks());
	int l=0;
	for(l = 0; l < CRYPTO_num_locks(); l++) {
		janus_mutex_init(&janus_dtls_locks[l]);
	}
	CRYPTO_THREADID_set_callback(janus_dtls_cb_openssl_threadid);
	CRYPTO_set_locking_callback(janus_dtls_cb_openssl_lock);
#else
	crypto_lib = "OpenSSL >= 1.1.0";
#endif
#ifdef HAVE_BORINGSSL
	crypto_lib = "BoringSSL";
#endif
	JANUS_LOG(LOG_INFO, "Crypto: %s\n", crypto_lib);
#ifndef HAVE_SRTP_AESGCM
	JANUS_LOG(LOG_WARN, "The libsrtp installation does not support AES-GCM profiles\n");
#endif

	/* Go on and create the DTLS context */
#if JANUS_USE_OPENSSL_PRE_1_1_API
	ssl_ctx = SSL_CTX_new(DTLSv1_method());
#else
	ssl_ctx = SSL_CTX_new(DTLS_method());
#endif
	if(!ssl_ctx) {
		JANUS_LOG(LOG_FATAL, "Ops, error creating DTLS context?\n");
		return -1;
	}
	SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, janus_dtls_verify_callback);
	SSL_CTX_set_tlsext_use_srtp(ssl_ctx,
#ifdef HAVE_SRTP_AESGCM
		"SRTP_AEAD_AES_256_GCM:SRTP_AEAD_AES_128_GCM:SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32");
#else
		"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32");
#endif

	if(!server_pem && !server_key) {
		JANUS_LOG(LOG_WARN, "No cert/key specified, autogenerating some...\n");
		if(janus_dtls_generate_keys(&ssl_cert, &ssl_key) != 0) {
			JANUS_LOG(LOG_FATAL, "Error generating DTLS key/certificate\n");
			return -2;
		}
	} else if(!server_pem || !server_key) {
		JANUS_LOG(LOG_FATAL, "DTLS certificate and key must be specified\n");
		return -2;
	} else if(janus_dtls_load_keys(server_pem, server_key, password, &ssl_cert, &ssl_key) != 0) {
		return -3;
	}

	if(!SSL_CTX_use_certificate(ssl_ctx, ssl_cert)) {
		JANUS_LOG(LOG_FATAL, "Certificate error (%s)\n", ERR_reason_error_string(ERR_get_error()));
		return -4;
	}
	if(!SSL_CTX_use_PrivateKey(ssl_ctx, ssl_key)) {
		JANUS_LOG(LOG_FATAL, "Certificate key error (%s)\n", ERR_reason_error_string(ERR_get_error()));
		return -5;
	}
	if(!SSL_CTX_check_private_key(ssl_ctx)) {
		JANUS_LOG(LOG_FATAL, "Certificate check error (%s)\n", ERR_reason_error_string(ERR_get_error()));
		return -6;
	}
	SSL_CTX_set_read_ahead(ssl_ctx,1);

	unsigned int size;
	unsigned char fingerprint[EVP_MAX_MD_SIZE];
	if(X509_digest(ssl_cert, EVP_sha256(), (unsigned char *)fingerprint, &size) == 0) {
		JANUS_LOG(LOG_FATAL, "Error converting X509 structure (%s)\n", ERR_reason_error_string(ERR_get_error()));
		return -7;
	}
	char *lfp = (char *)&local_fingerprint;
	unsigned int i = 0;
	for(i = 0; i < size; i++) {
		g_snprintf(lfp, 4, "%.2X:", fingerprint[i]);
		lfp += 3;
	}
	*(lfp-1) = 0;
	JANUS_LOG(LOG_INFO, "Fingerprint of our certificate: %s\n", local_fingerprint);
	SSL_CTX_set_cipher_list(ssl_ctx, DTLS_CIPHERS);

	if(janus_dtls_bio_filter_init() < 0) {
		JANUS_LOG(LOG_FATAL, "Error initializing BIO filter\n");
		return -8;
	}

	/* Initialize libsrtp */
	if(srtp_init() != srtp_err_status_ok) {
		JANUS_LOG(LOG_FATAL, "Ops, error setting up libsrtp?\n");
		return 5;
	}
	return 0;
}
SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const string &certchainfile):
    pCtx (NULL),
    PrivateKey (NULL),
    Certificate (NULL)
{
    /* TODO: the usage of the specified private-key and cert-chain filenames only applies to
     * client-side connections at this point. Server connections currently use the default materials.
     * That needs to be fixed asap.
     * Also, in this implementation, server-side connections use statically defined X-509 defaults.
     * One thing I'm really not clear on is whether or not you have to explicitly free X509 and EVP_PKEY
     * objects when we call our destructor, or whether just calling SSL_CTX_free is enough.
     */

    if (!bLibraryInitialized) {
        bLibraryInitialized = true;
        SSL_library_init();
        OpenSSL_add_ssl_algorithms();
        OpenSSL_add_all_algorithms();
        SSL_load_error_strings();
        ERR_load_crypto_strings();

        InitializeDefaultCredentials();
    }

    bIsServer = is_server;
    pCtx = SSL_CTX_new (is_server ? SSLv23_server_method() : SSLv23_client_method());
    if (!pCtx)
        throw std::runtime_error ("no SSL context");

    SSL_CTX_set_options (pCtx, SSL_OP_ALL);
    //SSL_CTX_set_options (pCtx, (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3));

    if (is_server) {
        // The SSL_CTX calls here do NOT allocate memory.
        int e;
        if (privkeyfile.length() > 0)
            e = SSL_CTX_use_PrivateKey_file (pCtx, privkeyfile.c_str(), SSL_FILETYPE_PEM);
        else
            e = SSL_CTX_use_PrivateKey (pCtx, DefaultPrivateKey);
        assert (e > 0);
        if (certchainfile.length() > 0)
            e = SSL_CTX_use_certificate_chain_file (pCtx, certchainfile.c_str());
        else
            e = SSL_CTX_use_certificate (pCtx, DefaultCertificate);
        assert (e > 0);
    }

    SSL_CTX_set_cipher_list (pCtx, "ALL:!ADH:!LOW:!EXP:!DES-CBC3-SHA:@STRENGTH");

    if (is_server) {
        SSL_CTX_sess_set_cache_size (pCtx, 128);
        SSL_CTX_set_session_id_context (pCtx, (unsigned char*)"eventmachine", 12);
    }
    else {
        int e;
        if (privkeyfile.length() > 0) {
            e = SSL_CTX_use_PrivateKey_file (pCtx, privkeyfile.c_str(), SSL_FILETYPE_PEM);
            assert (e > 0);
        }
        if (certchainfile.length() > 0) {
            e = SSL_CTX_use_certificate_chain_file (pCtx, certchainfile.c_str());
            assert (e > 0);
        }
    }
}
Example #12
0
int main(int argc, char **argv)
{
	int port = 0;
	int messagenumber = 5;
	char local_addr[256];
	char c;
	int mclient = 1;
	unsigned char ifname[1025] = "\0";
	char peer_address[129] = "\0";
	int peer_port = PEER_DEFAULT_PORT;

	set_execdir();

	srandom((unsigned int) time(NULL));

	memset(local_addr, 0, sizeof(local_addr));

	while ((c = getopt(argc, argv, "d:p:l:n:L:m:e:r:u:w:i:k:z:vsyhcxgtS")) != -1) {
		switch (c){
		case 'z':
			RTP_PACKET_INTERVAL = atoi(optarg);
			break;
		case 'u':
			STRCPY(g_uname, optarg);
			break;
		case 'w':
			STRCPY(g_upwd, optarg);
			break;
		case 'g':
			dont_fragment = 1;
			break;
		case 'd':
			STRCPY(ifname, optarg);
			break;
		case 'x':
			default_address_family
							= STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
			break;
		case 'l':
			clmessage_length = atoi(optarg);
			break;
		case 's':
			use_send_method = 1;
			break;
		case 'n':
			messagenumber = atoi(optarg);
			break;
		case 'p':
			port = atoi(optarg);
			break;
		case 'L':
			STRCPY(local_addr, optarg);
			break;
		case 'e':
			STRCPY(peer_address, optarg);
			break;
		case 'r':
			peer_port = atoi(optarg);
			break;
		case 'v':
			clnet_verbose = 1;
			break;
		case 'h':
			hang_on = 1;
			break;
		case 'c':
			no_rtcp = 1;
			break;
		case 'm':
			mclient = atoi(optarg);
			break;
		case 'y':
			c2c = 1;
			break;
		case 't':
			use_tcp = 1;
			break;
		case 'S':
			use_secure = 1;
			break;
		case 'i':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			strcpy(cert_file,fn);
			free(fn);
			break;
		}
		case 'k':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(pkey_file,fn);
			free(fn);
			break;
		}
		default:
			fprintf(stderr, "%s\n", Usage);
			exit(1);
		}
	}

	if(port == 0) {
		if(use_secure)
			port = DEFAULT_STUN_TLS_PORT;
		else
			port = DEFAULT_STUN_PORT;
	}

	if (clmessage_length < (int) sizeof(message_info))
		clmessage_length = (int) sizeof(message_info);

	if (optind >= argc) {
		fprintf(stderr, "%s\n", Usage);
		exit(-1);
	}

	if (!c2c) {
		if (make_ioa_addr((const u08bits*) peer_address, peer_port, &peer_addr) < 0)
			return -1;
	}

	/* SSL Init ==>> */

	if(use_secure) {

		SSL_load_error_strings();
		OpenSSL_add_ssl_algorithms();

		if(use_tcp) {
			root_tls_ctx = SSL_CTX_new(TLSv1_client_method());
		} else {
#if !defined(BIO_CTRL_DGRAM_QUERY_MTU)
		  fprintf(stderr,"ERROR: DTLS is not supported.\n");
		  exit(-1);
#else
		  if(OPENSSL_VERSION_NUMBER < 0x10000000L) {
		  	TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: OpenSSL version is rather old, DTLS may not be working correctly.\n");
		  }
		  root_tls_ctx = SSL_CTX_new(DTLSv1_client_method());
#endif
		}
		SSL_CTX_set_cipher_list(root_tls_ctx, "DEFAULT");

		if (!SSL_CTX_use_certificate_file(root_tls_ctx, cert_file,
			SSL_FILETYPE_PEM)) {
			TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no certificate found!\n");
			exit(-1);
		}

		if (!SSL_CTX_use_PrivateKey_file(root_tls_ctx, pkey_file,
						SSL_FILETYPE_PEM)) {
			TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no private key found!\n");
			exit(-1);
		}

		if (!SSL_CTX_check_private_key(root_tls_ctx)) {
			TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: invalid private key!\n");
			exit(-1);
		}

		SSL_CTX_set_verify_depth(root_tls_ctx, 2);
		SSL_CTX_set_read_ahead(root_tls_ctx, 1);
	}

	start_mclient(argv[optind], port, ifname, local_addr, messagenumber, mclient);

	return 0;
}
Example #13
0
int main(int argc, char **argv)
{
	int port = 0;
	int messagenumber = 5;
	char local_addr[256];
	int c;
	int mclient = 1;
	char peer_address[129] = "\0";
	int peer_port = PEER_DEFAULT_PORT;

	char rest_api_separator = ':';
	int use_null_cipher=0;

	set_logfile("stdout");

	set_execdir();

	set_system_parameters(0);

	ns_bzero(local_addr, sizeof(local_addr));

	while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:bZvsyhcxXgtTSAPDNOUMRIGBJ")) != -1) {
		switch (c){
		case 'J': {

			oauth = 1;

			oauth_key_data okd_array[3];
			convert_oauth_key_data_raw(&okdr_array[0], &okd_array[0]);
			convert_oauth_key_data_raw(&okdr_array[1], &okd_array[1]);
			convert_oauth_key_data_raw(&okdr_array[2], &okd_array[2]);

			char err_msg[1025] = "\0";
			size_t err_msg_size = sizeof(err_msg) - 1;

			if (convert_oauth_key_data(&okd_array[0], &okey_array[0], err_msg, err_msg_size) < 0) {
				fprintf(stderr, "%s\n", err_msg);
				exit(-1);
			}

			if (convert_oauth_key_data(&okd_array[1], &okey_array[1], err_msg, err_msg_size) < 0) {
				fprintf(stderr, "%s\n", err_msg);
				exit(-1);
			}

			if (convert_oauth_key_data(&okd_array[2], &okey_array[2], err_msg, err_msg_size) < 0) {
				fprintf(stderr, "%s\n", err_msg);
				exit(-1);
			}
		}
			break;
		case 'a':
			bps = (band_limit_t)strtoul(optarg,NULL,10);
			break;
		case 'o':
			STRCPY(origin,optarg);
			break;
		case 'B':
			random_disconnect = 1;
			break;
		case 'G':
			extra_requests = 1;
			break;
		case 'F':
			STRCPY(cipher_suite,optarg);
			break;
		case 'I':
			no_permissions = 1;
			break;
		case 'M':
			mobility = 1;
			break;
		case 'E':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(ca_cert_file,fn);
		}
			break;
		case 'O':
			dos = 1;
			break;
		case 'C':
			rest_api_separator=*optarg;
			break;
		case 'D':
			mandatory_channel_padding = 1;
			break;
		case 'N':
			negative_test = 1;
			break;
		case 'R':
			negative_protocol_test = 1;
			break;
		case 'z':
			RTP_PACKET_INTERVAL = atoi(optarg);
			break;
		case 'Z':
			dual_allocation = 1;
			break;
		case 'u':
			STRCPY(g_uname, optarg);
			break;
		case 'w':
			STRCPY(g_upwd, optarg);
			break;
		case 'g':
			dont_fragment = 1;
			break;
		case 'd':
			STRCPY(client_ifname, optarg);
			break;
		case 'x':
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
			break;
		case 'X':
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
			break;
		case 'l':
			clmessage_length = atoi(optarg);
			break;
		case 's':
			do_not_use_channel = 1;
			break;
		case 'n':
			messagenumber = atoi(optarg);
			break;
		case 'p':
			port = atoi(optarg);
			break;
		case 'L':
			STRCPY(local_addr, optarg);
			break;
		case 'e':
			STRCPY(peer_address, optarg);
			break;
		case 'r':
			peer_port = atoi(optarg);
			break;
		case 'v':
			clnet_verbose = TURN_VERBOSE_NORMAL;
			break;
		case 'h':
			hang_on = 1;
			break;
		case 'c':
			no_rtcp = 1;
			break;
		case 'm':
			mclient = atoi(optarg);
			break;
		case 'y':
			c2c = 1;
			break;
		case 't':
			use_tcp = 1;
			break;
		case 'b':
			use_sctp = 1;
			use_tcp = 1;
			break;
		case 'P':
			passive_tcp = 1;
			/* implies 'T': */
			/* no break */
		case 'T':
			relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE;
			break;
		case 'U':
		  use_null_cipher = 1;
		  /* implies 'S' */
		  /* no break */
		case 'S':
			use_secure = 1;
			break;
		case 'W':
			g_use_auth_secret_with_timestamp = 1;
			STRCPY(g_auth_secret,optarg);
			break;
		case 'i':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(cert_file,fn);
			free(fn);
		}
			break;
		case 'k':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(pkey_file,fn);
			free(fn);
		}
			break;
		default:
			fprintf(stderr, "%s\n", Usage);
			exit(1);
		}
	}

	if(dual_allocation) {
		no_rtcp = 1;
	}

	if(g_use_auth_secret_with_timestamp) {

		{
			char new_uname[1025];
			const unsigned long exp_time = 3600 * 24; /* one day */
			if(g_uname[0]) {
			  snprintf(new_uname,sizeof(new_uname),"%lu%c%s",(unsigned long)time(NULL) + exp_time,rest_api_separator, (char*)g_uname);
			} else {
			  snprintf(new_uname,sizeof(new_uname),"%lu", (unsigned long)time(NULL) + exp_time);
			}
			STRCPY(g_uname,new_uname);
		}
		{
			u08bits hmac[MAXSHASIZE];
			unsigned int hmac_len;

			switch(shatype) {
			case SHATYPE_SHA256:
				hmac_len = SHA256SIZEBYTES;
				break;
			case SHATYPE_SHA384:
				hmac_len = SHA384SIZEBYTES;
				break;
			case SHATYPE_SHA512:
				hmac_len = SHA512SIZEBYTES;
				break;
			default:
				hmac_len = SHA1SIZEBYTES;
			};

			hmac[0]=0;

			if(stun_calculate_hmac(g_uname, strlen((char*)g_uname), (u08bits*)g_auth_secret, strlen(g_auth_secret), hmac, &hmac_len, shatype)>=0) {
				size_t pwd_length = 0;
				char *pwd = base64_encode(hmac,hmac_len,&pwd_length);

				if(pwd) {
					if(pwd_length>0) {
						ns_bcopy(pwd,g_upwd,pwd_length);
						g_upwd[pwd_length]=0;
					}
				}
				free(pwd);
			}
		}
	}

	if(is_TCP_relay()) {
		dont_fragment = 0;
		no_rtcp = 1;
		c2c = 1;
		use_tcp = 1;
		do_not_use_channel = 1;
	}

	if(port == 0) {
		if(use_secure)
			port = DEFAULT_STUN_TLS_PORT;
		else
			port = DEFAULT_STUN_PORT;
	}

	if (clmessage_length < (int) sizeof(message_info))
		clmessage_length = (int) sizeof(message_info);

	const int max_header = 100;
	if(clmessage_length > (int)(STUN_BUFFER_SIZE-max_header)) {
		fprintf(stderr,"Message length was corrected to %d\n",(STUN_BUFFER_SIZE-max_header));
		clmessage_length = (int)(STUN_BUFFER_SIZE-max_header);
	}

	if (optind >= argc) {
		fprintf(stderr, "%s\n", Usage);
		exit(-1);
	}

	if (!c2c) {

		if (make_ioa_addr((const u08bits*) peer_address, peer_port, &peer_addr) < 0) {
			return -1;
		}

		if(peer_addr.ss.sa_family == AF_INET6) {
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
		} else if(peer_addr.ss.sa_family == AF_INET) {
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
		}

	}

	/* SSL Init ==>> */

	if(use_secure) {

		SSL_load_error_strings();
		OpenSSL_add_ssl_algorithms();

		const char *csuite = "ALL"; //"AES256-SHA" "DH"
		if(use_null_cipher)
			csuite = "eNULL";
		else if(cipher_suite[0])
			csuite=cipher_suite;

		if(use_tcp) {
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv23_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;

		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;

#if TLSv1_1_SUPPORTED
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#if TLSv1_2_SUPPORTED
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#endif
#endif
		} else {
#if !DTLS_SUPPORTED
		  fprintf(stderr,"ERROR: DTLS is not supported.\n");
		  exit(-1);
#else
		  if(OPENSSL_VERSION_NUMBER < 0x10000000L) {
		  	TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: OpenSSL version is rather old, DTLS may not be working correctly.\n");
		  }
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#if DTLSv1_2_SUPPORTED
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_2_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#endif
#endif
		}

		int sslind = 0;
		for(sslind = 0; sslind<root_tls_ctx_num; sslind++) {

			if(cert_file[0]) {
				if (!SSL_CTX_use_certificate_chain_file(root_tls_ctx[sslind], cert_file)) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no certificate found!\n");
					exit(-1);
				}
			}

			if (!SSL_CTX_use_PrivateKey_file(root_tls_ctx[sslind], pkey_file,
						SSL_FILETYPE_PEM)) {
				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no private key found!\n");
				exit(-1);
			}

			if(cert_file[0]) {
				if (!SSL_CTX_check_private_key(root_tls_ctx[sslind])) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: invalid private key!\n");
					exit(-1);
				}
			}

			if (ca_cert_file[0]) {
				if (!SSL_CTX_load_verify_locations(root_tls_ctx[sslind], ca_cert_file, NULL )) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
							"ERROR: cannot load CA from file: %s\n",
							ca_cert_file);
				}

				/* Set to require peer (client) certificate verification */
				SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_PEER, NULL );

				/* Set the verification depth to 9 */
				SSL_CTX_set_verify_depth(root_tls_ctx[sslind], 9);
			} else {
				SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_NONE, NULL );
			}

			if(!use_tcp)
				SSL_CTX_set_read_ahead(root_tls_ctx[sslind], 1);
		}
	}

	start_mclient(argv[optind], port, client_ifname, local_addr, messagenumber, mclient);

	return 0;
}
Example #14
0
int sslConnect(SSLCon* con, const char* ip, short port, int timeoutMs) {
    ST_TIMER timer = {0,0,0};
    SSL_load_error_strings();
    SSL_library_init();
    sslContext = SSL_CTX_new(SSLv23_client_method());// modify by Daniel 20151222
    if (sslContext == NULL ){
        ERR_print_errors_fp(stderr);
        return SSLERR;
    }
    
    SSL_CTX_set_options(sslContext, SSL_OP_ALL | SSL_OP_NO_SSLv2);
    SSL_CTX_set_cipher_list(sslContext, CIPHERS_LIMIT);

    // specify cipher list
    //int iRet = SSL_CTX_set_cipher_list(sslContext,"TLSv1.2");
    //if(iRet == 0){
    //    return SSLERR;
    //}

    // load CA cert
    //iRet = SSL_CTX_load_verify_locations(sslContext, con->szCA, NULL);
    //if(iRet == 0){
    //    return SSLERR;
    //}

    // Set flag in context to require peer (server) certificate verification
    //SSL_CTX_set_verify(sslContext,SSL_VERIFY_PEER,NULL);
    //SSL_CTX_set_verify_depth(sslContext,1);
    //SSL_CTX_set_default_passwd_cb_userdata(sslContext, "1234");

    // load client cert ssl3.0
    //SSL_CTX_use_certificate_file(sslContext, con->szCert, SSL_FILETYPE_PEM);
    
    // read private key
    //SSL_CTX_use_PrivateKey_file(sslContext, con->szKey,SSL_FILETYPE_PEM);
    
    // verify
    //SSL_CTX_check_private_key(sslContext);

    bzero(con, sizeof *con);
    con->socket = tcpConnect(ip, port);
    con->sslHandle = SSL_new(sslContext);
    if (con->sslHandle == NULL ) {
        ERR_print_errors_fp(stderr);
        check1(0, SSLERR, "SSL_new failed");
    }
    if (!SSL_set_fd(con->sslHandle, con->socket)) {
        ERR_print_errors_fp(stderr);
        check1(0, SSLERR, "SSL_set_fd failed");
    }
    SSL_set_connect_state(con->sslHandle);
    int r = 0;
    int events = POLLIN | POLLOUT | POLLERR;
    OsTimerSet(&timer, timeoutMs);
    while ((r = SSL_do_handshake(con->sslHandle)) != 1 && OsTimerCheck(&timer) > 0) {
        int err = SSL_get_error(con->sslHandle, r);
        if (err == SSL_ERROR_WANT_WRITE) {
            events |= POLLOUT;
            events &= ~POLLIN;
            OsLog( LOG_ERROR, "return want write set events %d\n", events);
        }
        else if (err == SSL_ERROR_WANT_READ) {
            events |= EPOLLIN;
            events &= ~EPOLLOUT;
            OsLog( LOG_ERROR, "return want read set events %d\n", events);
        }
        else {
            OsLog( LOG_ERROR, "SSL_do_handshake return %d error %d errno %d msg %s\n", r, err, errno, strerror(errno));
            ERR_print_errors_fp(stderr);
            check1(0, SSLERR_CONNECT, "do handshake error");
        }
        struct pollfd pfd;
        pfd.fd = con->socket;
        pfd.events = events;
        do {
            r = poll(&pfd, 1, 100);
        } while (r == 0 && OsTimerCheck(&timer) > 0);
        if(errno == EAGAIN){
        	OsTimerSet(&timer, timeoutMs);
        	continue;
        }
        check1(r == 1, SSLERR_CONNECT, "poll return %d error events: %d errno %d %s\n", r, pfd.revents, errno, strerror(errno));
    }
    if(1 == r && 0 == OsTimerCheck(&timer))
    {
        return SSLERR_TIMEOUT;
    }
    OsLog( LOG_ERROR, "ssl connected \n");
    return 0;
}
Example #15
0
static int __ssl_setup(struct ast_tls_config *cfg, int client)
{
#ifndef DO_SSL
    cfg->enabled = 0;
    return 0;
#else
    int disable_ssl = 0;
    long ssl_opts = 0;

    if (!cfg->enabled) {
        return 0;
    }

    /* Get rid of an old SSL_CTX since we're about to
     * allocate a new one
     */
    if (cfg->ssl_ctx) {
        SSL_CTX_free(cfg->ssl_ctx);
        cfg->ssl_ctx = NULL;
    }

    if (client) {
#if !defined(OPENSSL_NO_SSL2) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
        if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) {
            ast_log(LOG_WARNING, "Usage of SSLv2 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n");
            cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method());
        } else
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
            if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) {
                ast_log(LOG_WARNING, "Usage of SSLv3 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n");
                cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
            } else
#endif
                if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) {
                    cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
                } else {
                    disable_ssl = 1;
                    cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
                }
    } else {
        disable_ssl = 1;
        cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
    }

    if (!cfg->ssl_ctx) {
        ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n");
        cfg->enabled = 0;
        return 0;
    }

    /* Due to the POODLE vulnerability, completely disable
     * SSLv2 and SSLv3 if we are not explicitly told to use
     * them. SSLv23_*_method supports TLSv1+.
     */
    if (disable_ssl) {
        ssl_opts |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
    }

    if (ast_test_flag(&cfg->flags, AST_SSL_SERVER_CIPHER_ORDER)) {
        ssl_opts |= SSL_OP_CIPHER_SERVER_PREFERENCE;
    }

    if (ast_test_flag(&cfg->flags, AST_SSL_DISABLE_TLSV1)) {
        ssl_opts |= SSL_OP_NO_TLSv1;
    }
#if defined(HAVE_SSL_OP_NO_TLSV1_1) && defined(HAVE_SSL_OP_NO_TLSV1_2)
    if (ast_test_flag(&cfg->flags, AST_SSL_DISABLE_TLSV11)) {
        ssl_opts |= SSL_OP_NO_TLSv1_1;
    }
    if (ast_test_flag(&cfg->flags, AST_SSL_DISABLE_TLSV12)) {
        ssl_opts |= SSL_OP_NO_TLSv1_2;
    }
#else
    ast_log(LOG_WARNING, "Your version of OpenSSL leaves you potentially vulnerable "
            "to the SSL BEAST attack. Please upgrade to OpenSSL 1.0.1 or later\n");
#endif

    SSL_CTX_set_options(cfg->ssl_ctx, ssl_opts);

    SSL_CTX_set_verify(cfg->ssl_ctx,
                       ast_test_flag(&cfg->flags, AST_SSL_VERIFY_CLIENT) ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE,
                       NULL);

    if (!ast_strlen_zero(cfg->certfile)) {
        char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile;
        if (SSL_CTX_use_certificate_chain_file(cfg->ssl_ctx, cfg->certfile) == 0) {
            if (!client) {
                /* Clients don't need a certificate, but if its setup we can use it */
                ast_log(LOG_ERROR, "TLS/SSL error loading cert file. <%s>\n", cfg->certfile);
                cfg->enabled = 0;
                SSL_CTX_free(cfg->ssl_ctx);
                cfg->ssl_ctx = NULL;
                return 0;
            }
        }
        if ((SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, tmpprivate, SSL_FILETYPE_PEM) == 0) || (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 )) {
            if (!client) {
                /* Clients don't need a private key, but if its setup we can use it */
                ast_log(LOG_ERROR, "TLS/SSL error loading private key file. <%s>\n", tmpprivate);
                cfg->enabled = 0;
                SSL_CTX_free(cfg->ssl_ctx);
                cfg->ssl_ctx = NULL;
                return 0;
            }
        }
        if (!client) {
            size_t certfile_len = strlen(cfg->certfile);

            /* expects a file name which contains _rsa. like asterisk_rsa.pem
             * ignores any 3-character file-extension like .pem, .cer, .crt
             */
            if (certfile_len >= 8 && !strncmp(cfg->certfile + certfile_len - 8, "_rsa.", 5)) {
                __ssl_setup_certs(cfg, certfile_len, "_ecc.", "ECC");
                __ssl_setup_certs(cfg, certfile_len, "_dsa.", "DSA");
            }
        }
    }
    if (!ast_strlen_zero(cfg->cipher)) {
        if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) {
            if (!client) {
                ast_log(LOG_ERROR, "TLS/SSL cipher error <%s>\n", cfg->cipher);
                cfg->enabled = 0;
                SSL_CTX_free(cfg->ssl_ctx);
                cfg->ssl_ctx = NULL;
                return 0;
            }
        }
    }
    if (!ast_strlen_zero(cfg->cafile) || !ast_strlen_zero(cfg->capath)) {
        if (SSL_CTX_load_verify_locations(cfg->ssl_ctx, S_OR(cfg->cafile, NULL), S_OR(cfg->capath,NULL)) == 0) {
            ast_log(LOG_ERROR, "TLS/SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath);
        }
    }

#ifdef HAVE_OPENSSL_EC

    if (!ast_strlen_zero(cfg->pvtfile)) {
        BIO *bio = BIO_new_file(cfg->pvtfile, "r");
        if (bio != NULL) {
            DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
            if (dh != NULL) {
                if (SSL_CTX_set_tmp_dh(cfg->ssl_ctx, dh)) {
                    long options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE;
                    options = SSL_CTX_set_options(cfg->ssl_ctx, options);
                    ast_verb(2, "TLS/SSL DH initialized, PFS cipher-suites enabled\n");
                }
                DH_free(dh);
            }
            BIO_free(bio);
        }
    }
#ifndef SSL_CTRL_SET_ECDH_AUTO
#define SSL_CTRL_SET_ECDH_AUTO 94
#endif
    /* SSL_CTX_set_ecdh_auto(cfg->ssl_ctx, on); requires OpenSSL 1.0.2 which wraps: */
    if (SSL_CTX_ctrl(cfg->ssl_ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL)) {
        ast_verb(2, "TLS/SSL ECDH initialized (automatic), faster PFS ciphers enabled\n");
    } else {
        /* enables AES-128 ciphers, to get AES-256 use NID_secp384r1 */
        EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
        if (ecdh != NULL) {
            if (SSL_CTX_set_tmp_ecdh(cfg->ssl_ctx, ecdh)) {
                ast_verb(2, "TLS/SSL ECDH initialized (secp256r1), faster PFS cipher-suites enabled\n");
            }
            EC_KEY_free(ecdh);
        }
    }

#endif /* #ifdef HAVE_OPENSSL_EC */

    ast_verb(2, "TLS/SSL certificate ok\n");	/* We should log which one that is ok. This message doesn't really make sense in production use */
    return 1;
#endif
}
Example #16
0
static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_REC *server)
{
	GIOSSLChannel *chan;
	GIOChannel *gchan;
	int fd;
	SSL *ssl;
	SSL_CTX *ctx = NULL;

	const char *mycert = server->connrec->tls_cert;
	const char *mypkey = server->connrec->tls_pkey;
	const char *mypass = server->connrec->tls_pass;
	const char *cafile = server->connrec->tls_cafile;
	const char *capath = server->connrec->tls_capath;
	const char *ciphers = server->connrec->tls_ciphers;
	gboolean verify = server->connrec->tls_verify;

	g_return_val_if_fail(handle != NULL, NULL);

	if(!ssl_inited && !irssi_ssl_init())
		return NULL;

	if(!(fd = g_io_channel_unix_get_fd(handle)))
		return NULL;

	ERR_clear_error();
	ctx = SSL_CTX_new(SSLv23_client_method());
	if (ctx == NULL) {
		g_error("Could not allocate memory for SSL context");
		return NULL;
	}
	SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
	SSL_CTX_set_default_passwd_cb(ctx, get_pem_password_callback);
	SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)mypass);

	if (ciphers != NULL && ciphers[0] != '\0') {
		if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1)
			g_warning("No valid SSL cipher suite could be selected");
	}

	if (mycert && *mycert) {
		char *scert = NULL, *spkey = NULL;
		FILE *fp;
		scert = convert_home(mycert);
		if (mypkey && *mypkey)
			spkey = convert_home(mypkey);

		if ((fp = fopen(scert, "r"))) {
			X509 *cert;
			/* Let's parse the certificate by hand instead of using
			 * SSL_CTX_use_certificate_file so that we can validate
			 * some parts of it. */
			cert = PEM_read_X509(fp, NULL, get_pem_password_callback, (void *)mypass);
			if (cert != NULL) {
				/* Only the expiration date is checked right now */
				if (X509_cmp_current_time(X509_get_notAfter(cert))  <= 0 ||
				    X509_cmp_current_time(X509_get_notBefore(cert)) >= 0)
					g_warning("The client certificate is expired");

				ERR_clear_error();
				if (! SSL_CTX_use_certificate(ctx, cert))
					g_warning("Loading of client certificate '%s' failed: %s", mycert, ERR_reason_error_string(ERR_get_error()));
				else if (! SSL_CTX_use_PrivateKey_file(ctx, spkey ? spkey : scert, SSL_FILETYPE_PEM))
					g_warning("Loading of private key '%s' failed: %s", mypkey ? mypkey : mycert, ERR_reason_error_string(ERR_get_error()));
				else if (! SSL_CTX_check_private_key(ctx))
					g_warning("Private key does not match the certificate");

				X509_free(cert);
			} else
				g_warning("Loading of client certificate '%s' failed: %s", mycert, ERR_reason_error_string(ERR_get_error()));

			fclose(fp);
		} else
			g_warning("Could not find client certificate '%s'", scert);
		g_free(scert);
		g_free(spkey);
	}

	if ((cafile && *cafile) || (capath && *capath)) {
		char *scafile = NULL;
		char *scapath = NULL;
		if (cafile && *cafile)
			scafile = convert_home(cafile);
		if (capath && *capath)
			scapath = convert_home(capath);
		if (! SSL_CTX_load_verify_locations(ctx, scafile, scapath)) {
			g_warning("Could not load CA list for verifying TLS server certificate");
			g_free(scafile);
			g_free(scapath);
			SSL_CTX_free(ctx);
			return NULL;
		}
		g_free(scafile);
		g_free(scapath);
		verify = TRUE;
	} else if (store != NULL) {
		/* Make sure to increment the refcount every time the store is
		 * used, that's essential not to get it free'd by OpenSSL when
		 * the SSL_CTX is destroyed. */
		X509_STORE_up_ref(store);
		SSL_CTX_set_cert_store(ctx, store);
	}

	if(!(ssl = SSL_new(ctx)))
	{
		g_warning("Failed to allocate SSL structure");
		SSL_CTX_free(ctx);
		return NULL;
	}

	if(!SSL_set_fd(ssl, fd))
	{
		g_warning("Failed to associate socket to SSL stream");
		SSL_free(ssl);
		SSL_CTX_free(ctx);
		return NULL;
	}

#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
	SSL_set_tlsext_host_name(ssl, server->connrec->address);
#endif

	SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE |
			SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

	chan = g_new0(GIOSSLChannel, 1);
	chan->fd = fd;
	chan->giochan = handle;
	chan->ssl = ssl;
	chan->ctx = ctx;
	chan->server = server;
	chan->port = port;
	chan->verify = verify;

	gchan = (GIOChannel *)chan;
	gchan->funcs = &irssi_ssl_channel_funcs;
	g_io_channel_init(gchan);
	gchan->is_readable = gchan->is_writeable = TRUE;
	gchan->use_buffer = FALSE;

	return gchan;
}
Example #17
0
Result<SslFd> SslFd::init(SocketFd fd, CSlice host, CSlice cert_file, VerifyPeer verify_peer) {
#if TD_WINDOWS
  return Status::Error("TODO");
#else
  static bool init_openssl = [] {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
    return OPENSSL_init_ssl(0, nullptr) != 0;
#else
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    return OpenSSL_add_ssl_algorithms() != 0;
#endif
  }();
  CHECK(init_openssl);

  openssl_clear_errors("Before SslFd::init");
  CHECK(!fd.empty());

  auto ssl_method =
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
      TLS_client_method();
#else
      SSLv23_client_method();
#endif
  if (ssl_method == nullptr) {
    return create_openssl_error(-6, "Failed to create an SSL client method");
  }

  auto ssl_ctx = SSL_CTX_new(ssl_method);
  if (ssl_ctx == nullptr) {
    return create_openssl_error(-7, "Failed to create an SSL context");
  }
  auto ssl_ctx_guard = ScopeExit() + [&]() { SSL_CTX_free(ssl_ctx); };
  long options = 0;
#ifdef SSL_OP_NO_SSLv2
  options |= SSL_OP_NO_SSLv2;
#endif
#ifdef SSL_OP_NO_SSLv3
  options |= SSL_OP_NO_SSLv3;
#endif
  SSL_CTX_set_options(ssl_ctx, options);
  SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);

  if (cert_file.empty()) {
    SSL_CTX_set_default_verify_paths(ssl_ctx);
  } else {
    if (SSL_CTX_load_verify_locations(ssl_ctx, cert_file.c_str(), nullptr) == 0) {
      return create_openssl_error(-8, "Failed to set custom cert file");
    }
  }
  if (VERIFY_PEER && verify_peer == VerifyPeer::On) {
    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, verify_callback);

    if (VERIFY_DEPTH != -1) {
      SSL_CTX_set_verify_depth(ssl_ctx, VERIFY_DEPTH);
    }
  } else {
    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, nullptr);
  }

  // TODO(now): cipher list
  string cipher_list;
  if (SSL_CTX_set_cipher_list(ssl_ctx, cipher_list.empty() ? "DEFAULT" : cipher_list.c_str()) == 0) {
    return create_openssl_error(-9, PSLICE("Failed to set cipher list \"%s\"", cipher_list.c_str()));
  }

  auto ssl_handle = SSL_new(ssl_ctx);
  if (ssl_handle == nullptr) {
    return create_openssl_error(-13, "Failed to create an SSL handle");
  }
  auto ssl_handle_guard = ScopeExit() + [&]() {
    do_ssl_shutdown(ssl_handle);
    SSL_free(ssl_handle);
  };

#if OPENSSL_VERSION_NUMBER >= 0x10002000L
  X509_VERIFY_PARAM *param = SSL_get0_param(ssl_handle);
  /* Enable automatic hostname checks */
  // TODO: X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
  X509_VERIFY_PARAM_set_hostflags(param, 0);
  X509_VERIFY_PARAM_set1_host(param, host.c_str(), 0);
#else
#warning DANGEROUS! HTTPS HOST WILL NOT BE CHECKED. INSTALL OPENSSL >= 1.0.2 OR IMPLEMENT HTTPS HOST CHECK MANUALLY
#endif

  if (!SSL_set_fd(ssl_handle, fd.get_fd().get_native_fd())) {
    return create_openssl_error(-14, "Failed to set fd");
  }

#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
  auto host_str = host.str();
  SSL_set_tlsext_host_name(ssl_handle, MutableCSlice(host_str).begin());
#endif
  SSL_set_connect_state(ssl_handle);

  ssl_ctx_guard.dismiss();
  ssl_handle_guard.dismiss();
  return SslFd(std::move(fd), ssl_handle, ssl_ctx);
#endif
}
Example #18
0
int MAIN(int argc, char **argv)
{
    int ret = 1, i;
    int verbose = 0, Verbose = 0;
    const char **pp;
    const char *p;
    int badops = 0;
    SSL_CTX *ctx = NULL;
    SSL *ssl = NULL;
    char *ciphers = NULL;
    const SSL_METHOD *meth = NULL;
    STACK_OF(SSL_CIPHER) *sk;
    char buf[512];
    BIO *STDout = NULL;

    meth = SSLv23_server_method();

    apps_startup();

    if (bio_err == NULL)
        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
    STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
    {
        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
        STDout = BIO_push(tmpbio, STDout);
    }
#endif
    if (!load_config(bio_err, NULL))
        goto end;

    argc--;
    argv++;
    while (argc >= 1) {
        if (strcmp(*argv, "-v") == 0)
            verbose = 1;
        else if (strcmp(*argv, "-V") == 0)
            verbose = Verbose = 1;
#ifndef OPENSSL_NO_SSL2
        else if (strcmp(*argv, "-ssl2") == 0)
            meth = SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3
        else if (strcmp(*argv, "-ssl3") == 0)
            meth = SSLv3_client_method();
#endif
#ifndef OPENSSL_NO_TLS1
        else if (strcmp(*argv, "-tls1") == 0)
            meth = TLSv1_client_method();
#endif
        else if ((strncmp(*argv, "-h", 2) == 0) || (strcmp(*argv, "-?") == 0)) {
            badops = 1;
            break;
        } else {
            ciphers = *argv;
        }
        argc--;
        argv++;
    }

    if (badops) {
        for (pp = ciphers_usage; (*pp != NULL); pp++)
            BIO_printf(bio_err, "%s", *pp);
        goto end;
    }

    OpenSSL_add_ssl_algorithms();

    ctx = SSL_CTX_new(meth);
    if (ctx == NULL)
        goto err;
    if (ciphers != NULL) {
        if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
            BIO_printf(bio_err, "Error in cipher list\n");
            goto err;
        }
    }
    ssl = SSL_new(ctx);
    if (ssl == NULL)
        goto err;

    if (!verbose) {
        for (i = 0;; i++) {
            p = SSL_get_cipher_list(ssl, i);
            if (p == NULL)
                break;
            if (i != 0)
                BIO_printf(STDout, ":");
            BIO_printf(STDout, "%s", p);
        }
        BIO_printf(STDout, "\n");
    } else {                    /* verbose */

        sk = SSL_get_ciphers(ssl);

        for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
            SSL_CIPHER *c;

            c = sk_SSL_CIPHER_value(sk, i);

            if (Verbose) {
                unsigned long id = SSL_CIPHER_get_id(c);
                int id0 = (int)(id >> 24);
                int id1 = (int)((id >> 16) & 0xffL);
                int id2 = (int)((id >> 8) & 0xffL);
                int id3 = (int)(id & 0xffL);

                if ((id & 0xff000000L) == 0x02000000L) {
                    /* SSL2 cipher */
                    BIO_printf(STDout, "     0x%02X,0x%02X,0x%02X - ", id1,
                               id2, id3);
                } else if ((id & 0xff000000L) == 0x03000000L) {
                    /* SSL3 cipher */
                    BIO_printf(STDout, "          0x%02X,0x%02X - ", id2,
                               id3);
                } else {
                    /* whatever */
                    BIO_printf(STDout, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0,
                               id1, id2, id3);
                }
            }

            BIO_puts(STDout, SSL_CIPHER_description(c, buf, sizeof buf));
        }
    }

    ret = 0;
    if (0) {
 err:
        SSL_load_error_strings();
        ERR_print_errors(bio_err);
    }
 end:
    if (ctx != NULL)
        SSL_CTX_free(ctx);
    if (ssl != NULL)
        SSL_free(ssl);
    if (STDout != NULL)
        BIO_free_all(STDout);
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
Example #19
0
int main_tls_client() {
  SSL_CTX *ctx;
  SSL *ssl;
  int server = 0;
  int ret;

  if ( (ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)
    printf("Unable to create a new SSL context structure.\n");

  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
  // Force gcm(aes) mode
  SSL_CTX_set_cipher_list(ctx, "ECDH-ECDSA-AES128-GCM-SHA256");

  ssl = SSL_new(ctx);

  server = create_socket();

  SSL_set_fd(ssl, server);

  if ( SSL_connect(ssl) != 1 ) {
    printf("Error: Could not build a SSL session\n");
    exit(-1);
  }

// Start tests

  clock_t start, end;
  double cpu_time_used;

  int filefd;
  int bytes;
  int totalbytes = 0;
  bytes_recv = 0;
  char buf[16384];

  int res = 0;
  int total_recv = 0;

  start = clock();

  filefd = open(test_data, O_RDONLY);
  totalbytes = 0;

  do {
    bytes = read(filefd, buf, sizeof(buf));
    totalbytes += bytes;
    if (bytes > 0)
      SSL_write(ssl, buf, bytes);
  } while(bytes > 0);

  close(filefd);


    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

    printf("OpenSSL receive time: %.02f\n", cpu_time_used);

  res = 0;
  total_recv = 0;

  res = SSL_read(ssl, buf, 1);

  total_recv += res;
  if (res < 0) {
    printf("SSL Read error: %i\n", res);
  }
  printf("Received openssl test data: %i %i\n", res, total_recv);

/* Kernel TLS tests */
  int tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
  if (tfmfd == -1) {
    perror("socket error:");
    exit(-1);
  }

  struct sockaddr_alg sa = {
    .salg_family = AF_ALG,
    .salg_type = "tls", /* this selects the hash logic in the kernel */
    .salg_name = "rfc5288(gcm(aes))" /* this is the cipher name */
  };

  if (bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
    perror("AF_ALG: bind failed");
    close(tfmfd);
    exit(-1);
  }

  int opfd = accept(tfmfd, NULL, 0);
  if (opfd == -1) {
    perror("accept:");
    close(tfmfd);
    exit(-1);
  }

  if (setsockopt(tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 16)) {
    perror("AF_ALG: set authsize failed\n");
    exit(-1);
  }

  EVP_CIPHER_CTX * writeCtx = ssl->enc_write_ctx;
  EVP_CIPHER_CTX * readCtx = ssl->enc_read_ctx;

  EVP_AES_GCM_CTX* gcmWrite = (EVP_AES_GCM_CTX*)(writeCtx->cipher_data);
  EVP_AES_GCM_CTX* gcmRead = (EVP_AES_GCM_CTX*)(readCtx->cipher_data);

  unsigned char* writeKey = (unsigned char*)(gcmWrite->gcm.key);
  unsigned char* readKey = (unsigned char*)(gcmRead->gcm.key);

  unsigned char* writeIV = gcmWrite->iv;
  unsigned char* readIV = gcmRead->iv;

  char keyiv[20];
  memcpy(keyiv, writeKey, 16);
  memcpy(keyiv + 16, writeIV, 4);

  if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, keyiv, 20)) {
    perror("AF_ALG: set write key failed\n");
    exit(-1);
  }

  memcpy(keyiv, readKey, 16);
  memcpy(keyiv + 16, readIV, 4);

  if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, keyiv, 20)) {
    perror("AF_ALG: set read key failed\n");
    exit(-1);
  }

  // Load up the cmsg data
  struct cmsghdr *header = NULL;
  uint32_t *type = NULL;
  struct msghdr msg;

  /* IV data */
  struct af_alg_iv *alg_iv = NULL;
  int ivsize = 12;
  uint32_t iv_msg_size = CMSG_SPACE(sizeof(*alg_iv) + ivsize);

  /* AEAD data */
  uint32_t *assoclen = NULL;
  uint32_t assoc_msg_size = CMSG_SPACE(sizeof(*assoclen));

  uint32_t bufferlen =
    CMSG_SPACE(sizeof(*type)) + /* Encryption / Decryption */
    iv_msg_size +/* IV */
    assoc_msg_size;/* AEAD associated data size */

  memset(&msg, 0, sizeof(msg));

  char* buffer = calloc(1, bufferlen);
  if (!buffer)
    return -ENOMEM;

  msg.msg_control = buffer;
  msg.msg_controllen = bufferlen;
  msg.msg_iov = NULL;
  msg.msg_iovlen = 0;

  /* encrypt/decrypt operation */
  header = CMSG_FIRSTHDR(&msg);
  header->cmsg_level = SOL_ALG;
  header->cmsg_type = ALG_SET_OP;
  header->cmsg_len = CMSG_LEN(sizeof(*type));
  type = (void*)CMSG_DATA(header);
  *type = server;


  /* set IV */
  header = CMSG_NXTHDR(&msg, header);
  header->cmsg_level = SOL_ALG;
  header->cmsg_type = ALG_SET_IV;
  header->cmsg_len = iv_msg_size;
  alg_iv = (void*)CMSG_DATA(header);
  alg_iv->ivlen = 8;
  uint64_t writeSeq;
  unsigned char* writeSeqNum = ssl->s3->write_sequence;
  memcpy(&writeSeq, writeSeqNum, sizeof(writeSeq));

  memcpy(alg_iv->iv, &writeSeq, 8);


  /* set AEAD information */
  /* Set associated data length */
  header = CMSG_NXTHDR(&msg, header);
  header->cmsg_level = SOL_ALG;
  header->cmsg_type = ALG_SET_AEAD_ASSOCLEN;
  header->cmsg_len = CMSG_LEN(sizeof(*assoclen));
  assoclen = (void*)CMSG_DATA(header);
  *assoclen = 13 + 8;

  ret = sendmsg(opfd, &msg, MSG_MORE);
  if (ret < 0) {
    perror("sendmsg");
    exit(-1);
  }

  header = CMSG_FIRSTHDR(&msg);
  header = CMSG_NXTHDR(&msg, header);
  alg_iv = (void*)CMSG_DATA(header);
  uint64_t readSeq;
  unsigned char* readSeqNum = ssl->s3->read_sequence;
  memcpy(&readSeq, readSeqNum, sizeof(readSeq));
  memcpy(alg_iv->iv, &readSeq, 8);

  ret = sendmsg(opfd, &msg, MSG_MORE);
  if (ret < 0) {
    perror("sendmsg recv");
    exit(-1);
  }

  // Try some simple writes

  send(opfd, buf, 10, 0);
  send(opfd, buf, 100, 0);
  send(opfd, buf, 16000, 0);
  printf("Successful send\n");

  res = 0;
  total_recv = 0;

  res = recv(opfd, &buf, 1, 0);

  total_recv += res;
  if (res < 0) {
    printf("Ktls recv error: %i\n", res);
  }
  printf("Recvd ktls test data: %i %i\n", res, total_recv);

  start = clock();
  off_t offset = 0;


  filefd = open(test_data, O_RDONLY);

  res = sendfile(opfd, filefd, &offset, totalbytes);

  close(filefd);

  end = clock();
  cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

  printf("ktls receive time: %.02f\n", cpu_time_used);

  SSL_free(ssl);
  close(server);
  SSL_CTX_free(ctx);
  return(0);
}

int OpenListener(int port)
{   int sd;
  struct sockaddr_in6 addr;

  sd = socket(PF_INET6, SOCK_STREAM, 0);
  bzero(&addr, sizeof(addr));
  addr.sin6_family = AF_INET6;
  addr.sin6_port = htons(port);
  memcpy(addr.sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any));

  if ( bind(sd, (const struct sockaddr*)&addr, sizeof(addr)) != 0 )
    {
      perror("can't bind port");
      abort();
    }
  if ( listen(sd, 10) != 0 )
    {
      perror("Can't configure listening port");
      abort();
    }
  return sd;
}
Example #20
0
/*
 * Create a new TLS_CONTEXT instance.
 *  Returns: Pointer to TLS_CONTEXT instance on success
 *           NULL on failure;
 */
TLS_CONTEXT *new_tls_context(const char *ca_certfile, const char *ca_certdir,
                             const char *certfile, const char *keyfile,
                             CRYPTO_PEM_PASSWD_CB *pem_callback,
                             const void *pem_userdata, const char *dhfile,
                             bool verify_peer)
{
   TLS_CONTEXT *ctx;
   BIO *bio;
   DH *dh;

   ctx = (TLS_CONTEXT *)malloc(sizeof(TLS_CONTEXT));

   /* Allocate our OpenSSL TLSv1 Context */
   ctx->openssl = SSL_CTX_new(TLSv1_method());

   if (!ctx->openssl) {
      openssl_post_errors(M_FATAL, _("Error initializing SSL context"));
      goto err;
   }

   /* Set up pem encryption callback */
   if (pem_callback) {
      ctx->pem_callback = pem_callback;
      ctx->pem_userdata = pem_userdata;
   } else {
      ctx->pem_callback = crypto_default_pem_callback;
      ctx->pem_userdata = NULL;
   }
   SSL_CTX_set_default_passwd_cb(ctx->openssl, tls_pem_callback_dispatch);
   SSL_CTX_set_default_passwd_cb_userdata(ctx->openssl, (void *) ctx);

   /*
    * Set certificate verification paths. This requires that at least one
    * value be non-NULL
    */
   if (ca_certfile || ca_certdir) {
      if (!SSL_CTX_load_verify_locations(ctx->openssl, ca_certfile, ca_certdir)) {
         openssl_post_errors(M_FATAL, _("Error loading certificate verification stores"));
         goto err;
      }
   } else if (verify_peer) {
      /* At least one CA is required for peer verification */
      Jmsg0(NULL, M_ERROR, 0, _("Either a certificate file or a directory must be"
                         " specified as a verification store\n"));
      goto err;
   }

   /*
    * Load our certificate file, if available. This file may also contain a
    * private key, though this usage is somewhat unusual.
    */
   if (certfile) {
      if (!SSL_CTX_use_certificate_chain_file(ctx->openssl, certfile)) {
         openssl_post_errors(M_FATAL, _("Error loading certificate file"));
         goto err;
      }
   }

   /* Load our private key. */
   if (keyfile) {
      if (!SSL_CTX_use_PrivateKey_file(ctx->openssl, keyfile, SSL_FILETYPE_PEM)) {
         openssl_post_errors(M_FATAL, _("Error loading private key"));
         goto err;
      }
   }

   /* Load Diffie-Hellman Parameters. */
   if (dhfile) {
      if (!(bio = BIO_new_file(dhfile, "r"))) {
         openssl_post_errors(M_FATAL, _("Unable to open DH parameters file"));
         goto err;
      }
      dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
      BIO_free(bio);
      if (!dh) {
         openssl_post_errors(M_FATAL, _("Unable to load DH parameters from specified file"));
         goto err;
      }
      if (!SSL_CTX_set_tmp_dh(ctx->openssl, dh)) {
         openssl_post_errors(M_FATAL, _("Failed to set TLS Diffie-Hellman parameters"));
         DH_free(dh);
         goto err;
      }
      /* Enable Single-Use DH for Ephemeral Keying */
      SSL_CTX_set_options(ctx->openssl, SSL_OP_SINGLE_DH_USE);
   }

   if (SSL_CTX_set_cipher_list(ctx->openssl, TLS_DEFAULT_CIPHERS) != 1) {
      Jmsg0(NULL, M_ERROR, 0,
             _("Error setting cipher list, no valid ciphers available\n"));
      goto err;
   }

   /* Verify Peer Certificate */
   if (verify_peer) {
      /* SSL_VERIFY_FAIL_IF_NO_PEER_CERT has no effect in client mode */
      SSL_CTX_set_verify(ctx->openssl,
                         SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                         openssl_verify_peer);
   }

   return ctx;

err:
   /* Clean up after ourselves */
   if(ctx->openssl) {
      SSL_CTX_free(ctx->openssl);
   }
   free(ctx);
   return NULL;
}
Example #21
0
File: ssl.c Project: N0NB/aprx
int ssl_create(struct ssl_t *ssl, void *data)
{
	ssl->ctx = SSL_CTX_new(SSLv23_method());
	
	if (ssl->ctx == NULL) {
		ssl_error(LOG_ERR, "ssl_create SSL_CTX_new failed");
		return -1;
	}
	
	if (SSL_CTX_set_ex_data(ssl->ctx, ssl_server_conf_index, data) == 0) {
		ssl_error(LOG_ERR, "ssl_create SSL_CTX_set_ex_data failed");
		return -1;
	}
	
	/* client side options */
	
	SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
	SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
	
	/* server side options */
	
	SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
	SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
	
	/* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
	SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
	
	SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
	SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
	SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
	
	SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
	
	SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
	
	/* SSL protocols not configurable for now */
	int protocols = SSL_PROTOCOLS;
	
	if (!(protocols & NGX_SSL_SSLv2)) {
		SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
	}
	if (!(protocols & NGX_SSL_SSLv3)) {
		SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
	}
	if (!(protocols & NGX_SSL_TLSv1)) {
		SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
	}
	
#ifdef SSL_OP_NO_TLSv1_1
	if (!(protocols & NGX_SSL_TLSv1_1)) {
		SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
	}
#endif
#ifdef SSL_OP_NO_TLSv1_2
	if (!(protocols & NGX_SSL_TLSv1_2)) {
		SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
	}
#endif

#ifdef SSL_OP_NO_COMPRESSION
	SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
#endif

#ifdef SSL_MODE_RELEASE_BUFFERS
	SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
#endif

	SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
	
	SSL_CTX_set_read_ahead(ssl->ctx, 1);
	
	SSL_CTX_set_info_callback(ssl->ctx, (void *)ssl_info_callback);
	
	if (SSL_CTX_set_cipher_list(ssl->ctx, SSL_DEFAULT_CIPHERS) == 0) {
		ssl_error(LOG_ERR, "ssl_create SSL_CTX_set_cipher_list failed");
		return -1;
	}
	
	/* prefer server-selected ciphers */
	SSL_CTX_set_options(ssl->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
	
	return 0;
}
Example #22
0
THREAD_RETURN CYASSL_THREAD server_test(void* args)
{
    SOCKET_T sockfd   = WOLFSSL_SOCKET_INVALID;
    SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID;

    wolfSSL_method_func method = NULL;
    SSL_CTX*    ctx    = 0;
    SSL*        ssl    = 0;

#ifndef WOLFSSL_ALT_TEST_STRINGS
    const char msg[] = "I hear you fa shizzle!";
#else
    const char msg[] = "I hear you fa shizzle!\n";
#endif
    char   input[80];
    int    ch;
    int    version = SERVER_DEFAULT_VERSION;
    int    doCliCertCheck = 1;
    int    useAnyAddr = 0;
    word16 port = wolfSSLPort;
    int    usePsk = 0;
    int    usePskPlus = 0;
    int    useAnon = 0;
    int    doDTLS = 0;
    int    needDH = 0;
    int    useNtruKey   = 0;
    int    nonBlocking  = 0;
    int    trackMemory  = 0;
    int    fewerPackets = 0;
    int    pkCallbacks  = 0;
    int    wc_shutdown     = 0;
    int    resume = 0;
    int    resumeCount = 0;
    int    loopIndefinitely = 0;
    int    echoData = 0;
    int    throughput = 0;
    int    minDhKeyBits  = DEFAULT_MIN_DHKEY_BITS;
    short  minRsaKeyBits = DEFAULT_MIN_RSAKEY_BITS;
    short  minEccKeyBits = DEFAULT_MIN_ECCKEY_BITS;
    int    doListen = 1;
    int    crlFlags = 0;
    int    ret;
    int    err = 0;
    char*  serverReadyFile = NULL;
    char*  alpnList = NULL;
    unsigned char alpn_opt = 0;
    char*  cipherList = NULL;
    const char* verifyCert = cliCert;
    const char* ourCert    = svrCert;
    const char* ourKey     = svrKey;
    const char* ourDhParam = dhParam;
    tcp_ready*  readySignal = NULL;
    int    argc = ((func_args*)args)->argc;
    char** argv = ((func_args*)args)->argv;

#ifdef WOLFSSL_TRUST_PEER_CERT
    const char* trustCert  = NULL;
#endif

#ifndef NO_PSK
    int sendPskIdentityHint = 1;
#endif

#ifdef HAVE_SNI
    char*  sniHostName = NULL;
#endif

#ifdef HAVE_OCSP
    int    useOcsp  = 0;
    char*  ocspUrl  = NULL;
#endif

#ifdef HAVE_WNR
    const char* wnrConfigFile = wnrConfig;
#endif

#ifdef WOLFSSL_STATIC_MEMORY
    #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \
        || defined(SESSION_CERTS)
        /* big enough to handle most cases including session certs */
        byte memory[204000];
    #else
        byte memory[80000];
    #endif
    byte memoryIO[34500]; /* max of 17k for IO buffer (TLS packet can be 16k) */
    WOLFSSL_MEM_CONN_STATS ssl_stats;
#endif

    ((func_args*)args)->return_code = -1; /* error state */

#ifdef NO_RSA
    verifyCert = (char*)cliEccCert;
    ourCert    = (char*)eccCert;
    ourKey     = (char*)eccKey;
#endif
    (void)pkCallbacks;
    (void)needDH;
    (void)ourKey;
    (void)ourCert;
    (void)ourDhParam;
    (void)verifyCert;
    (void)useNtruKey;
    (void)doCliCertCheck;
    (void)minDhKeyBits;
    (void)minRsaKeyBits;
    (void)minEccKeyBits;
    (void)alpnList;
    (void)alpn_opt;
    (void)crlFlags;
    (void)readySignal;

#ifdef CYASSL_TIRTOS
    fdOpenSession(Task_self());
#endif

#ifdef WOLFSSL_VXWORKS
    useAnyAddr = 1;
#else
    while ((ch = mygetopt(argc, argv,
                  "?jdbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) {
        switch (ch) {
            case '?' :
                Usage();
                exit(EXIT_SUCCESS);

            case 'd' :
                doCliCertCheck = 0;
                break;

            case 'b' :
                useAnyAddr = 1;
                break;

            case 's' :
                usePsk = 1;
                break;

            case 'j' :
                usePskPlus = 1;
                break;

            case 't' :
            #ifdef USE_WOLFSSL_MEMORY
                trackMemory = 1;
            #endif
                break;

            case 'n' :
                useNtruKey = 1;
                break;

            case 'u' :
                doDTLS  = 1;
                break;

            case 'f' :
                fewerPackets = 1;
                break;

            case 'R' :
                serverReadyFile = myoptarg;
                break;

            case 'r' :
                #ifndef NO_SESSION_CACHE
                    resume = 1;
                #endif
                break;

            case 'P' :
            #ifdef HAVE_PK_CALLBACKS
                pkCallbacks = 1;
            #endif
                break;

            case 'p' :
                port = (word16)atoi(myoptarg);
                break;

            case 'w' :
                wc_shutdown = 1;
                break;

            case 'v' :
                version = atoi(myoptarg);
                if (version < 0 || version > 3) {
                    Usage();
                    exit(MY_EX_USAGE);
                }
                break;

            case 'l' :
                cipherList = myoptarg;
                break;

            case 'A' :
                verifyCert = myoptarg;
                break;

            case 'c' :
                ourCert = myoptarg;
                break;

            case 'k' :
                ourKey = myoptarg;
                break;

            case 'D' :
                #ifndef NO_DH
                    ourDhParam = myoptarg;
                #endif
                break;

            case 'Z' :
                #ifndef NO_DH
                    minDhKeyBits = atoi(myoptarg);
                    if (minDhKeyBits <= 0 || minDhKeyBits > 16000) {
                        Usage();
                        exit(MY_EX_USAGE);
                    }
                #endif
                break;

            case 'N':
                nonBlocking = 1;
                break;

            case 'S' :
                #ifdef HAVE_SNI
                    sniHostName = myoptarg;
                #endif
                break;

            case 'o' :
                #ifdef HAVE_OCSP
                    useOcsp = 1;
                #endif
                break;

            case 'O' :
                #ifdef HAVE_OCSP
                    useOcsp = 1;
                    ocspUrl = myoptarg;
                #endif
                break;

            case 'a' :
                #ifdef HAVE_ANON
                    useAnon = 1;
                #endif
                break;
            case 'I':
                #ifndef NO_PSK
                    sendPskIdentityHint = 0;
                #endif
                break;

            case 'L' :
                #ifdef HAVE_ALPN
                    alpnList = myoptarg;

                    if (alpnList[0] == 'C' && alpnList[1] == ':')
                        alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
                    else if (alpnList[0] == 'F' && alpnList[1] == ':')
                        alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH;
                    else {
                        Usage();
                        exit(MY_EX_USAGE);
                    }

                    alpnList += 2;

                #endif
                break;

            case 'i' :
                loopIndefinitely = 1;
                break;

            case 'e' :
                echoData = 1;
                break;

            case 'B':
                throughput = atoi(myoptarg);
                if (throughput <= 0) {
                    Usage();
                    exit(MY_EX_USAGE);
                }
                break;

            #ifdef WOLFSSL_TRUST_PEER_CERT
            case 'E' :
                 trustCert = myoptarg;
                break;
            #endif

            case 'q' :
                #ifdef HAVE_WNR
                    wnrConfigFile = myoptarg;
                #endif
                break;

            default:
                Usage();
                exit(MY_EX_USAGE);
        }
    }

    myoptind = 0;      /* reset for test cases */
#endif /* !WOLFSSL_VXWORKS */

    /* sort out DTLS versus TLS versions */
    if (version == CLIENT_INVALID_VERSION) {
        if (doDTLS)
            version = CLIENT_DTLS_DEFAULT_VERSION;
        else
            version = CLIENT_DEFAULT_VERSION;
    }
    else {
        if (doDTLS) {
            if (version == 3)
                version = -2;
            else
                version = -1;
        }
    }

#if defined(USE_CYASSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
    if (trackMemory)
        InitMemoryTracker();
#endif

#ifdef HAVE_WNR
    if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0)
        err_sys("can't load whitewood net random config file");
#endif

    switch (version) {
#ifndef NO_OLD_TLS
    #ifdef WOLFSSL_ALLOW_SSLV3
        case 0:
            method = wolfSSLv3_server_method_ex;
            break;
    #endif

    #ifndef NO_TLS
        case 1:
            method = wolfTLSv1_server_method_ex;
            break;


        case 2:
            method = wolfTLSv1_1_server_method_ex;
            break;

        #endif
#endif

#ifndef NO_TLS
        case 3:
            method = wolfTLSv1_2_server_method_ex;
            break;
#endif

#ifdef CYASSL_DTLS
    #ifndef NO_OLD_TLS
        case -1:
            method = wolfDTLSv1_server_method_ex;
            break;
    #endif

        case -2:
            method = wolfDTLSv1_2_server_method_ex;
            break;
#endif

        default:
            err_sys("Bad SSL version");
    }

    if (method == NULL)
        err_sys("unable to get method");

#ifdef WOLFSSL_STATIC_MEMORY
    #ifdef DEBUG_WOLFSSL
    /* print off helper buffer sizes for use with static memory
     * printing to stderr incase of debug mode turned on */
    fprintf(stderr, "static memory management size = %d\n",
            wolfSSL_MemoryPaddingSz());
    fprintf(stderr, "calculated optimum general buffer size = %d\n",
            wolfSSL_StaticBufferSz(memory, sizeof(memory), 0));
    fprintf(stderr, "calculated optimum IO buffer size      = %d\n",
            wolfSSL_StaticBufferSz(memoryIO, sizeof(memoryIO),
                                                  WOLFMEM_IO_POOL_FIXED));
    #endif /* DEBUG_WOLFSSL */

    if (wolfSSL_CTX_load_static_memory(&ctx, method, memory, sizeof(memory),0,1)
            != SSL_SUCCESS)
        err_sys("unable to load static memory and create ctx");

    /* load in a buffer for IO */
    if (wolfSSL_CTX_load_static_memory(&ctx, NULL, memoryIO, sizeof(memoryIO),
                                 WOLFMEM_IO_POOL_FIXED | WOLFMEM_TRACK_STATS, 1)
            != SSL_SUCCESS)
        err_sys("unable to load static memory and create ctx");
#else
    ctx = SSL_CTX_new(method(NULL));
#endif
    if (ctx == NULL)
        err_sys("unable to get ctx");

#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
                                    defined(HAVE_POLY1305)
    if (TicketInit() != 0)
        err_sys("unable to setup Session Ticket Key context");
    wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
#endif

    if (cipherList)
        if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
            err_sys("server can't set cipher list 1");

#ifdef CYASSL_LEANPSK
    if (!usePsk) {
        usePsk = 1;
    }
#endif

#if defined(NO_RSA) && !defined(HAVE_ECC)
    if (!usePsk) {
        usePsk = 1;
    }
#endif

    if (fewerPackets)
        CyaSSL_CTX_set_group_messages(ctx);

#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
    SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif

#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
    if ((!usePsk || usePskPlus) && !useAnon) {
        if (SSL_CTX_use_certificate_chain_file(ctx, ourCert)
                                         != SSL_SUCCESS)
            err_sys("can't load server cert file, check file and run from"
                    " wolfSSL home dir");
    }
#endif

#ifndef NO_DH
    if (wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits) != SSL_SUCCESS) {
        err_sys("Error setting minimum DH key size");
    }
#endif
#ifndef NO_RSA
    if (wolfSSL_CTX_SetMinRsaKey_Sz(ctx, minRsaKeyBits) != SSL_SUCCESS){
        err_sys("Error setting minimum RSA key size");
    }
#endif
#ifdef HAVE_ECC
    if (wolfSSL_CTX_SetMinEccKey_Sz(ctx, minEccKeyBits) != SSL_SUCCESS){
        err_sys("Error setting minimum ECC key size");
    }
#endif

#ifdef HAVE_NTRU
    if (useNtruKey) {
        if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey)
                                != SSL_SUCCESS)
            err_sys("can't load ntru key file, "
                    "Please run from wolfSSL home dir");
    }
#endif
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
    if (!useNtruKey && (!usePsk || usePskPlus) && !useAnon) {
        if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM)
                                         != SSL_SUCCESS)
            err_sys("can't load server private key file, check file and run "
                "from wolfSSL home dir");
    }
#endif

    if (usePsk || usePskPlus) {
#ifndef NO_PSK
        SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb);

        if (sendPskIdentityHint == 1)
            SSL_CTX_use_psk_identity_hint(ctx, "cyassl server");

        if (cipherList == NULL && !usePskPlus) {
            const char *defaultCipherList;
            #if defined(HAVE_AESGCM) && !defined(NO_DH)
                defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
                needDH = 1;
            #elif defined(HAVE_NULL_CIPHER)
                defaultCipherList = "PSK-NULL-SHA256";
            #else
                defaultCipherList = "PSK-AES128-CBC-SHA256";
            #endif
            if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS)
                err_sys("server can't set cipher list 2");
        }
#endif
    }

    if (useAnon) {
#ifdef HAVE_ANON
        CyaSSL_CTX_allow_anon_cipher(ctx);
        if (cipherList == NULL) {
            if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != SSL_SUCCESS)
                err_sys("server can't set cipher list 4");
        }
#endif
    }

#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
    /* if not using PSK, verify peer with certs
       if using PSK Plus then verify peer certs except PSK suites */
    if (doCliCertCheck && (usePsk == 0 || usePskPlus) && useAnon == 0) {
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER |
                                ((usePskPlus)? SSL_VERIFY_FAIL_EXCEPT_PSK :
                                SSL_VERIFY_FAIL_IF_NO_PEER_CERT),0);
        if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS)
            err_sys("can't load ca file, Please run from wolfSSL home dir");
        #ifdef WOLFSSL_TRUST_PEER_CERT
        if (trustCert) {
            if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert,
                                            SSL_FILETYPE_PEM)) != SSL_SUCCESS) {
                err_sys("can't load trusted peer cert file");
            }
        }
        #endif /* WOLFSSL_TRUST_PEER_CERT */
   }
#endif

#if defined(CYASSL_SNIFFER)
    /* don't use EDH, can't sniff tmp keys */
    if (cipherList == NULL) {
        if (SSL_CTX_set_cipher_list(ctx, "AES128-SHA") != SSL_SUCCESS)
            err_sys("server can't set cipher list 3");
    }
#endif

#ifdef HAVE_SNI
    if (sniHostName)
        if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName,
                                           XSTRLEN(sniHostName)) != SSL_SUCCESS)
            err_sys("UseSNI failed");
#endif

#ifdef USE_WINDOWS_API
    if (port == 0) {
        /* Generate random port for testing */
        port = GetRandomPort();
    }
#endif /* USE_WINDOWS_API */

    while (1) {
        /* allow resume option */
        if(resumeCount > 1) {
            if (doDTLS == 0) {
                SOCKADDR_IN_T client;
                socklen_t client_len = sizeof(client);
                clientfd = accept(sockfd, (struct sockaddr*)&client,
                                 (ACCEPT_THIRD_T)&client_len);
            } else {
                tcp_listen(&sockfd, &port, useAnyAddr, doDTLS);
                clientfd = sockfd;
            }
            if(WOLFSSL_SOCKET_IS_INVALID(clientfd)) {
                err_sys("tcp accept failed");
            }
        }
#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL)
    {
        WOLFSSL_MEM_STATS mem_stats;
        fprintf(stderr, "Before creating SSL\n");
        if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1)
            err_sys("ctx not using static memory");
        if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */
            err_sys("error printing out memory stats");
    }
#endif

        ssl = SSL_new(ctx);
        if (ssl == NULL)
            err_sys("unable to get SSL");

#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL)
    {
        WOLFSSL_MEM_STATS mem_stats;
        fprintf(stderr, "After creating SSL\n");
        if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1)
            err_sys("ctx not using static memory");
        if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */
            err_sys("error printing out memory stats");
    }
#endif

#ifndef NO_HANDSHAKE_DONE_CB
        wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL);
#endif
#ifdef HAVE_CRL
#ifdef HAVE_CRL_MONITOR
        crlFlags = CYASSL_CRL_MONITOR | CYASSL_CRL_START_MON;
#endif
        if (CyaSSL_EnableCRL(ssl, 0) != SSL_SUCCESS)
            err_sys("unable to enable CRL");
        if (CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, crlFlags)
                                                                 != SSL_SUCCESS)
            err_sys("unable to load CRL");
        if (CyaSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS)
            err_sys("unable to set CRL callback url");
#endif
#ifdef HAVE_OCSP
        if (useOcsp) {
            if (ocspUrl != NULL) {
                CyaSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
                CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE
                                                        | CYASSL_OCSP_URL_OVERRIDE);
            }
            else
                CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE);
        }
#endif
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
 || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
        if (wolfSSL_CTX_EnableOCSPStapling(ctx) != SSL_SUCCESS)
            err_sys("can't enable OCSP Stapling Certificate Manager");
        if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate1-ca-cert.pem", 0) != SSL_SUCCESS)
            err_sys("can't load ca file, Please run from wolfSSL home dir");
        if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate2-ca-cert.pem", 0) != SSL_SUCCESS)
            err_sys("can't load ca file, Please run from wolfSSL home dir");
        if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate3-ca-cert.pem", 0) != SSL_SUCCESS)
            err_sys("can't load ca file, Please run from wolfSSL home dir");
#endif
#ifdef HAVE_PK_CALLBACKS
        if (pkCallbacks)
            SetupPkCallbacks(ctx, ssl);
#endif

        /* do accept */
        readySignal = ((func_args*)args)->signal;
        if (readySignal) {
            readySignal->srfName = serverReadyFile;
        }
        tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr,
                       doDTLS, serverReadyFile ? 1 : 0, doListen);
        doListen = 0; /* Don't listen next time */

        if (SSL_set_fd(ssl, clientfd) != SSL_SUCCESS) {
            err_sys("error in setting fd");
        }

#ifdef HAVE_ALPN
        if (alpnList != NULL) {
            printf("ALPN accepted protocols list : %s\n", alpnList);
            wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt);
        }
#endif

#ifdef WOLFSSL_DTLS
        if (doDTLS) {
            SOCKADDR_IN_T cliaddr;
            byte          b[1500];
            int           n;
            socklen_t     len = sizeof(cliaddr);

            /* For DTLS, peek at the next datagram so we can get the client's
             * address and set it into the ssl object later to generate the
             * cookie. */
            n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK,
                              (struct sockaddr*)&cliaddr, &len);
            if (n <= 0)
                err_sys("recvfrom failed");

            wolfSSL_dtls_set_peer(ssl, &cliaddr, len);
        }
#endif
        if ((usePsk == 0 || usePskPlus) || useAnon == 1 || cipherList != NULL
                                                               || needDH == 1) {
            #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN)
                CyaSSL_SetTmpDH_file(ssl, ourDhParam, SSL_FILETYPE_PEM);
            #elif !defined(NO_DH)
                SetDH(ssl);  /* repick suites with DHE, higher priority than PSK */
            #endif
        }

#ifndef CYASSL_CALLBACKS
        if (nonBlocking) {
            CyaSSL_set_using_nonblock(ssl, 1);
            tcp_set_nonblocking(&clientfd);
        }
#endif

        do {
#ifdef WOLFSSL_ASYNC_CRYPT
            if (err == WC_PENDING_E) {
                ret = AsyncCryptPoll(ssl);
                if (ret < 0) { break; } else if (ret == 0) { continue; }
            }
#endif

            err = 0; /* Reset error */
#ifndef CYASSL_CALLBACKS
            if (nonBlocking) {
                ret = NonBlockingSSL_Accept(ssl);
            }
            else {
                ret = SSL_accept(ssl);
            }
#else
            ret = NonBlockingSSL_Accept(ssl);
#endif
            if (ret != SSL_SUCCESS) {
                err = SSL_get_error(ssl, 0);
            }
        } while (ret != SSL_SUCCESS && err == WC_PENDING_E);

        if (ret != SSL_SUCCESS) {
            char buffer[CYASSL_MAX_ERROR_SZ];
            err = SSL_get_error(ssl, 0);
            printf("error = %d, %s\n", err, ERR_error_string(err, buffer));
            err_sys("SSL_accept failed");
        }

        showPeer(ssl);

#ifdef HAVE_ALPN
        if (alpnList != NULL) {
            char *protocol_name = NULL, *list = NULL;
            word16 protocol_nameSz = 0, listSz = 0;

            err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz);
            if (err == SSL_SUCCESS)
                printf("Sent ALPN protocol : %s (%d)\n",
                       protocol_name, protocol_nameSz);
            else if (err == SSL_ALPN_NOT_FOUND)
                printf("No ALPN response sent (no match)\n");
            else
                printf("Getting ALPN protocol name failed\n");

            err = wolfSSL_ALPN_GetPeerProtocol(ssl, &list, &listSz);
            if (err == SSL_SUCCESS)
                printf("List of protocol names sent by Client: %s (%d)\n",
                       list, listSz);
            else
                printf("Get list of client's protocol name failed\n");

            free(list);
        }
#endif
        if(echoData == 0 && throughput == 0) {
            ret = SSL_read(ssl, input, sizeof(input)-1);
            if (ret > 0) {
                input[ret] = 0;
                printf("Client message: %s\n", input);

            }
            else if (ret < 0) {
                int readErr = SSL_get_error(ssl, 0);
                if (readErr != SSL_ERROR_WANT_READ)
                    err_sys("SSL_read failed");
            }

            if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg))
                err_sys("SSL_write failed");
        }
        else {
            ServerEchoData(ssl, clientfd, echoData, throughput);
        }

#if defined(WOLFSSL_MDK_SHELL) && defined(HAVE_MDK_RTX)
        os_dly_wait(500) ;
#elif defined (CYASSL_TIRTOS)
        Task_yield();
#endif

        if (doDTLS == 0) {
            ret = SSL_shutdown(ssl);
            if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
                SSL_shutdown(ssl);    /* bidirectional shutdown */
        }
        /* display collected statistics */
#ifdef WOLFSSL_STATIC_MEMORY
        if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1)
            err_sys("static memory was not used with ssl");

        fprintf(stderr, "\nprint off SSL memory stats\n");
        fprintf(stderr, "*** This is memory state before wolfSSL_free is called\n");
        fprintf(stderr, "peak connection memory = %d\n", ssl_stats.peakMem);
        fprintf(stderr, "current memory in use  = %d\n", ssl_stats.curMem);
        fprintf(stderr, "peak connection allocs = %d\n", ssl_stats.peakAlloc);
        fprintf(stderr, "current connection allocs = %d\n",ssl_stats.curAlloc);
        fprintf(stderr, "total connection allocs   = %d\n",ssl_stats.totalAlloc);
        fprintf(stderr, "total connection frees    = %d\n\n", ssl_stats.totalFr);

#endif
        SSL_free(ssl);

        CloseSocket(clientfd);

        if (resume == 1 && resumeCount == 0) {
            resumeCount++;           /* only do one resume for testing */
            continue;
        }
        resumeCount = 0;

        if(!loopIndefinitely) {
            break;  /* out of while loop, done with normal and resume option */
        }
    } /* while(1) */


    CloseSocket(sockfd);
    SSL_CTX_free(ctx);

    ((func_args*)args)->return_code = 0;


#if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \
                            && defined(HAVE_THREAD_LS)
    ecc_fp_free();  /* free per thread cache */
#endif

#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
    if (trackMemory)
        ShowMemoryTracker();
#endif

#ifdef CYASSL_TIRTOS
    fdCloseSession(Task_self());
#endif

#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
                                    defined(HAVE_POLY1305)
    TicketCleanup();
#endif

    /* There are use cases  when these assignments are not read. To avoid
     * potential confusion those warnings have been handled here.
     */
    (void) ourKey;
    (void) verifyCert;
    (void) doCliCertCheck;
    (void) useNtruKey;
    (void) ourDhParam;
    (void) ourCert;
    (void) trackMemory;
#ifndef CYASSL_TIRTOS
    return 0;
#endif
}
static ngx_int_t
ngx_http_lua_set_ssl(ngx_conf_t *cf, ngx_http_lua_loc_conf_t *llcf)
{
    ngx_pool_cleanup_t  *cln;

    llcf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
    if (llcf->ssl == NULL) {
        return NGX_ERROR;
    }

    llcf->ssl->log = cf->log;

    if (ngx_ssl_create(llcf->ssl, llcf->ssl_protocols, NULL) != NGX_OK) {
        return NGX_ERROR;
    }

    cln = ngx_pool_cleanup_add(cf->pool, 0);
    if (cln == NULL) {
        return NGX_ERROR;
    }

    cln->handler = ngx_ssl_cleanup_ctx;
    cln->data = llcf->ssl;

    if (SSL_CTX_set_cipher_list(llcf->ssl->ctx,
                                (const char *) llcf->ssl_ciphers.data)
        == 0)
    {
        ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
                      "SSL_CTX_set_cipher_list(\"%V\") failed",
                      &llcf->ssl_ciphers);
        return NGX_ERROR;
    }

    if (llcf->ssl_trusted_certificate.len) {

#if defined(nginx_version) && nginx_version >= 1003007

        if (ngx_ssl_trusted_certificate(cf, llcf->ssl,
                                        &llcf->ssl_trusted_certificate,
                                        llcf->ssl_verify_depth)
            != NGX_OK)
        {
            return NGX_ERROR;
        }

#else

        ngx_log_error(NGX_LOG_CRIT, cf->log, 0, "at least nginx 1.3.7 is "
                      "required for the \"lua_ssl_trusted_certificate\" "
                      "directive");
        return NGX_ERROR;

#endif
    }

    dd("ssl crl: %.*s", (int) llcf->ssl_crl.len, llcf->ssl_crl.data);

    if (ngx_ssl_crl(cf, llcf->ssl, &llcf->ssl_crl) != NGX_OK) {
        return NGX_ERROR;
    }

    return NGX_OK;
}
Example #24
0
extern	SSL_CTX	*
MakeSSL_CTX(
	char	*key,
	char	*cert,
	char	*cafile,
	char	*capath,
	char	*ciphers)
{
	SSL_CTX *ctx = NULL;
	int	 mode = SSL_VERIFY_NONE;

	if ((ctx = SSL_CTX_new(SSLv23_method())) == NULL){
		SSL_Error(_d("SSL_CTX_new failure:\n %s\n"), GetSSLErrorString());
		return NULL;
	}

	SSL_CTX_set_default_passwd_cb(ctx, passphrase_callback);
	SSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)ASKPASS_PROMPT);

	if (!SSL_CTX_set_cipher_list(ctx, ciphers)){
		SSL_Error(_d("SSL_CTX_set_cipher_list(%s) failure:\n %s\n"),
				ciphers, GetSSLErrorString());
		SSL_CTX_free(ctx);
		return NULL;
	}

	mode = SSL_VERIFY_PEER;
	mode |= SSL_VERIFY_CLIENT_ONCE;
	SSL_CTX_set_verify(ctx, mode, RemoteVerifyCallBack);
	SSL_CTX_set_options(ctx, SSL_OP_ALL);

	if ((cafile == NULL) && (capath == NULL)){
		if (!SSL_CTX_set_default_verify_paths(ctx)){
			SSL_Error(_d("SSL_CTX_set_default_verify_paths error:\n %s\n"),
					GetSSLErrorString());
		}
	}
	else if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)){
		if (cafile == NULL) cafile = capath;
		SSL_Error(_d("SSL_CTX_load_verify_locations(%s)\n"), cafile);
		SSL_CTX_free(ctx);
		return NULL;
	}

	if (cert != NULL){
		if (IsPKCS12(cert)){
			if (LoadPKCS12(ctx, cert)){
				return ctx;
			}
			else {
				SSL_CTX_free(ctx);
				return NULL; 
			}
		}
		else {
			if (SSL_CTX_use_certificate_file_with_check(ctx, cert, SSL_FILETYPE_PEM) <= 0){
				SSL_Error(_d("SSL_CTX_use_certificate_file(%s) failure:\n %s\n"),
						cert, GetSSLErrorString());
				SSL_CTX_free(ctx);
				return NULL;
			}
			if (key == NULL) key = cert;
			for (;;){ 
				if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0){
					int err_reason;
					err_reason = ERR_GET_REASON(ERR_peek_error());
					SSL_Error(_d("SSL_CTX_use_PrivateKey_file(%s) failure:\n %s\n"),
							key, GetSSLErrorString());
					if (err_reason == PEM_R_BAD_DECRYPT ||
						err_reason == EVP_R_BAD_DECRYPT) continue;
					SSL_CTX_free(ctx);
					return NULL;
				}
				break;
			}
			if (!SSL_CTX_check_private_key(ctx)){
				SSL_Error(_d("SSL_CTX_check_private_key failure:\n %s\n"),
						GetSSLErrorString());
				SSL_CTX_free(ctx);
				return NULL;
			}
		}
	} else {
		SSL_Error(_d("Please specify certificate file"));
		return NULL;
	}

	return ctx;
}
Example #25
0
int
__bro_openssl_init(void)
{
  static int deja_vu = FALSE;
  int use_ssl = FALSE;
  const char *our_cert, *our_key, *our_pass, *ca_cert;
  
  D_ENTER;

  if (deja_vu)
    D_RETURN_(TRUE);

  deja_vu = TRUE;

  /* I hope these should go before SSL_library_init() -- not even the
   * O'Reilly book is clear on that. :( --cpk
   */
  if (global_ctx)
    {
      if (global_ctx->id_func)
	CRYPTO_set_id_callback(global_ctx->id_func);
      if (global_ctx->lock_func)
	CRYPTO_set_locking_callback(global_ctx->lock_func);
      if (global_ctx->dl_create_func)
	CRYPTO_set_dynlock_create_callback(global_ctx->dl_create_func);
      if (global_ctx->dl_lock_func)
	CRYPTO_set_dynlock_lock_callback(global_ctx->dl_lock_func);
      if (global_ctx->dl_free_func)
	CRYPTO_set_dynlock_destroy_callback(global_ctx->dl_free_func);
    }
  
  SSL_library_init();
  prng_init();
  
#ifdef BRO_DEBUG
  D(("Loading OpenSSL error strings for debugging\n"));
  SSL_load_error_strings();
#endif

  if (__bro_conf_get_int("/broccoli/use_ssl", &use_ssl) && ! use_ssl)
    {
      D(("SSL disabled in configuration, not using SSL.\n"));
      D_RETURN_(TRUE);
    }

  our_cert = __bro_conf_get_str("/broccoli/host_cert");
  our_key = __bro_conf_get_str("/broccoli/host_key");
  if (our_key == NULL)
    {
    /* No private key configured; get it from the certificate file */
    our_key = our_cert;
    }

  if (our_cert == NULL)
    {
      if (use_ssl)
	{
	  D(("SSL requested but host certificate not given -- aborting.\n"));
	  D_RETURN_(FALSE);
	}
      else
	{
	  D(("use_ssl not used and host certificate not given -- not using SSL.\n"));
	  D_RETURN_(TRUE);
	}
    }

  if (our_key == NULL)
    {
      if (use_ssl)
	{
	  D(("SSL requested but host key not given -- aborting.\n"));
	  D_RETURN_(FALSE);
	}
      else
	{
	  D(("use_ssl not used and host key not given -- not using SSL.\n"));
	  D_RETURN_(TRUE);
	}
    }


  /* At this point we either haven't seen use_ssl but a host_cert, or
   * we have seen use_ssl and it is set to true. Either way, we attempt
   * to set up an SSL connection now and abort if this fails in any way.
   */

  if (! (ctx = SSL_CTX_new(SSLv3_method())))
    D_RETURN_(FALSE);
  
  /* We expect things to be stored in PEM format, which means that we
   * can store multiple entities in one file. In this case, our own
   * certificate is expected to be stored along with the private key
   * in the file pointed to by preference setting /broccoli/certificate.
   *
   * See page 121 in O'Reilly's OpenSSL book for details.
   */
  if (SSL_CTX_use_certificate_chain_file(ctx, our_cert) != 1)
    {
      D(("Error loading certificate from '%s'.\n", our_cert));
      goto error_return;
    }
  
  if ( (our_pass = __bro_conf_get_str("/broccoli/host_pass")))
    {
      D(("Host passphrase given in config file, not prompting for input.\n"));
      SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
      SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) our_pass);
    }
  
  if (SSL_CTX_use_PrivateKey_file(ctx, our_key, SSL_FILETYPE_PEM) != 1)
    {
      D(("SSL used but error loading private key from '%s' -- aborting.\n", our_key));
      goto error_return;
    }
  
  /* We should not need the passphrase, if existant, ever again.
   * Therefore we erase it from memory now.
   */
  if (our_pass)
    {
      our_pass = NULL;
      __bro_conf_forget_item("/broccoli/host_pass");
    }

  /* For validation purposes, our trusted CA's certificate will
   * be needed as well:
   */
  if (! (ca_cert = __bro_conf_get_str("/broccoli/ca_cert")))
    {
      D(("SSL used but CA certificate not given -- aborting."));
      goto error_return;
    }
  
  if (! SSL_CTX_load_verify_locations(ctx, ca_cert, 0))
    {
      D(("SSL used but CA certificate could not be loaded -- aborting\n"));
      goto error_return;
    }
  
  /* Check the consistency of the certificate vs. the private key */
  if (SSL_CTX_check_private_key(ctx) != 1)
    {
      D(("SSL used but private key does not match the certificate -- aborting\n"));
      goto error_return;
    }
  
  /* Only use real ciphers.
   */
  if (! SSL_CTX_set_cipher_list(ctx, "HIGH"))
    {
      D(("SSL used but can't set cipher list -- aborting\n"));
      goto error_return;
    }
  
  /* We require certificates from all communication peers, regardless of
   * whether we're the "server" or "client" (these concepts are blurred in our
   * case anyway). In order to be able to give better error feedback, we
   * add our own verification filter callback, "verify_cb".
   */
  SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
		     verify_cb);
  
  D(("SSL setup successful.\n"));
  D_RETURN_(TRUE);
  
 error_return:
  SSL_CTX_free(ctx);
  ctx = NULL;
  D_RETURN_(FALSE);
}
Example #26
0
/**
 * @warning Make sure you've called CryptoInitialize() first!
 */
bool ServerTLSInitialize()
{
    int ret;

    /* OpenSSL is needed for our new protocol over TLS. */
    SSL_library_init();
    SSL_load_error_strings();

    assert(SSLSERVERCONTEXT == NULL);
    SSLSERVERCONTEXT = SSL_CTX_new(SSLv23_server_method());
    if (SSLSERVERCONTEXT == NULL)
    {
        Log(LOG_LEVEL_ERR, "SSL_CTX_new: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err1;
    }

    /* Use only TLS v1 or later.
       TODO option for SSL_OP_NO_TLSv{1,1_1} */
    SSL_CTX_set_options(SSLSERVERCONTEXT,
                        SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

    /*
     * CFEngine is not a web server so we don't need many ciphers. We only
     * allow a safe but very common subset by default, extensible via
     * "allowciphers" in body server control. By default allow:
     *     AES256-GCM-SHA384: most high-grade RSA-based cipher from TLSv1.2
     *     AES256-SHA: most backwards compatible but high-grade, from SSLv3
     */
    const char *cipher_list = SV.allowciphers;
    if (cipher_list == NULL)
        cipher_list ="AES256-GCM-SHA384:AES256-SHA";
    ret = SSL_CTX_set_cipher_list(SSLSERVERCONTEXT, cipher_list);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR,
            "No valid ciphers in cipher list: %s",
            cipher_list);
    }

    /* Never bother with retransmissions, SSL_write() should
     * always either write the whole amount or fail. */
    SSL_CTX_set_mode(SSLSERVERCONTEXT, SSL_MODE_AUTO_RETRY);

    /*
     * Create cert into memory and load it into SSL context.
     */

    if (PRIVKEY == NULL || PUBKEY == NULL)
    {
        Log(LOG_LEVEL_ERR,
            "No public/private key pair is loaded, create one with cf-key");
        goto err2;
    }
    assert(SSLSERVERCERT == NULL);
    /* Generate self-signed cert valid from now to 50 years later. */
    {
        X509 *x509 = X509_new();
        X509_gmtime_adj(X509_get_notBefore(x509), 0);
        X509_time_adj(X509_get_notAfter(x509), 60*60*24*365*50, NULL);
        EVP_PKEY *pkey = EVP_PKEY_new();
        EVP_PKEY_set1_RSA(pkey, PRIVKEY);
        X509_NAME *name = X509_get_subject_name(x509);
        X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                                   (const char *) "",
                                   -1, -1, 0);
        X509_set_issuer_name(x509, name);
        X509_set_pubkey(x509, pkey);

        const EVP_MD *md = EVP_get_digestbyname("sha384");
        if (md == NULL)
        {
            Log(LOG_LEVEL_ERR, "Uknown digest algorithm %s",
                "sha384");
            return false;
        }
        ret = X509_sign(x509, pkey, md);

        EVP_PKEY_free(pkey);
        SSLSERVERCERT = x509;

        if (ret <= 0)
        {
            Log(LOG_LEVEL_ERR,
                "Couldn't sign the public key for the TLS handshake: %s",
                ERR_reason_error_string(ERR_get_error()));
            goto err3;
        }
    }

    SSL_CTX_use_certificate(SSLSERVERCONTEXT, SSLSERVERCERT);

    ret = SSL_CTX_use_RSAPrivateKey(SSLSERVERCONTEXT, PRIVKEY);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR, "Failed to use RSA private key: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err3;
    }

    /* Verify cert consistency. */
    ret = SSL_CTX_check_private_key(SSLSERVERCONTEXT);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR, "Inconsistent key and TLS cert: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err3;
    }

    /* Set options to always request a certificate from the peer, either we
     * are client or server. */
    SSL_CTX_set_verify(SSLSERVERCONTEXT, SSL_VERIFY_PEER, NULL);
    /* Always accept that certificate, we do proper checking after TLS
     * connection is established since OpenSSL can't pass a connection
     * specific pointer to the callback (so we would have to lock).  */
    SSL_CTX_set_cert_verify_callback(SSLSERVERCONTEXT, TLSVerifyCallback, NULL);

    return true;

  err3:
    X509_free(SSLSERVERCERT);
    SSLSERVERCERT = NULL;
  err2:
    SSL_CTX_free(SSLSERVERCONTEXT);
    SSLSERVERCONTEXT = NULL;
  err1:
    return false;
}
Example #27
0
SSL *SSLSocket::createSSL(SSL_CTX *ctx) {
  ERR_clear_error();

  /* look at options in the stream and set appropriate verification flags */
  if (m_context[s_verify_peer].toBoolean()) {
    /* turn on verification callback */
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verifyCallback);

    /* CA stuff */
    String cafile = m_context[s_cafile].toString();
    String capath = m_context[s_capath].toString();

    if (!FileUtil::isValidPath(cafile)) {
      raise_warning("cafile expected to be a path, string given");
      return nullptr;
    } else if (!FileUtil::isValidPath(capath)) {
      raise_warning("capath expected to be a path, string given");
      return nullptr;
    } else if (!cafile.empty() || !capath.empty()) {
      const char* cafileptr = cafile.empty() ? nullptr : cafile.data();
      const char* capathptr = capath.empty() ? nullptr : capath.data();
      if (!SSL_CTX_load_verify_locations(ctx, cafileptr, capathptr)) {
        raise_warning("Unable to set verify locations `%s' `%s'",
                      cafile.data(), capath.data());
        return nullptr;
      }
    } else if (m_data->m_client && !SSL_CTX_set_default_verify_paths(ctx)) {
      raise_warning(
        "Unable to set default verify locations and no CA settings specified");
      return nullptr;
    }

    int64_t depth = m_context[s_verify_depth].toInt64();
    if (depth) {
      SSL_CTX_set_verify_depth(ctx, depth);
    }
  } else {
    SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr);
  }

  /* callback for the passphrase (for localcert) */
  if (!m_context[s_passphrase].toString().empty()) {
    SSL_CTX_set_default_passwd_cb_userdata(ctx, this);
    SSL_CTX_set_default_passwd_cb(ctx, passwdCallback);
  }

  String cipherlist = m_context[s_ciphers].toString();
  if (cipherlist.empty()) {
    cipherlist = "DEFAULT";
  }
  SSL_CTX_set_cipher_list(ctx, cipherlist.data());

  String certfile = m_context[s_local_cert].toString();
  if (!FileUtil::isValidPath(certfile)) {
    raise_warning("local_cert expected to be a path, string given");
    return nullptr;
  } else if (!certfile.empty()) {
    String resolved_path_buff = File::TranslatePath(certfile);
    if (!resolved_path_buff.empty()) {
      /* a certificate to use for authentication */
      if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff.data())
          != 1) {
        raise_warning("Unable to set local cert chain file `%s'; Check "
                      "that your cafile/capath settings include details of "
                      "your certificate and its issuer", certfile.data());
        return nullptr;
      }

      if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff.data(),
                                      SSL_FILETYPE_PEM) != 1) {
        raise_warning("Unable to set private key file `%s'",
                      resolved_path_buff.data());
        return nullptr;
      }

      SSL *tmpssl = SSL_new(ctx);
      X509 *cert = SSL_get_certificate(tmpssl);
      if (cert) {
        EVP_PKEY *key = X509_get_pubkey(cert);
        EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl));
        EVP_PKEY_free(key);
      }
      SSL_free(tmpssl);

      if (!SSL_CTX_check_private_key(ctx)) {
        raise_warning("Private key does not match certificate!");
      }
    }
  }

  SSL *ssl = SSL_new(ctx);
  if (ssl) {
    SSL_set_ex_data(ssl, GetSSLExDataIndex(), this); /* map SSL => stream */
  }
  return ssl;
}
Example #28
0
int MAIN(int argc, char **argv)
{
    int off=0;
    SSL *con=NULL,*con2=NULL;
    X509_STORE *store = NULL;
    int s,k,width,state=0;
    char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL;
    int cbuf_len,cbuf_off;
    int sbuf_len,sbuf_off;
    fd_set readfds,writefds;
    short port=PORT;
    int full_log=1;
    char *host=SSL_HOST_NAME;
    char *cert_file=NULL,*key_file=NULL;
    int cert_format = FORMAT_PEM, key_format = FORMAT_PEM;
    char *passarg = NULL, *pass = NULL;
    X509 *cert = NULL;
    EVP_PKEY *key = NULL;
    char *CApath=NULL,*CAfile=NULL,*cipher=NULL;
    int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0;
    int crlf=0;
    int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending;
    SSL_CTX *ctx=NULL;
    int ret=1,in_init=1,i,nbio_test=0;
    int starttls_proto = 0;
    int prexit = 0, vflags = 0;
    SSL_METHOD *meth=NULL;
#ifdef sock_type
#undef sock_type
#endif
    int sock_type=SOCK_STREAM;
    BIO *sbio;
    char *inrand=NULL;
#ifndef OPENSSL_NO_ENGINE
    char *engine_id=NULL;
    ENGINE *e=NULL;
#endif
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
    struct timeval tv;
#endif

    struct sockaddr peer;
    int peerlen = sizeof(peer);
    int enable_timeouts = 0 ;
    long mtu = 0;

#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
    meth=SSLv23_client_method();
#elif !defined(OPENSSL_NO_SSL3)
    meth=SSLv3_client_method();
#elif !defined(OPENSSL_NO_SSL2)
    meth=SSLv2_client_method();
#endif

    apps_startup();
    c_Pause=0;
    c_quiet=0;
    c_ign_eof=0;
    c_debug=0;
    c_msg=0;
    c_showcerts=0;

    if (bio_err == NULL)
        bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);

    if (!load_config(bio_err, NULL))
        goto end;

    if (	((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) ||
            ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) ||
            ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL))
    {
        BIO_printf(bio_err,"out of memory\n");
        goto end;
    }

    verify_depth=0;
    verify_error=X509_V_OK;
#ifdef FIONBIO
    c_nbio=0;
#endif

    argc--;
    argv++;
    while (argc >= 1)
    {
        if	(strcmp(*argv,"-host") == 0)
        {
            if (--argc < 1) goto bad;
            host= *(++argv);
        }
        else if	(strcmp(*argv,"-port") == 0)
        {
            if (--argc < 1) goto bad;
            port=atoi(*(++argv));
            if (port == 0) goto bad;
        }
        else if (strcmp(*argv,"-connect") == 0)
        {
            if (--argc < 1) goto bad;
            if (!extract_host_port(*(++argv),&host,NULL,&port))
                goto bad;
        }
        else if	(strcmp(*argv,"-verify") == 0)
        {
            verify=SSL_VERIFY_PEER;
            if (--argc < 1) goto bad;
            verify_depth=atoi(*(++argv));
            BIO_printf(bio_err,"verify depth is %d\n",verify_depth);
        }
        else if	(strcmp(*argv,"-cert") == 0)
        {
            if (--argc < 1) goto bad;
            cert_file= *(++argv);
        }
        else if	(strcmp(*argv,"-certform") == 0)
        {
            if (--argc < 1) goto bad;
            cert_format = str2fmt(*(++argv));
        }
        else if	(strcmp(*argv,"-crl_check") == 0)
            vflags |= X509_V_FLAG_CRL_CHECK;
        else if	(strcmp(*argv,"-crl_check_all") == 0)
            vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
        else if	(strcmp(*argv,"-prexit") == 0)
            prexit=1;
        else if	(strcmp(*argv,"-crlf") == 0)
            crlf=1;
        else if	(strcmp(*argv,"-quiet") == 0)
        {
            c_quiet=1;
            c_ign_eof=1;
        }
        else if	(strcmp(*argv,"-ign_eof") == 0)
            c_ign_eof=1;
        else if	(strcmp(*argv,"-pause") == 0)
            c_Pause=1;
        else if	(strcmp(*argv,"-debug") == 0)
            c_debug=1;
#ifdef WATT32
        else if (strcmp(*argv,"-wdebug") == 0)
            dbug_init();
#endif
        else if	(strcmp(*argv,"-msg") == 0)
            c_msg=1;
        else if	(strcmp(*argv,"-showcerts") == 0)
            c_showcerts=1;
        else if	(strcmp(*argv,"-nbio_test") == 0)
            nbio_test=1;
        else if	(strcmp(*argv,"-state") == 0)
            state=1;
#ifndef OPENSSL_NO_SSL2
        else if	(strcmp(*argv,"-ssl2") == 0)
            meth=SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3
        else if	(strcmp(*argv,"-ssl3") == 0)
            meth=SSLv3_client_method();
#endif
#ifndef OPENSSL_NO_TLS1
        else if	(strcmp(*argv,"-tls1") == 0)
            meth=TLSv1_client_method();
#endif
#ifndef OPENSSL_NO_DTLS1
        else if	(strcmp(*argv,"-dtls1") == 0)
        {
            meth=DTLSv1_client_method();
            sock_type=SOCK_DGRAM;
        }
        else if (strcmp(*argv,"-timeout") == 0)
            enable_timeouts=1;
        else if (strcmp(*argv,"-mtu") == 0)
        {
            if (--argc < 1) goto bad;
            mtu = atol(*(++argv));
        }
#endif
        else if (strcmp(*argv,"-bugs") == 0)
            bugs=1;
        else if	(strcmp(*argv,"-keyform") == 0)
        {
            if (--argc < 1) goto bad;
            key_format = str2fmt(*(++argv));
        }
        else if	(strcmp(*argv,"-pass") == 0)
        {
            if (--argc < 1) goto bad;
            passarg = *(++argv);
        }
        else if	(strcmp(*argv,"-key") == 0)
        {
            if (--argc < 1) goto bad;
            key_file= *(++argv);
        }
        else if	(strcmp(*argv,"-reconnect") == 0)
        {
            reconnect=5;
        }
        else if	(strcmp(*argv,"-CApath") == 0)
        {
            if (--argc < 1) goto bad;
            CApath= *(++argv);
        }
        else if	(strcmp(*argv,"-CAfile") == 0)
        {
            if (--argc < 1) goto bad;
            CAfile= *(++argv);
        }
        else if (strcmp(*argv,"-no_tls1") == 0)
            off|=SSL_OP_NO_TLSv1;
        else if (strcmp(*argv,"-no_ssl3") == 0)
            off|=SSL_OP_NO_SSLv3;
        else if (strcmp(*argv,"-no_ssl2") == 0)
            off|=SSL_OP_NO_SSLv2;
        else if (strcmp(*argv,"-serverpref") == 0)
            off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
        else if	(strcmp(*argv,"-cipher") == 0)
        {
            if (--argc < 1) goto bad;
            cipher= *(++argv);
        }
#ifdef FIONBIO
        else if (strcmp(*argv,"-nbio") == 0)
        {
            c_nbio=1;
        }
#endif
        else if	(strcmp(*argv,"-starttls") == 0)
        {
            if (--argc < 1) goto bad;
            ++argv;
            if (strcmp(*argv,"smtp") == 0)
                starttls_proto = 1;
            else if (strcmp(*argv,"pop3") == 0)
                starttls_proto = 2;
            else
                goto bad;
        }
#ifndef OPENSSL_NO_ENGINE
        else if	(strcmp(*argv,"-engine") == 0)
        {
            if (--argc < 1) goto bad;
            engine_id = *(++argv);
        }
#endif
        else if (strcmp(*argv,"-rand") == 0)
        {
            if (--argc < 1) goto bad;
            inrand= *(++argv);
        }
        else
        {
            BIO_printf(bio_err,"unknown option %s\n",*argv);
            badop=1;
            break;
        }
        argc--;
        argv++;
    }
    if (badop)
    {
bad:
        sc_usage();
        goto end;
    }

    OpenSSL_add_ssl_algorithms();
    SSL_load_error_strings();

#ifndef OPENSSL_NO_ENGINE
    e = setup_engine(bio_err, engine_id, 1);
#endif
    if (!app_passwd(bio_err, passarg, NULL, &pass, NULL))
    {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (key_file == NULL)
        key_file = cert_file;


    if (key_file)

    {

        key = load_key(bio_err, key_file, key_format, 0, pass, e,
                       "client certificate private key file");
        if (!key)
        {
            ERR_print_errors(bio_err);
            goto end;
        }

    }

    if (cert_file)

    {
        cert = load_cert(bio_err,cert_file,cert_format,
                         NULL, e, "client certificate file");

        if (!cert)
        {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL
            && !RAND_status())
    {
        BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
    }
    if (inrand != NULL)
        BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
                   app_RAND_load_files(inrand));

    if (bio_c_out == NULL)
    {
        if (c_quiet && !c_debug && !c_msg)
        {
            bio_c_out=BIO_new(BIO_s_null());
        }
        else
        {
            if (bio_c_out == NULL)
                bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE);
        }
    }

    ctx=SSL_CTX_new(meth);
    if (ctx == NULL)
    {
        ERR_print_errors(bio_err);
        goto end;
    }

    if (bugs)
        SSL_CTX_set_options(ctx,SSL_OP_ALL|off);
    else
        SSL_CTX_set_options(ctx,off);
    /* DTLS: partial reads end up discarding unread UDP bytes :-(
     * Setting read ahead solves this problem.
     */
    if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);

    if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
    if (cipher != NULL)
        if(!SSL_CTX_set_cipher_list(ctx,cipher)) {
            BIO_printf(bio_err,"error setting cipher list\n");
            ERR_print_errors(bio_err);
            goto end;
        }
#if 0
        else
            SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER"));
#endif

    SSL_CTX_set_verify(ctx,verify,verify_callback);
    if (!set_cert_key_stuff(ctx,cert,key))
        goto end;

    if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
            (!SSL_CTX_set_default_verify_paths(ctx)))
    {
        /* BIO_printf(bio_err,"error setting default verify locations\n"); */
        ERR_print_errors(bio_err);
        /* goto end; */
    }

    store = SSL_CTX_get_cert_store(ctx);
    X509_STORE_set_flags(store, vflags);

    con=SSL_new(ctx);
#ifndef OPENSSL_NO_KRB5
    if (con  &&  (con->kssl_ctx = kssl_ctx_new()) != NULL)
    {
        kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host);
    }
#endif	/* OPENSSL_NO_KRB5  */
    /*	SSL_set_cipher_list(con,"RC4-MD5"); */

re_start:

    if (init_client(&s,host,port,sock_type) == 0)
    {
        BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error());
        SHUTDOWN(s);
        goto end;
    }
    BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s);

#ifdef FIONBIO
    if (c_nbio)
    {
        unsigned long l=1;
        BIO_printf(bio_c_out,"turning on non blocking io\n");
        if (BIO_socket_ioctl(s,FIONBIO,&l) < 0)
        {
            ERR_print_errors(bio_err);
            goto end;
        }
    }
#endif
    if (c_Pause & 0x01) con->debug=1;

    if ( SSL_version(con) == DTLS1_VERSION)
    {
        struct timeval timeout;

        sbio=BIO_new_dgram(s,BIO_NOCLOSE);
        if (getsockname(s, &peer, (void *)&peerlen) < 0)
        {
            BIO_printf(bio_err, "getsockname:errno=%d\n",
                       get_last_socket_error());
            SHUTDOWN(s);
            goto end;
        }

        BIO_ctrl_set_connected(sbio, 1, &peer);

        if ( enable_timeouts)
        {
            timeout.tv_sec = 0;
            timeout.tv_usec = DGRAM_RCV_TIMEOUT;
            BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);

            timeout.tv_sec = 0;
            timeout.tv_usec = DGRAM_SND_TIMEOUT;
            BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
        }

        if ( mtu > 0)
        {
            SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
            SSL_set_mtu(con, mtu);
        }
        else
            /* want to do MTU discovery */
            BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
    }
    else
        sbio=BIO_new_socket(s,BIO_NOCLOSE);



    if (nbio_test)
    {
        BIO *test;

        test=BIO_new(BIO_f_nbio_test());
        sbio=BIO_push(test,sbio);
    }

    if (c_debug)
    {
        con->debug=1;
        BIO_set_callback(sbio,bio_dump_callback);
        BIO_set_callback_arg(sbio,bio_c_out);
    }
    if (c_msg)
    {
        SSL_set_msg_callback(con, msg_cb);
        SSL_set_msg_callback_arg(con, bio_c_out);
    }

    SSL_set_bio(con,sbio,sbio);
    SSL_set_connect_state(con);

    /* ok, lets connect */
    width=SSL_get_fd(con)+1;

    read_tty=1;
    write_tty=0;
    tty_on=0;
    read_ssl=1;
    write_ssl=1;

    cbuf_len=0;
    cbuf_off=0;
    sbuf_len=0;
    sbuf_off=0;

    /* This is an ugly hack that does a lot of assumptions */
    if (starttls_proto == 1)
    {
        BIO_read(sbio,mbuf,BUFSIZZ);
        BIO_printf(sbio,"STARTTLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    if (starttls_proto == 2)
    {
        BIO_read(sbio,mbuf,BUFSIZZ);
        BIO_printf(sbio,"STLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }

    for (;;)
    {
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);

        if (SSL_in_init(con) && !SSL_total_renegotiations(con))
        {
            in_init=1;
            tty_on=0;
        }
        else
        {
            tty_on=1;
            if (in_init)
            {
                in_init=0;
                print_stuff(bio_c_out,con,full_log);
                if (full_log > 0) full_log--;

                if (starttls_proto)
                {
                    BIO_printf(bio_err,"%s",mbuf);
                    /* We don't need to know any more */
                    starttls_proto = 0;
                }

                if (reconnect)
                {
                    reconnect--;
                    BIO_printf(bio_c_out,"drop connection and then reconnect\n");
                    SSL_shutdown(con);
                    SSL_set_connect_state(con);
                    SHUTDOWN(SSL_get_fd(con));
                    goto re_start;
                }
            }
        }

        ssl_pending = read_ssl && SSL_pending(con);

        if (!ssl_pending)
        {
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE)
            if (tty_on)
            {
                if (read_tty)  FD_SET(fileno(stdin),&readfds);
                if (write_tty) FD_SET(fileno(stdout),&writefds);
            }
            if (read_ssl)
                FD_SET(SSL_get_fd(con),&readfds);
            if (write_ssl)
                FD_SET(SSL_get_fd(con),&writefds);
#else
            if(!tty_on || !write_tty) {
                if (read_ssl)
                    FD_SET(SSL_get_fd(con),&readfds);
                if (write_ssl)
                    FD_SET(SSL_get_fd(con),&writefds);
            }
#endif
            /*			printf("mode tty(%d %d%d) ssl(%d%d)\n",
            				tty_on,read_tty,write_tty,read_ssl,write_ssl);*/

            /* Note: under VMS with SOCKETSHR the second parameter
             * is currently of type (int *) whereas under other
             * systems it is (void *) if you don't have a cast it
             * will choke the compiler: if you do have a cast then
             * you can either go for (int *) or (void *).
             */
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
            /* Under Windows/DOS we make the assumption that we can
            * always write to the tty: therefore if we need to
            		 * write to the tty we just fall through. Otherwise
            		 * we timeout the select every second and see if there
            		 * are any keypresses. Note: this is a hack, in a proper
            		 * Windows application we wouldn't do this.
            		 */
            i=0;
            if(!write_tty) {
                if(read_tty) {
                    tv.tv_sec = 1;
                    tv.tv_usec = 0;
                    i=select(width,(void *)&readfds,(void *)&writefds,
                             NULL,&tv);
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
                    if(!i && (!_kbhit() || !read_tty) ) continue;
#else
                    if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue;
#endif
                } else 	i=select(width,(void *)&readfds,(void *)&writefds,
                                     NULL,NULL);
            }
#elif defined(OPENSSL_SYS_NETWARE)
            if(!write_tty) {
                if(read_tty) {
                    tv.tv_sec = 1;
                    tv.tv_usec = 0;
                    i=select(width,(void *)&readfds,(void *)&writefds,
                             NULL,&tv);
                } else 	i=select(width,(void *)&readfds,(void *)&writefds,
                                     NULL,NULL);
            }
#else
            i=select(width,(void *)&readfds,(void *)&writefds,
                     NULL,NULL);
#endif
            if ( i < 0)
            {
                BIO_printf(bio_err,"bad select %d\n",
                           get_last_socket_error());
                goto shut;
                /* goto end; */
            }
        }

        if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))
        {
            k=SSL_write(con,&(cbuf[cbuf_off]),
                        (unsigned int)cbuf_len);
            switch (SSL_get_error(con,k))
            {
            case SSL_ERROR_NONE:
                cbuf_off+=k;
                cbuf_len-=k;
                if (k <= 0) goto end;
                /* we have done a  write(con,NULL,0); */
                if (cbuf_len <= 0)
                {
                    read_tty=1;
                    write_ssl=0;
                }
                else /* if (cbuf_len > 0) */
                {
                    read_tty=0;
                    write_ssl=1;
                }
                break;
            case SSL_ERROR_WANT_WRITE:
                BIO_printf(bio_c_out,"write W BLOCK\n");
                write_ssl=1;
                read_tty=0;
                break;
            case SSL_ERROR_WANT_READ:
                BIO_printf(bio_c_out,"write R BLOCK\n");
                write_tty=0;
                read_ssl=1;
                write_ssl=0;
                break;
            case SSL_ERROR_WANT_X509_LOOKUP:
                BIO_printf(bio_c_out,"write X BLOCK\n");
                break;
            case SSL_ERROR_ZERO_RETURN:
                if (cbuf_len != 0)
                {
                    BIO_printf(bio_c_out,"shutdown\n");
                    goto shut;
                }
                else
                {
                    read_tty=1;
                    write_ssl=0;
                    break;
                }

            case SSL_ERROR_SYSCALL:
                if ((k != 0) || (cbuf_len != 0))
                {
                    BIO_printf(bio_err,"write:errno=%d\n",
                               get_last_socket_error());
                    goto shut;
                }
                else
                {
                    read_tty=1;
                    write_ssl=0;
                }
                break;
            case SSL_ERROR_SSL:
                ERR_print_errors(bio_err);
                goto shut;
            }
        }
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
        /* Assume Windows/DOS can always write */
        else if (!ssl_pending && write_tty)
#else
        else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds))
#endif
        {
#ifdef CHARSET_EBCDIC
            ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len);
#endif
            i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len);

            if (i <= 0)
            {
                BIO_printf(bio_c_out,"DONE\n");
                goto shut;
                /* goto end; */
            }

            sbuf_len-=i;;
            sbuf_off+=i;
            if (sbuf_len <= 0)
            {
                read_ssl=1;
                write_tty=0;
            }
        }
        else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds))
        {
#ifdef RENEG
        { static int iiii; if (++iiii == 52) {
                    SSL_renegotiate(con);
                    iiii=0;
                }
            }
#endif
#if 1
            k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ );
#else
            /* Demo for pending and peek :-) */
            k=SSL_read(con,sbuf,16);
            {   char zbuf[10240];
                printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240));
            }
#endif

            switch (SSL_get_error(con,k))
            {
            case SSL_ERROR_NONE:
                if (k <= 0)
                    goto end;
                sbuf_off=0;
                sbuf_len=k;

                read_ssl=0;
                write_tty=1;
                break;
            case SSL_ERROR_WANT_WRITE:
                BIO_printf(bio_c_out,"read W BLOCK\n");
                write_ssl=1;
                read_tty=0;
                break;
            case SSL_ERROR_WANT_READ:
                BIO_printf(bio_c_out,"read R BLOCK\n");
                write_tty=0;
                read_ssl=1;
                if ((read_tty == 0) && (write_ssl == 0))
                    write_ssl=1;
                break;
            case SSL_ERROR_WANT_X509_LOOKUP:
                BIO_printf(bio_c_out,"read X BLOCK\n");
                break;
            case SSL_ERROR_SYSCALL:
                BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error());
                goto shut;
            case SSL_ERROR_ZERO_RETURN:
                BIO_printf(bio_c_out,"closed\n");
                goto shut;
            case SSL_ERROR_SSL:
                ERR_print_errors(bio_err);
                goto shut;
                /* break; */
            }
        }

#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
        else if (_kbhit())
#else
        else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0)))
#endif
#elif defined (OPENSSL_SYS_NETWARE)
        else if (_kbhit())
#else
        else if (FD_ISSET(fileno(stdin),&readfds))
#endif
        {
            if (crlf)
            {
                int j, lf_num;

                i=read(fileno(stdin),cbuf,BUFSIZZ/2);
                lf_num = 0;
                /* both loops are skipped when i <= 0 */
                for (j = 0; j < i; j++)
                    if (cbuf[j] == '\n')
                        lf_num++;
                for (j = i-1; j >= 0; j--)
                {
                    cbuf[j+lf_num] = cbuf[j];
                    if (cbuf[j] == '\n')
                    {
                        lf_num--;
                        i++;
                        cbuf[j+lf_num] = '\r';
                    }
                }
                assert(lf_num == 0);
            }
            else
                i=read(fileno(stdin),cbuf,BUFSIZZ);

            if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q')))
            {
                BIO_printf(bio_err,"DONE\n");
                goto shut;
            }

            if ((!c_ign_eof) && (cbuf[0] == 'R'))
            {
                BIO_printf(bio_err,"RENEGOTIATING\n");
                SSL_renegotiate(con);
                cbuf_len=0;
            }
            else
            {
                cbuf_len=i;
                cbuf_off=0;
#ifdef CHARSET_EBCDIC
                ebcdic2ascii(cbuf, cbuf, i);
#endif
            }

            write_ssl=1;
            read_tty=0;
        }
    }
shut:
    SSL_shutdown(con);
    SHUTDOWN(SSL_get_fd(con));
    ret=0;
end:
    if(prexit) print_stuff(bio_c_out,con,1);
    if (con != NULL) SSL_free(con);
    if (con2 != NULL) SSL_free(con2);
    if (ctx != NULL) SSL_CTX_free(ctx);
    if (cert)
        X509_free(cert);
    if (key)
        EVP_PKEY_free(key);
    if (pass)
        OPENSSL_free(pass);
    if (cbuf != NULL) {
        OPENSSL_cleanse(cbuf,BUFSIZZ);
        OPENSSL_free(cbuf);
    }
    if (sbuf != NULL) {
        OPENSSL_cleanse(sbuf,BUFSIZZ);
        OPENSSL_free(sbuf);
    }
    if (mbuf != NULL) {
        OPENSSL_cleanse(mbuf,BUFSIZZ);
        OPENSSL_free(mbuf);
    }
    if (bio_c_out != NULL)
    {
        BIO_free(bio_c_out);
        bio_c_out=NULL;
    }
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
Example #29
0
int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
{
	int rc = 1;
	const char* ciphers = NULL;
	
	FUNC_ENTRY;
	if (net->ctx == NULL)
		if ((net->ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)	/* SSLv23 for compatibility with SSLv2, SSLv3 and TLSv1 */
		{
			SSLSocket_error("SSL_CTX_new", NULL, net->socket, rc);
			goto exit;
		}
	
	if (opts->keyStore)
	{
		int rc1 = 0;

		if ((rc = SSL_CTX_use_certificate_chain_file(net->ctx, opts->keyStore)) != 1)
		{
			SSLSocket_error("SSL_CTX_use_certificate_chain_file", NULL, net->socket, rc);
			goto free_ctx; /*If we can't load the certificate (chain) file then loading the privatekey won't work either as it needs a matching cert already loaded */
		}	
			
		if (opts->privateKey == NULL)
			opts->privateKey = opts->keyStore;   /* the privateKey can be included in the keyStore */

		if (opts->privateKeyPassword != NULL)
		{
			SSL_CTX_set_default_passwd_cb(net->ctx, pem_passwd_cb);
			SSL_CTX_set_default_passwd_cb_userdata(net->ctx, (void*)opts->privateKeyPassword);
    }
		
		/* support for ASN.1 == DER format? DER can contain only one certificate? */
		rc1 = SSL_CTX_use_PrivateKey_file(net->ctx, opts->privateKey, SSL_FILETYPE_PEM);
		if (opts->privateKey == opts->keyStore)
			opts->privateKey = NULL;
		if (rc1 != 1)
		{
			SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc);
			goto free_ctx;
		}  
	}

	if (opts->trustStore)
	{
		if ((rc = SSL_CTX_load_verify_locations(net->ctx, opts->trustStore, NULL)) != 1)
		{
			SSLSocket_error("SSL_CTX_load_verify_locations", NULL, net->socket, rc);
			goto free_ctx;
		}                               
	}
	else if ((rc = SSL_CTX_set_default_verify_paths(net->ctx)) != 1)
	{
		SSLSocket_error("SSL_CTX_set_default_verify_paths", NULL, net->socket, rc);
		goto free_ctx;
	}

	if (opts->enabledCipherSuites == NULL)
		ciphers = "DEFAULT"; 
	else
		ciphers = opts->enabledCipherSuites;

	if ((rc = SSL_CTX_set_cipher_list(net->ctx, ciphers)) != 1)
	{
		SSLSocket_error("SSL_CTX_set_cipher_list", NULL, net->socket, rc);
		goto free_ctx;
	}       
	
	SSL_CTX_set_mode(net->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

	goto exit;
free_ctx:
	SSL_CTX_free(net->ctx);
	net->ctx = NULL;
	
exit:
	FUNC_EXIT_RC(rc);
	return rc;
}
Example #30
0
/*
 *	Initialize global SSL context.
 */
static void
initialize_SSL(void)
{
	struct stat buf;

	STACK_OF(X509_NAME) *root_cert_list = NULL;

	if (!SSL_context)
	{
#if SSLEAY_VERSION_NUMBER >= 0x0907000L
		OPENSSL_config(NULL);
#endif
		SSL_library_init();
		SSL_load_error_strings();

		/*
		 * We use SSLv23_method() because it can negotiate use of the highest
		 * mutually supported protocol version, while alternatives like
		 * TLSv1_2_method() permit only one specific version.  Note that we
		 * don't actually allow SSL v2 or v3, only TLS protocols (see below).
		 */
		SSL_context = SSL_CTX_new(SSLv23_method());
		if (!SSL_context)
			ereport(FATAL,
					(errmsg("could not create SSL context: %s",
							SSLerrmessage())));

		/*
		 * Disable OpenSSL's moving-write-buffer sanity check, because it
		 * causes unnecessary failures in nonblocking send cases.
		 */
		SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

		/*
		 * Load and verify server's certificate and private key
		 */
		if (SSL_CTX_use_certificate_chain_file(SSL_context,
											   ssl_cert_file) != 1)
			ereport(FATAL,
					(errcode(ERRCODE_CONFIG_FILE_ERROR),
				  errmsg("could not load server certificate file \"%s\": %s",
						 ssl_cert_file, SSLerrmessage())));

		if (stat(ssl_key_file, &buf) != 0)
			ereport(FATAL,
					(errcode_for_file_access(),
					 errmsg("could not access private key file \"%s\": %m",
							ssl_key_file)));

		/*
		 * Require no public access to key file.
		 *
		 * XXX temporarily suppress check when on Windows, because there may
		 * not be proper support for Unix-y file permissions.  Need to think
		 * of a reasonable check to apply on Windows.  (See also the data
		 * directory permission check in postmaster.c)
		 */
#if !defined(WIN32) && !defined(__CYGWIN__)
		if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
			ereport(FATAL,
					(errcode(ERRCODE_CONFIG_FILE_ERROR),
				  errmsg("private key file \"%s\" has group or world access",
						 ssl_key_file),
				   errdetail("Permissions should be u=rw (0600) or less.")));
#endif

		if (SSL_CTX_use_PrivateKey_file(SSL_context,
										ssl_key_file,
										SSL_FILETYPE_PEM) != 1)
			ereport(FATAL,
					(errmsg("could not load private key file \"%s\": %s",
							ssl_key_file, SSLerrmessage())));

		if (SSL_CTX_check_private_key(SSL_context) != 1)
			ereport(FATAL,
					(errmsg("check of private key failed: %s",
							SSLerrmessage())));
	}

	/* set up ephemeral DH keys, and disallow SSL v2/v3 while at it */
	SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);
	SSL_CTX_set_options(SSL_context,
						SSL_OP_SINGLE_DH_USE |
						SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

	/* set up ephemeral ECDH keys */
	initialize_ecdh();

	/* set up the allowed cipher list */
	if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1)
		elog(FATAL, "could not set the cipher list (no valid ciphers available)");

	/* Let server choose order */
	if (SSLPreferServerCiphers)
		SSL_CTX_set_options(SSL_context, SSL_OP_CIPHER_SERVER_PREFERENCE);

	/*
	 * Load CA store, so we can verify client certificates if needed.
	 */
	if (ssl_ca_file[0])
	{
		if (SSL_CTX_load_verify_locations(SSL_context, ssl_ca_file, NULL) != 1 ||
			(root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL)
			ereport(FATAL,
					(errmsg("could not load root certificate file \"%s\": %s",
							ssl_ca_file, SSLerrmessage())));
	}

	/*----------
	 * Load the Certificate Revocation List (CRL).
	 * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
	 *----------
	 */
	if (ssl_crl_file[0])
	{
		X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context);

		if (cvstore)
		{
			/* Set the flags to check against the complete CRL chain */
			if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1)
			{
				/* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
#ifdef X509_V_FLAG_CRL_CHECK
				X509_STORE_set_flags(cvstore,
						  X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
#else
				ereport(LOG,
				(errmsg("SSL certificate revocation list file \"%s\" ignored",
						ssl_crl_file),
				 errdetail("SSL library does not support certificate revocation lists.")));
#endif
			}
			else
				ereport(FATAL,
						(errmsg("could not load SSL certificate revocation list file \"%s\": %s",
								ssl_crl_file, SSLerrmessage())));
		}
	}

	if (ssl_ca_file[0])
	{
		/*
		 * Always ask for SSL client cert, but don't fail if it's not
		 * presented.  We might fail such connections later, depending on what
		 * we find in pg_hba.conf.
		 */
		SSL_CTX_set_verify(SSL_context,
						   (SSL_VERIFY_PEER |
							SSL_VERIFY_CLIENT_ONCE),
						   verify_cb);

		/* Set flag to remember CA store is successfully loaded */
		ssl_loaded_verify_locations = true;

		/*
		 * Tell OpenSSL to send the list of root certs we trust to clients in
		 * CertificateRequests.  This lets a client with a keystore select the
		 * appropriate client certificate to send to us.
		 */
		SSL_CTX_set_client_CA_list(SSL_context, root_cert_list);
	}
}