Exemple #1
0
static void do_free_upto(BIO *f, BIO *upto)
	{
	if (upto)
		{
		BIO *tbio;
		do 
			{
			tbio = BIO_pop(f);
			BIO_free(f);
			f = tbio;
			}
		while (f != upto);
		}
	else
		BIO_free_all(f);
	}
Exemple #2
0
void *cliserver(void *arg) {

        struct srv_ctx *srv = (struct srv_ctx *)arg;
        struct freeq_ctx *freeqctx = srv->freeqctx;
        struct conn_ctx *conn_ctx;
        int res;
        pthread_t tid;
        BIO *acc, *client;

        static stralloc aggport = {0};

        res = control_readline(&aggport, "control/aggport");
        if (!res)
        {
                err(freeqctx, "unable to read control/aggport");
                exit(FREEQ_ERR);
        }

        stralloc_0(&aggport);

        dbg(freeqctx, "starting aggregation listener on %s\n", (char *)aggport.s);
        acc = BIO_new_accept((char *)aggport.s);
        if (!acc)
        {
                int_error("Error creating server socket");
                exit(FREEQ_ERR);
        }

        if (BIO_do_accept(acc) <= 0)
                int_error("Error binding server socket");

        for (;;)
        {
                dbg(freeqctx, "waiting for connection\n");
                if (BIO_do_accept(acc) <= 0)
                        int_error("Error accepting connection");
                dbg(freeqctx, "accepted connection, setting up ssl\n");

                //bio_peername(acc);

                client = BIO_pop(acc);
                conn_ctx = malloc(sizeof(struct conn_ctx));
                conn_ctx->srvctx = srv;
                conn_ctx->client = client;
                pthread_create(&tid, 0, &conn_handler, (void *)conn_ctx);
        }
}
Exemple #3
0
void *sqlserver(void *arg) {
        struct srv_ctx *srv = (struct srv_ctx *)arg;
        struct freeq_ctx *freeqctx = srv->freeqctx;
        int res;
        pthread_t thread;
        BIO *acc, *client;

        signal(SIGINT, cleanup);
        signal(SIGTERM, cleanup);
        signal(SIGPIPE, SIG_IGN);

        static stralloc sqlport = {0};

        res = control_readline(&sqlport, "control/sqlport");
        if (!res)
        {
                err(freeqctx, "unable to read control/sqlport\n");
                exit(FREEQ_ERR);
        }

        stralloc_0(&sqlport);
        dbg(freeqctx, "starting query listener on %s\n", (char *)sqlport.s);
        acc = BIO_new_accept((char *)sqlport.s);
        if (!acc)
        {
                int_error("Error creating server socket");
                exit(FREEQ_ERR);
        }

        if (BIO_do_accept(acc) <= 0)
                int_error("Error binding server socket");

        for (;;)
        {
                if (BIO_do_accept(acc) <= 0)
                        int_error("Error accepting connection");
                client = BIO_pop(acc);
                struct conn_ctx *conn = malloc(sizeof(struct conn_ctx));
                conn->srvctx = srv;
                conn->client = client;
                pthread_create(&thread, 0, &sqlhandler, (void *)conn);
        }

        BIO_free(acc);
        pthread_exit(FREEQ_OK);;
}
/* Base 64 write of PKCS#7 structure */
int B64_write_bio_PKCS7 ( BIO *bio, PKCS7 *p7 ) {
	BIO *b64 = NULL;
	int ret = 0;

	if( !p7 ) return 0;

	if(!(b64 = BIO_new(BIO_f_base64()))) {
		PKCS7err(PKCS7_F_B64_WRITE_PKCS7,ERR_R_MALLOC_FAILURE);
		return 0;
	}
	
	bio = BIO_push(b64, bio);
	ret = i2d_PKCS7_bio(bio, p7);
	BIO_flush(bio);
	bio = BIO_pop(bio);
	BIO_free(b64);
	
	return ret;
}
Exemple #5
0
/* Callback for int_smime_write_ASN1 */
static int cms_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
                           const ASN1_ITEM *it)
{
    CMS_ContentInfo *cms = (CMS_ContentInfo *)val;
    BIO *tmpbio, *cmsbio;
    int r = 0;

    if (!(flags & SMIME_DETACHED)) {
        SMIME_crlf_copy(data, out, flags);
        return 1;
    }

    /* Let CMS code prepend any needed BIOs */

    cmsbio = CMS_dataInit(cms, out);

    if (!cmsbio)
        return 0;

    /* Copy data across, passing through filter BIOs for processing */
    SMIME_crlf_copy(data, cmsbio, flags);

    /* Finalize structure */
    if (CMS_dataFinal(cms, cmsbio) <= 0)
        goto err;

    r = 1;

err:

    /* Now remove any digests prepended to the BIO */

    while (cmsbio != out) {
        tmpbio = BIO_pop(cmsbio);
        BIO_free(cmsbio);
        cmsbio = tmpbio;
    }

    return r;

}
Exemple #6
0
int main(int argc, char * argv[]) {
    BIO * acc, * client;
    THREAD_TYPE tid;
    SSL * ssl;
    SSL_CTX * ctx;

    init_OpenSSL();
    seed_prng();

    ctx = setup_server_ctx();
    
    acc = BIO_new_accept(PORT);
    if (!acc)
        int_error("Error creating server socket");
    if (BIO_do_accept(acc) <= 0)
        int_error("Error binding server socket");
    // BIO_do_accept() will block and wait for a remote connection.
    while (1) {
        if (BIO_do_accept(acc) <= 0)
            int_error("Error accepting connection");
        // get the client BIO
        client = BIO_pop(acc);
        if (!(ssl = SSL_new(ctx)))
            int_error("Error creating SSL context");
        SSL_set_accept_state(ssl);
        SSL_set_bio(ssl, client, client);
        // create a new thread to handle the new connection,
        // The thread will call do_server_loop with the client BIO.
        // THREAD_CREATE(tid, entry, arg);
        // tid is the id of the new thread.
        // server_thread is the function defined above, which will call
        // do_server_loop() with the client BIO.
        THREAD_CREATE(tid, server_thread, ssl);
    }
    SSL_CTX_free(ctx);
    BIO_free(acc);
    return 0;
}
Exemple #7
0
int STS_ServerMain(char **argv) {

    BIO *bio_listen = BIO_new_accept(argv[0]);
    argv++;
    BIO_set_bind_mode(bio_listen, BIO_BIND_REUSEADDR);

    /* First call to BIO_accept() sets up accept BIO */
    if(BIO_do_accept(bio_listen) <= 0) {
        printf("Ошибка при создании сокета\n");
        return 1;
    }

    printf("Ждем подключения клиента.\n");

    /* Wait for incoming connection */
    if(BIO_do_accept(bio_listen) <= 0) {
        printf("Ошибка подключения!\n");
        return 1;
    }
    printf("Соединение установлено.\n");

    return STS_ServerHandleConnection(BIO_pop(bio_listen), argv);
}
NOEXPORT char *base64(int encode, char *in, int len) {
    BIO *bio, *b64;
    char *out;
    int n;

    b64=BIO_new(BIO_f_base64());
    if(!b64)
        return NULL;
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    bio=BIO_new(BIO_s_mem());
    if(!bio) {
        str_free(b64);
        return NULL;
    }
    if(encode)
        bio=BIO_push(b64, bio);
    BIO_write(bio, in, len);
    (void)BIO_flush(bio); /* ignore the error if any */
    if(encode) {
        bio=BIO_pop(bio);
        BIO_free(b64);
    } else {
        bio=BIO_push(b64, bio);
    }
    n=BIO_pending(bio);
    /* 32 bytes as a safety precaution for passing decoded data to crypt_DES */
    /* n+1 to get null-terminated string on encode */
    out=str_alloc(n<32?32:n+1);
    n=BIO_read(bio, out, n);
    if(n<0) {
        BIO_free_all(bio);
        str_free(out);
        return NULL;
    }
    BIO_free_all(bio);
    return out;
}
Exemple #9
0
int serverMain(char ** argv) {

    Server server;
    int i;
    
    if (serverReadKey(&server, argv[1])) {
        fprintf(stderr, "Can't read key from file %s!", argv[1]);
        return 1;
    }

    BIO * bio_listen = BIO_new_accept(argv[0]);
    BIO_set_bind_mode(bio_listen, BIO_BIND_REUSEADDR);

    /* First call to BIO_accept() sets up accept BIO */
    if(BIO_do_accept(bio_listen) <= 0) {
        fprintf(stderr, "Error setting up accept\n");
        return 1;
    }

    /* Wait for incoming connection */
    if(BIO_do_accept(bio_listen) <= 0) {
        fprintf(stderr, "Ошибка подключения!\n");
        return 1;
    }
    fprintf(stderr, "Соединение установлено.\n");

    server.conn = BIO_pop(bio_listen);

    if(serverHandleClient(&server)) {
        printf("Клиент не смог доказать знание закрытого ключа RSA!\n\n\n");
    } else {
        printf("Клиент доказал знание закрытого ключа RSA.\n\n\n");
    }
    BIO_free(server.conn);
    BIO_free(bio_listen);
    return 0;
}
Exemple #10
0
int main(int argc, char *argv[])
{
    BIO     *acc, *client;
    SSL     *ssl;
    SSL_CTX *ctx;
    THREAD_TYPE tid;

    init_OpenSSL(  );
    seed_prng();

 
    ctx = setup_server_ctx(  );
 
    acc = BIO_new_accept(PORT);
    if (!acc)
        int_error("Error creating server socket");
 
    if (BIO_do_accept(acc) <= 0)
        int_error("Error binding server socket");
 
    while(1)
    {
        if (BIO_do_accept(acc) <= 0)
            int_error("Error accepting connection");
 
        client = BIO_pop(acc);
        if (!(ssl = SSL_new(ctx)))
        int_error("Error creating SSL context");
        SSL_set_accept_state(ssl);
        SSL_set_bio(ssl, client, client);
        THREAD_CREATE(tid, (void *)server_thread, ssl);
    }
 
    SSL_CTX_free(ctx);
    BIO_free(acc);
    return 0;
}
Exemple #11
0
int main(int argc, char *argv[])
{
	BIO *acc, *client;
	SSL *ssl;
	SSL_CTX *ctx;
	THREAD_TYPE tid;
	void* (*func)(void*) = &server_thread;


	std::cout << "before init\n";
	init_OpenSSL();
	//seed_prng();
	std::cout << "after init\n";

	ctx = setup_server_ctx();

	acc = BIO_new_accept(PORT);
	if(!acc)
		int_error("Error creating socket");
	if(BIO_do_accept(acc) <= 0)
		int_error("Error binding socket");

	for(;;)
	{
		if(BIO_do_accept(acc) <= 0)
			int_error("Error accepting connection");

		client = BIO_pop(acc);
		if(!(ssl = SSL_new(ctx)))
			int_error("Error creating ssl object");
		SSL_set_bio(ssl,client,client);
		THREAD_CREATE(tid,func,ssl);
	}
	BIO_free(acc);
	SSL_CTX_free(ctx);
	return 0;
}
Exemple #12
0
int main(int argc, char *argv[])
{
    char *port = "*:4433";
    BIO *ssl_bio, *tmp;
    SSL_CTX *ctx;
    SSL_CONF_CTX *cctx;
    char buf[512];
    BIO *in = NULL;
    int ret = 1, i;
    char **args = argv + 1;
    int nargs = argc - 1;

    SSL_load_error_strings();

    /* Add ciphers and message digests */
    OpenSSL_add_ssl_algorithms();

    ctx = SSL_CTX_new(SSLv23_server_method());

    cctx = SSL_CONF_CTX_new();
    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
    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 err;
        }
        if (rv < 0) {
            fprintf(stderr, "Error in command %s\n", *args);
            ERR_print_errors_fp(stderr);
            goto err;
        }
        /* If rv > 0 we processed something so proceed to next arg */
        if (rv > 0)
            continue;
        /* Otherwise application specific argument processing */
        if (strcmp(*args, "-port") == 0) {
            port = args[1];
            if (port == NULL) {
                fprintf(stderr, "Missing -port argument\n");
                goto err;
            }
            args += 2;
            nargs -= 2;
            continue;
        } else {
            fprintf(stderr, "Unknown argument %s\n", *args);
            goto err;
        }
    }

    if (!SSL_CONF_CTX_finish(cctx)) {
        fprintf(stderr, "Finish error\n");
        ERR_print_errors_fp(stderr);
        goto err;
    }
