Exemple #1
0
void *handle_connection(void *arg)
{
	char buf[1024];
	BIO *bio = (BIO *)arg;
	X509 *peer;
	SSL *ssl;

	BIO_get_ssl(bio, &ssl);

	if (BIO_do_handshake(bio) <= 0) {
		printf("Failed handshake.\n");
		ERR_print_errors_fp(stdout);
		return (void *)-1;
	}

	if ((peer = SSL_get_peer_certificate(ssl))) {
		if (SSL_get_verify_result(ssl) == X509_V_OK) {
			/* The client sent a certificate which verified OK */
			printf("The client sent a certificate which verified OK\n");
		} else {
			printf("The client sent a certificate which verified failed\n");
		}
	} else {
		fprintf(stderr, "cannot get peer certificate\n");
	}

	BIO_read(bio, buf, 1024);
	printf("Received: %s\n", buf);
	BIO_puts(bio, "Connection: Sending out Data on initial connection\n");
	printf("Sent out data on connection\n");

	BIO_free_all(bio);

	return (void *)0;
}
Exemple #2
0
static Pfd*
opensslconnect(char *host)
{
	Pfd *pfd;
	BIO *sbio;
	SSL_CTX *ctx;
	SSL *ssl;
	static int didinit;
	char buf[1024];

	if(!didinit){
		httpsinit();
		didinit = 1;
	}

	ctx = SSL_CTX_new(SSLv23_client_method());
	sbio = BIO_new_ssl_connect(ctx);
	BIO_get_ssl(sbio, &ssl);
	SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
	
	snprint(buf, sizeof buf, "%s:https", host);
	BIO_set_conn_hostname(sbio, buf);
	
	if(BIO_do_connect(sbio) <= 0 || BIO_do_handshake(sbio) <= 0){
		ERR_error_string_n(ERR_get_error(), buf, sizeof buf);
		BIO_free_all(sbio);
		werrstr("openssl: %s", buf);
		return nil;
	}

	pfd = emalloc(sizeof *pfd);
	pfd->sbio = sbio;
	return pfd;
}
Exemple #3
0
BIO *neo4j_openssl_new_bio(BIO *delegate, const char *hostname, int port,
        const neo4j_config_t *config, uint_fast32_t flags)
{
    neo4j_logger_t *logger = neo4j_get_logger(config, "tls");

    SSL_CTX *ctx = new_ctx(config, logger);
    if (ctx == NULL)
    {
        return NULL;
    }

    BIO *ssl_bio = BIO_new_ssl(ctx, 1);
    if (ssl_bio == NULL)
    {
        errno = openssl_error(logger, NEO4J_LOG_ERROR, __FILE__, __LINE__);
        SSL_CTX_free(ctx);
        goto failure;
    }

    SSL_CTX_free(ctx);

    BIO_push(ssl_bio, delegate);
    if (BIO_set_close(ssl_bio, BIO_CLOSE) != 1)
    {
        errno = openssl_error(logger, NEO4J_LOG_ERROR, __FILE__, __LINE__);
        goto failure;
    }

    int result = BIO_do_handshake(ssl_bio);
    if (result != 1)
    {
        if (result == 0)
        {
            errno = NEO4J_NO_SERVER_TLS_SUPPORT;
            goto failure;
        }
        errno = openssl_error(logger, NEO4J_LOG_ERROR, __FILE__, __LINE__);
        goto failure;
    }

    SSL *ssl = NULL;
    BIO_get_ssl(ssl_bio, &ssl);
    assert(ssl != NULL);
    if (verify(ssl, hostname, port, config, flags, logger))
    {
        goto failure;
    }

    return ssl_bio;

    int errsv;
failure:
    errsv = errno;
    BIO_free(ssl_bio);
    errno = errsv;
    return NULL;
}
Exemple #4
0
bool Email::sendCode(std::string user, std::string code)
{
    std::string msg,to;
    
    msg = m_m1 + code + m_m2;
    to = m_to1 + user + m_to3;
    
    SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
    SSL* ssl;
    
    BIO* bio = BIO_new_ssl_connect(ctx);
    BIO_get_ssl(bio, &ssl);
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
    BIO_set_conn_hostname(bio, m_amazonHostname.c_str());
    
    if(BIO_do_connect(bio) <= 0){
        BIO_free_all(bio);
        SSL_CTX_free(ctx);
        return false;
    }
    
    if(BIO_do_handshake(bio) <= 0){
        BIO_free_all(bio);
        SSL_CTX_free(ctx);
        return false;
    }

    m_len = BIO_read(bio, m_buf, BUF_LEN) - 1;
    BIO_puts(bio, "HELO localhost\r\n");
    m_len = BIO_read(bio, m_buf, BUF_LEN) - 1;
    BIO_puts(bio,"AUTH LOGIN\r\n");
    m_len = BIO_read(bio,m_buf,BUF_LEN) - 1;
    BIO_puts(bio,"QUtJQUlFVzJDMlU3RUZYTU5PUVE=\r\n"); 
    m_len = BIO_read(bio,m_buf,BUF_LEN) - 1;
    BIO_puts(bio,"QWd3TkZSOUJyb2dUTUkxYlJHeXh4dHZMYm4reldGZCtYSFJMbnJpNzZ5RC8=\r\n"); 
    m_len = BIO_read(bio,m_buf,BUF_LEN) - 1;
    BIO_puts(bio,"MAIL FROM:[email protected]\r\n"); 
    m_len = BIO_read(bio,m_buf,BUF_LEN) - 1;
    BIO_puts(bio,to.c_str()); 
    m_len = BIO_read(bio,m_buf,BUF_LEN) - 1;
    BIO_puts(bio,"DATA\r\n"); 
    m_len = BIO_read(bio,m_buf,BUF_LEN) - 1;
    BIO_puts(bio,"Subject:OneBrown Verification\r\n\r\n"); 
    BIO_puts(bio,msg.c_str()); 
    BIO_puts(bio,"\r\n.\r\n"); 
    m_len = BIO_read(bio,m_buf,BUF_LEN) - 1;
    BIO_puts(bio,"QUIT\r\n"); 
    m_len = BIO_read(bio,m_buf,BUF_LEN) - 1;
    
    BIO_free_all(bio);
    SSL_CTX_free(ctx);
    
    return true;
}
Exemple #5
0
const char *dbapi_lookup(const char *key) {
	long res = 1;
	SSL_CTX* ctx = NULL;
	BIO *web = NULL, *out = NULL;
	SSL *ssl = NULL;
	const SSL_METHOD* method;
	char *token, *tmpout, *buf;
	int hlen=0, len=0, maxlen=2048;
	(void)SSL_library_init();
	SSL_load_error_strings();
	OPENSSL_config(NULL);
	method = SSLv23_method(); if(method==NULL) return NULL;
	ctx = SSL_CTX_new(method); if(ctx==NULL) return NULL;
	SSL_CTX_set_verify_depth(ctx, 4);
	SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|
		SSL_OP_NO_COMPRESSION);
	web = BIO_new_ssl_connect(ctx); if(web==NULL) return NULL;
	res = BIO_set_conn_hostname(web, DB_API_SERVER); if(res!=1) return NULL;
	BIO_get_ssl(web, &ssl); if(ssl==NULL) return NULL;
	res = SSL_set_cipher_list(ssl, SECURE_CIPHER_LIST); if(res!=1) return NULL;
	res = SSL_set_tlsext_host_name(ssl, DB_API_HOST); if(res!=1) return NULL;
	out = BIO_new_fp(stdout, BIO_NOCLOSE); if(NULL==out) return NULL;
	res = BIO_do_connect(web); if(res!=1) return NULL;
	res = BIO_do_handshake(web); if(res!=1) return NULL;
	len=(60+strlen(key)+strlen(DB_API_HOST)+strlen(DB_API_AUTH));
	char *request=malloc(sizeof(char)*(len+1));
	snprintf(request,len,
		"GET %s HTTP/1.1\nHost: %s\nx-api-key: %s\nConnection: close\n\n",
		key, DB_API_HOST, DB_API_AUTH);
	request[len]='\0';
	BIO_puts(web, request);
	BIO_puts(out, "\n");
	buf = malloc(sizeof(char)*maxlen);
	do {
		char buff[1536] = {};
		len=BIO_read(web, buff, sizeof(buff));
		hlen+=len;
		if(hlen<maxlen&&len>0) strncat(buf,buff,len);
	} while (len>0 || BIO_should_retry(web));
	buf[maxlen]='\0';
	tmpout = malloc(sizeof(char)*(HASH_MAXLENGTH+1));
	token = strtok(buf, "\n");
	while (token) {
		snprintf(tmpout,HASH_MAXLENGTH,"%s",token);
		token = strtok(NULL, "\n");
	}
	tmpout[strlen(tmpout)]='\0';
	free(buf);
	free(request);
	if(out) BIO_free(out);
	if(web != NULL) BIO_free_all(web);
	if(NULL != ctx) SSL_CTX_free(ctx);
	return tmpout;
}
/*
  At first the arguments are read and passed. Then the ssl context is gotten
  by calling 'BIO_get_ssl(client, &ssl)'. Afterwards the ssl handshake is 
  performed and the certificate verified. Then the line is read from the certificate. 
  This value is mapped to 'organizationalUnitName'.
  An example usage of the connection is shown and then the connectino will be
  terminated.
 */
