Example #1
0
static void ssl_handshake(struct ssl_proxy *proxy)
{
	int ret, dir;

        ret = gnutls_handshake(proxy->session);
	if (ret >= 0) {
		/* handshake done, now we can start reading */
		if (proxy->io_ssl != NULL)
			io_remove(proxy->io_ssl);

		proxy->io_plain = io_add(proxy->fd_plain, IO_READ,
					 plain_input, proxy);
		proxy->io_ssl = io_add(proxy->fd_ssl, IO_READ,
				       ssl_input, proxy);
		return;
	}

	if (handle_ssl_error(proxy, ret) < 0)
		return;

	/* i/o interrupted */
	dir = gnutls_record_get_direction(proxy->session) == 0 ?
		IO_READ : IO_WRITE;
	if (proxy->io_ssl_dir != dir) {
		if (proxy->io_ssl != NULL)
			io_remove(proxy->io_ssl);
		proxy->io_ssl = io_add(proxy->fd_ssl, dir,
				       ssl_handshake, proxy);
		proxy->io_ssl_dir = dir;
	}
}
Example #2
0
static int proxy_recv_ssl(struct ssl_proxy *proxy, void *data, size_t size)
{
	int rcvd;

	rcvd = gnutls_record_recv(proxy->session, data, size);
	if (rcvd > 0)
		return rcvd;

	if (rcvd == 0 || rcvd == GNUTLS_E_UNEXPECTED_PACKET_LENGTH) {
		/* disconnected, either by nicely telling us that we'll
		   close the connection, or by simply killing the
		   connection which gives us the packet length error. */
		ssl_proxy_destroy(proxy);
		return -1;
	}

	return handle_ssl_error(proxy, rcvd);
}
Example #3
0
static int proxy_send_ssl(struct ssl_proxy *proxy,
			  const void *data, size_t size)
{
	int sent;

	sent = gnutls_record_send(proxy->session, data, size);
	if (sent >= 0)
		return sent;

	if (sent == GNUTLS_E_PUSH_ERROR || sent == GNUTLS_E_INVALID_SESSION) {
		/* don't warn about errors related to unexpected
		   disconnection */
		ssl_proxy_destroy(proxy);
		return -1;
	}

	return handle_ssl_error(proxy, sent);
}
Example #4
0
ssl_server_con * ssl_server_accept(ssl_server_client * scli, int fd){
  BIO_set_fd(SSL_get_rbio(scli->ssl), fd, BIO_NOCLOSE);
  BIO_ctrl(SSL_get_rbio(scli->ssl), BIO_CTRL_DGRAM_SET_CONNECTED, 0, &scli->addr);
  int ret = 0;
  do{ret = SSL_accept(scli->ssl);}
  while(ret == 0);
  if(ret < 0){
    handle_ssl_error(scli->ssl, ret);
    return NULL;
  }
  ASSERT(ret > 0);
  struct timeval timeout;
  timeout.tv_sec = 5;
  timeout.tv_usec = 0;
  BIO_ctrl(SSL_get_rbio(scli->ssl), BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
  ssl_server_con * con = alloc0(sizeof(ssl_server_con));
  con->ssl = scli->ssl;
  return con;
}
Example #5
0
ssl_client * ssl_start_client(int fd, struct sockaddr * remote_addr){
  ssl_ensure_initialized();
  SSL_CTX * ctx = SSL_CTX_new(DTLSv1_client_method());
  SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!MD5:!RC4");
  
  if (!SSL_CTX_use_certificate_file(ctx, "certs/client-cert.pem", SSL_FILETYPE_PEM))
    printf("\nERROR: no certificate found!");
  
  if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/client-key.pem", SSL_FILETYPE_PEM))
    printf("\nERROR: no private key found!");
  
  if (!SSL_CTX_check_private_key (ctx))
    printf("\nERROR: invalid private key!");
  
  SSL_CTX_set_verify_depth (ctx, 2);
  SSL_CTX_set_read_ahead(ctx, 1);
  
  SSL * ssl = SSL_new(ctx);
  
  // Create BIO, connect and set to already connected.
  BIO * bio = BIO_new_dgram(fd, BIO_CLOSE);
  
  BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, remote_addr);
  SSL_set_bio(ssl, bio, bio);
  int ret = SSL_connect(ssl);
  if(ret < 0){
    handle_ssl_error(ssl, ret);
  }
  
  {
    struct timeval timeout;
    timeout.tv_sec = 3;
    timeout.tv_usec = 0;
    BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
  }

  ssl_client * cli = alloc0(sizeof(ssl_client));
  cli->ssl = ssl;
  cli->ctx = ctx;
  return cli;
}
Example #6
0
/**
 * Check the transmitted client certs and a compare with client cert database
 */
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {

    char subject[STRLEN];
    X509_OBJECT found_cert;

    /* RATS: ignore */ /* buffer size is limited by STRLEN */
    X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), subject,
                      STRLEN-1);

    if(!preverify_ok) {

        if (!check_preverify(ctx)) {

            goto reject;

        }

    }

    if(ctx->error_depth==0 &&
            X509_STORE_get_by_subject(ctx, X509_LU_X509,
                                      X509_get_subject_name(ctx->current_cert),
                                      &found_cert)!=1) {

        handle_ssl_error("verify_callback()");
        log("%s: verify_callback(): SSL connection rejected. No matching "
            "certificate found.", prog);

        goto reject;

    }

    return 1;