#ifdef ITERATE_CERTS
    /*
     * Demo of how to iterate over all certificates in an SSL_CTX structure.
     */
    {
        X509 *x;
        int rv;
        rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_FIRST);
        while (rv) {
            X509 *x = SSL_CTX_get0_certificate(ctx);
            X509_NAME_print_ex_fp(stdout, X509_get_subject_name(x), 0,
                                  XN_FLAG_ONELINE);
            printf("\n");
            rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_NEXT);
        }
        fflush(stdout);
    }
#endif
    /* Setup server side SSL bio */
    ssl_bio = BIO_new_ssl(ctx, 0);

    if ((in = BIO_new_accept(port)) == NULL)
        goto err;

    /*
     * This means that when a new connection is accepted on 'in', The ssl_bio
     * will be 'duplicated' and have the new socket BIO push into it.
     * Basically it means the SSL BIO will be automatically setup
     */
    BIO_set_accept_bios(in, ssl_bio);

 again:
    /*
     * The first call will setup the accept socket, and the second will get a
     * socket.  In this loop, the first actual accept will occur in the
     * BIO_read() function.
     */

    if (BIO_do_accept(in) <= 0)
        goto err;

    for (;;) {
        i = BIO_read(in, buf, 512);
        if (i == 0) {
            /*
             * If we have finished, remove the underlying BIO stack so the
             * next time we call any function for this BIO, it will attempt
             * to do an accept
             */
            printf("Done\n");
            tmp = BIO_pop(in);
            BIO_free_all(tmp);
            goto again;
        }
        if (i < 0)
            goto err;
        fwrite(buf, 1, i, stdout);
        fflush(stdout);
    }

    ret = 0;
 err:
    if (ret) {
        ERR_print_errors_fp(stderr);
    }
    BIO_free(in);
    exit(ret);
    return (!ret);
}
Exemple #13
0
int ssl_run(int sd) {
  SSL_CTX *ctx = SSL_CTX_new(TLS_method());

  int ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
                            SSL_OP_SINGLE_ECDH_USE |
                            SSL_OP_CIPHER_SERVER_PREFERENCE;

  SSL_CTX_set_options(ctx, ssl_opts);


  struct timespec tp[3];
  clock_gettime(CLOCK_REALTIME, &tp[0]);
  SSL_CTX_use_certificate_file(ctx, "gw.cert.pem", SSL_FILETYPE_PEM);
  SSL_CTX_set_default_passwd_cb(ctx, password_cb);
  SSL_CTX_use_PrivateKey_file(ctx, "gw.key.pem", SSL_FILETYPE_PEM);
  SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);

  SSL *ssl = SSL_new(ctx);

  BIO *accept_bio = BIO_new_socket(sd, BIO_CLOSE);
  SSL_set_bio(ssl, accept_bio, accept_bio);

  SSL_accept(ssl);
  ERR_print_errors_fp(stderr);
  BIO *bio = BIO_pop(accept_bio);

  clock_gettime(CLOCK_REALTIME, &tp[1]);
  char buf[8192];
  while (1) {
    // first read data
    int r = SSL_read(ssl, buf, sizeof buf); 
    switch (SSL_get_error(ssl, r)) { 
      case SSL_ERROR_NONE: 
        break;
      case SSL_ERROR_ZERO_RETURN: 
        goto end; 
      default: 
        printf("SSL read problem");
        goto end;
    }

      
    clock_gettime(CLOCK_REALTIME, &tp[2]);
    long sh_time = (tp[1].tv_sec - tp[0].tv_sec) * 1000 + (tp[1].tv_nsec - tp[0].tv_nsec) / 1000000;
    long serv_time = (tp[2].tv_sec - tp[1].tv_sec) * 1000000 + (tp[2].tv_nsec - tp[1].tv_nsec) / 1000;
    char content[200];
    int cnt_len = snprintf(content, sizeof (content), "ssl hank shake: %ldms, service: %ldus\r\n", sh_time, serv_time);
    int len = snprintf(buf, sizeof buf,
                                    "HTTP/1.1 200 OK\r\n"
                                    "Content-Type: text/plain\r\n"
                                    "Content-Length: %d\r\n"
                                    "Access-Control-Allow-Origin: *\r\n\r\n%s", cnt_len, content);

    // now keep writing until we've written everything
    int offset = 0;
    while (len) {
      r = SSL_write(ssl, buf + offset, len); 
      switch (SSL_get_error(ssl, r)) { 
        case SSL_ERROR_NONE: 
          len -= r;
          offset += r; 
          break;
        default:
          printf("SSL write problem");
          goto end;
      }
    }
    break;
  }
end:
  SSL_shutdown(ssl);

  BIO_free_all(bio);
  BIO_free_all(accept_bio);
}
Exemple #14
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 #15
0
/*
 * This starts a minimal TLS server that only does a
 * handshake and then closes the connection.  This is
 * strictly used to test TLS session negotiation
 * behavior with EST.
 */
