/* The first line specifiy some settings in the ctx and ssl object: SSL_OP_ALL: enables all work around codes SSL_OP_NO_SSLv2: no SSLv2 connections are allowed (this should fail anyway because only TLSv1 connection are allowed) SSL_OP_SINGLE_DH_USE: the server generates a new private key for each new connection SSL_VERIFY_PEER: asks the client for a certificate SSL_VERIFY_FAIL_IF_NO_PEER_CERT: if the client doesn't present a cert the connection gets terminated CIPHER_LIST: is defined in ssl_server.h (look there for a detailed description) After setting up these things the bio object will be created and a ssl object assigned. Then the ssl engine mode is set to SSL_MODE_AUTO_RETRY. All available modes are: SSL_MODE_ENABLE_PARTIAL_WRITE: Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success when just a single record has been written). When not set (the default), SSL_write() will only report success once the complete chunk was written. Once SSL_write() returns with r, r bytes have been successfully written and the next call to SSL_write() must only send the n-r bytes left, imitating the behaviour of write(). SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER: Make it possible to retry SSL_write() with changed buffer location (the buffer contents must stay the same). This is not the default to avoid the misconception that non-blocking SSL_write() behaves like non-blocking write(). SSL_MODE_AUTO_RETRY: Never bother the application with retries if the transport is blocking. If a renegotiation take place during normal operation, a ssl_read(3) or ssl_write(3) would return with -1 and indicate the need to retry with SSL_ERROR_WANT_READ . In a non-blocking environment applications must be prepared to handle incomplete read/write operations. In a blocking environment, applications are not always prepared to deal with read/write operations returning without success report. The flag SSL_MODE_AUTO_RETRY will cause read/write operations to only return after the handshake and successful completion. The server contains 3 bio objects: bio, abio and out. 'bio' contains the context, 'abio' binds to the socket and 'out' is the established connection. */ void SSL_Server::bind(){ SSL_CTX_set_verify(getCTX(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); SSL_CTX_set_options(getCTX(), SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE); SSL_CTX_set_tmp_dh_callback(getCTX(), tmp_dh_callback); if(SSL_CTX_set_cipher_list(getCTX(), CIPHER_LIST) != 1) msgHandler->error("setting cipher list failed (no valid ciphers)", CRITICAL); msgHandler->debug("trying to set context to bio"); bio = BIO_new_ssl(getCTX(), 0); if(bio == NULL){ string error("Cannot set context to bio "); error.append(getSocket()); error.append("\nSSL_ERROR: "); error.append(ERR_reason_error_string(ERR_get_error())); msgHandler->error(error, CRITICAL); } else msgHandler->debug("set context to bio successful"); BIO_get_ssl(bio, &ssl); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); msgHandler->debug("trying to bind to socket"); abio = BIO_new_accept((char*)getSocket().c_str()); BIO_set_accept_bios(abio, bio); if(BIO_do_accept(abio) <= 0){ string error("Bind to socket "); error.append(getSocket()); error.append(" failed.\nSSL_ERROR: "); error.append(ERR_reason_error_string(ERR_get_error())); msgHandler->error(error, CRITICAL); } else msgHandler->log("bind to socket successful"); }
static int openssl_ssl_ctx_new_bio(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); const char* host_addr = luaL_checkstring(L, 2); int server = lua_isnoneornil(L, 3) ? 0 : auxiliar_checkboolean(L, 3); int autoretry = lua_isnoneornil(L, 4) ? 1 : auxiliar_checkboolean(L, 4); SSL *ssl = NULL; BIO *bio = server ? BIO_new_ssl(ctx, 0) : BIO_new_ssl_connect(ctx); int ret = BIO_get_ssl(bio, &ssl); if (ret == 1 && ssl) { if (autoretry) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); if (server) { BIO* acpt = BIO_new_accept((char*)host_addr); BIO_set_accept_bios(acpt, bio); bio = acpt; } else { ret = BIO_set_conn_hostname(bio, host_addr); } if (ret == 1) { PUSH_OBJECT(bio, "openssl.bio"); openssl_newvalue(L, bio); lua_pushboolean(L, 1); openssl_setvalue(L, bio, "free_all"); return 1; } else return openssl_pushresult(L, ret); } else { BIO_free(bio); bio = NULL; return 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; }
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); }
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); } }
/****** * 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; }
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); }
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; }
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; }