reject:
    return 0;

}
Example #7
0
/**
 * Handle errors during read, write, connect and accept
 * @return TRUE if non fatal, FALSE if non fatal and retry
 */
static int handle_connection_error(int code, ssl_connection *ssl,
                                   char *operation, int timeout) {

    int ssl_error= 0;

    switch ((ssl_error= SSL_get_error(ssl->handler, code))) {

    case SSL_ERROR_WANT_READ:
        if (can_read(ssl->socket, timeout))
            return TRUE;
        else
            log("%s: %s: Openssl read timeout error!\n", prog, operation);
        return FALSE;

    case SSL_ERROR_WANT_WRITE:
        if (can_read(ssl->socket, timeout))
            return TRUE;
        else
            log("%s: %s: Openssl write timeout error!\n", prog, operation);
        return FALSE;

    case SSL_ERROR_SYSCALL:
        log("%s: %s: Openssl syscall error: %s!\n", prog, operation,
            STRERROR);
        return FALSE;

    case SSL_ERROR_SSL:
        handle_ssl_error(operation);
        return FALSE;

    default:
        log("%s: %s: Openssl error!\n", prog, operation);

    }

    return FALSE;
}
Example #8
0
/**
 * Initializes a ssl connection for server use.
 * @param pemfilename Filename for the key/cert file
 * @return An ssl connection, or NULL if an error occured.
 */
ssl_server_connection *init_ssl_server (char *pemfile, char *clientpemfile) {

#ifdef HAVE_OPENSSL

    ssl_server_connection *ssl_server = new_ssl_server_connection(pemfile,
                                        clientpemfile);

    ASSERT(pemfile);

    if (!ssl_initilized) {

        start_ssl();

    }

    if ((ssl_server->method= SSLv23_server_method()) == NULL ) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server (): Cannot initialize the SSL method!\n", prog);
        goto sslerror;

    }

    if ((ssl_server->ctx= SSL_CTX_new(ssl_server->method)) == NULL ) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server (): Cannot initialize SSL server"
            " certificate handler!\n"
            , prog);
        goto sslerror;

    }

    if (SSL_CTX_use_certificate_file(ssl_server->ctx, pemfile,
                                     SSL_FILETYPE_PEM) <= 0) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server(): Cannot initialize SSL server"
            " certificate!\n", prog);
        goto sslerror;

    }

    if (SSL_CTX_use_PrivateKey_file(ssl_server->ctx, pemfile,
                                    SSL_FILETYPE_PEM) <= 0) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server(): Cannot initialize SSL server"
            " private key!\n", prog);
        goto sslerror;

    }

    if (!SSL_CTX_check_private_key(ssl_server->ctx)) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server(): The private key does not match the"
            " certificate public key!\n", prog);
        goto sslerror;

    }

    /*
     * We need this to force transmission of client certs
     */
    if (!verify_init(ssl_server)) {

        handle_ssl_error("init_ssl_server()");
        log("%s: init_ssl_server(): Verification engine was not"
            " properly initilized!\n", prog);
        goto sslerror;

    }

    if (ssl_server->clientpemfile != NULL) {

        verify_info(ssl_server);

    }

    return ssl_server;

sslerror:

    cleanup_ssl_server_socket(ssl_server);
    return NULL;

#else

    return NULL;

#endif

}
Example #9
0
/**
 * Embeds a socket in a ssl connection.
 * @param socket the socket to be used.
 * @return The ssl connection or NULL if an error occured.
 */