static void us1060_start_tls_server (char *cipherstring)
{
    BIO *conn;
    BIO *listener;
    BIO *berr;
    char h_p[25];
    SSL *ssl;
    SSL_CTX *ssl_ctx = NULL;
    int nid, rv;
    EC_KEY *ecdh = NULL;

    berr = BIO_new_fp(stderr, BIO_NOCLOSE);

    ssl_ctx = SSL_CTX_new(SSLv23_server_method());
    if (!ssl_ctx) {
	printf("Failed to create SSL context\n");
	ERR_print_errors(berr);
	return;
    }

    SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);

    if (SSL_CTX_use_certificate_chain_file(ssl_ctx, US1060_RSA_CERT) != 1) {
	printf("Failed to load server certificate\n");
	ERR_print_errors(berr);
	return;
    }
    if (SSL_CTX_use_PrivateKey_file(ssl_ctx, US1060_RSA_KEY, SSL_FILETYPE_PEM) != 1) {
	printf("Failed to load server private key\n");
	ERR_print_errors(berr);
	return;
    }

    SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 |
	                         SSL_OP_NO_SSLv3 |
				 SSL_OP_NO_TLSv1 |
                                 SSL_OP_SINGLE_ECDH_USE | 
				 SSL_OP_SINGLE_DH_USE |
			         SSL_OP_NO_TICKET);

    nid = OBJ_sn2nid("prime256v1");
    ecdh = EC_KEY_new_by_curve_name(nid);
    if (ecdh == NULL) {
	printf("Failed to retreive ECDH curve\n");
	ERR_print_errors(berr);
	return;
    }
    SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
    EC_KEY_free(ecdh);

    if (SSL_CTX_set_cipher_list(ssl_ctx, cipherstring) != 1) {
	printf("Failed to set server cipher list\n");
	ERR_print_errors(berr);
	return;
    }
    SSL_CTX_set_srp_username_callback(ssl_ctx, us1060_srp_cb);

    sprintf(h_p, "%s:%d", US1060_SERVER_IP, US1060_TLS_PORT);
    listener = BIO_new_accept(h_p);
    if (listener == NULL) {
	printf("IP connection failed\n");
	return;
    }
    BIO_set_bind_mode(listener, BIO_BIND_REUSEADDR);

    /*
     * The first call to do_accept binds the socket
     */
    if (BIO_do_accept(listener) <= 0) {
	printf("TCP bind failed\n");
	BIO_free_all(listener);
	return;
    }

    /*
     * The second call to do_accept waits for a new
     * connection request on the listener.
     * Note that we are in blocking mode for this socket
     */
    if (BIO_do_accept(listener) <= 0) {
	printf("TCP accept failed\n");
	BIO_free_all(listener);
	return;
    }
    conn = BIO_pop(listener);

    ssl = SSL_new(ssl_ctx);
    SSL_set_bio(ssl, conn, conn);
    /*
     * Now that we have everything ready, let's start waiting for
     * a client to contact us.  Normally we might using a pthread
     * or some other construct to avoid blocking on the main 
     * thread while waiting for an incoming connection.  This
     * code is simply a contrived example, we will wait on the
     * main thread for an incoming connection.
     */
    rv = SSL_accept(ssl);
    if (rv <= 0) {
	printf("\nFailed to complete TLS handshake %d\n", rv);
	ERR_print_errors(berr);
    }
    SSL_shutdown(ssl);
    SSL_free(ssl);
    SSL_CTX_free(ssl_ctx);
    BIO_free(berr);
    (void)BIO_reset(listener);
    BIO_free_all(listener);
    pthread_exit(0);
}
Exemple #16
0
int main(int argc, char *argv[])
{
    SSL_library_init();
    SSL_load_error_strings();
    
    SSL * new_ssl;
    SSL_CTX * new_ctx;
    
    new_ctx = dh_setup_ctx();
    
    BIO * acc, * client;
    char port[sizeof(argv[1])] = "";  
    int check = 0;
    long port_num;
    parse_port(argc,argv,port);
    acc = BIO_new_accept("1300");
    port_num = BIO_set_accept_port(acc,port);
    if ( !acc )
    { 
	printf("%s \n", "Error in new bio accept");
	return -1;
    }
    if ( BIO_do_accept(acc) <= 0)
    {
	printf("%s \n", "Error in do accept" );
	return -1;
    }
    int get = 0;
    while ( 1 )
    {
	if( BIO_do_accept(acc) <= 0 )
	{
	    printf("%s \n", "Error in accepting connections");
	    return -1;
	}
	client = BIO_pop(acc);
	if ( !(new_ssl = SSL_new(new_ctx)))
	{
	    printf("%s \n", "Error in creating new SSL");
	    return -1;
	}
	SSL_set_bio(new_ssl,client,client);
	if( SSL_accept(new_ssl) <= 0 )
	{
	    get = SSL_get_error(new_ssl,get);
	    printf("%s \n", "Error in accepting SSL connection");
	    printf("%d \n", get);
	    printf("%s \n",ERR_error_string(get,NULL)); 
	    return -1;
	}
	int buf[256] = { 0 };
	int count = 0;
	if ( SSL_read(new_ssl,buf,sizeof(buf)) > 0)
	{
	    /*get = SSL_get_error(new_ssl,get);
	    printf("%d \n", get);
	    printf("%s \n",ERR_error_string(get,NULL)); 
*/
	    while( (char)buf[count] != EOF )
	    {
		printf("%c" , (char)buf[count]);
		count++;
	    }
	}
	SSL_shutdown(new_ssl);
	SSL_free(new_ssl);
    }
    SSL_CTX_free(new_ctx);
    BIO_free(acc);
    return 0;
}
Exemple #17
0
int main(int argc, char **argv)
{
  char buf[BUFFER_SIZE];

  SSL_CTX *ctx;
  const SSL_METHOD *method;
  BIO *abio, *cbio;

  if (argc < 2) {
    fprintf(stderr, "Usage: %s [port]\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  // init openssl lib.
  SSL_library_init(); // call OpenSSL_add_ssl_algorithms();
  ERR_load_BIO_strings();
  SSL_load_error_strings();

  // setup tls context.
  method = TLSv1_2_server_method(); // SSLv23_server_method();
  ctx = SSL_CTX_new(method);
  if (!ctx) {
    perror("Unable to create SSL context");
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
  }
  /* Set the key and cert */
  if (SSL_CTX_use_certificate_file(ctx, CERT_FILE_PATH, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
  }
  if (SSL_CTX_use_PrivateKey_file(ctx, KEY_FILE_PATH, SSL_FILETYPE_PEM) <= 0 ) {
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
  }
  SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384");
  SSL_CTX_set_ecdh_auto(ctx, 1);

  // create BIO(high level API); for accept
  abio = BIO_new_accept(argv[1]);
  if(BIO_do_accept(abio) <= 0) {
    // first BIO_do_accept() is as to init BIO.
    fprintf(stderr, "Error setting up accept\n");
    ERR_print_errors_fp(stderr);
    exit(0);
  }
  // configuration for I/O operation over ssl/tls.
  BIO_set_accept_bios(abio, BIO_new_ssl(ctx, 0));

  // listen loop
  printf("Server is listening on %d\n", atoi(argv[1]));
  while (1) {
    if(BIO_do_accept(abio) <= 0) {
      fprintf(stderr, "Error accepting connection\n");
      ERR_print_errors_fp(stderr);
      exit(0);
    }
    fprintf(stderr, "Connection 1 established\n");
    /* Retrieve BIO for connection */
    cbio = BIO_pop(abio);
    while (1) {
      int len, err;
      len = BIO_read(cbio, buf, BUFFER_SIZE);
      if (!len) break;
      if (len < 0) {
        fprintf(stderr, "error SSL_read");
        break;
      }
      err = BIO_write(cbio, buf, len);
      if (err < 0) {
        fprintf(stderr, "error SSL_write");
        break;
      }
    }
    BIO_free(cbio);
  }
}
Exemple #18
0
/******
 * Everything starts here...
 ******/
int main(int argc, char **argv)
{
  BIO *abio = NULL;
  BIO *biobuf = NULL;
  int rc = 0;

  if (rc = init(argc, argv, &cfg))
    goto done;

  signal(SIGQUIT, SIGQUIThandler);
  
  /* We need a BIO to accept connections */
  abio = BIO_new_accept(cfg->hostport);
  if (!abio)
  {
    fprintf(stderr, "Unable to create a new accept BIO.\n");
    rc = -1;
    goto done;
  }
  BIO_set_bind_mode(abio, BIO_BIND_REUSEADDR);
  if ((rc = BIO_do_accept(abio)) <= 0)
  {
    fprintf(stderr, "Unable to accept connections.\n");
    goto done;
  }

  /* And we add a buffer BIO that will be duplicated for each created
   * connections
   */
  biobuf = BIO_new(BIO_f_buffer());
  if (!biobuf)
  {
    fprintf(stderr, "Unable to create a buffer BIO.\n");
    rc = -1;
    goto done;
  }
  BIO_set_accept_bios(abio, biobuf);

  /* Release all rights and go background */
  if (!cfg->debug)
  {
    changeidentity(cfg->user, cfg->group);
    beadaemon();
  }

  while (1)
  {
    BIO *cbio = NULL;

    /* This is a blocking call */
    BIO_do_accept(abio);

    /* A connection has arrived, detach the corresponding BIO and
     * process the request
     */
    cbio = BIO_pop(abio);
    processrequest(cbio);
  }
  
done:
  BIO_free(abio);
  return rc;
}
Exemple #19
0
int do_starttls(enum APP_STARTTLS starttls, BIO *sbio,
                char *service, const char *hostname)
{
    int rc = 0;
    char buffer[MYBUFSIZE], myhostname[MYBUFSIZE], param[MYBUFSIZE], *cp;
    int read_len;
    switch (starttls) {
    case STARTTLS_SMTP: {
        int seen_starttls = 0, reply_code = -1;
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        /* consume greeting (possibly multiline) & inspect reply code */
        while (1) {
            read_len = BIO_gets(fbio, buffer, MYBUFSIZE);
            (void) sscanf(buffer, "%3d", &reply_code);
            if (debug) {
                cp = strstr(buffer, "\r\n");
                *cp = '\0';
                fprintf(stdout, "recv: %s\n", buffer);
            }
            if (read_len <= 3 || buffer[3] != '-')
                break;
        }
        if (reply_code != 220) {
            fprintf(stdout, "Invalid ESMTP greeting: %s\n", buffer);
            BIO_pop(fbio);
            BIO_free(fbio);
            return rc;
        }
        /* Send EHLO, read response, and look for STARTTLS parameter */
        (void) gethostname(myhostname, MYBUFSIZE);
        if (debug) {
            fprintf(stdout, "send: EHLO %s\n", myhostname);
        }
        BIO_printf(fbio, "EHLO %s\r\n", myhostname);
        (void)BIO_flush(fbio);
        while (1) {
            read_len = BIO_gets(fbio, buffer, MYBUFSIZE);
            (void) sscanf(buffer, "%3d", &reply_code);
            (void) sscanf(buffer+4, "%255s", param);
            if (strcmp(param, "STARTTLS") == 0)
                seen_starttls = 1;
            if (debug) {
                cp = strstr(buffer, "\r\n");
                *cp = '\0';
                fprintf(stdout, "recv: %s\n", buffer);
            }
            if (read_len <= 3 || buffer[3] != '-')
                break;
        }
        BIO_pop(fbio);
        BIO_free(fbio);
        if (reply_code == 250 && seen_starttls) {
            /* send STARTTLS command and inspect reply code */
            if (debug) {
                fprintf(stdout, "send: STARTTLS\n");
            }
            BIO_printf(sbio, "STARTTLS\r\n");
            BIO_read(sbio, buffer, MYBUFSIZE);
            if (debug) {
                cp = strstr(buffer, "\r\n");
                *cp = '\0';
                fprintf(stdout, "recv: %s\n", buffer);
            }
            (void) sscanf(buffer, "%3d", &reply_code);
            if (reply_code == 220)
                rc = 1;
            else
                fprintf(stdout, "Invalid response to STARTTLS: %s\n", buffer);
        } else if (reply_code != 250) {
            fprintf(stdout, "Invalid reply code to SMTP EHLO: %d\n", reply_code);
        } else {
            fprintf(stdout, "Unable to find STARTTLS in SMTP EHLO response.\n");
        }
        break;
    }
    case STARTTLS_IMAP: {
        int seen_starttls = 0;
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        BIO_gets(fbio, buffer, MYBUFSIZE);
        if (debug) {
            cp = strstr(buffer, "\r\n");
            *cp = '\0';
            fprintf(stdout, "recv: %s\n", buffer);
            fprintf(stdout, "send: . CAPABILITY\n");
        }
        BIO_printf(fbio, ". CAPABILITY\r\n");
        (void) BIO_flush(fbio);
        while (1) {
            read_len = BIO_gets(fbio, buffer, MYBUFSIZE);
            if (debug) {
                cp = strstr(buffer, "\r\n");
                *cp = '\0';
                fprintf(stdout, "recv: %s\n", buffer);
            }
            if (strstr(buffer, "STARTTLS"))
                seen_starttls = 1;
            if (read_len <= 3 || buffer[0] == '.')
                break;
        }
        (void) BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        if (seen_starttls) {
            if (debug) {
                fprintf(stdout, "send: . STARTTLS\n");
            }
            BIO_printf(sbio, ". STARTTLS\r\n");
            BIO_read(sbio, buffer, MYBUFSIZE);
            if (debug) {
                cp = strstr(buffer, "\r\n");
                *cp = '\0';
                fprintf(stdout, "recv: %s\n", buffer);
            }
            if (strncmp(buffer, ". OK", 4) == 0)
                rc = 1;
            else
                fprintf(stdout, "ERROR: STARTTLS ready response failed.\n");
        } else {
            fprintf(stdout, "ERROR: no STARTTLS capability found.\n");
        }
        break;
    }
    case STARTTLS_POP3: {
        BIO_read(sbio, buffer, MYBUFSIZE);
        if (debug) {
            cp = strstr(buffer, "\r\n");
            *cp = '\0';
            fprintf(stdout, "recv: %s\n", buffer);
            fprintf(stdout, "send: STLS\n");
        }
        BIO_printf(sbio, "STLS\r\n");
        BIO_read(sbio, buffer, MYBUFSIZE);
        if (debug) {
            cp = strstr(buffer, "\r\n");
            *cp = '\0';
            fprintf(stdout, "recv: %s\n", buffer);
        }
        if (strncmp(buffer, "+OK", 3) == 0)
            rc = 1;
        else
            fprintf(stdout, "ERROR: Didn't get +OK in response to STARTTLS.\n");
        break;
    }
    case STARTTLS_XMPP_CLIENT:
    case STARTTLS_XMPP_SERVER: {
        int readn, seen_starttls = 0;
        snprintf(buffer, sizeof(buffer),
                 "<?xml version='1.0'?>"
                 "<stream:stream "
                 "to='%s' "
                 "version='1.0' xml:lang='en' "
                 "xmlns='jabber:%s' "
                 "xmlns:stream='http://etherx.jabber.org/streams'>",
                 service ? service : hostname,
                 starttls == STARTTLS_XMPP_CLIENT ? "client" : "server");
        if (debug) {
            fprintf(stdout, "send: %s\n", buffer);
        }
        BIO_printf(sbio, buffer);
        while (1) {
            readn = BIO_read(sbio, buffer, MYBUFSIZE);
            if (readn == 0) break;
            buffer[readn] = '\0';
            if (debug) {
                fprintf(stdout, "recv: %s\n", buffer);
            }
            if (strstr(buffer, "<starttls xmlns") &&
                    strstr(buffer, "urn:ietf:params:xml:ns:xmpp-tls")) {
                seen_starttls = 1;
                break;
            }
        }
        if (!seen_starttls)
            fprintf(stdout, "Unable to find STARTTLS in XMPP response.\n");
        else {
            snprintf(buffer, sizeof(buffer),
                     "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
            if (debug) {
                fprintf(stdout, "send: %s\n", buffer);
            }
            BIO_printf(sbio, buffer);
            readn = BIO_read(sbio, buffer, MYBUFSIZE);
            buffer[readn] = '\0';
            if (debug) {
                fprintf(stdout, "recv: %s\n", buffer);
            }
            if (strstr(buffer, "<proceed"))
                rc = 1;
        }
        break;
    }
    default:
        fprintf(stdout, "STARTTLS application not implemented.\n");
        break;
    }
    return rc;
}
static int execute_test_ssl_bio(SSL_BIO_TEST_FIXTURE fix)
{
    BIO *sslbio = NULL, *membio1 = NULL, *membio2 = NULL;
    SSL_CTX *ctx = SSL_CTX_new(TLS_method());
    SSL *ssl = NULL;
    int testresult = 0;

    if (ctx == NULL) {
        printf("Failed to allocate SSL_CTX\n");
        return 0;
    }

    ssl = SSL_new(ctx);
    if (ssl == NULL) {
        printf("Failed to allocate SSL object\n");
        goto end;
    }

    sslbio = BIO_new(BIO_f_ssl());
    membio1 = BIO_new(BIO_s_mem());

    if (sslbio == NULL || membio1 == NULL) {
        printf("Malloc failure creating BIOs\n");
        goto end;
    }

    BIO_set_ssl(sslbio, ssl, BIO_CLOSE);

    /*
     * If anything goes wrong here then we could leak memory, so this will
     * be caught in a crypto-mdebug build
     */
    BIO_push(sslbio, membio1);

    /* Verify changing the rbio/wbio directly does not cause leaks */
    if (fix.change_bio != NO_BIO_CHANGE) {
        membio2 = BIO_new(BIO_s_mem());
        if (membio2 == NULL) {
            printf("Malloc failure creating membio2\n");
            goto end;
        }
        if (fix.change_bio == CHANGE_RBIO)
            SSL_set0_rbio(ssl, membio2);
        else
            SSL_set0_wbio(ssl, membio2);
    }
    ssl = NULL;

    if (fix.pop_ssl)
        BIO_pop(sslbio);
    else
        BIO_pop(membio1);

    testresult = 1;
 end:
    BIO_free(membio1);
    BIO_free(sslbio);
    SSL_free(ssl);
    SSL_CTX_free(ctx);

    return testresult;
}
Exemple #21
0
/** Thread body.  Accepts SSL connections and adds peers as they connect */
wxThread::ExitCode RAIN::ConnectionListener::Entry()
{
	BIO *listener, *client;
	SSL *client_ssl;
	SSL_CTX* ssl_ctx = globalCredentialManager->GetSSLContext();

	wxLogVerbose(wxT("starting up RAIN::ConnectionListener; ssl_ctx = %08x"), ssl_ctx);

	listener = BIO_new_accept(DEFAULT_ACCEPT_STR);

	if (!listener)
	{
		wxLogError("Server socket creation failed");
		return NULL;
	}

	/* set listener to be non blocking - needed for
	 * this thread's proper behaviour with timely exiting 
	 * 
	 * also set BIO_BIND_REUSEADDR */
	// broken in gcc severely
	const char a[] = "a";
	BIO_ctrl(listener, BIO_C_SET_ACCEPT, 1, (void*)a);
	BIO_set_bind_mode(listener, BIO_BIND_REUSEADDR);

	// now bind the port
	if (BIO_do_accept(listener) <= 0)
	{
		wxLogError("Server socket binding failed");
		BIO_free_all(listener);
		return NULL;
	}

	while (true)
	{
		if (this->GetThread()->TestDestroy())
		{
			wxLogVerbose("RAIN::ConnectionListener thread finishing");
			BIO_free_all(listener);
			return NULL;
		} else {
			//wxLogVerbose("RAIN::ConnectionListener thread continuing");
		}

		if (BIO_do_accept(listener) > 0)
		{
			// there's a connection waiting to be accepted
			client = BIO_pop(listener);

			if (!(client_ssl = SSL_new(ssl_ctx)))
			{
				wxLogFatalError("RAIN::ConnectionListener - Error creating new SSL connection from context");
				BIO_free_all(client);
				BIO_free_all(listener);
				return NULL;
			} else {
				SSL_set_bio(client_ssl, client, client);

				int sa_ret = SSL_accept(client_ssl);
				int SSLge = SSL_get_error(client_ssl, sa_ret);
				int runawayGuard = 15;

				while (runawayGuard-- && sa_ret == -1 && (SSLge == SSL_ERROR_SSL || SSLge == SSL_ERROR_WANT_READ || SSLge == SSL_ERROR_WANT_WRITE))
				{
					/* the handshaking occurs in a non-blocking way, the underlying bio 'client'
					 * inherits the listener's non-blockingness */
					sa_ret = SSL_accept(client_ssl);
					SSLge = SSL_get_error(client_ssl, sa_ret);
					wxThread::Sleep(1000);
				}

				if (runawayGuard < 1 || sa_ret <= 0)
				{
					SSL_free(client_ssl);

					if (runawayGuard < 1)
						wxLogError("RAIN::ConnectionListener - Timeout while handshaking for new SSL connection");
					else
						wxLogError("RAIN::ConnectionListener - Error accepting new SSL connection: ssl_accept returned %d; ssl_get_error returned %d", sa_ret, SSLge);
				} else {
					wxLogVerbose("RAIN::ConnectionListener - SSL_accept succeeded");

					RAIN::Connection *nc = new RAIN::Connection(client_ssl);
					this->connectionPool->AddServedPeer(nc);
				}
			}
		}

		wxThread::Sleep(2000);
	}
}
void *phr_authority_list_loading_main(void *arg)
{
	BIO         *bio_acc    = NULL;
	BIO         *bio_client = NULL;
    	SSL         *ssl_client = NULL;
    	SSL_CTX     *ctx        = NULL;

	int         err;
	char        *hosts[2];

    	ctx = setup_server_ctx(ESA_CERTFILE_PATH, ESA_CERTFILE_PASSWD, EMU_ROOT_CA_ONLY_CERT_CERTFILE_PATH);
    	bio_acc = BIO_new_accept(ESA_PHR_AUTHORITY_LIST_LOADING_PORT);
    	if(!bio_acc)
        	int_error("Creating server socket failed");
  
    	if(BIO_do_accept(bio_acc) <= 0)
        	int_error("Binding server socket failed");
  
    	for(;;)
    	{
        	if(BIO_do_accept(bio_acc) <= 0)
            		int_error("Accepting connection failed");
 
        	bio_client = BIO_pop(bio_acc);

        	if(!(ssl_client = SSL_new(ctx)))
            		int_error("Creating SSL context failed");

        	SSL_set_bio(ssl_client, bio_client, bio_client);
		if(SSL_accept(ssl_client) <= 0)
		{
        		fprintf(stderr, "Accepting SSL connection failed\n");
			goto ERROR_AT_SSL_LAYER;
		}

		hosts[0] = ADMIN_CN; 
		hosts[1] = USER_CN; 
    		if((err = post_connection_check(ssl_client, hosts, 2, true, GLOBAL_authority_name)) != X509_V_OK)
    		{
        		fprintf(stderr, "Checking peer certificate failed\n\"%s\"\n", X509_verify_cert_error_string(err));
        		goto ERROR_AT_SSL_LAYER;
    		}

		// Serve the PHR authority list
		if(!load_phr_authority_list(ssl_client))
			goto ERROR_AT_SSL_LAYER;
		
ERROR_AT_SSL_LAYER:

		SSL_cleanup(ssl_client);
		ssl_client = NULL;
    		ERR_remove_state(0);
    	}
    
    	SSL_CTX_free(ctx);
	ctx = NULL;

    	BIO_free(bio_acc);
	bio_acc = NULL;

	pthread_exit(NULL);
    	return NULL;
}
Exemple #23
0
int main(int argc, char *argv[])
{
	SSL *ssl;
	SSL_CTX *ctx;
	BIO *bio, *abio, *cbio;
	pthread_t t;
	X509 *peer;
	int (*callback)(char *, int, int, void *) = &password_callback;

	SSL_library_init();

	SSL_load_error_strings();
	ERR_load_BIO_strings();
	ERR_load_SSL_strings();

	printf("Attempting to create SSL context...\n");
	ctx = SSL_CTX_new(SSLv3_server_method());
	if(ctx == NULL) {
		printf("Failed. Aborting.\n");
		ERR_print_errors_fp(stdout);
		return 0;
	}

	printf("Loading certificates...\n");
	SSL_CTX_set_default_passwd_cb(ctx, callback);
	//if (SSL_CTX_use_certificate_file(ctx, "./CA/server_cert.pem", SSL_FILETYPE_PEM) != 1) {
	if (SSL_CTX_use_certificate_chain_file(ctx, "./CAtest/server_cert.pem") != 1) {
		/* Handle failed load here */
		ERR_print_errors_fp(stdout);
		exit(1);
	}
	if (SSL_CTX_use_PrivateKey_file(ctx, "./CAtest/private/server_key.pem", SSL_FILETYPE_PEM) != 1) {
		/* Handle failed load here */
		ERR_print_errors_fp(stdout);
		exit(1);
	}
	if (!SSL_CTX_load_verify_locations(ctx, "./CAtest/cacert.pem", "./CA/")) {
		/* Handle failed load here */
        ERR_print_errors_fp(stdout);
		exit(1);
	}

	SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, verify_callback);
	SSL_CTX_set_verify_depth(ctx, 5);

	printf("Attempting to create BIO object...\n");
	bio = BIO_new_ssl(ctx, 0);
	if(bio == NULL) {
		printf("Failed. Aborting.\n");
		ERR_print_errors_fp(stdout);
		SSL_CTX_free(ctx);
		return 0;
	}

	printf("Attempting to set up BIO for SSL...\n");
	BIO_get_ssl(bio, &ssl);
	SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

	abio = BIO_new_accept("4422");
	BIO_set_accept_bios(abio, bio);

	/* First call to BIO_accept() sets up accept BIO */
	if (BIO_do_accept(abio) <= 0) {
		fprintf(stderr, "Error setting up accept\n");
		ERR_print_errors_fp(stderr);
		exit(0);
	}

	do {
		/* Wait for incoming connection */
		if (BIO_do_accept(abio) <= 0) {
			fprintf(stderr, "Error accepting connection\n");
			ERR_print_errors_fp(stderr);
			exit(0);
		}

		fprintf(stderr, "Connection 1 established\n");
		/* Retrieve BIO for connection */
		cbio = BIO_pop(abio);
		pthread_create(&t, NULL, handle_connection, cbio);
	} while (1);

	SSL_shutdown(ssl);
	BIO_free_all(bio);
	BIO_free_all(abio);
	SSL_CTX_free(ctx);
	SSL_free(ssl);

	return 0;
}
Exemple #24
0
static int decode(Gzb64* gzb64, bool last)
{
	int b64in_size;
	struct evbuffer_iovec v[2];
	int n, i;
	size_t n_to_add = BUFF_SIZE;

	if( last ) {
		b64in_size = evbuffer_get_length(gzb64->decode_input_buffer); /* dump everything in */		
		gzb64->decoded_last_chunk = true;	
	} else {
		int contiguous = evbuffer_get_contiguous_space(gzb64->decode_input_buffer);	
		b64in_size = contiguous - (contiguous % 4); /* must be mutliple of 4 */	 
	}

	if(DEBUG) printf("Decode In:%zu\n", evbuffer_get_length(gzb64->decode_input_buffer));

	unsigned char* b64in_buf = evbuffer_pullup(gzb64->decode_input_buffer, b64in_size);
	BIO *b64_src_temp = BIO_new_mem_buf(b64in_buf, b64in_size);
	gzb64->b64_decoder = BIO_push(gzb64->b64_decoder, b64_src_temp);

	int b64_output_len = BUFF_SIZE;

	while(b64_output_len == BUFF_SIZE) {

		/* Reserve BUFF_SIZE bytes.*/
		n = evbuffer_reserve_space(gzb64->decode_output_buffer, n_to_add, v, 2);
		if (n<=0)
		   return -1; /* Unable to reserve the space for some reason. */

		for (i=0; i<n && n_to_add > 0; ++i) {
		   size_t len = v[i].iov_len;
		   if (len > n_to_add) /* Don't write more than n_to_add bytes. */
			  len = n_to_add;

		   b64_output_len = BIO_read(gzb64->b64_decoder, v[i].iov_base, len);

		   if ( b64_output_len < 0) {
			  /* If there was a problem during data generation, we can just stop
				 here; no data will be committed to the buffer. */
			  return -1;
		   }
		   /* Set iov_len to the number of bytes we actually wrote, so we
			  don't commit too much. */
		   v[i].iov_len = b64_output_len;
			if(DEBUG) printf("Decode B64 Out:%d\n", b64_output_len);
		}

		/* We commit the space here.  Note that we give it 'i' (the number of
		   vectors we actually used) rather than 'n' (the number of vectors we
		   had available. */
		if (evbuffer_commit_space(gzb64->decode_output_buffer, v, i) < 0)
		   return -1; /* Error committing */
	}

	if(DEBUG) printf("Inflate In:%zu\n", evbuffer_get_length(gzb64->decode_output_buffer));

	BIO_pop(gzb64->b64_decoder);
	BIO_free(b64_src_temp);
	BIO_reset(gzb64->b64_decoder);

	evbuffer_drain(gzb64->decode_input_buffer, b64in_size);
	
	return 0;
}
Exemple #25
0
int main(int argc, char *argv[])
{
    char *port = "*:4433";
    BIO *in = NULL;
    BIO *ssl_bio, *tmp;
    SSL_CTX *ctx;
    SSL_CONF_CTX *cctx = NULL;
    CONF *conf = NULL;
    STACK_OF(CONF_VALUE) *sect = NULL;
    CONF_VALUE *cnf;
    long errline = -1;
    char buf[512];
    int ret = EXIT_FAILURE, i;

    ctx = SSL_CTX_new(TLS_server_method());

    conf = NCONF_new(NULL);

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

    sect = NCONF_get_section(conf, "default");

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

    cctx = SSL_CONF_CTX_new();
    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
    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++) {
        int rv;
        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 err;
        }
        if (strcmp(cnf->name, "Port") == 0) {
            port = cnf->value;
        } else {
            fprintf(stderr, "Unknown configuration option %s\n", cnf->name);
            goto err;
        }
    }

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

    /* Setup server side SSL bio */
    ssl_bio = BIO_new_ssl(ctx, 0);

    if ((in = BIO_new_accept(port)) == NULL)
        goto err;

    /*
     * This means that when a new connection is accepted on 'in', The ssl_bio
     * will be 'duplicated' and have the new socket BIO push into it.
     * Basically it means the SSL BIO will be automatically setup
     */
    BIO_set_accept_bios(in, ssl_bio);

 again:
    /*
     * The first call will setup the accept socket, and the second will get a
     * socket.  In this loop, the first actual accept will occur in the
     * BIO_read() function.
     */

    if (BIO_do_accept(in) <= 0)
        goto err;

    for (;;) {
        i = BIO_read(in, buf, 512);
        if (i == 0) {
            /*
             * If we have finished, remove the underlying BIO stack so the
             * next time we call any function for this BIO, it will attempt
             * to do an accept
             */
            printf("Done\n");
            tmp = BIO_pop(in);
            BIO_free_all(tmp);
            goto again;
        }
        if (i < 0) {
            if (BIO_should_retry(in))
                continue;
            goto err;
        }
        fwrite(buf, 1, i, stdout);
        fflush(stdout);
    }

    ret = EXIT_SUCCESS;
 err:
    if (ret != EXIT_SUCCESS)
        ERR_print_errors_fp(stderr);
    BIO_free(in);
    return ret;
}
Exemple #26
0
int main(int argc, char *argv[])
{
    char *port = NULL;
    BIO *ssl_bio, *tmp;
    SSL_CTX *ctx;
    char buf[512];
    int ret = 1, i;

    if (argc <= 1)
        port = "*:4433";
    else
        port = argv[1];

    signal(SIGINT, close_up);

    SSL_load_error_strings();

    /* Add ciphers and message digests */
    OpenSSL_add_ssl_algorithms();

    ctx = SSL_CTX_new(TLS_server_method());
    if (!SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM))
        goto err;
    if (!SSL_CTX_use_PrivateKey_file(ctx, CERT_FILE, SSL_FILETYPE_PEM))
        goto err;
    if (!SSL_CTX_check_private_key(ctx))
        goto err;

    /* Setup server side SSL bio */
    ssl_bio = BIO_new_ssl(ctx, 0);

    if ((in = BIO_new_accept(port)) == NULL)
        goto err;

    /*
     * This means that when a new connection is accepted on 'in', The ssl_bio
     * will be 'duplicated' and have the new socket BIO push into it.
     * Basically it means the SSL BIO will be automatically setup
     */
    BIO_set_accept_bios(in, ssl_bio);

again:
    /*
     * The first call will setup the accept socket, and the second will get a
     * socket.  In this loop, the first actual accept will occur in the
     * BIO_read() function.
     */

    if (BIO_do_accept(in) <= 0)
        goto err;

    for (;;) {
        i = BIO_read(in, buf, 512);
        if (i == 0) {
            /*
             * If we have finished, remove the underlying BIO stack so the
             * next time we call any function for this BIO, it will attempt
             * to do an accept
             */
            printf("Done\n");
            tmp = BIO_pop(in);
            BIO_free_all(tmp);
            goto again;
        }
        if (i < 0)
            goto err;
        fwrite(buf, 1, i, stdout);
        fflush(stdout);
    }

    ret = 0;
err:
    if (ret) {
        ERR_print_errors_fp(stderr);
    }
    BIO_free(in);
    exit(ret);
    return (!ret);
}
void *emergency_delegation_list_loading_main(void *arg)
{
	BIO     *bio_acc    = NULL;
	BIO     *bio_client = NULL;
    	SSL     *ssl_client = NULL;
    	SSL_CTX *ctx        = NULL;

	int     err;
	char    *host[1];

    	ctx = setup_server_ctx(EMS_CERTFILE_PATH, EMS_CERTFILE_PASSWD, PHR_ROOT_CA_ONLY_CERT_CERTFILE_PATH);
    	bio_acc = BIO_new_accept(EMS_EMERGENCY_DELEGATION_LIST_LOADING_PORT);
    	if(!bio_acc)
        	int_error("Creating server socket failed");
  
    	if(BIO_do_accept(bio_acc) <= 0)
        	int_error("Binding server socket failed");
  
    	for(;;)
    	{
        	if(BIO_do_accept(bio_acc) <= 0)
            		int_error("Accepting connection failed");
 
        	bio_client = BIO_pop(bio_acc);

        	if(!(ssl_client = SSL_new(ctx)))
            		int_error("Creating SSL context failed");

        	SSL_set_bio(ssl_client, bio_client, bio_client);
		if(SSL_accept(ssl_client) <= 0)
		{
        		fprintf(stderr, "Accepting SSL connection failed\n");
			goto ERROR_AT_SSL_LAYER;
		}

		host[0] = USER_CN; 
    		if((err = post_connection_check(ssl_client, host, 1, true, GLOBAL_authority_name)) != X509_V_OK)
    		{
        		fprintf(stderr, "Checking peer certificate failed\n\"%s\"\n", X509_verify_cert_error_string(err));
        		goto ERROR_AT_SSL_LAYER;
    		}

		// Process types of request
		if(!process_request(ssl_client))
			goto ERROR_AT_SSL_LAYER;

ERROR_AT_SSL_LAYER:

		SSL_cleanup(ssl_client);
		ssl_client = NULL;
    		ERR_remove_state(0);
    	}
    
    	SSL_CTX_free(ctx);
	ctx = NULL;

    	BIO_free(bio_acc);
	bio_acc = NULL;

	pthread_exit(NULL);
    	return NULL;
}
Exemple #28
0
int
s_client_main(int argc, char **argv)
{
	unsigned int off = 0, clr = 0;
	SSL *con = NULL;
	int s, k, width, state = 0, af = AF_UNSPEC;
	char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL;
	int cbuf_len, cbuf_off;
	int sbuf_len, sbuf_off;
	fd_set readfds, writefds;
	char *port = PORT_STR;
	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 = PROTO_OFF;
	int prexit = 0;
	X509_VERIFY_PARAM *vpm = NULL;
	int badarg = 0;
	const SSL_METHOD *meth = NULL;
	int socket_type = SOCK_STREAM;
	BIO *sbio;
	int mbuf_len = 0;
	struct timeval timeout, *timeoutp;
	const char *errstr = NULL;
#ifndef OPENSSL_NO_ENGINE
	char *engine_id = NULL;
	char *ssl_client_engine_id = NULL;
	ENGINE *ssl_client_engine = NULL;
#endif
	ENGINE *e = NULL;
#ifndef OPENSSL_NO_TLSEXT
	char *servername = NULL;
	tlsextctx tlsextcbp =
	{NULL, 0};
#ifndef OPENSSL_NO_NEXTPROTONEG
	const char *next_proto_neg_in = NULL;
#endif
#endif
	char *sess_in = NULL;
	char *sess_out = NULL;
	struct sockaddr peer;
	int peerlen = sizeof(peer);
	int enable_timeouts = 0;
	long socket_mtu = 0;

	meth = SSLv23_client_method();

	c_Pause = 0;
	c_quiet = 0;
	c_ign_eof = 0;
	c_debug = 0;
	c_msg = 0;
	c_showcerts = 0;

	if (((cbuf = malloc(BUFSIZZ)) == NULL) ||
	    ((sbuf = malloc(BUFSIZZ)) == NULL) ||
	    ((mbuf = malloc(BUFSIZZ + 1)) == NULL)) {	/* NUL byte */
		BIO_printf(bio_err, "out of memory\n");
		goto end;
	}
	verify_depth = 0;
	verify_error = X509_V_OK;
	c_nbio = 0;

	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 = *(++argv);
			if (port == NULL || *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 = strtonum(*(++argv), 0, INT_MAX, &errstr);
			if (errstr)
				goto bad;
			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, "-sess_out") == 0) {
			if (--argc < 1)
				goto bad;
			sess_out = *(++argv);
		} else if (strcmp(*argv, "-sess_in") == 0) {
			if (--argc < 1)
				goto bad;
			sess_in = *(++argv);
		} else if (strcmp(*argv, "-certform") == 0) {
			if (--argc < 1)
				goto bad;
			cert_format = str2fmt(*(++argv));
		} else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) {
			if (badarg)
				goto bad;
			continue;
		} else if (strcmp(*argv, "-verify_return_error") == 0)
			verify_return_error = 1;
		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, "-no_ign_eof") == 0)
			c_ign_eof = 0;
		else if (strcmp(*argv, "-pause") == 0)
			c_Pause = 1;
		else if (strcmp(*argv, "-debug") == 0)
			c_debug = 1;