void* handleConn(void *argsv){
  connArgs* args = (connArgs*) argsv;
  MessageHandler* msgHandler = args->msgHandler;
  BIO* client = args->conn;
  SSL* ssl;

  BIO_get_ssl(client, &ssl);

  /*ssl handshake*/
  msgHandler->debug("performing ssl handshake");
  if(BIO_do_handshake(client) != 1){
    string fail("handshake failed\nSSL_ERROR: ");
    fail.append(ERR_reason_error_string(ERR_get_error()));
    msgHandler->log(fail);
  } else
    msgHandler->log("handshake successful");

  /*verifying the certificate*/
  X509* peerCert;

  if(SSL_get_verify_result(ssl) != X509_V_OK){
    string error("verification failed\nSSL_Error: ");
    error.append(ERR_reason_error_string(ERR_get_error()));
    msgHandler->error(error, CRITICAL);
  } else {
    msgHandler->debug("verification successful");
    peerCert  = SSL_get_peer_certificate(ssl);
  }

  msgHandler->debug("trying to get the line");
  /*getting the line*/
  char lineN[6];
  X509_NAME* name = X509_get_subject_name(peerCert);
  X509_NAME_get_text_by_NID(name, NID_organizationalUnitName, lineN, 6);
  string line("line is: ");
  line.append(lineN);
  msgHandler->debug(line);

  /*example use of the connection (echoing the incoming msg)*/
  char buffer[1024];
  bzero(buffer, 1024);
  SSL_read(ssl, buffer, 1024);
  string debug("message received: ");
  debug.append(buffer);
  msgHandler->debug(debug);
  SSL_write(ssl, buffer, 1024);

  /*closing the connection*/
  BIO_reset(client);
  X509_free(peerCert);
  return NULL;
}
void* handleConn(void *argsv){
  connArgs* args = (connArgs*) argsv;
  BIO* client = args->conn;

  char* testBuf = new char[1024];

  BIO_do_handshake(client);

  sleep(3);
  bzero(testBuf, 1024);
  BIO_read(client, testBuf, 1024);

  BIO_write(client, testBuf, 1024);

  cout << "client: " << testBuf << endl;

  BIO_reset(client);  

  return NULL;
}
Exemple #8
0
/*
  Connect to host on the given port using tls and return the BIO object
  representing the connection.
*/
BIO* connect_tls(const char *host, const char *port){
  init_ssl_lib();
  //the assignment is redundant, but it's weird not having it
  ctx = init_ssl_ctx();
  if(!ctx){return NULL;}

  BIO *bio = BIO_new_ssl_connect(ctx);
  if(!bio){goto err;}

  if(BIO_set_conn_hostname(bio, host) == 0){
    goto err;
  }
  if(BIO_set_conn_port(bio, port) == 0){
    goto err;
  }

  SSL *ssl;
  BIO_get_ssl(bio, &ssl);
  //Handle renegotiation transparently
  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
  //this is to let the server know what name we used to connect to it
  SSL_set_tlsext_host_name(ssl, host);
  if(BIO_do_connect(bio) == 0){
    goto err;
  }
  if(BIO_do_handshake(bio) == 0){
    goto err;
  }
  //make sure that the certificate was valid
  if(SSL_get_verify_result(ssl) != X509_V_OK){
    goto err;
  }

  return bio;
 err:
  print_errors();
  BIO_free_all(bio);
  SSL_CTX_free(ctx);
  return NULL;
}
BIO* establishSSLConnection(char * serveraddress, char * port){
	printf("Attempting to establish SSL Connection.\n");
    //============================
    // SSL init 
	SSL_library_init(); 
	SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
	SSL *ssl;
	
	SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE,NULL); 
	
	// Establish an SSL Connection
    strcat(serveraddress, ":");
    strcat(serveraddress, port);
    char * concatenate = serveraddress;
    char * connection = malloc(sizeof(char) * (sizeof(concatenate) + 1));
	strcpy(connection, concatenate); 

	BIO* bio = BIO_new_connect(connection); 
	
	BIO_get_ssl(bio,&ssl); 
	SSL_set_mode(ssl,SSL_MODE_AUTO_RETRY); 
	if (BIO_do_connect(bio) <= 0){
		printf("Error: SSL connect failed.\n"); 
		BIO_free_all(bio);
		SSL_CTX_free(ctx); 
		exit(1); 
	}
	if (BIO_do_handshake(bio)<=0){
		printf("Error: SSL handshake failed.\n"); 
		SSL_CTX_free(ctx); 
		exit(1); 
	}
	// ============== SSL init //

	printf("SSL Connection has been established!\n");
	return bio;
}
/**
 * mongoc_stream_tls_do_handshake:
 *
 * force an ssl handshake
 *
 * This will happen on the first read or write otherwise
 */