int embed_ssl_socket (ssl_connection *ssl, int socket) {

#ifdef HAVE_OPENSSL

    int ssl_error;
    time_t ssl_time;

    if ( ssl == NULL ) {

        return FALSE;

    }

    if (!ssl_initilized) {

        start_ssl();

    }

    if ( socket >= 0 ) {

        ssl->socket= socket;

    } else {

        log("%s: embed_ssl_socket (): Socket error!\n", prog);
        goto sslerror;
    }

    if ((ssl->handler= SSL_new (ssl->ctx)) == NULL ) {

        handle_ssl_error("embed_ssl_socket()");
        log("%s: embed_ssl_socket (): Cannot initialize the SSL handler!\n",
            prog);
        goto sslerror;

    }

    set_noblock(ssl->socket);

    if((ssl->socket_bio= BIO_new_socket(ssl->socket, BIO_NOCLOSE)) == NULL) {

        handle_ssl_error("embed_ssl_socket()");
        log("%s: embed_ssl_socket (): Cannot generate IO buffer!\n", prog);
        goto sslerror;

    }

    SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio);

    ssl_time=time(NULL);

    while((ssl_error= SSL_connect (ssl->handler)) < 0) {

        if((time(NULL)-ssl_time) > SSL_TIMEOUT) {

            log("%s: embed_ssl_socket (): SSL service timeout!\n",
                prog);
            goto sslerror;

        }

        if (!handle_connection_error(ssl_error, ssl, "embed_ssl_socket()", SSL_TIMEOUT)) {

            goto sslerror;

        }

        if (!BIO_should_retry(ssl->socket_bio)) {

            goto sslerror;

        }


    }

    ssl->cipher= (char *) SSL_get_cipher(ssl->handler);

    if (! update_ssl_cert_data(ssl)) {

        log("%s: embed_ssl_socket (): Cannot get the SSL server certificate!\n",
            prog);
        goto sslerror;

    }

    return TRUE;

sslerror:

    cleanup_ssl_socket(ssl);
    return FALSE;

#else

    return FALSE;

#endif
}
Example #10
0
/**
 * Init verification of transmitted client certs
 */
static int verify_init(ssl_server_connection *ssl_server) {

    struct stat stat_buf;

    if (ssl_server->clientpemfile==NULL) {

        allow_any_purpose= TRUE;
        SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_PEER ,
                           verify_callback_noclientcert);
        goto end_success; /* No verification, but we have to call the callback! */

    }

    if ( -1 == stat(ssl_server->clientpemfile, &stat_buf )) {

        log("%s: verify_init(): Cannot stat the SSL pem path '%s' -- %s\n",
            prog, Run.httpsslclientpem, STRERROR);

        goto end_error;

    }

    if (S_ISDIR(stat_buf.st_mode)) {

        if (!SSL_CTX_load_verify_locations(ssl_server->ctx, NULL ,
                                           ssl_server->clientpemfile)) {

            handle_ssl_error("verify_init()");
            log("%s: verify_init(): Error setting verify directory to %s\n",
                Run.httpsslclientpem);

            goto end_error;

        }

        log("%s: verify_init(): Loaded SSL client pem directory '%s'\n",
            prog, ssl_server->clientpemfile);

        /* Monits server cert for cli support ! */

        if(!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile,
                                          NULL)) {

            handle_ssl_error("verify_init()");
            log("%s: verify_init(): Error loading verify certificates from %s\n",
                prog, ssl_server->pemfile);

            goto end_error;

        }

        log("%s: verify_init(): Loaded monit's SSL pem server file '%s'\n",
            prog, ssl_server->pemfile);

    } else if (S_ISREG(stat_buf.st_mode)) {

        if(!SSL_CTX_load_verify_locations(ssl_server->ctx,
                                          ssl_server->clientpemfile,
                                          NULL)) {

            handle_ssl_error("verify_init()");
            log("%s: verify_init(): Error loading verify certificates from %s\n",
                prog, Run.httpsslclientpem);

            goto end_error;

        }

        log("%s: verify_init(): Loaded SSL pem client file '%s'\n",
            prog, ssl_server->clientpemfile);

        /* Monits server cert for cli support ! */

        if(!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile,
                                          NULL)) {

            handle_ssl_error("verify_init()");
            log("%s: verify_init(): Error loading verify certificates from %s\n",
                prog, ssl_server->pemfile);

            goto end_error;

        }

        log("%s: verify_init(): Loaded monit's SSL pem server file '%s'\n",
            prog, ssl_server->pemfile);

        SSL_CTX_set_client_CA_list(ssl_server->ctx,
                                   SSL_load_client_CA_file(ssl_server->clientpemfile));

    } else {

        log("%s: verify_init(): SSL client pem path is no file or directory %s\n",
            prog, ssl_server->clientpemfile);

        goto end_error;

    }

    allow_any_purpose= FALSE;
    SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_PEER , verify_callback);

end_success:

    return TRUE;

end_error:

    return FALSE;
}
Example #11
0
/**
 * Generate a new ssl connection
 * @return ssl connection container
 */