#ifndef OPENSSL_NO_TLSEXT
		else if (strcmp(*argv, "-tlsextdebug") == 0)
			c_tlsextdebug = 1;
		else if (strcmp(*argv, "-status") == 0)
			c_status_req = 1;
#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;
		else if (strcmp(*argv, "-ssl3") == 0)
			meth = SSLv3_client_method();
		else if (strcmp(*argv, "-tls1_2") == 0)
			meth = TLSv1_2_client_method();
		else if (strcmp(*argv, "-tls1_1") == 0)
			meth = TLSv1_1_client_method();
		else if (strcmp(*argv, "-tls1") == 0)
			meth = TLSv1_client_method();
#ifndef OPENSSL_NO_DTLS1
		else if (strcmp(*argv, "-dtls1") == 0) {
			meth = DTLSv1_client_method();
			socket_type = SOCK_DGRAM;
		} else if (strcmp(*argv, "-timeout") == 0)
			enable_timeouts = 1;
		else if (strcmp(*argv, "-mtu") == 0) {
			if (--argc < 1)
				goto bad;
			socket_mtu = strtonum(*(++argv), 0, LONG_MAX, &errstr);
			if (errstr)
				goto bad;
		}
#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_2") == 0)
			off |= SSL_OP_NO_TLSv1_2;
		else if (strcmp(*argv, "-no_tls1_1") == 0)
			off |= SSL_OP_NO_TLSv1_1;
		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, "-no_comp") == 0) {
			off |= SSL_OP_NO_COMPRESSION;
		}