bool
mongoc_stream_tls_do_handshake (mongoc_stream_t *stream,
                                int32_t          timeout_msec)
{
   mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *)stream;

   BSON_ASSERT (tls);

   tls->timeout_msec = timeout_msec;

   if (BIO_do_handshake (tls->bio) == 1) {
      return true;
   }

   if (!errno) {
#ifdef _WIN32
      errno = WSAETIMEDOUT;
#else
      errno = ETIMEDOUT;
#endif
   }

   return false;
}
Exemple #11
0
int main(int argc, char **argv)
{
    BIO *sbio = NULL, *out = NULL;
    int i, len, rv;
    char tmpbuf[1024];
    SSL_CTX *ctx = NULL;
    SSL_CONF_CTX *cctx = NULL;
    SSL *ssl = NULL;
    CONF *conf = NULL;
    STACK_OF(CONF_VALUE) *sect = NULL;
    CONF_VALUE *cnf;
    const char *connect_str = "localhost:4433";
    long errline = -1;

    ERR_load_crypto_strings();
    ERR_load_SSL_strings();
    SSL_library_init();

    conf = NCONF_new(NULL);

    if (NCONF_load(conf, "connect.cnf", &errline) <= 0) {
        if (errline <= 0)
            fprintf(stderr, "Error processing config file\n");
        else
            fprintf(stderr, "Error on line %ld\n", errline);
        goto end;
    }

    sect = NCONF_get_section(conf, "default");

    if (sect == NULL) {
        fprintf(stderr, "Error retrieving default section\n");
        goto end;
    }

    ctx = SSL_CTX_new(SSLv3_client_method());
    cctx = SSL_CONF_CTX_new();
    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
    SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
    for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
        cnf = sk_CONF_VALUE_value(sect, i);
        rv = SSL_CONF_cmd(cctx, cnf->name, cnf->value);
        if (rv > 0)
            continue;
        if (rv != -2) {
            fprintf(stderr, "Error processing %s = %s\n",
                    cnf->name, cnf->value);
            ERR_print_errors_fp(stderr);
            goto end;
        }
        if (!strcmp(cnf->name, "Connect")) {
            connect_str = cnf->value;
        } else {
            fprintf(stderr, "Unknown configuration option %s\n", cnf->name);
            goto end;
        }
    }

    if (!SSL_CONF_CTX_finish(cctx)) {
        fprintf(stderr, "Finish error\n");
        ERR_print_errors_fp(stderr);
        goto err;
    }

    /*
     * We'd normally set some stuff like the verify paths and * mode here
     * because as things stand this will connect to * any server whose
     * certificate is signed by any CA.
     */

    sbio = BIO_new_ssl_connect(ctx);

    BIO_get_ssl(sbio, &ssl);

    if (!ssl) {
        fprintf(stderr, "Can't locate SSL pointer\n");
        goto end;
    }

    /* Don't want any retries */
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

    /* We might want to do other things with ssl here */

    BIO_set_conn_hostname(sbio, connect_str);

    out = BIO_new_fp(stdout, BIO_NOCLOSE);
    if (BIO_do_connect(sbio) <= 0) {
        fprintf(stderr, "Error connecting to server\n");
        ERR_print_errors_fp(stderr);
        goto end;
    }

    if (BIO_do_handshake(sbio) <= 0) {
        fprintf(stderr, "Error establishing SSL connection\n");
        ERR_print_errors_fp(stderr);
        goto end;
    }

    /* Could examine ssl here to get connection info */

    BIO_puts(sbio, "GET / HTTP/1.0\n\n");
    for (;;) {
        len = BIO_read(sbio, tmpbuf, 1024);
        if (len <= 0)
            break;
        BIO_write(out, tmpbuf, len);
    }
 end:
    SSL_CONF_CTX_free(cctx);
    BIO_free_all(sbio);
    BIO_free(out);
    NCONF_free(conf);
    return 0;
}
Exemple #12
0
static LUA_FUNCTION(openssl_bio_handshake)
{
  BIO* bio = CHECK_OBJECT(1, BIO, "openssl.bio");
  int ret = BIO_do_handshake(bio);
  return openssl_pushresult(L, ret);
}
Exemple #13
0
int redisContextConnectSSL(redisContext *c, const char *addr, int port, char* certfile, char* certdir, struct timeval *timeout) {
    struct timeval  start_time;
    int             has_timeout = 0;
    int             is_nonblocking = 0;

    c->ssl.sd = -1;
    c->ssl.ctx = NULL;
    c->ssl.ssl = NULL;
    c->ssl.bio = NULL;

    // Set up a SSL_CTX object, which will tell our BIO object how to do its work
    SSL_CTX* ctx = SSL_CTX_new(TLSv1_1_client_method());
    c->ssl.ctx = ctx;

    // Create a SSL object pointer, which our BIO object will provide.
    SSL* ssl;

    // Create our BIO object for SSL connections.
    BIO* bio = BIO_new_ssl_connect(ctx);
    c->ssl.bio = bio;

    // Failure?
    if (bio == NULL) {
        char errorbuf[1024];
        __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Error creating BIO!\n");

        ERR_error_string(1024,errorbuf);
        __redisSetError(c,REDIS_ERR_OTHER,errorbuf);

        // We need to free up the SSL_CTX before we leave.
        cleanupSSL( &c->ssl );
        return REDIS_ERR;
    }

    // Makes ssl point to bio's SSL object.
    BIO_get_ssl(bio, &ssl);
    c->ssl.ssl = ssl;

    // Set the SSL to automatically retry on failure.
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

    char* connect_str = (char *)calloc( 1, strlen( addr ) + 10 );
    sprintf( connect_str, "%s:%d", addr, port );
    c->ssl.conn_str = connect_str;

    // We're connection to the REDIS server at host:port
    BIO_set_conn_hostname(bio, connect_str);

    SSL_CTX_load_verify_locations(ctx, certfile, certdir);

    // Are we supposed to be blocking or non-blocking?
    if( (c->flags & REDIS_BLOCK) == 0) {
        is_nonblocking = 1;
        BIO_set_nbio(bio,1);
    }

    // What about a timeout?
    // If we're blocking and have a timeout, we need to handle that specially
    if( NULL != timeout ) {
        BIO_set_nbio(bio,1);
        has_timeout = 1;
        gettimeofday(&start_time, NULL);
    }

    while(1) {
        struct timeval	cur_time,
                    elapsed_time;

        if (has_timeout) {
            gettimeofday(&cur_time, NULL);
            elapsed_time = subtractTimeval( cur_time, start_time );

            if (compareTimeval( elapsed_time, *timeout) > 0) {
                char errorbuf[1024];

                __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Connection timed out.");
                ERR_error_string(1024,errorbuf);
                __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
                cleanupSSL( &(c->ssl) );
                return REDIS_ERR;
            }
        }

        // Same as before, try to connect.
        if (BIO_do_connect(bio) <= 0 ) {
            if( BIO_should_retry( bio ) ) {
                // We need to retry.
            } else {
                char errorbuf[1024];
                __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Failed to connect");
                ERR_error_string(1024,errorbuf);
                __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
                cleanupSSL( &(c->ssl) );
                return REDIS_ERR;
            }
        } else {
            // connect is done...
            break;
        }

        if( has_timeout ) {
            // Do select and seelct on it
            int result;
            int fd = BIO_get_fd( bio, NULL );
            struct timeval time_left;

            if (has_timeout) {
                time_left = subtractTimeval( *timeout, elapsed_time );
            }

            fd_set readset, writeset;
            FD_ZERO(&readset);
            FD_SET(fd, &readset);
            FD_ZERO(&writeset);
            FD_SET(fd, &writeset);

            do {
                result = select( fd+1, &readset, &writeset, NULL, &time_left);
            } while( result == -1 && errno == EINTR );
        }

    }

    while(1) {
        struct timeval	cur_time,
                    elapsed_time;

        if (has_timeout) {
            gettimeofday(&cur_time, NULL);
            elapsed_time = subtractTimeval( cur_time, start_time );

            if (compareTimeval( elapsed_time, *timeout) > 0) {
                char errorbuf[1024];

                __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Connection timed out.");
                ERR_error_string(1024,errorbuf);
                __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
                cleanupSSL( &(c->ssl) );
                return REDIS_ERR;
            }
        }

        // Now we need to do the SSL handshake, so we can communicate.
        if (BIO_do_handshake(bio) <= 0) {
            if( BIO_should_retry( bio ) ) {
                // We need to retry.
            } else {
                char errorbuf[1024];
                __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: handshake failure");
                ERR_error_string(1024,errorbuf);
                __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
                cleanupSSL( &(c->ssl) );
                return REDIS_ERR;
            }
        } else {
            // handshake is done...
            break;
        }

        if( has_timeout ) {
            // Do select and seelct on it
            int result;
            int fd = BIO_get_fd( bio, NULL );
            struct timeval time_left;

            if (has_timeout) {
                time_left = subtractTimeval( *timeout, elapsed_time );
            }

            fd_set readset, writeset;
            FD_ZERO(&readset);
            FD_SET(fd, &readset);
            FD_ZERO(&writeset);
            FD_SET(fd, &writeset);

            do {
                result = select( fd+1, &readset, &writeset, NULL, &time_left);
            } while( result == -1 && errno == EINTR );
        }

    }

    long verify_result = SSL_get_verify_result(ssl);
    if( verify_result == X509_V_OK) {
        X509* peerCertificate = SSL_get_peer_certificate(ssl);

        char commonName [512];
        X509_NAME * name = X509_get_subject_name(peerCertificate);
        X509_NAME_get_text_by_NID(name, NID_commonName, commonName, 512);

        // TODO: Add a redis config parameter for the common name to check for.
        //       Since Redis connections are generally done with an IP address directly,
        //       we can't just assume that the name we get on the addr is an actual name.
        //
        //    if(strcasecmp(commonName, "BradBroerman") != 0) {
        //      __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Error validating cert common name.\n\n" );
        //      cleanupSSL( &(c->ssl) );
        //      return REDIS_ERR;

    } else {
        char errorbuf[1024];
        __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Error retrieving peer certificate.\n" );
        ERR_error_string(1024,errorbuf);
        __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
        cleanupSSL( &(c->ssl) );
        return REDIS_ERR;
    }

    BIO_set_nbio(bio,is_nonblocking);

    return REDIS_OK;
}
Exemple #14
0
/**
 * Run SSL handshake and store the resulting time value in the
 * 'time_map'.
 *
 * @param time_map where to store the current time
 */