ssl_connection *new_ssl_connection(char *clientpemfile, int sslversion) {

#ifdef HAVE_OPENSSL

    ssl_connection *ssl = (ssl_connection *) NEW(ssl);

    if (!ssl_initilized) {

        start_ssl();

    }

    ssl->socket_bio= NULL;
    ssl->handler= NULL;
    ssl->cert= NULL;
    ssl->cipher= NULL;
    ssl->socket= 0;
    ssl->next = NULL;
    ssl->accepted = FALSE;
    ssl->cert_md5 = NULL;
    ssl->cert_md5_len = 0;

    if(clientpemfile!=NULL) {

        ssl->clientpemfile= xstrdup(clientpemfile);

    } else {

        ssl->clientpemfile= NULL;

    }

    switch (sslversion) {

    case SSL_VERSION_AUTO:

        ssl->method = SSLv23_client_method();
        break;

    case SSL_VERSION_SSLV2:

        ssl->method = SSLv2_client_method();
        break;

    case SSL_VERSION_SSLV3:

        ssl->method = SSLv3_client_method();
        break;

    case SSL_VERSION_TLS:

        ssl->method = TLSv1_client_method();
        break;

    default:

        log("%s: new_ssl_connection(): Unknown SSL version!\n", prog);
        goto sslerror;

    }

    if (ssl->method == NULL ) {

        handle_ssl_error("new_ssl_connection()");
        log("%s: new_ssl_connection(): Cannot initilize SSL method!\n", prog);
        goto sslerror;

    }

    if ((ssl->ctx= SSL_CTX_new (ssl->method)) == NULL ) {

        handle_ssl_error("new_ssl_connection()");
        log("%s: new_ssl_connection(): Cannot initilize SSL server certificate"
            " handler!\n", prog);
        goto sslerror;

    }

    if ( ssl->clientpemfile!=NULL ) {

        if (SSL_CTX_use_certificate_file(ssl->ctx, ssl->clientpemfile,
                                         SSL_FILETYPE_PEM) <= 0) {

            handle_ssl_error("new_ssl_connection()");
            log("%s: new_ssl_connection(): Cannot initilize SSL server"
                " certificate!\n", prog);
            goto sslerror;

        }

        if (SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->clientpemfile,
                                        SSL_FILETYPE_PEM) <= 0) {

            handle_ssl_error("new_ssl_connection()");
            log("%s: new_ssl_connection(): Cannot initilize SSL server"
                " private key!\n", prog);
            goto sslerror;

        }

        if (!SSL_CTX_check_private_key(ssl->ctx)) {

            handle_ssl_error("new_ssl_connection()");
            log("%s: new_ssl_connection(): Private key does not match the"
                " certificate public key!\n",
                prog);
            goto sslerror;

        }

    }


    return ssl;

sslerror:

    delete_ssl_socket(ssl);

    return NULL;

#else

    return NULL;

#endif

}
Example #12
0
/**
 * Embeds an accepted server socket in an existing ssl connection.
 * @param ssl ssl connection
 * @param socket the socket to be used.
 * @return TRUE, or FALSE if an error has occured.
 */
int embed_accepted_ssl_socket(ssl_connection *ssl, int socket) {

#ifdef HAVE_OPENSSL

    int ssl_error;
    time_t ssl_time;

    ASSERT(ssl);

    ssl->socket=socket;

    if(!ssl_initilized) {

        start_ssl();

    }

    if((ssl->handler= SSL_new(ssl->ctx)) == NULL) {

        handle_ssl_error("embed_accepted_ssl_socket()");
        log("%s: embed_accepted_ssl_socket(): Cannot initialize the"
            " SSL handler!\n", prog);
        goto sslerror;

    }

    if(socket < 0) {

        log("Socket error!\n");
        goto sslerror;

    }

    set_noblock(ssl->socket);

    if((ssl->socket_bio= BIO_new_socket(ssl->socket, BIO_NOCLOSE)) == NULL) {

        handle_ssl_error("embed_accepted_ssl_socket()");
        log("%s: embed_accepted_ssl_socket(): Cannot generate IO buffer!\n",
            prog);
        goto sslerror;

    }

    SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio);

    ssl_time= time(NULL);

    while((ssl_error= SSL_accept(ssl->handler)) < 0) {

        if((time(NULL)-ssl_time) > SSL_TIMEOUT) {

            log("%s: embed_accepted_ssl_socket(): SSL service timeout!\n",
                prog);
            goto sslerror;

        }

        if (!handle_connection_error(ssl_error, ssl,
                                     "embed_accepted_ssl_socket()", SSL_TIMEOUT)) {

            goto sslerror;

        }

        if (!BIO_should_retry(ssl->socket_bio)) {

            goto sslerror;

        }

    }

    ssl->cipher= (char *) SSL_get_cipher(ssl->handler);

    if(!update_ssl_cert_data(ssl) && (ssl->clientpemfile != NULL)) {

        log("%s: The client did not supply a required client certificate!\n",
            prog);
        goto sslerror;

    }

    if (SSL_get_verify_result(ssl->handler)>0) {

        log("%s: Verification of the certificate has failed!\n",
            prog);
        goto sslerror;

    }

    return TRUE;

sslerror:

    return FALSE;

#else

    return FALSE;

#endif

}