#ifndef OPENSSL_NO_TLSEXT
		else if (strcmp(*argv, "-no_ticket") == 0) {
			off |= SSL_OP_NO_TICKET;
		}
#ifndef OPENSSL_NO_NEXTPROTONEG
		else if (strcmp(*argv, "-nextprotoneg") == 0) {
			if (--argc < 1)
				goto bad;
			next_proto_neg_in = *(++argv);
		}
#endif
#endif
		else if (strcmp(*argv, "-serverpref") == 0)
			off |= SSL_OP_CIPHER_SERVER_PREFERENCE;
		else if (strcmp(*argv, "-legacy_renegotiation") == 0)
			; /* no-op */
		else if (strcmp(*argv, "-legacy_server_connect") == 0) {
			off |= SSL_OP_LEGACY_SERVER_CONNECT;
		} else if (strcmp(*argv, "-no_legacy_server_connect") == 0) {
			clr |= SSL_OP_LEGACY_SERVER_CONNECT;
		} else if (strcmp(*argv, "-cipher") == 0) {
			if (--argc < 1)
				goto bad;
			cipher = *(++argv);
		}
		else if (strcmp(*argv, "-nbio") == 0) {
			c_nbio = 1;
		}
		else if (strcmp(*argv, "-starttls") == 0) {
			if (--argc < 1)
				goto bad;
			++argv;
			if (strcmp(*argv, "smtp") == 0)
				starttls_proto = PROTO_SMTP;
			else if (strcmp(*argv, "lmtp") == 0)
				starttls_proto = PROTO_LMTP;
			else if (strcmp(*argv, "pop3") == 0)
				starttls_proto = PROTO_POP3;
			else if (strcmp(*argv, "imap") == 0)
				starttls_proto = PROTO_IMAP;
			else if (strcmp(*argv, "ftp") == 0)
				starttls_proto = PROTO_FTP;
			else if (strcmp(*argv, "xmpp") == 0)
				starttls_proto = PROTO_XMPP;
			else
				goto bad;
		}