static void
run_ssl (uint32_t *time_map)
{
  BIO *s_bio;
  BIO *c_bio;
  SSL_CTX *ctx;
  SSL *ssl;

  SSL_load_error_strings();
  SSL_library_init();

  ctx = NULL;
  if (0 == strcmp("sslv23", protocol))
  {
    verb ("V: using SSLv23_client_method()\n");
    ctx = SSL_CTX_new(SSLv23_client_method());
  } else if (0 == strcmp("sslv3", protocol))
  {
    verb ("V: using SSLv3_client_method()\n");
    ctx = SSL_CTX_new(SSLv3_client_method());
  } else if (0 == strcmp("tlsv1", protocol))
  {
    verb ("V: using TLSv1_client_method()\n");
    ctx = SSL_CTX_new(TLSv1_client_method());
  } else
    die("Unsupported protocol `%s'\n", protocol);

  if (ctx == NULL)
    die("OpenSSL failed to support protocol `%s'\n", protocol);

  if (ca_racket)
  {
    // For google specifically:
    // SSL_CTX_load_verify_locations(ctx, "/etc/ssl/certs/Equifax_Secure_CA.pem", NULL);
    if (1 != SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ssl/certs/"))
      fprintf(stderr, "SSL_CTX_load_verify_locations failed\n");
  }

  if (NULL == (s_bio = BIO_new_ssl_connect(ctx)))
    die ("SSL BIO setup failed\n");
  BIO_get_ssl(s_bio, &ssl);
  if (NULL == ssl)
    die ("SSL setup failed\n");
  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
  if ( (1 != BIO_set_conn_hostname(s_bio, host)) ||
       (1 != BIO_set_conn_port(s_bio, port)) )
    die ("Failed to initialize connection to `%s:%s'\n", host, port);

  if (NULL == (c_bio = BIO_new_fp(stdout, BIO_NOCLOSE)))
    die ("FIXME: error message");

  // This should run in seccomp
  // eg:     prctl(PR_SET_SECCOMP, 1);
  if (1 != BIO_do_connect(s_bio)) // XXX TODO: BIO_should_retry() later?
    die ("SSL connection failed\n");    
  if (1 != BIO_do_handshake(s_bio))
    die ("SSL handshake failed\n");
  // Verify the peer certificate against the CA certs on the local system
  if (ca_racket) {
    X509 *x509;
    long ssl_verify_result;

    if (NULL == (x509 = SSL_get_peer_certificate(ssl)) )
      die ("Getting SSL certificate failed\n");

    // In theory, we verify that the cert is valid
    ssl_verify_result = SSL_get_verify_result(ssl);
    switch (ssl_verify_result)
    {
    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
      die ("SSL certificate is self signed\n");
    case X509_V_OK:
      verb ("V: SSL certificate verification passed\n");
      break;
    default:
      die ("SSL certification verification error: %ld\n", 
	   ssl_verify_result);
    }
  } else {
    verb ("V: Certificate verification skipped!\n");
  }

  // from /usr/include/openssl/ssl3.h
  //  ssl->s3->server_random is an unsigned char of 32 bytes
  memcpy(time_map, ssl->s3->server_random, sizeof (uint32_t));  
}
Exemple #15
0
struct dyString *bio(char *host, char *url, char *certFile, char *certPath)
/*
This SSL/TLS client example, attempts to retrieve a page from an SSL/TLS web server. 
The I/O routines are identical to those of the unencrypted example in BIO_s_connect(3).
*/
{
struct dyString *dy = dyStringNew(0);
char hostnameProto[256];
char requestLine[4096];

BIO *sbio;
int len;
char tmpbuf[1024];
SSL_CTX *ctx;
SSL *ssl;

SSL_library_init();
ERR_load_crypto_strings();
ERR_load_SSL_strings();
OpenSSL_add_all_algorithms();

/* We would seed the PRNG here if the platform didn't
* do it automatically
*/

ctx = SSL_CTX_new(SSLv23_client_method());
if (certFile || certPath)
    {
    SSL_CTX_load_verify_locations(ctx,certFile,certPath);
#if (OPENSSL_VERSION_NUMBER < 0x0090600fL)
    SSL_CTX_set_verify_depth(ctx,1);
#endif
    }

/* We'd normally set some stuff like the verify paths and
* mode here because as things stand this will connect to
* any server whose certificate is signed by any CA.
*/

sbio = BIO_new_ssl_connect(ctx);

BIO_get_ssl(sbio, &ssl);

if(!ssl) 
    {
    fprintf(stderr, "Can't locate SSL pointer\n");
    return NULL;
    }

/* Don't want any retries */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

/* We might want to do other things with ssl here */

safef(hostnameProto,sizeof(hostnameProto),"%s:https",host);
BIO_set_conn_hostname(sbio, hostnameProto);

if(BIO_do_connect(sbio) <= 0) 
    {
    fprintf(stderr, "Error connecting to server\n");
    ERR_print_errors_fp(stderr);
    return NULL;
    }

if(BIO_do_handshake(sbio) <= 0) 
    {
    fprintf(stderr, "Error establishing SSL connection\n");
    ERR_print_errors_fp(stderr);
    return NULL;
    }

if (certFile || certPath)
    if (!check_cert(ssl, host))
	return NULL;

/* Could examine ssl here to get connection info */

safef(requestLine,sizeof(requestLine),"GET %s HTTP/1.0\n\n",url);
BIO_puts(sbio, requestLine);
for(;;) 
    {
    len = BIO_read(sbio, tmpbuf, 1024);
    if(len <= 0) break;
    dyStringAppendN(dy, tmpbuf, len);
    }
BIO_free_all(sbio);

return dy;
}
Exemple #16
0
int main(){
  int len = 1024; //buffer length
  char buf[len]; //read buffer
  
  /* Initializing OpenSSL */
  SSL_load_error_strings();
  ERR_load_BIO_strings();
  OpenSSL_add_all_algorithms();
  SSL_library_init();

  BIO *bio, *abio, *out; //the sockets
  SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
  SSL *ssl;

  if( ctx == NULL ){
    fprintf(stderr, "DEBUG ctx is null\n");
    fprintf(stderr, "ERROR::OpenSLL: %s\n", ERR_reason_error_string(ERR_get_error()));
    exit(1);
  }
  
  //get password for private key
  //  SSL_CTX_set_default_passwd_cb( ctx, &pem_passwd_cb );

  //load certificate (with public key)
  SSL_CTX_use_certificate_file( ctx, "/home/mml/Develop/ca/certs/01.pem", SSL_FILETYPE_PEM);
  //load private key
  SSL_CTX_use_PrivateKey_file( ctx, "/home/mml/Develop/ca/testkey.pem", SSL_FILETYPE_PEM);

  bio = BIO_new_ssl(ctx, 0);
  if( bio == NULL ){
    fprintf(stderr, "ERROR cannot bind\n");
    exit(1);
  }

  BIO_get_ssl(bio, &ssl);
  SSL_set_mode( ssl, SSL_MODE_AUTO_RETRY );

  abio = BIO_new_accept("localhost:15001");
  BIO_set_accept_bios(abio, bio);

  BIO_do_accept(abio);

  fprintf(stdout, "DEBUG: waiting for connection\n");
  BIO_do_accept(abio);

  out = BIO_pop(abio);

  fprintf(stdout, "DEBUG: doing handshake\n");
  BIO_do_handshake(out);
  
  if(BIO_write(out, "Hello", 5) <= 0){
    if(! BIO_should_retry(bio)) {
      fprintf(stderr, "ERROR connection is already closed. (write)\n");
      exit(1);
    } else {
      //retry routine
    }
  }
  
  bzero(buf, len); 
  if( BIO_read(out, buf, len) <= 0 ){
    if( !(BIO_should_retry(bio)) ){
      fprintf(stderr, "ERROR connection is already closed (read)\n");
      exit(0);
      
    } else {
      //retry routine
    }
  }

  fprintf(stdout, "Hello%s\n", buf);

  //close connection
  BIO_free_all(abio);
  BIO_free_all(out);
  BIO_free_all(bio);
  SSL_CTX_free(ctx);
  
  return 0;
}
Exemple #17
0
HTTPScode
https_open(struct https_request **reqp, const char *host)
{
        struct https_request *req;
        BIO *b64, *sbio;
        char *p;
        int n;
        int connection_error = 0;
        const char *api_host;
        const char *api_port;

        /* Set up our handle */
        n = 1;
        if ((req = calloc(1, sizeof(*req))) == NULL ||
            (req->host = strdup(host)) == NULL ||
            (req->parser = malloc(sizeof(http_parser))) == NULL) {
                ctx->errstr = strerror(errno);
                https_close(&req);
                return (HTTPS_ERR_SYSTEM);
        }
        if ((p = strchr(req->host, ':')) != NULL) {
                *p = '\0';
                req->port = p + 1;
        } else {
                req->port = "443";
        }
        if ((req->body = BIO_new(BIO_s_mem())) == NULL) {
                ctx->errstr = _SSL_strerror();
                https_close(&req);
                return (HTTPS_ERR_LIB);
        }
        http_parser_init(req->parser, HTTP_RESPONSE);
        req->parser->data = req;

        /* Connect to server */
        if (ctx->proxy) {
            api_host = ctx->proxy;
            api_port = ctx->proxy_port;
        } else {
            api_host = req->host;
            api_port = req->port;
        }
        connection_error = _establish_connection(req, api_host, api_port);
        if (connection_error != HTTPS_OK) {
            https_close(&req);
            return connection_error;
        }

        /* Tunnel through proxy, if specified */
        if (ctx->proxy != NULL) {
                BIO_printf(req->cbio,
                    "CONNECT %s:%s HTTP/1.0\r\n"
                    "User-Agent: %s\r\n",
                    req->host, req->port, ctx->useragent);
                
                if (ctx->proxy_auth != NULL) {
                        b64 = BIO_push(BIO_new(BIO_f_base64()),
                            BIO_new(BIO_s_mem()));
                        BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL);
                        BIO_write(b64, ctx->proxy_auth,
                            strlen(ctx->proxy_auth));
                        (void)BIO_flush(b64);
                        n = BIO_get_mem_data(b64, &p);

                        BIO_puts(req->cbio, "Proxy-Authorization: Basic ");
                        BIO_write(req->cbio, p, n);
                        BIO_puts(req->cbio, "\r\n");
                        BIO_free_all(b64);
                }
                BIO_puts(req->cbio, "\r\n");
                (void)BIO_flush(req->cbio);
                
                while ((n = BIO_read(req->cbio, ctx->parse_buf,
                            sizeof(ctx->parse_buf))) <= 0) {
                        _BIO_wait(req->cbio, 5000);
                }
                if (strncmp("HTTP/1.0 200", ctx->parse_buf, 12) != 0) {
                        snprintf(ctx->errbuf, sizeof(ctx->errbuf),
                            "Proxy error: %s", ctx->parse_buf);
                        ctx->errstr = strtok(ctx->errbuf, "\r\n");
                        https_close(&req);
                        if (n < 12 || atoi(ctx->parse_buf + 9) < 500)
                                return (HTTPS_ERR_CLIENT);
                        return (HTTPS_ERR_SERVER);
                }
        }
        /* Establish SSL connection */
        if ((sbio = BIO_new_ssl(ctx->ssl_ctx, 1)) == NULL) {
                https_close(&req);
                return (HTTPS_ERR_LIB);
        }
        req->cbio = BIO_push(sbio, req->cbio);
        BIO_get_ssl(req->cbio, &req->ssl);
        
        while (BIO_do_handshake(req->cbio) <= 0) {
                if ((n = _BIO_wait(req->cbio, 5000)) != 1) {
                        ctx->errstr = n ? _SSL_strerror() :
                            "SSL handshake timed out";
                        https_close(&req);
                        return (n ? HTTPS_ERR_SYSTEM : HTTPS_ERR_SERVER);
                }
        }
        /* Validate server certificate name */
        if (_SSL_check_server_cert(req->ssl, req->host) != 1) {
                ctx->errstr = "Certificate name validation failed";
                https_close(&req);
                return (HTTPS_ERR_LIB);
        }
        *reqp = req;
        
        return (HTTPS_OK);
}
Exemple #18
0
//construct an SSL connection to the server at the desired address
//gives back a struct containing the BIO and SSL constructs necessary
//to manage a connection.
//
//Requires a directory where require certificates and public keys are stored and their names
struct ssl_connection * connect_to(char *address, char *certpath, char *cacert, char *cert, char *privkey)
{
	struct ssl_connection *conn = calloc(1, sizeof *conn);
	//BIO *bio;
	//SSL *ssl;
	SSL_CTX *ctx = (SSL_CTX *)SSL_CTX_new(SSLv23_client_method());

	printf("LOADING CA CERT\n");
	//load our ca certificate
	if(SSL_CTX_load_verify_locations(ctx, string_cat(3,certpath,"/",cacert), NULL) == 0) 
	{
		printf("FAILING\n");
		ssl_error("Server cert load fail");
		exit(1);
	}

	printf("LOADING CLIENT CERT\n");
	//load our certificate used to send files
	if(SSL_CTX_use_certificate_file(ctx, string_cat(3,certpath,"/",cert), SSL_FILETYPE_PEM) < 1)
	{
		ssl_error("failed to load client cert");
		exit(1);
	}
	
	
	printf("LOADING PRIVATE KEY\n");
	//load our private key
	if(SSL_CTX_use_PrivateKey_file(ctx, string_cat(3,certpath,"/",privkey), SSL_FILETYPE_PEM) < 1)
	{
		ssl_error("failed to load private key");
		exit(1);
	}
	
	SSL_CTX_set_timeout(ctx, 5);

	conn->bio = BIO_new_ssl_connect(ctx);
	if(conn->bio == NULL)
	{
		ssl_error("bio creation fail");
		exit(1);
	}