#ifndef OPENSSL_NO_ENGINE
		else if (strcmp(*argv, "-engine") == 0) {
			if (--argc < 1)
				goto bad;
			engine_id = *(++argv);
		} else if (strcmp(*argv, "-ssl_client_engine") == 0) {
			if (--argc < 1)
				goto bad;
			ssl_client_engine_id = *(++argv);
		}
#endif
		else if (strcmp(*argv, "-4") == 0) {
			af = AF_INET;
		} else if (strcmp(*argv, "-6") == 0) {
			af = AF_INET6;
		}
#ifndef OPENSSL_NO_TLSEXT
		else if (strcmp(*argv, "-servername") == 0) {
			if (--argc < 1)
				goto bad;
			servername = *(++argv);
			/* meth=TLSv1_client_method(); */
		}
#endif
#ifndef OPENSSL_NO_SRTP
		else if (strcmp(*argv, "-use_srtp") == 0) {
			if (--argc < 1)
				goto bad;
			srtp_profiles = *(++argv);
		}
#endif
		else if (strcmp(*argv, "-keymatexport") == 0) {
			if (--argc < 1)
				goto bad;
			keymatexportlabel = *(++argv);
		} else if (strcmp(*argv, "-keymatexportlen") == 0) {
			const char *errstr;

			if (--argc < 1)
				goto bad;
			keymatexportlen = strtonum(*(++argv), 1, INT_MAX, &errstr);
			if (errstr)
				goto bad;
		} else {
			BIO_printf(bio_err, "unknown option %s\n", *argv);
			badop = 1;
			break;
		}
		argc--;
		argv++;
	}
	if (badop) {
bad:
		if (errstr)
			BIO_printf(bio_err, "invalid argument %s: %s\n",
			    *argv, errstr);
		else
			sc_usage();
		goto end;
	}

#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
	next_proto.status = -1;
	if (next_proto_neg_in) {
		next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in);
		if (next_proto.data == NULL) {
			BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n");
			goto end;
		}
	} else
		next_proto.data = NULL;
#endif

#ifndef OPENSSL_NO_ENGINE
	e = setup_engine(bio_err, engine_id, 1);
	if (ssl_client_engine_id) {
		ssl_client_engine = ENGINE_by_id(ssl_client_engine_id);
		if (!ssl_client_engine) {
			BIO_printf(bio_err,
			    "Error getting client auth engine\n");
			goto end;
		}
	}
#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 (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 (vpm)
		SSL_CTX_set1_param(ctx, vpm);

#ifndef OPENSSL_NO_ENGINE
	if (ssl_client_engine) {
		if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) {
			BIO_puts(bio_err, "Error setting client auth engine\n");
			ERR_print_errors(bio_err);
			ENGINE_free(ssl_client_engine);
			goto end;
		}
		ENGINE_free(ssl_client_engine);
	}
#endif

#ifndef OPENSSL_NO_SRTP
	if (srtp_profiles != NULL)
		SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles);
#endif
	if (bugs)
		SSL_CTX_set_options(ctx, SSL_OP_ALL | off);
	else
		SSL_CTX_set_options(ctx, off);

	if (clr)
		SSL_CTX_clear_options(ctx, clr);
	/*
	 * DTLS: partial reads end up discarding unread UDP bytes :-( Setting
	 * read ahead solves this problem.
	 */
	if (socket_type == SOCK_DGRAM)
		SSL_CTX_set_read_ahead(ctx, 1);

#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
	if (next_proto.data)
		SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
#endif

	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;
		}

	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; */
	}
#ifndef OPENSSL_NO_TLSEXT
	if (servername != NULL) {
		tlsextcbp.biodebug = bio_err;
		SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
		SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
	}
#endif

	con = SSL_new(ctx);
	if (sess_in) {
		SSL_SESSION *sess;
		BIO *stmp = BIO_new_file(sess_in, "r");
		if (!stmp) {
			BIO_printf(bio_err, "Can't open session file %s\n",
			    sess_in);
			ERR_print_errors(bio_err);
			goto end;
		}
		sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
		BIO_free(stmp);
		if (!sess) {
			BIO_printf(bio_err, "Can't open session file %s\n",
			    sess_in);
			ERR_print_errors(bio_err);
			goto end;
		}
		SSL_set_session(con, sess);
		SSL_SESSION_free(sess);
	}
#ifndef OPENSSL_NO_TLSEXT
	if (servername != NULL) {
		if (!SSL_set_tlsext_host_name(con, servername)) {
			BIO_printf(bio_err, "Unable to set TLS servername extension.\n");
			ERR_print_errors(bio_err);
			goto end;
		}
	}
#endif
/*	SSL_set_cipher_list(con,"RC4-MD5"); */

re_start:

	if (init_client(&s, host, port, socket_type, af) == 0) {
		BIO_printf(bio_err, "connect:errno=%d\n", errno);
		shutdown(s, SHUT_RD);
		close(s);
		goto end;
	}
	BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);

	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;
		}
	}
	if (c_Pause & 0x01)
		SSL_set_debug(con, 1);

	if (SSL_version(con) == DTLS1_VERSION) {

		sbio = BIO_new_dgram(s, BIO_NOCLOSE);
		if (getsockname(s, &peer, (void *) &peerlen) < 0) {
			BIO_printf(bio_err, "getsockname:errno=%d\n",
			    errno);
			shutdown(s, SHUT_RD);
			close(s);
			goto end;
		}
		(void) 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 (socket_mtu > 28) {
			SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
			SSL_set_mtu(con, socket_mtu - 28);
		} 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) {
		SSL_set_debug(con, 1);
		BIO_set_callback(sbio, bio_dump_callback);
		BIO_set_callback_arg(sbio, (char *) bio_c_out);
	}
	if (c_msg) {
		SSL_set_msg_callback(con, msg_cb);
		SSL_set_msg_callback_arg(con, bio_c_out);
	}
#ifndef OPENSSL_NO_TLSEXT
	if (c_tlsextdebug) {
		SSL_set_tlsext_debug_callback(con, tlsext_cb);
		SSL_set_tlsext_debug_arg(con, bio_c_out);
	}
	if (c_status_req) {
		SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp);
		SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb);
		SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out);
	}
#endif

	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 */
	/*
	 * We do have to handle multi-line responses which may come in a
	 * single packet or not. We therefore have to use BIO_gets() which
	 * does need a buffering BIO. So during the initial chitchat we do
	 * push a buffering BIO into the chain that is removed again later on
	 * to not disturb the rest of the s_client operation.
	 */
	if (starttls_proto == PROTO_SMTP || starttls_proto == PROTO_LMTP) {
		int foundit = 0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from SMTP */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		/* STARTTLS command requires EHLO... */
		BIO_printf(fbio, "%cHLO openssl.client.net\r\n",
			   starttls_proto == PROTO_SMTP ? 'E' : 'L');
		(void) BIO_flush(fbio);
		/* wait for multi-line response to end EHLO SMTP response */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
			if (strstr(mbuf, "STARTTLS"))
				foundit = 1;
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
			    "didn't found starttls in server response,"
			    " try anyway...\n");
		BIO_printf(sbio, "STARTTLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_POP3) {
		mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
		if (mbuf_len == -1) {
			BIO_printf(bio_err, "BIO_read failed\n");
			goto end;
		}
		BIO_printf(sbio, "STLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_IMAP) {
		int foundit = 0;
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		BIO_gets(fbio, mbuf, BUFSIZZ);
		/* STARTTLS command requires CAPABILITY... */
		BIO_printf(fbio, ". CAPABILITY\r\n");
		(void) BIO_flush(fbio);
		/* wait for multi-line CAPABILITY response */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
			if (strstr(mbuf, "STARTTLS"))
				foundit = 1;
		}
		while (mbuf_len > 3 && mbuf[0] != '.');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		if (!foundit)
			BIO_printf(bio_err,
			    "didn't found STARTTLS in server response,"
			    " try anyway...\n");
		BIO_printf(sbio, ". STARTTLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	} else if (starttls_proto == PROTO_FTP) {
		BIO *fbio = BIO_new(BIO_f_buffer());
		BIO_push(fbio, sbio);
		/* wait for multi-line response to end from FTP */
		do {
			mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
		}
		while (mbuf_len > 3 && mbuf[3] == '-');
		(void) BIO_flush(fbio);
		BIO_pop(fbio);
		BIO_free(fbio);
		BIO_printf(sbio, "AUTH TLS\r\n");
		BIO_read(sbio, sbuf, BUFSIZZ);
	}
	if (starttls_proto == PROTO_XMPP) {
		int seen = 0;
		BIO_printf(sbio, "<stream:stream "
		    "xmlns:stream='http://etherx.jabber.org/streams' "
		    "xmlns='jabber:client' to='%s' version='1.0'>", host);
		seen = BIO_read(sbio, mbuf, BUFSIZZ);
		mbuf[seen] = 0;
		while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")) {
			if (strstr(mbuf, "/stream:features>"))
				goto shut;
			seen = BIO_read(sbio, mbuf, BUFSIZZ);
			mbuf[seen] = 0;
		}
		BIO_printf(sbio, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
		seen = BIO_read(sbio, sbuf, BUFSIZZ);
		sbuf[seen] = 0;
		if (!strstr(sbuf, "<proceed"))
			goto shut;
		mbuf[0] = 0;
	}
	for (;;) {
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);

		if ((SSL_version(con) == DTLS1_VERSION) &&
		    DTLSv1_get_timeout(con, &timeout))
			timeoutp = &timeout;
		else
			timeoutp = NULL;

		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;
				if (sess_out) {
					BIO *stmp = BIO_new_file(sess_out, "w");
					if (stmp) {
						PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con));
						BIO_free(stmp);
					} else
						BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
				}
				print_stuff(bio_c_out, con, full_log);
				if (full_log > 0)
					full_log--;

				if (starttls_proto) {
					BIO_write(bio_err, mbuf, mbuf_len);
					/* We don't need to know any more */
					starttls_proto = PROTO_OFF;
				}
				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), SHUT_RD);
					close(SSL_get_fd(con));
					goto re_start;
				}
			}
		}

		ssl_pending = read_ssl && SSL_pending(con);

		/* XXX should add tests for fd_set overflow */

		if (!ssl_pending) {
			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);
/*			printf("mode tty(%d %d%d) ssl(%d%d)\n",
				tty_on,read_tty,write_tty,read_ssl,write_ssl);*/

			i = select(width, &readfds, &writefds,
			    NULL, timeoutp);
			if (i < 0) {
				BIO_printf(bio_err, "bad select %d\n",
				    errno);
				goto shut;
				/* goto end; */
			}
		}
		if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) {
			BIO_printf(bio_err, "TIMEOUT occured\n");
		}
		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");
					ret = 0;
					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",
					    errno);
					goto shut;
				} else {
					read_tty = 1;
					write_ssl = 0;
				}
				break;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
			}
		} else if (!ssl_pending && FD_ISSET(fileno(stdout), &writefds)) {
			i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len);

			if (i <= 0) {
				BIO_printf(bio_c_out, "DONE\n");
				ret = 0;
				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
			k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ );

			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:
				ret = errno;
				BIO_printf(bio_err, "read:errno=%d\n", ret);
				goto shut;
			case SSL_ERROR_ZERO_RETURN:
				BIO_printf(bio_c_out, "closed\n");
				ret = 0;
				goto shut;
			case SSL_ERROR_SSL:
				ERR_print_errors(bio_err);
				goto shut;
				/* break; */
			}
		} else if (FD_ISSET(fileno(stdin), &readfds)) {
			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");
				ret = 0;
				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;
			}

			write_ssl = 1;
			read_tty = 0;
		}
	}

	ret = 0;
shut:
	if (in_init)
		print_stuff(bio_c_out, con, full_log);
	SSL_shutdown(con);
	shutdown(SSL_get_fd(con), SHUT_RD);
	close(SSL_get_fd(con));
end:
	if (con != NULL) {
		if (prexit != 0)
			print_stuff(bio_c_out, con, 1);
		SSL_free(con);
	}
#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
	free(next_proto.data);