	//set up connection
	BIO_get_ssl(conn->bio, &conn->ssl);
	SSL_set_mode(conn->ssl, SSL_MODE_AUTO_RETRY);
	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);

	

	//client stuff goes here
	//set server hostname
	if(BIO_set_conn_hostname(conn->bio, address) <= 0)
	{
		printf("Address error\n");
		ssl_error("BIO connect error");
		exit(1);

	}
	//printf("attempting to connect to %s\n",address);
	//test connection
	if(BIO_do_connect(conn->bio) <= 0)
	{
		printf("CONNECTION ERROR!?!?!?\n");
		ssl_error("BIO connect error");
		exit(1);
	}
	
	

	//verify the certificate
	if(BIO_do_handshake(conn->bio) > 0) {
		//printf("HANDSHAKE SUCCESS\n");
		if(SSL_get_verify_result(conn->ssl) == X509_V_OK) {
			X509 *server_cert = SSL_get_peer_certificate(conn->ssl);
			if(server_cert == NULL) {
				printf("Didn't get a server certificate\n");
				return NULL;
			}
			return conn;
		} else
			printf("CANNOT VERIFY SERVER CERTIFICATE! SHUTTING DOWN!!!\n");
	} else
		printf("HANDSHAKE FAIL\n");
	return NULL; //FAILURE
}
Exemple #19
0
int crashreport_send(char *fname)
{
	char buf[1024];
	char header[512], footer[512];
	char delimiter[41];
	int filesize;
	int n;
	FILE *fd;
	SSL_CTX *ctx_client;
	BIO *socket = NULL;
	
	filesize = getfilesize(fname);
	if (filesize < 0)
		return 0;
	
	for (n = 0; n < sizeof(delimiter); n++)
		delimiter[n] = getrandom8()%26 + 'a';
	delimiter[sizeof(delimiter)-1] = '\0';
	
	snprintf(header, sizeof(header), "--%s\r\n"
	                           "Content-Disposition: form-data; name=\"upload\"; filename=\"crash.txt\"\r\n"
	                           "Content-Type: text/plain\r\n"
	                           "\r\n",
	                           delimiter);
	snprintf(footer, sizeof(footer), "\r\n--%s--\r\n", delimiter);

	ctx_client = crashreport_init_ssl();
	if (!ctx_client)
	{
		printf("ERROR: SSL initalization failure (I)\n");
		return 0;
	}
	
	socket = BIO_new_ssl_connect(ctx_client);
	if (!socket)
	{
		printf("ERROR: SSL initalization failure (II)\n");
		return 0;
	}
	
	BIO_set_conn_hostname(socket, CRASH_REPORT_HOST ":443");

	if (BIO_do_connect(socket) != 1)
	{
		printf("ERROR: Could not connect to %s\n", CRASH_REPORT_HOST);
		return 0;
	}
	
	if (BIO_do_handshake(socket) != 1)
	{
		printf("ERROR: Could not connect to %s (SSL handshake failed)\n", CRASH_REPORT_HOST);
		return 0;
	}
	
	snprintf(buf, sizeof(buf), "POST /crash.php HTTP/1.1\r\n"
	                    "User-Agent: UnrealIRCd %s\r\n"
	                    "Host: %s\r\n"
	                    "Accept: */*\r\n"
	                    "Content-Length: %d\r\n"
	                    "Expect: 100-continue\r\n"
	                    "Content-Type: multipart/form-data; boundary=%s\r\n"
	                    "\r\n",
	                    VERSIONONLY,
	                    CRASH_REPORT_HOST,
	                    (int)(filesize+strlen(header)+strlen(footer)),
	                    delimiter);
	
	BIO_puts(socket, buf);
	
	memset(buf, 0, sizeof(buf));
	n = BIO_read(socket, buf, 255);
	if ((n < 0) || strncmp(buf, "HTTP/1.1 100", 12))
	{
		printf("Error transmitting bug report (stage II, n=%d)\n", n);
		return 0;
	}
	
	fd = fopen(fname, "rb");
	if (!fd)
		return 0;

	BIO_puts(socket, header);
	
	while ((fgets(buf, sizeof(buf), fd)))
	{
		BIO_puts(socket, buf);
	}
	fclose(fd);

	BIO_puts(socket, footer);

	do { } while(BIO_should_retry(socket)); /* make sure we are really finished (you never know with SSL) */
	
	BIO_free_all(socket);
	
	SSL_CTX_free(ctx_client);
	
	return 1;
}
Exemple #20
0
bool tls_socket::connect()
{
	sock_closed = false;
	if(BIO_do_connect(bio) != 1)
	{
		print_error();
		return false;
	}

	if(BIO_do_handshake(bio) != 1)
	{
		print_error();
		return false;
	}

	/* Step 1: verify a server certificate was presented during the negotiation */
	X509* cert = SSL_get_peer_certificate(ssl);
	if(cert == nullptr)
	{
		print_error();
		return false;
	}

	const EVP_MD* digest;
	unsigned char md[EVP_MAX_MD_SIZE];
	unsigned int dlen;

	digest = EVP_get_digestbyname("sha256");
	if(digest == nullptr)
	{
		print_error();
		return false;
	}

	if(X509_digest(cert, digest, md, &dlen) != 1)
	{
		X509_free(cert);
		print_error();
		return false;
	}

	//Base64 encode digest
	BIO *bmem, *b64;
	b64 = BIO_new(BIO_f_base64());
	bmem = BIO_new(BIO_s_mem());

	BIO_puts(bmem, "SHA256:");
	b64 = BIO_push(b64, bmem);
	BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
	BIO_write(b64, md, dlen);
	BIO_flush(b64);

	const char* conf_md = pCallback->get_tls_fp();
	char *b64_md = nullptr;
	size_t b64_len = BIO_get_mem_data(bmem, &b64_md);

	if(strlen(conf_md) == 0)
	{
		if(!pCallback->is_dev_pool())
			printer::inst()->print_msg(L1, "TLS fingerprint [%s] %.*s", pCallback->get_pool_addr(), (int)b64_len, b64_md);
	}
	else if(strncmp(b64_md, conf_md, b64_len) != 0)
	{
		if(!pCallback->is_dev_pool())
		{
			printer::inst()->print_msg(L0, "FINGERPRINT FAILED CHECK [%s] %.*s was given, %s was configured",
				pCallback->get_pool_addr(), (int)b64_len, b64_md, conf_md);
		}

		pCallback->set_socket_error("FINGERPRINT FAILED CHECK");
		BIO_free_all(b64);
		X509_free(cert);
		return false;
	}

	BIO_free_all(b64);

	X509_free(cert);
	return true;
}
Exemple #21
0
int main(int argc, char **argv)
{
    BIO *sbio = NULL, *out = NULL;
    int len;
    char tmpbuf[1024];
    SSL_CTX *ctx;
    SSL_CONF_CTX *cctx;
    SSL *ssl;
    char **args = argv + 1;
    const char *connect_str = "localhost:4433";
    int nargs = argc - 1;

    ERR_load_crypto_strings();
    ERR_load_SSL_strings();
    SSL_library_init();

    ctx = SSL_CTX_new(TLS_client_method());
    cctx = SSL_CONF_CTX_new();
    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
    SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
    while (*args && **args == '-') {
        int rv;
        /* Parse standard arguments */
        rv = SSL_CONF_cmd_argv(cctx, &nargs, &args);
        if (rv == -3) {
            fprintf(stderr, "Missing argument for %s\n", *args);
            goto end;
        }
        if (rv < 0) {
            fprintf(stderr, "Error in command %s\n", *args);
            ERR_print_errors_fp(stderr);
            goto end;
        }
        /* If rv > 0 we processed something so proceed to next arg */
        if (rv > 0)
            continue;
        /* Otherwise application specific argument processing */
        if (strcmp(*args, "-connect") == 0) {
            connect_str = args[1];
            if (connect_str == NULL) {
                fprintf(stderr, "Missing -connect argument\n");
                goto end;
            }
            args += 2;
            nargs -= 2;
            continue;
        } else {
            fprintf(stderr, "Unknown argument %s\n", *args);
            goto end;
        }
    }

    if (!SSL_CONF_CTX_finish(cctx)) {
        fprintf(stderr, "Finish error\n");
        ERR_print_errors_fp(stderr);
        goto end;
    }

    /*
     * We'd normally set some stuff like the verify paths and * mode here
     * because as things stand this will connect to * any server whose
     * certificate is signed by any CA.
     */

    sbio = BIO_new_ssl_connect(ctx);

    BIO_get_ssl(sbio, &ssl);

    if (!ssl) {
        fprintf(stderr, "Can't locate SSL pointer\n");
        goto end;
    }

    /* Don't want any retries */
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

    /* We might want to do other things with ssl here */

    BIO_set_conn_hostname(sbio, connect_str);

    out = BIO_new_fp(stdout, BIO_NOCLOSE);
    if (BIO_do_connect(sbio) <= 0) {
        fprintf(stderr, "Error connecting to server\n");
        ERR_print_errors_fp(stderr);
        goto end;
    }

    if (BIO_do_handshake(sbio) <= 0) {
        fprintf(stderr, "Error establishing SSL connection\n");
        ERR_print_errors_fp(stderr);
        goto end;
    }

    /* Could examine ssl here to get connection info */

    BIO_puts(sbio, "GET / HTTP/1.0\n\n");
    for (;;) {
        len = BIO_read(sbio, tmpbuf, 1024);
        if (len <= 0)
            break;
        BIO_write(out, tmpbuf, len);
    }
 end:
    SSL_CONF_CTX_free(cctx);
    BIO_free_all(sbio);
    BIO_free(out);
    return 0;
}
Exemple #22
0
/**
 * Run SSL handshake and store the resulting time value in the
 * 'time_map'.
 *
 * @param time_map where to store the current time
 */
static void
run_ssl (uint32_t *time_map, int time_is_an_illusion)
{
  BIO *s_bio;
  SSL_CTX *ctx;
  SSL *ssl;

  SSL_load_error_strings();
  SSL_library_init();

  ctx = NULL;
  if (0 == strcmp("sslv23", protocol))
  {
    verb ("V: using SSLv23_client_method()\n");
    ctx = SSL_CTX_new(SSLv23_client_method());
  } else if (0 == strcmp("sslv3", protocol))
  {
    verb ("V: using SSLv3_client_method()\n");
    ctx = SSL_CTX_new(SSLv3_client_method());
  } else if (0 == strcmp("tlsv1", protocol))
  {
    verb ("V: using TLSv1_client_method()\n");
    ctx = SSL_CTX_new(TLSv1_client_method());
  } else
    die("Unsupported protocol `%s'\n", protocol);

  if (ctx == NULL)
    die("OpenSSL failed to support protocol `%s'\n", protocol);

  if (ca_racket)
  {
    if (1 != SSL_CTX_load_verify_locations(ctx, NULL, certdir))
      fprintf(stderr, "SSL_CTX_load_verify_locations failed\n");
  }

  if (NULL == (s_bio = BIO_new_ssl_connect(ctx)))
    die ("SSL BIO setup failed\n");
  BIO_get_ssl(s_bio, &ssl);
  if (NULL == ssl)
    die ("SSL setup failed\n");

  if (time_is_an_illusion)
  {
    SSL_set_info_callback(ssl, openssl_time_callback);
  }

  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
  if ( (1 != BIO_set_conn_hostname(s_bio, host)) ||
       (1 != BIO_set_conn_port(s_bio, port)) )
    die ("Failed to initialize connection to `%s:%s'\n", host, port);

  if (NULL == BIO_new_fp(stdout, BIO_NOCLOSE))
    die ("BIO_new_fp returned error, possibly: %s", strerror(errno));

  // This should run in seccomp
  // eg:     prctl(PR_SET_SECCOMP, 1);
  if (1 != BIO_do_connect(s_bio)) // XXX TODO: BIO_should_retry() later?
    die ("SSL connection failed\n");
  if (1 != BIO_do_handshake(s_bio))
    die ("SSL handshake failed\n");

  // Verify the peer certificate against the CA certs on the local system
  if (ca_racket) {
    inspect_key (ssl, host);
  } else {
    verb ("V: Certificate verification skipped!\n");
  }
  check_key_length(ssl);
  // from /usr/include/openssl/ssl3.h
  //  ssl->s3->server_random is an unsigned char of 32 bits
  memcpy(time_map, ssl->s3->server_random, sizeof (uint32_t));
  SSL_free(ssl);
  SSL_CTX_free(ctx);
}
Exemple #23
0
int tls_do_handshake(rdpTls* tls, BOOL clientMode)
{
	CryptoCert cert;
	int verify_status, status;

	do
	{
#ifdef HAVE_POLL_H
		struct pollfd pollfds;
#else
		struct timeval tv;
		fd_set rset;
#endif
		int fd;

		status = BIO_do_handshake(tls->bio);

		if (status == 1)
			break;

		if (!BIO_should_retry(tls->bio))
			return -1;

		/* we select() only for read even if we should test both read and write
		 * depending of what have blocked */
		fd = BIO_get_fd(tls->bio, NULL);

		if (fd < 0)
		{
			DEBUG_WARN( "%s: unable to retrieve BIO fd\n", __FUNCTION__);
			return -1;
		}

#ifdef HAVE_POLL_H
		pollfds.fd = fd;
		pollfds.events = POLLIN;
		pollfds.revents = 0;

		do
		{
			status = poll(&pollfds, 1, 10 * 1000);
		}
		while ((status < 0) && (errno == EINTR));
#else
		FD_ZERO(&rset);
		FD_SET(fd, &rset);
		tv.tv_sec = 0;
		tv.tv_usec = 10 * 1000; /* 10ms */

		status = _select(fd + 1, &rset, NULL, NULL, &tv);
#endif
		if (status < 0)
		{
			DEBUG_WARN( "%s: error during select()\n", __FUNCTION__);
			return -1;
		}
	}
	while (TRUE);

	cert = tls_get_certificate(tls, clientMode);
	if (!cert)
	{
		DEBUG_WARN( "%s: tls_get_certificate failed to return the server certificate.\n", __FUNCTION__);
		return -1;
	}

	tls->Bindings = tls_get_channel_bindings(cert->px509);
	if (!tls->Bindings)
	{
		DEBUG_WARN( "%s: unable to retrieve bindings\n", __FUNCTION__);
		verify_status = -1;
		goto out;
	}

	if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
	{
		DEBUG_WARN( "%s: crypto_cert_get_public_key failed to return the server public key.\n", __FUNCTION__);
		verify_status = -1;
		goto out;
	}

	/* Note: server-side NLA needs public keys (keys from us, the server) but no
	 * 		certificate verify
	 */
	verify_status = 1;
	if (clientMode)
	{
		verify_status = tls_verify_certificate(tls, cert, tls->hostname, tls->port);

		if (verify_status < 1)
		{
			DEBUG_WARN( "%s: certificate not trusted, aborting.\n", __FUNCTION__);
			tls_disconnect(tls);
			verify_status = 0;
		}
	}

out:
	tls_free_certificate(cert);

	return verify_status;
}
Exemple #24
0
BIO *
httpsGetFileDesc(char * hostname, int port, char * remotename,
	char *extraHeaders, int *errorcode, char **returnedHeaders) 
{
	char *buf;
	char headers[4096];
	char *nextChar = headers;
	char *hstr;
	int sock;
	int rc;
	int checkedCode;
	int headerslen;

	int bufsize;
	int byteswritten;
	struct loaderData_s * loaderData;
	SSL_CTX *ssl_context;
	SSL *ssl;
	BIO *sbio = 0;
	X509 *server_cert;

	*errorcode = 0;

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (sock < 0) {
		logMessage(ERROR,
			"ROCKS:httpsGetFileDesc:Could not get a socket");
		*errorcode = FTPERR_FAILED_CONNECT;
		return NULL;
	}

	/* OpenSSL_add_all_algorithms(); */
	SSLeay_add_ssl_algorithms();

	ssl_context = SSL_CTX_new(SSLv23_client_method());
	if (!ssl_context) {
		logMessage(ERROR, "Could not create SSLv2,3 context");
		*errorcode = FTPERR_FAILED_CONNECT;
		goto error;
	}

	/* Pull in the Global Loader Data structure. */
	loaderData = rocks_global_loaderData;

	/* I have a Certificate */
	if (loaderData->cert_filename) {
		rc = SSL_CTX_use_certificate_file(ssl_context, 
			loaderData->cert_filename,
			SSL_FILETYPE_PEM);
		if (!rc) {
			logMessage(ERROR, "Could not read Cluster Certificate");
			*errorcode = FTPERR_CLIENT_SECURITY;
			goto error;
		}

		rc = SSL_CTX_use_PrivateKey_file(ssl_context, 
			loaderData->priv_filename,
			SSL_FILETYPE_PEM);
		if (!rc) {
			logMessage(ERROR,
				"Could not read Cluster cert private key");
			*errorcode = FTPERR_CLIENT_SECURITY;
			goto error;
		}

		/* Only connect to servers that have certs signed by
		 * our trusted CA. */
		if (loaderData->authParent) {
			rc = SSL_CTX_load_verify_locations(ssl_context,
				loaderData->ca_filename, 0);
			if (!rc) {
				logMessage(ERROR,
					"Could not read Server CA cert");
				*errorcode = FTPERR_CLIENT_SECURITY;
				goto error;
			}
			SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, 0);
			SSL_CTX_set_verify_depth(ssl_context, 1);
		}
	}

	sbio = BIO_new_ssl_connect(ssl_context);
	if (!sbio) {
		logMessage(ERROR, "Could not create SSL object");
		*errorcode = FTPERR_CLIENT_SECURITY;
		goto error;
	}

	BIO_get_ssl(sbio, &ssl);
	if (!ssl) {
		logMessage(ERROR, "Could not find ssl pointer.");
		*errorcode = FTPERR_CLIENT_SECURITY;
		goto error;
	}

	SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

	BIO_set_conn_hostname(sbio, hostname);
	BIO_set_conn_port(sbio, "https");

	rc = BIO_do_connect(sbio);
	if (rc<=0) {
		rc = SSL_get_verify_result(ssl);
		if (rc) {
			logMessage(ERROR, "Could not verify %s's identity",
				hostname);	
			*errorcode = FTPERR_REFUSED;
			goto error;
		}
		logMessage(ERROR, "Could not connect to %s:https", hostname);
		*errorcode = FTPERR_FAILED_CONNECT;
		goto error;
	}

	rc = BIO_do_handshake(sbio);
	if (rc<=0) {
		logMessage(ERROR,
			"Could not establish HTTPS connection with %s", 
			hostname);
		*errorcode = FTPERR_FAILED_CONNECT;
		goto error;
	}

	server_cert = SSL_get_peer_certificate(ssl);

	/* Show credentials if appropriate. */
	/* Don't Show Credentials */
	if ( (0 == 1)  && !loaderData->cert_filename 
			&& !loaderData->ekv
			&& !loaderData->dropCert) {

		rc = show_cert(server_cert);
		if (rc != 1) {
			*errorcode = FTPERR_REFUSED;
			goto error;
		}
	}

	if (extraHeaders)
		hstr = extraHeaders;
	else
		hstr = "";

	bufsize = strlen(remotename) + strlen(hostname) + strlen(hstr) + 30;

	if ((buf = malloc(bufsize)) == NULL) {
			logMessage(ERROR,
				"ROCKS:httpsGetFileDesc:malloc failed");
			*errorcode = FTPERR_FAILED_CONNECT;
			goto error;
	}

	sprintf(buf, "GET %s HTTP/1.0\r\nHost: %s\r\n%s\r\n", remotename, 
		hostname, hstr);

	byteswritten = BIO_puts(sbio, buf);

	logMessage(INFO,
		"ROCKS:httpsGetFileDesc:byteswritten(%d)", byteswritten);
	logMessage(INFO,
		"ROCKS:httpsGetFileDesc:bufsize(%d)", (int)strlen(buf));

	free(buf);

	/* This is fun; read the response a character at a time until we:
	1) Get our first \r\n; which lets us check the return code
	2) Get a \r\n\r\n, which means we're done */

	*nextChar = '\0';
	checkedCode = 0;
	headerslen = 0;
	while (!strstr(headers, "\r\n\r\n")) {

		if (BIO_read(sbio, nextChar, 1) != 1) {
			*errorcode = FTPERR_SERVER_SECURITY;
			goto error;
		}

		nextChar++;
		*nextChar = '\0';
		++headerslen;

		if (nextChar - headers == sizeof(headers)) {
			goto error;
		}

		if (!checkedCode && strstr(headers, "\r\n")) {
			char * start, * end;

			checkedCode = 1;
			start = headers;
			while (!isspace(*start) && *start) start++;
			if (!*start) {
				goto error;
			}

			while (isspace(*start) && *start) start++;

			end = start;
			while (!isspace(*end) && *end) end++;
			if (!*end) {
				goto error;
			}

			logMessage(INFO,
				"ROCKS:httpsGetFileDesc:status %s.", start);

			*end = '\0';
			if (!strcmp(start, "404"))
				goto error;
			else if (!strcmp(start, "403")) {
				*errorcode = FTPERR_SERVER_SECURITY;
				goto error;
			}
			else if (!strcmp(start, "503")) {
				/* A server nack - busy */
				logMessage(WARNING, "ROCKS:server busy");
				watchdog_reset();
				*errorcode = FTPERR_FAILED_DATA_CONNECT;
				goto error;
			}
			else if (strcmp(start, "200")) {
				*errorcode = FTPERR_BAD_SERVER_RESPONSE;
				goto error;
			}

			*end = ' ';
		}
	}

	if ((*returnedHeaders = (char *)malloc(headerslen + 1)) != NULL) {
		memcpy(*returnedHeaders, headers, headerslen + 1);
	}

	return sbio;