#endif
	if (ctx != NULL)
		SSL_CTX_free(ctx);
	if (cert)
		X509_free(cert);
	if (key)
		EVP_PKEY_free(key);
	free(pass);
	if (vpm)
		X509_VERIFY_PARAM_free(vpm);
	if (cbuf != NULL) {
		OPENSSL_cleanse(cbuf, BUFSIZZ);
		free(cbuf);
	}
	if (sbuf != NULL) {
		OPENSSL_cleanse(sbuf, BUFSIZZ);
		free(sbuf);
	}
	if (mbuf != NULL) {
		OPENSSL_cleanse(mbuf, BUFSIZZ);
		free(mbuf);
	}
	if (bio_c_out != NULL) {
		BIO_free(bio_c_out);
		bio_c_out = NULL;
	}

	return (ret);
}
Exemple #29
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 = PROTO_OFF;
    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;
    int mbuf_len=0;
#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 = PROTO_SMTP;
            else if (strcmp(*argv,"pop3") == 0)
                starttls_proto = PROTO_POP3;
            else if (strcmp(*argv,"imap") == 0)
                starttls_proto = PROTO_IMAP;
            else if (strcmp(*argv,"ftp") == 0)
                starttls_proto = PROTO_FTP;
            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;
        }

        (void)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,(char *)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 */
    /* We do have to handle multi-line responses which may come
       in a single packet or not. We therefore have to use
       BIO_gets() which does need a buffering BIO. So during
       the initial chitchat we do push a buffering BIO into the
       chain that is removed again later on to not disturb the
       rest of the s_client operation. */
    if (starttls_proto == PROTO_SMTP)
    {
        int foundit=0;
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        /* wait for multi-line response to end from SMTP */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
        }
        while (mbuf_len>3 && mbuf[3]=='-');
        /* STARTTLS command requires EHLO... */
        BIO_printf(fbio,"EHLO openssl.client.net\r\n");
        (void)BIO_flush(fbio);
        /* wait for multi-line response to end EHLO SMTP response */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
            if (strstr(mbuf,"STARTTLS"))
                foundit=1;
        }
        while (mbuf_len>3 && mbuf[3]=='-');
        (void)BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        if (!foundit)
            BIO_printf(bio_err,
                       "didn't found starttls in server response,"
                       " try anyway...\n");
        BIO_printf(sbio,"STARTTLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    else if (starttls_proto == PROTO_POP3)
    {
        BIO_read(sbio,mbuf,BUFSIZZ);
        BIO_printf(sbio,"STLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    else if (starttls_proto == PROTO_IMAP)
    {
        int foundit=0;
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        BIO_gets(fbio,mbuf,BUFSIZZ);
        /* STARTTLS command requires CAPABILITY... */
        BIO_printf(fbio,". CAPABILITY\r\n");
        (void)BIO_flush(fbio);
        /* wait for multi-line CAPABILITY response */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
            if (strstr(mbuf,"STARTTLS"))
                foundit=1;
        }
        while (mbuf_len>3 && mbuf[0]!='.');
        (void)BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        if (!foundit)
            BIO_printf(bio_err,
                       "didn't found STARTTLS in server response,"
                       " try anyway...\n");
        BIO_printf(sbio,". STARTTLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    else if (starttls_proto == PROTO_FTP)
    {
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        /* wait for multi-line response to end from FTP */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
        }
        while (mbuf_len>3 && mbuf[3]=='-');
        (void)BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        BIO_printf(sbio,"AUTH TLS\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 = PROTO_OFF;
                }

                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);
}
Exemple #30
0
/** Add a DSA key to the tspc key file
 *
 * @param dsa        the DSA param pointer filled with our key info
 * @param host       the hostname of the corresponding broker
 * @param filename   the keyfile to use
 *
 * @return  0 if error
 *          1 if ok
 *
 */
int
add_dsakey_to_keyfile(DSA *dsa, char *host, char *filename, tBoolean autoaccept)
{

  FILE *fp = NULL;
  Buffer buf;
  char *str = NULL;
  int ret = 0;

  switch (is_dsakey_in_keyfile(dsa, host, filename)) {

  case 0:
    Display(LOG_LEVEL_3, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_ERR_IN_KEY_VERIF);
    Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED);
    break;
  case 1: /* not in, we add and continue */
#if defined(WIN32) && !defined(WINCE)
// When running as a service we can't ask user
// permission. Compromise and accept the key auto
//
    if (!IsService && !autoaccept)
    {
#else
    if (!autoaccept)
    {
#endif
      if (!ask(GOGO_STR_UNKNOWN_HOST_ADD_KEY, host))
      {
        Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED_USER);
        break;
      }
    }
    else
  Display(LOG_LEVEL_1, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_SERVER_KEY_AUTO_ADDED);

    Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_ACCEPTED_ADDED);

    buffer_init(&buf);
    if (buf.buf == NULL)
      break;
    buffer_put_cstring(&buf, "ssh-dss");
    buffer_put_bignum(&buf, dsa->p);
    buffer_put_bignum(&buf, dsa->q);
    buffer_put_bignum(&buf, dsa->g);
    buffer_put_bignum(&buf, dsa->pub_key);

    if ( (str = pal_malloc(2 * buffer_len(&buf))) == NULL)
      break;

    if ( (base64encode(str, buffer_ptr(&buf), (int) buffer_len(&buf))) < 1)
      break;

    fp = fopen(filename, "a");
    if (fp) {
      fprintf(fp, "%s ssh-dss %s\n", host, str);
      fclose(fp);
      ret = 1;
    }
    buffer_free(&buf);
    pal_free(str);
    break;
  case 2: /* in and matching correctly, hurray */
    Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_MATCHING_KEY_FOUND_USED);
    ret = 1;
    break;
  case 3: /* in and NOT matching correctly */
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_STORED_LOCAL_KEY_NO_MATCH, filename, host);
  Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED);
    ret = 0;
    break;
  }

  return ret;
}


/**
 * Authenticate to the Migration Broker using PASSDSS-3DES-1
 *
 * Buf_H will contain the data used to validate the server
 * signature. The data is a concatenation of the following parameters,
 * in that order:
 * azname,authname,DH_public_key,pklength,"ssh-dss",p,q,g,z,Y,ssecmask,sbuflen,dh_K
 *
 * @param socket
 * @param user
 * @param passwd
 * @param host
 * @param nt
 *
 * @return
 *
 * @todo DH public key validation  (RFC2631, 2.1.5)
 * @todo Local storage for server public keys
 *
 */
gogoc_status AuthPASSDSS_3DES_1(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list)
{
  DH   *dh = NULL;        /**< client DH key used to exchange key with server */
  DSA  *dsa = NULL; /**< Remote server DSA key public information */
  DSA_SIG *sig = NULL;    /**< DSA signature */
  char authenticate[] = "AUTHENTICATE PASSDSS-3DES-1\r\n";
  char *BufferIn  = NULL;
  char *BufferOut = NULL;
  char *BufferPtr = NULL;
  Buffer BufH;    /**< Buffer to hold data used for signature. */
  Buffer BufSpace;  /**< Space to hold data before/after base64 conversion */
  Buffer *Buf_H = &BufH;
  Buffer *Buf_Space = &BufSpace;
  BIO  *bio_rw = NULL;    /**< Memory buffer bio */
  BIO  *b64= NULL;    /**< Base64 bio */
  BIO  *cipher = NULL;    /**< Symmetric crypto bio */
  BIGNUM *server_pubkey = NULL; /**< received server public DH key */
  BIGNUM *dh_K = NULL;          /**< DH computed shared secret */
  u_char hash[20];  /**< SHA1 hash */
  u_char enc_key[24]; /**< encryption key (3des) */
  u_char enc_iv[8]; /**< initialization vector (3des) */
  u_char int_key[20]; /**< cs integrity key */
  u_char tmphash[40]; /**< temporary hash storage */
  u_char hmac[EVP_MAX_MD_SIZE]; /**< HMAC for integrity of sent data (step L) */
  int  pklength = 0;  /**< length of SSH-style DSA server public key */
  int ssecmask = 0; /**< SASL security layers offered */
  int sbuflen = 0;  /**< maximum server security layer block size */
  char *s = NULL;
  u_char num[3];    /**< Array to manupulate 3 octet number (sbuflen)  */
  /* Temporary variables */
  int  buflen, readlen, keysize, siglength;
  gogoc_status status = STATUS_SUCCESS_INIT;
  sint32_t tsp_status;

/* From draft-newman-sasl-passdss-01.  "This group was taken from the
 * ISAKMP/Oakley specification, and was originally generated by
 * Richard Schroeppel at the University of Arizona.  Properties of
 * this prime are described in [Orm96]"
 */

        /* RFC2409, DH group 2 (second Oakley group) */
  static char *dh_group2=
      "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
      "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
      "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
      "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
      "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
      "FFFFFFFF" "FFFFFFFF";
  static unsigned char dh_g[]={
    0x02,
  };


  /* Initialize Diffie Hellman variables */
  if ((dh = DH_new()) == NULL || (server_pubkey = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Convert dh_group2 and dh_g to BIGNUM type */
  BN_hex2bn(&dh->p, dh_group2);
  dh->g = BN_bin2bn(dh_g,sizeof(dh_g),NULL);
  if ((dh->p == NULL) || (dh->g == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_INITIALIZATION_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  if ((dh_K = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /* Reserve storage for DSA key */
  if ((dsa = DSA_new()) == NULL || (dsa->p = BN_new()) == NULL ||
      (dsa->q = BN_new()) == NULL ||  (dsa->g = BN_new()) == NULL ||
      (dsa->pub_key = BN_new()) == NULL || (dsa->priv_key = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /* Allocate memory for DSA signature */
  if ((sig = DSA_SIG_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Initialize data buffers */
  BufferIn  = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE);
  BufferOut = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE);

  if ((BufferIn == NULL) || (BufferOut == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  buffer_init(Buf_Space);
  buffer_init(Buf_H);
  if (Buf_Space->buf == NULL || Buf_H->buf == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Create a read/write memory BIO. Memory is segment is
   * created and resized as needed. When BIO is destroyed, the
   * memory is freed. */
  bio_rw = BIO_new(BIO_s_mem());
  /* Create a base64 BIO filter */
  b64 = BIO_new(BIO_f_base64());
  if ((bio_rw == NULL) || (b64 == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /*
    Compute the Diffie-Hellman public value "X" as follows.  If
    X has a value of 0, repeat.

         x
    X = g  mod n

    where g = dh_g = 2
          n = dh_group2
    x = DH secret key
    X = DH public key
  */
  if (DH_generate_key(dh) == 0)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_GEN_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }

  /* Validate DH public key (RFC2631, 2.1.5) */

  /* Send  message with SASL mechanism identifier */
  if ( nt->netsend(socket, authenticate, sizeof(authenticate)) == -1 )
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_W_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }

  /* First PASSDSS  message from client to server:
     string azname       ; the user name to login as, may be empty if
                           same as authentication name
     string authname     ; the authentication name
     mpint  X            ; Diffie-Hellman parameter X
  */
  /* azname is empty. Just insert a string length zero */
  buffer_put_int(Buf_Space, 0);
  /* authname */
  buffer_put_cstring(Buf_Space, conf->userid);
  /* DH public key */
  buffer_put_bignum(Buf_Space, dh->pub_key);

  /* At this point, save the buffer into Buf_H. Used later for
   * signature verification. */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), buffer_len(Buf_Space));

  /* Push base64 filter */
  BIO_push(b64, bio_rw);
  /* no newline */
  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
  /* Write Buffer content into bio_rw. Buffer will be base64
   * encoded. */
  BIO_write(b64, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space));
  BIO_flush(b64);
  /* Get pointer to the result */
  buflen = BIO_get_mem_data(bio_rw, &BufferPtr);

  // Send data to server, save response in BufferIn.
  if((readlen = nt->netsendrecv(socket,
               BufferPtr, buflen,
               BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }
  /* remove base64 filter */
  BIO_pop(bio_rw);
  buffer_clear(Buf_Space);
  buflen = 0;

  /* Decode response (base64) and extract server response
   *
   * The response format is as follows:

       uint32   pklength   ; length of SSH-style DSA server public key
           (number of bytes up to y, inclusively)
         string "ssh-dss"  ; constant string "ssh-dss" (lower case)
         mpint  p          ; DSA public key parameters
         mpint  q
         mpint  g
         mpint  z            (y in draft)
       mpint    Y          ; Diffie-Hellman parameter Y
       OCTET    ssecmask   ; SASL security layers offered
       3 OCTET  sbuflen    ; maximum server security layer block size
       uint32   siglength  ; length of SSH-style dss signature
           (number of bytes up to s inclusively)
         string "ssh-dss"  ; constant string "ssh-dss" (lower case)
         mpint  r          ; DSA signature parameters
         mpint  s

   */

  buflen = base64decode(BufferOut, BufferIn);

  buffer_append(Buf_Space, BufferOut, buflen);
  /* Get pklength */
  pklength = buffer_get_int(Buf_Space);
  /* Assuming that
   * p, g, and y are 512 bits,
   * q is 160 bits,
   * "ssh-dss" is 7 bytes
   * pklength should be at least 240 bytes.
   */
  if (pklength < 240)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }

  /* Make a copy of (pklength|"ssh-dss"|p|q|g|z) in Buf_H */
  /* Add pklength */
  buffer_put_int(Buf_H, pklength);
  /* Add "ssh-dss"|p|q|g|z */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), pklength);

  /* Get "ssh-dss" string */
  s = buffer_get_string(Buf_Space, (unsigned int*)&buflen);
  pal_free(s); s = NULL;
  /* Get p */
  buffer_get_bignum(Buf_Space, dsa->p);
  /* Get q */
  buffer_get_bignum(Buf_Space, dsa->q);
  /* Get g */
  buffer_get_bignum(Buf_Space, dsa->g);
  /* Get z (pub_key) */
  buffer_get_bignum(Buf_Space, dsa->pub_key);
  /* Get DH public key */
  buffer_get_bignum(Buf_Space, server_pubkey);
  /* Copy in Buf_H for signature verification later */
  buffer_put_bignum(Buf_H, server_pubkey);

  /* Buffer now points at ssecmask (1 octet), followed by
   * sbuflen (3 octets). Make a copy of these 4 octets in Buf_H
   * now, then extract these values. */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), 4);

  /* Get ssecmask */
  ssecmask = buffer_get_octet(Buf_Space);
  /* Get sbuflen
   * Big endian binary unsigned integer */
  buffer_get(Buf_Space, (char *)num, 3);
  sbuflen =  (((u_long)(u_char)(num)[0] << 16) |
        ((u_long)(u_char)(num)[1] << 8) |
        ((u_long)(u_char)(num)[2]));

  /* DSS signature */
  /* Get siglength */
  siglength = buffer_get_int(Buf_Space);
  /* r and s are 20 bytes each, encoded as mpint (2*24)
   * "ssh-dss" is 7 bytes + int32 siglength should be >= 59
   * octets (mpint may have leading zero byte)
   */
  if (siglength < 59)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  /* Get "ssh-dss" string */
  s = buffer_get_string(Buf_Space, (unsigned int*)&buflen);
  pal_free(s); s = NULL;
  /* Get DSA signature r and s*/
  if ((sig->r= BN_new()) == NULL || (sig->s = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Get r */
  buffer_get_bignum(Buf_Space, sig->r);
  /* Get s */
  buffer_get_bignum(Buf_Space, sig->s);

  /* Validate server DH public key  (RFC2631, 2.1.5) */

  {
    if( !add_dsakey_to_keyfile(dsa, conf->server, TSPC_DSA_KEYFILE, conf->no_questions) )
    {
      Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_KEY_VERIF_ERROR);
      status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
      goto error;
    }
  }

  /* Verify that DSA public key belongs to server */

  /* Compute DH shared secret */
  if ((s = calloc(1, DH_size(dh))) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  if( (keysize = DH_compute_key((unsigned char*)s, server_pubkey, dh)) < 0 )
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_SHARED_COMPUTE_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  BN_bin2bn((const unsigned char*)s, keysize, dh_K);
  memset(s, 0, keysize);
  pal_free(s);
  s = NULL;
  Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
    GOGO_STR_DH_SHARED_KEY, BN_bn2hex(dh_K));

  /* Append dh_K in to complete the buffer. Use Buffer to hold
   * result to keep Bf_H intact, since to will be used (without
   * dh_K) to compute HMAC for packet integrity. */
  buffer_clear(Buf_Space);
  buffer_append(Buf_Space, buffer_ptr(Buf_H), buffer_len(Buf_H));
  buffer_put_bignum(Buf_Space, dh_K);

  /* Compute SHA1 hash of Buffer */
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), hash);

  /* Debug information available at level 4 */
 {
   BIGNUM *h;
   h = BN_bin2bn(hash, 20, NULL);
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_SIGNED_HASH, BN_bn2hex(h));
   BN_free(h);
 }
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_DSA_SIGN_R, BN_bn2hex(sig->r));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_DSA_SIGN_S, BN_bn2hex(sig->s));

  // Verify that the DSS signature is a signature of hash.
  switch( DSA_do_verify(hash, sizeof(hash), sig, dsa) )
  {
  case 0:
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_BAD_SIG_FROM_SERVER);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
    break; /* NOTREACHED */

  case 1:  /* correct signature */
    break;

  default: /* -1 on error */
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SIG_VERIF_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
    break; /* NOTREACHED */
  }

  /* Step I: Compute 3DES key and iv */
  /*
    cs-encryption-iv    = SHA1( K || "A" || H )
    sc-encryption-iv    = SHA1( K || "B" || H )
    cs-encryption-key-1 = SHA1( K || "C" || H )
    cs-encryption-key-2 = SHA1( K || cs-encryption-key-1 )
    cs-encryption-key   = cs-encryption-key-1 || cs-encryption-key-2
    sc-encryption-key-1 = SHA1( K || "D" || H )
    sc-encryption-key-2 = SHA1( K || sc-encryption-key-1 )
    sc-encryption-key   = sc-encryption-key-1 || sc-encryption-key-2
    cs-integrity-key    = SHA1( K || "E" || H )
    sc-integrity-key    = SHA1( K || "F" || H )

    K is dh_k in mpint format (string)
    H is hash
  */

  /* Since we won't support SASL security layers, we need to
   * compute the following only:
   * cs-encryption-iv
   * cs-encryption-key
   * cs-integrity-key
   */
  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'A');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash);
  /* Use first 8 octets as iv */
  memcpy(enc_iv, tmphash, 8);

  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'E');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), int_key);

  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'C');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash);
  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_append(Buf_Space, tmphash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash+20);
  /* Use first 24 octets as key */
  memcpy(enc_key, tmphash, 24);
 {
   BIGNUM *enc, *i, *iv;
   enc = BN_bin2bn(enc_key, 24, NULL);
   iv = BN_bin2bn(enc_iv, 8, NULL);
   i = BN_bin2bn(int_key, 20, NULL);

   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_ENC_KEY, BN_bn2hex(enc));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_IV, BN_bn2hex(iv));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_INTEG_KEY, BN_bn2hex(i));
   BN_free(enc);
   BN_free(i);
   BN_free(iv);
 }
  /*
    (J) Create a buffer beginning with a bit mask for the
    selected security layer (it MUST be one offered from server)
    followed by three octets representing the maximum
    cipher-text buffer size (at least 32) the client can accept
    in network byte order.  This is followed by a string
    containing the passphrase.
  */
  buffer_clear(Buf_Space);
  buffer_put_octet(Buf_Space, ssecmask);
  buffer_put_octet(Buf_Space, 0);
  buffer_put_octet(Buf_Space, 0);
  buffer_put_octet(Buf_Space, 0); /**< @bug must be at least 32 */
  buffer_put_cstring(Buf_Space, conf->passwd);

  /*
    (K) Create a buffer containing items (1) through (7)
    immediately followed by the first four octets of (J).
  */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), 4);

  /*
    (L) Compute HMAC-SHA-1 with (K) as the data and the
    cs-integrity- key from step (I) as the key.  This produces a
    20 octet result.
  */
  HMAC(EVP_sha1(), int_key, sizeof(int_key),
       buffer_ptr(Buf_H), buffer_len(Buf_H), hmac, (unsigned int*)&keysize);
  /*
    (M) Create a buffer containing (J) followed by (L) followed
    by an arbitrary number of zero octets as necessary to reach
    the block size of DES and conceal the passphrase length from
    an eavesdropper.
  */
  buffer_append(Buf_Space, hmac, keysize);

  /*
    (N) Apply the triple-DES algorithm to (M) with the first 8
    octets of cs-encryption-iv from step (I) as the
    initialization vector and the first 24 octets of
    cs-encryption-key as the key.
  */
  /*
    Padding is automatically done. From OpenSSL EVP_EncryptInit(3):
    EVP_CIPHER_CTX_set_padding() enables or disables padding. By default
    encryption operations are padded using standard block padding and the
    padding is checked and removed when decrypting.
  */

  /*
    Create BIO filter to encrypt using 3des + convert to
    base64. Result is written in memory BIO.
  */
  /* Erase BIO and buffer memory */
  BIO_reset(bio_rw);
  memset(BufferOut, 0, TSP_AUTH_PASSDSS_BUFFERSIZE);
  memset(BufferIn, 0, TSP_AUTH_PASSDSS_BUFFERSIZE);
  buflen = 0;

  /* Create cipher BIO */
  cipher = BIO_new(BIO_f_cipher());
  BIO_set_cipher(cipher, EVP_des_ede3_cbc(), enc_key, enc_iv, 1);
  /* Assemble filters as cipher->b64->bio_rw */
  BIO_push(cipher, b64);
  BIO_push(b64, bio_rw);

  /* Write Buffer content into bio_rw */
  BIO_write(cipher, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space));
  BIO_flush(cipher);
  /* Get pointer to the result. */
  buflen = BIO_get_mem_data(bio_rw, &BufferPtr);

  /* wipe encryption material */
  memset(enc_key, 0, sizeof(enc_key));
  memset(enc_iv, 0, sizeof(enc_iv));

  /* Send data to server, save response in BufferIn */
  if( (readlen = nt->netsendrecv(socket, BufferPtr, buflen,
       BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }
  tsp_status = tspGetStatusCode(BufferIn);

  // Check if the reply status indicated a broker redirection.
  if( tspIsRedirectStatus(tsp_status) )
  {
    if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK )
    {
      status = make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION);
    }
    else
    {
      // Redirect error.
      status = make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION);
    }
    goto error;
  }

  // Check if authentication was successful.
  switch( tsp_status )
  {
  case TSP_PROTOCOL_SUCCESS:
    break;

  case TSP_PROTOCOL_AUTH_FAILED:
    Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_AUTH_FAILED_USER, conf->userid);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;

  default:
    Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status));
    status = make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR);
    goto error;
  }

  status = STATUS_SUCCESS_INIT;

 error:

  /* Free storage for DSA key */
  if (dsa != NULL) DSA_free(dsa); /* Also frees BIGNUMs inside struct */
  /* DSA signature */
  if (sig != NULL) DSA_SIG_free(sig);
  /* Free Diffie Hellman variables */
  if (dh != NULL) DH_free(dh); /* Also frees BIGNUMs inside struct */
  if (server_pubkey != NULL) BN_free(server_pubkey);
  if (dh_K != NULL) BN_free(dh_K);
  /* Buffers */
  if (Buf_Space->buf != NULL) buffer_free(Buf_Space);
  if (Buf_H->buf != NULL)  buffer_free(Buf_H);
  /* malloc'ed space*/
  if (BufferIn != NULL) pal_free(BufferIn);
  if (BufferOut != NULL) pal_free(BufferOut);
  /* BIOs */
  if (cipher != NULL) BIO_vfree(cipher);
  if (b64 != NULL) BIO_vfree(b64);
  if (bio_rw != NULL) BIO_vfree(bio_rw);
  /* strings buffers */
  if (s != NULL) pal_free(s);

  return status;
}