error:
	close(sock);
	if (sbio)
		BIO_free_all(sbio);
	if (!*errorcode)
		*errorcode = FTPERR_SERVER_IO_ERROR;
	logMessage(ERROR, "ROCKS:httpsGetFileDesc:Error %s", 
		ftpStrerror(*errorcode, URL_METHOD_HTTP));
	return NULL;
}
Exemple #25
0
/**
 * Run SSL handshake and store the resulting time value in the
 * 'time_map'.
 *
 * @param time_map where to store the current time
 * @param time_is_an_illusion
 * @param http whether to do an http request and take the date from that
 *     instead.
 */
static void
run_ssl (uint32_t *time_map, int time_is_an_illusion, int http)
{
  BIO *s_bio;
  SSL_CTX *ctx;
  SSL *ssl;
  struct stat statbuf;
  uint32_t result_time;

  SSL_load_error_strings();
  SSL_library_init();

  ctx = NULL;
  if (0 == strcmp("sslv23", protocol))
  {
    verb ("V: using SSLv23_client_method()");
    ctx = SSL_CTX_new(SSLv23_client_method());
  } else if (0 == strcmp("sslv3", protocol))
  {
    verb ("V: using SSLv3_client_method()");
    ctx = SSL_CTX_new(SSLv3_client_method());
  } else if (0 == strcmp("tlsv1", protocol))
  {
    verb ("V: using TLSv1_client_method()");
    ctx = SSL_CTX_new(TLSv1_client_method());
  } else
    die("Unsupported protocol `%s'", protocol);

  if (ctx == NULL)
    die("OpenSSL failed to support protocol `%s'", protocol);

  verb("V: Using OpenSSL for SSL");
  if (ca_racket)
  {
    if (-1 == stat(ca_cert_container, &statbuf))
    {
      die("Unable to stat CA certficate container %s", ca_cert_container);
    } else
    {
      switch (statbuf.st_mode & S_IFMT)
      {
      case S_IFREG:
        if (1 != SSL_CTX_load_verify_locations(ctx, ca_cert_container, NULL))
          fprintf(stderr, "SSL_CTX_load_verify_locations failed");
        break;
      case S_IFDIR:
        if (1 != SSL_CTX_load_verify_locations(ctx, NULL, ca_cert_container))
          fprintf(stderr, "SSL_CTX_load_verify_locations failed");
        break;
      default:
        if (1 != SSL_CTX_load_verify_locations(ctx, NULL, ca_cert_container))
        {
          fprintf(stderr, "SSL_CTX_load_verify_locations failed");
          die("Unable to load CA certficate container %s", ca_cert_container);
        }
      }
    }
  }

  if (NULL == (s_bio = make_ssl_bio(ctx)))
    die ("SSL BIO setup failed");
  BIO_get_ssl(s_bio, &ssl);
  if (NULL == ssl)
    die ("SSL setup failed");

  if (time_is_an_illusion)
  {
    SSL_set_info_callback(ssl, openssl_time_callback);
  }

  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
  verb("V: opening socket to %s:%s", host, port);
  if ( (1 != BIO_set_conn_hostname(s_bio, host)) ||
       (1 != BIO_set_conn_port(s_bio, port)) )
    die ("Failed to initialize connection to `%s:%s'", host, port);

  if (NULL == BIO_new_fp(stdout, BIO_NOCLOSE))
    die ("BIO_new_fp returned error, possibly: %s", strerror(errno));

  // This should run in seccomp
  // eg:     prctl(PR_SET_SECCOMP, 1);
  if (1 != BIO_do_connect(s_bio)) // XXX TODO: BIO_should_retry() later?
    die ("SSL connection failed");
  if (1 != BIO_do_handshake(s_bio))
    die ("SSL handshake failed");

  // from /usr/include/openssl/ssl3.h
  //  ssl->s3->server_random is an unsigned char of 32 bits
  memcpy(&result_time, ssl->s3->server_random, sizeof (uint32_t));
  verb("V: In TLS response, T=%lu", (unsigned long)ntohl(result_time));

  if (http) {
    char buf[1024];
    verb_debug ("V: Starting HTTP");
    if (snprintf(buf, sizeof(buf),
                 HTTP_REQUEST, HTTPS_USER_AGENT, hostname_to_verify) >= 1024)
      die("hostname too long");
    buf[1023]='\0'; /* Unneeded. */
    verb_debug ("V: Writing HTTP request");
    if (1 != write_all_to_bio(s_bio, buf))
      die ("write all to bio failed.");
    verb_debug ("V: Reading HTTP response");
    if (1 != read_http_date_from_bio(s_bio, &result_time))
      die ("read all from bio failed.");
    verb ("V: Received HTTP response. T=%lu", (unsigned long)result_time);

    result_time = htonl(result_time);
  }

  // Verify the peer certificate against the CA certs on the local system
  if (ca_racket) {
    inspect_key (ssl, hostname_to_verify);
  } else {
    verb ("V: Certificate verification skipped!");
  }
  check_key_length(ssl);

  memcpy(time_map, &result_time, sizeof (uint32_t));

  SSL_free(ssl);
  SSL_CTX_free(ctx);
}
Exemple #26
0
int tls_do_handshake(rdpTls* tls, BOOL clientMode)
{
	CryptoCert cert;
	int verify_status;

	do
	{
#ifdef HAVE_POLL_H
		int fd;
		int status;
		struct pollfd pollfds;
#elif !defined(_WIN32)
		int fd;
		int status;
		fd_set rset;
		struct timeval tv;
#else
		HANDLE event;
		DWORD status;
#endif
		status = BIO_do_handshake(tls->bio);

		if (status == 1)
			break;

		if (!BIO_should_retry(tls->bio))
			return -1;

#ifndef _WIN32
		/* we select() only for read even if we should test both read and write
		 * depending of what have blocked */
		fd = BIO_get_fd(tls->bio, NULL);

		if (fd < 0)
		{
			WLog_ERR(TAG, "unable to retrieve BIO fd");
			return -1;
		}

#else
		BIO_get_event(tls->bio, &event);

		if (!event)
		{
			WLog_ERR(TAG, "unable to retrieve BIO event");
			return -1;
		}

#endif
#ifdef HAVE_POLL_H
		pollfds.fd = fd;
		pollfds.events = POLLIN;
		pollfds.revents = 0;

		do
		{
			status = poll(&pollfds, 1, 10 * 1000);
		}
		while ((status < 0) && (errno == EINTR));

#elif !defined(_WIN32)
		FD_ZERO(&rset);
		FD_SET(fd, &rset);
		tv.tv_sec = 0;
		tv.tv_usec = 10 * 1000; /* 10ms */
		status = _select(fd + 1, &rset, NULL, NULL, &tv);
#else
		status = WaitForSingleObject(event, 10);
#endif
#ifndef _WIN32

		if (status < 0)
		{
			WLog_ERR(TAG, "error during select()");
			return -1;
		}

#else

		if ((status != WAIT_OBJECT_0) && (status != WAIT_TIMEOUT))
		{
			WLog_ERR(TAG, "error during WaitForSingleObject(): 0x%04X", status);
			return -1;
		}

#endif
	}
	while (TRUE);

	cert = tls_get_certificate(tls, clientMode);

	if (!cert)
	{
		WLog_ERR(TAG, "tls_get_certificate failed to return the server certificate.");
		return -1;
	}

	tls->Bindings = tls_get_channel_bindings(cert->px509);

	if (!tls->Bindings)
	{
		WLog_ERR(TAG, "unable to retrieve bindings");
		verify_status = -1;
		goto out;
	}

	if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
	{
		WLog_ERR(TAG,
		         "crypto_cert_get_public_key failed to return the server public key.");
		verify_status = -1;
		goto out;
	}

	/* server-side NLA needs public keys (keys from us, the server) but no certificate verify */
	verify_status = 1;

	if (clientMode)
	{
		verify_status = tls_verify_certificate(tls, cert, tls->hostname, tls->port);

		if (verify_status < 1)
		{
			WLog_ERR(TAG, "certificate not trusted, aborting.");
			tls_send_alert(tls);
			verify_status = 0;
		}
	}

out:
	tls_free_certificate(cert);
	return verify_status;
}
Status getTLSCertificate(std::string hostname, QueryData& results) {
  SSL_library_init();

  const auto method = TLSv1_method();
  if (method == nullptr) {
    return Status(1, "Failed to create OpenSSL method object");
  }

  auto delCTX = [](SSL_CTX* ctx) { SSL_CTX_free(ctx); };
  auto ctx =
      std::unique_ptr<SSL_CTX, decltype(delCTX)>(SSL_CTX_new(method), delCTX);
  if (ctx == nullptr) {
    return Status(1, "Failed to create OpenSSL CTX object");
  }

  auto delBIO = [](BIO* bio) { BIO_free_all(bio); };
  auto server = std::unique_ptr<BIO, decltype(delBIO)>(
      BIO_new_ssl_connect(ctx.get()), delBIO);
  if (server == nullptr) {
    return Status(1, "Failed to create OpenSSL BIO object");
  }

  std::string port = ":443";
  auto ext_hostname = hostname;
  auto conn_hostname = hostname;
  auto delim = hostname.find(":");
  if (delim == std::string::npos) {
    conn_hostname += ":443";
  } else {
    ext_hostname = hostname.substr(0, delim);
  }

  auto ret = BIO_set_conn_hostname(server.get(), conn_hostname.c_str());
  if (ret != 1) {
    return Status(1, "Failed to set OpenSSL hostname: " + std::to_string(ret));
  }

  SSL* ssl = nullptr;
  BIO_get_ssl(server.get(), &ssl);
  if (ssl == nullptr) {
    return Status(1, "Failed to retrieve OpenSSL object");
  }

  ret = SSL_set_tlsext_host_name(ssl, ext_hostname.c_str());
  if (ret != 1) {
    return Status(1,
                  "Failed to set OpenSSL server name: " + std::to_string(ret));
  }

  ret = BIO_do_connect(server.get());
  if (ret != 1) {
    return Status(1,
                  "Failed to establish TLS connection: " + std::to_string(ret));
  }

  ret = BIO_do_handshake(server.get());
  if (ret != 1) {
    return Status(1,
                  "Failed to complete TLS handshake: " + std::to_string(ret));
  }

  auto delX509 = [](X509* cert) { X509_free(cert); };
  auto cert = std::unique_ptr<X509, decltype(delX509)>(
      SSL_get_peer_certificate(ssl), delX509);
  if (cert == nullptr) {
    return Status(1, "No certificate");
  }

  Row r;
  r["hostname"] = hostname;
  fillRow(r, cert.get());
  results.push_back(r);
  return Status();
}
Exemple #28
0
int anetSSLGenericConnect( char* err, char* addr, int port, int flags, anetSSLConnection* sslctn, char* certFilePath, char* certDirPath, char* checkCommonName ) {
  sslctn->sd = -1;
  sslctn->ctx = NULL;
  sslctn->ssl = NULL;
  sslctn->bio = NULL;
  sslctn->conn_str = NULL;

  // Set up a SSL_CTX object, which will tell our BIO object how to do its work
  SSL_CTX* ctx = SSL_CTX_new(TLSv1_1_client_method());
  sslctn->ctx = ctx;

  // Create a SSL object pointer, which our BIO object will provide.
  SSL* ssl;

  // Create our BIO object for SSL connections.
  BIO* bio = BIO_new_ssl_connect(ctx);
  sslctn->bio = bio;

  // Failure?
  if (bio == NULL) {
     char errorbuf[1024];

     ERR_error_string(1024,errorbuf);
     anetSetError(err, "SSL Error: Error creating BIO: %s\n", errorbuf);

     // We need to free up the SSL_CTX before we leave.
     anetCleanupSSL( sslctn );
     return ANET_ERR;
  }

  // Makes ssl point to bio's SSL object.
  BIO_get_ssl(bio, &ssl);
  sslctn->ssl = ssl;

  // Set the SSL to automatically retry on failure.
  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

  char* connect_str = (char *)calloc( 1, strlen( addr ) + 10 );
  sprintf( connect_str, "%s:%d", addr, port );
  sslctn->conn_str = connect_str;

  // We're connection to to the redis server at IP:port.
  BIO_set_conn_hostname(bio, connect_str);

  SSL_CTX_load_verify_locations(ctx, certFilePath, certDirPath);

  // Same as before, try to connect.
  if (BIO_do_connect(bio) <= 0) {
    char errorbuf[1024];
    ERR_error_string(1024,errorbuf);
    anetSetError(err, "SSL Error: Failed to connect: %s\n", errorbuf);
    anetCleanupSSL( sslctn );
    return ANET_ERR;
  }

  // Now we need to do the SSL handshake, so we can communicate.
  if (BIO_do_handshake(bio) <= 0) {
    char errorbuf[1024];
    ERR_error_string(1024,errorbuf);
    anetSetError(err, "SSL Error: handshake failure: %s\n", errorbuf);
    anetCleanupSSL( sslctn );
    return ANET_ERR;
  }

  long verify_result = SSL_get_verify_result(ssl);
  if( verify_result == X509_V_OK) {
    X509* peerCertificate = SSL_get_peer_certificate(ssl);

    char commonName [512];
    X509_NAME * name = X509_get_subject_name(peerCertificate);
    X509_NAME_get_text_by_NID(name, NID_commonName, commonName, 512);
    if( checkCommonName != NULL && strlen( checkCommonName ) > 0 ) {
      if(wildcmp(commonName, checkCommonName, strlen(checkCommonName)) == 0) {
        anetSetError(err, "SSL Error: Error validating peer common name: %s\n", commonName);
        anetCleanupSSL( sslctn );
        return ANET_ERR;
      }
    }
  } else {
     char errorbuf[1024];
     ERR_error_string(1024,errorbuf);
     anetSetError(err, "SSL Error: Error retrieving peer certificate: %s\n", errorbuf);
     anetCleanupSSL( sslctn );
     return ANET_ERR;
  }

  int s = BIO_get_fd( bio, NULL );

  if (flags & ANET_CONNECT_NONBLOCK) {
       if (anetNonBlock(err,s) != ANET_OK)
         return ANET_ERR;
  }

  return s;
}
Exemple #29
0
POP_SESSION *pop_set_socket(POP_SESSION *psp, int s, int opt)
{
    if (s < 0) {
	return NULL;
    }

    if (psp == NULL && (psp = pop_session_create()) == NULL) {
	return NULL;
    }

#ifdef WITH_OPENSSL
    if ((psp->bio = BIO_new_socket(s, BIO_NOCLOSE)) == NULL) {
	__pop_set_error_openssl(psp, "BIO_new_socket(): ");
	pop_session_destroy(psp);
	return NULL;
    }

#ifdef ENABLE_SSL
    if (opt & POP_OPT_SSL) {
	SSL_CTX *ctxp;
	BIO *bio_ssl;

	if ((ctxp = SSL_CTX_new(SSLv23_client_method())) == NULL) {
	    __pop_set_error_openssl(psp, "SSL_CTX_new(): ");
	    pop_session_destroy(psp);
	    return NULL;
	}
	if ((bio_ssl = BIO_new_ssl(ctxp, 1)) == NULL) {
	    __pop_set_error_openssl(psp, "BIO_new_ssl(): ");
	    pop_session_destroy(psp);
	    return NULL;
	}
	BIO_push(bio_ssl, psp->bio);
	psp->bio = bio_ssl;
	BIO_do_handshake(psp->bio);
    }
#endif /* ENABLE_SSL */

    {
	BIO *bio_buffer;

	if ((bio_buffer = BIO_new(BIO_f_buffer())) == NULL) {
	    __pop_set_error_openssl(psp, "BIO_new(): ");
	    pop_session_destroy(psp);
	    return NULL;
	}
	BIO_push(bio_buffer, psp->bio);
	psp->bio = bio_buffer;
    }
#else /* WITH_OPENSSL */
    if ((psp->sw = dup(s)) < 0) {
	__pop_set_error_errno(psp, "dup(s): ");
	pop_session_destroy(psp);
	return NULL;
    }
    if ((psp->fw = fdopen(psp->sw, "w")) == NULL) {
	__pop_set_error_errno(psp, "fdopen(fw): ");
	pop_session_destroy(psp);
	return NULL;
    }
    if ((psp->fr = fdopen(s, "r")) == NULL) {
	__pop_set_error_errno(psp, "fdopen(fr): ");
	pop_session_destroy(psp);
	return NULL;
    }
    psp->sr = s;
#endif /* WITH_OPENSSL */

    return psp;
}