biginteger OpenSSLRSAPermutation::computeRSA(biginteger elementP) { ERR_load_crypto_strings(); //SSL_load_error_strings(); // Seed the random geneartor. #ifdef _WIN32 RAND_screen(); // only defined for windows, reseeds from screen contents #else RAND_poll(); // reseeds using hardware state (clock, interrupts, etc). #endif // Allocate a new byte array to hold the output. int size = RSA_size(rsa); std::shared_ptr<byte> ret(new byte[size], std::default_delete<byte[]>()); size_t encodedSize = bytesCount(elementP); std::shared_ptr<byte> encodedBi(new byte[encodedSize], std::default_delete<byte[]>()); encodeBigInteger(elementP, encodedBi.get(), encodedSize); int success = RSA_public_encrypt(encodedSize, encodedBi.get(), ret.get(), rsa, RSA_NO_PADDING); if (-1 == success) { string error(ERR_reason_error_string(ERR_get_error())); throw runtime_error("failed to compute rsa " + error); } biginteger result = decodeBigInteger(ret.get(), size); return result; }
void OpenSSL::ClassInit() { MS_TRACE(); MS_DEBUG("loaded openssl version: %s", SSLeay_version(SSLEAY_VERSION)); // First initialize OpenSSL stuff. SSL_load_error_strings(); SSL_library_init(); RAND_poll(); // Make OpenSSL thread-safe. OpenSSL::mutexes = new pthread_mutex_t[CRYPTO_num_locks()]; if (! OpenSSL::mutexes) MS_THROW_ERROR("allocation of mutexes failed"); OpenSSL::numMutexes = CRYPTO_num_locks(); for (int i=0; i<OpenSSL::numMutexes; i++) { int err = pthread_mutex_init(&OpenSSL::mutexes[i], nullptr); if (err) MS_THROW_ERROR("pthread_mutex_init() failed with return code %d\n", err); } CRYPTO_THREADID_set_callback(OpenSSL::SetThreadId); CRYPTO_set_locking_callback(OpenSSL::LockingFunction); CRYPTO_set_dynlock_create_callback(OpenSSL::DynCreateFunction); CRYPTO_set_dynlock_lock_callback(OpenSSL::DynLockFunction); CRYPTO_set_dynlock_destroy_callback(OpenSSL::DynDestroyFunction); }
static SSL_CTX * evssl_init(void) { SSL_CTX *server_ctx; /* Initialize the OpenSSL library */ SSL_load_error_strings(); SSL_library_init(); /* We MUST have entropy, or else there's no point to crypto. */ if (!RAND_poll()) return NULL; server_ctx = SSL_CTX_new(SSLv23_server_method()); if (! SSL_CTX_use_certificate_chain_file(server_ctx, "cert") || ! SSL_CTX_use_PrivateKey_file(server_ctx, "pkey", SSL_FILETYPE_PEM)) { puts("Couldn't read 'pkey' or 'cert' file. To generate a key\n" "and self-signed certificate, run:\n" " openssl genrsa -out pkey 2048\n" " openssl req -new -key pkey -out cert.req\n" " openssl x509 -req -days 365 -in cert.req -signkey pkey -out cert"); return NULL; } SSL_CTX_set_options(server_ctx, SSL_OP_NO_SSLv2); return server_ctx; }
void openssl_bioBS_random() { int size; const char *p; unsigned char outs[SHA_DIGEST_LENGTH + 16] = { 0 }; char buf[32], filename[COMM_LEN]; strcpy(buf, "bioBS random"); RAND_add(buf, 32, strlen(buf)); strcpy(buf, "beike2012"); RAND_seed(buf, 32); while (1) { if (RAND_status() == 1) break; else RAND_poll(); } p = RAND_file_name(filename, COMM_LEN); RAND_write_file(p); RAND_load_file(p, MAX1_LEN); RAND_bytes(outs, sizeof(outs)); printf("\nBIO_RANDOM() = "); for (size = 0; size < strlen((char *)&outs); size++) printf("%.02x", outs[size]); printf("\n"); RAND_cleanup(); }
/* * 执行ssl请求,返回chttp_str_t * 需要释放内存 */ chttp_str_t* chttp_ssl_request(chttp_socket_t socket, void *buffer, size_t size) { #if defined(_HTTPS) SSL_CTX *ctx = NULL; SSL *ssl = NULL; int ret = 0; char text[1024]; chttp_str_t *html = NULL; SSL_library_init(); SSL_load_error_strings(); ctx = SSL_CTX_new(SSLv23_client_method()); if (ctx == NULL) return NULL; ssl = SSL_new(ctx); if (ssl == NULL) return NULL; ret = SSL_set_fd(ssl, socket); if (0 == ret) return NULL; RAND_poll(); while (RAND_status() == 0) { unsigned short rand_ret = rand() % 65536; RAND_seed(&rand_ret, sizeof(rand_ret)); } ret = SSL_connect(ssl); if (ret != 1) return NULL; if (!(SSL_write(ssl, buffer, size))) { return NULL; } while ((ret = SSL_read(ssl, text, 1024)) > 0) { html = chttp_str_size_append(html, text, ret); } //free resource if (ssl) { SSL_free(ssl); SSL_CTX_free(ctx); ERR_free_strings(); } return html; #else printf("不支持https方式请求,请在编译的时候加入开启 _HTTPS \n"); exit(1); #endif }
Global::Global() { SSL_library_init(); ERR_load_CRYPTO_strings(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); RAND_poll(); event_base = event_base_new(); dns_base = evdns_base_new(event_base, 1); };
QByteArray KeyHelper::getRandomBytes(int bytes) { RAND_poll(); unsigned char buff1[bytes]; memset(buff1, 0, bytes); RAND_bytes(buff1, bytes); return QByteArray::fromRawData((const char *)buff1, bytes); }
golle_error golle_random_seed (void) { LOAD_HARDWARE_ENGINE; /* Only seed when needed */ if (!RAND_status ()) { RAND_poll (); } return GOLLE_OK; }
SSL_CTX * evssl_init() { DH *dh; SSL_CTX *ctx; SSL_load_error_strings(); SSL_library_init(); RAND_poll(); if ((passport = pki_passport_load_from_file(cfg->cert, cfg->pkey, cfg->tcert)) == NULL) { return NULL; } if ((ctx = SSL_CTX_new(TLSv1_2_client_method())) == NULL) { jlog(L_ERROR, "SSL_CTX_new failed"); return NULL; } if ((dh = get_dh_1024()) == NULL) { jlog(L_ERROR, "get_dh_1024 failed"); goto out; } if ((SSL_CTX_set_tmp_dh(ctx, dh)) == 0) { jlog(L_ERROR, "SSL_CTX_set_tmp_dh failed"); goto out; } //SSL_CTX_set_cipher_list(ctx, "ECDHE-ECDSA-AES256-GCM-SHA384"); if ((SSL_CTX_set_cipher_list(ctx, "AES256-GCM-SHA384")) == 0) { jlog(L_ERROR, "SSL_CTX_set_cipher failed"); goto out; } SSL_CTX_set_cert_store(ctx, passport->cacert_store); if ((SSL_CTX_use_certificate(ctx, passport->certificate)) == 0) { jlog(L_ERROR, "SSL_CTX_use_certificate failed"); goto out; } if ((SSL_CTX_use_PrivateKey(ctx, passport->keyring)) == 0) { jlog(L_ERROR, "SSL_CTX_use_PrivateKey failed"); goto out; } DH_free(dh); return ctx; out: DH_free(dh); SSL_CTX_free(ctx); return NULL; }
QByteArray KeyHelper::generateSenderKey() { RAND_poll(); unsigned char buff1[32]; memset(buff1, 0, 32); RAND_bytes(buff1, 32); QByteArray key = QByteArray::fromRawData((const char*)buff1, 32); return key; }
static int rand_status(void) { CRYPTO_THREAD_ID cur; int ret; int do_not_lock; if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) return 0; cur = CRYPTO_THREAD_get_current_id(); /* * check if we already have the lock (could happen if a RAND_poll() * implementation calls RAND_status()) */ if (crypto_lock_rand) { CRYPTO_THREAD_read_lock(rand_tmp_lock); do_not_lock = CRYPTO_THREAD_compare_id(locking_threadid, cur); CRYPTO_THREAD_unlock(rand_tmp_lock); } else do_not_lock = 0; if (!do_not_lock) { CRYPTO_THREAD_write_lock(rand_lock); /* * Prevent deadlocks in case we end up in an async engine */ ASYNC_block_pause(); /* * prevent rand_bytes() from trying to obtain the lock again */ CRYPTO_THREAD_write_lock(rand_tmp_lock); locking_threadid = cur; CRYPTO_THREAD_unlock(rand_tmp_lock); crypto_lock_rand = 1; } if (!initialized) { RAND_poll(); initialized = 1; } ret = entropy >= ENTROPY_NEEDED; if (!do_not_lock) { /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; ASYNC_unblock_pause(); CRYPTO_THREAD_unlock(rand_lock); } return ret; }
quint64 KeyHelper::getRandomFFFF() { RAND_poll(); unsigned char buff1[2]; memset(buff1, 0, 2); RAND_bytes(buff1, 2); quint64 rand1 = ((unsigned int)buff1[1] << 8) + (unsigned int)buff1[0]; return rand1; }
quint64 KeyHelper::getRandomFFFFFFFF() { RAND_poll(); unsigned char buff1[4]; memset(buff1, 0, 4); RAND_bytes(buff1, 4); quint64 rand1 = ((unsigned long)buff1[3] << 24) + ((unsigned int)buff1[2] << 16) + ((unsigned int)buff1[1] << 8) + (unsigned int)buff1[0]; return rand1; }
Global::Global() { SSL_library_init(); ERR_load_CRYPTO_strings(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); RAND_poll(); #ifndef _NO_LIBEVENT_THREADS evthread_use_pthreads(); #endif event_base = event_base_new(); dns_base = evdns_base_new(event_base, 1); };
void ntp_crypto_srandom( void ) { #ifdef USE_OPENSSL_CRYPTO_RAND if (!crypto_rand_init) { RAND_poll(); crypto_rand_init = 1; } #else /* No initialization needed for arc4random() */ #endif }
bool SecureRNG::seed() { #if QT_VERSION >= 0x040700 QElapsedTimer timer; timer.start(); #endif #ifdef Q_OS_WIN /* RAND_poll is very unreliable on windows; with older versions of OpenSSL, * it can take up to several minutes to run and has been known to crash. * Even newer versions seem to take around 400ms, which is far too long for * interactive startup. Random data from the windows CSP is used as a seed * instead, as it should be very high quality random and fast. */ HCRYPTPROV provider = 0; if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { qWarning() << "Failed to acquire CSP context for RNG seed:" << hex << GetLastError(); return false; } /* Same amount of entropy OpenSSL uses, apparently. */ char buf[32]; if (!CryptGenRandom(provider, sizeof(buf), reinterpret_cast<BYTE*>(buf))) { qWarning() << "Failed to get entropy from CSP for RNG seed: " << hex << GetLastError(); CryptReleaseContext(provider, 0); return false; } CryptReleaseContext(provider, 0); RAND_seed(buf, sizeof(buf)); memset(buf, 0, sizeof(buf)); #else if (!RAND_poll()) { qWarning() << "OpenSSL RNG seed failed:" << ERR_get_error(); return false; } #endif #if QT_VERSION >= 0x040700 qDebug() << "RNG seed took" << timer.elapsed() << "ms"; #endif return true; }
quint64 KeyHelper::getRandom7FFFFFFF() { RAND_poll(); quint64 rand2 = 0; for (int i = 0; i < 0x80; i++) { unsigned char buff0[3]; memset(buff0, 0, 3); RAND_bytes(buff0, 3); rand2 += ((unsigned int)buff0[2] << 16); rand2 += ((unsigned int)buff0[1] << 8); rand2 += (unsigned int)buff0[0]; } return rand2; }
static int ssleay_rand_status(void) { CRYPTO_THREADID cur; int ret; int do_not_lock; CRYPTO_THREADID_current(&cur); /* check if we already have the lock * (could happen if a RAND_poll() implementation calls RAND_status()) */ if (crypto_lock_rand) { CRYPTO_r_lock(CRYPTO_LOCK_RAND2); do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur); CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); } else do_not_lock = 0; if (!do_not_lock) { CRYPTO_w_lock(CRYPTO_LOCK_RAND); /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ CRYPTO_w_lock(CRYPTO_LOCK_RAND2); CRYPTO_THREADID_cpy(&locking_threadid, &cur); CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); crypto_lock_rand = 1; } if (!initialized) { RAND_poll(); initialized = 1; } ret = entropy >= ENTROPY_NEEDED; if (!do_not_lock) { /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; CRYPTO_w_unlock(CRYPTO_LOCK_RAND); } return ret; }
static SSL_CTX * ssl_server_init(const char *keypath, const char *certpath) { SSL_CTX *ctx; ENGINE *e; ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); e = ENGINE_by_id("padlock"); if (e) { fprintf(stderr, "[*] Using padlock engine for default ciphers\n"); ENGINE_set_default_ciphers(ENGINE_by_id("padlock")); use_padlock_engine = 1; } else { fprintf(stderr, "[*] Padlock engine not available\n"); use_padlock_engine = 0; } SSL_load_error_strings(); SSL_library_init(); if (!RAND_poll()) return NULL; ctx = SSL_CTX_new(SSLv23_server_method()); if (!SSL_CTX_use_certificate_chain_file(ctx, certpath) || !SSL_CTX_use_PrivateKey_file(ctx, keypath, SSL_FILETYPE_PEM)) { fprintf(stderr, "Could not read %s or %s file\n", keypath, certpath); fprintf(stderr, "To generate a key and self-signed certificate, run:\n"); fprintf(stderr, "\topenssl genrsa -out key.pem 2048\n"); fprintf(stderr, "\topenssl req -new -key key.pem -out cert.req\n"); fprintf(stderr, "\topenssl x509 -req -days 365 -in cert.req -signkey key.pem -out cert.pem\n"); return NULL; } SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); if (use_padlock_engine == 1) { if (SSL_CTX_set_cipher_list(ctx, "AES+SHA") != 1) { fprintf(stderr, "Error setting client cipher list\n"); return NULL; } } return ctx; }
/* * DRBG has two sets of callbacks; we only discuss the "entropy" one * here. When the DRBG needs additional randomness bits (called entropy * in the NIST document), it calls the get_entropy callback which fills in * a pointer and returns the number of bytes. When the DRBG is finished with * the buffer, it calls the cleanup_entropy callback, with the value of * the buffer that the get_entropy callback filled in. * * Get entropy from the system, via RAND_poll if needed. The |entropy| * is the bits of randomness required, and is expected to fit into a buffer * of |min_len|..|max__len| size. We assume we're getting high-quality * randomness from the system, and that |min_len| bytes will do. */ size_t drbg_entropy_from_system(RAND_DRBG *drbg, unsigned char **pout, int entropy, size_t min_len, size_t max_len) { int i; if (min_len > (size_t)drbg->size) { /* Should not happen. See comment near RANDOMNESS_NEEDED. */ min_len = drbg->size; } if (drbg->filled) { /* Re-use what we have. */ *pout = drbg->randomness; return drbg->size; } drbg->randomness = drbg->secure ? OPENSSL_secure_malloc(drbg->size) : OPENSSL_malloc(drbg->size); /* If we don't have enough, try to get more. */ CRYPTO_THREAD_write_lock(rand_bytes.lock); for (i = RAND_POLL_RETRIES; rand_bytes.curr < min_len && --i >= 0; ) { CRYPTO_THREAD_unlock(rand_bytes.lock); RAND_poll(); CRYPTO_THREAD_write_lock(rand_bytes.lock); } /* Get desired amount, but no more than we have. */ if (min_len > rand_bytes.curr) min_len = rand_bytes.curr; if (min_len != 0) { memcpy(drbg->randomness, rand_bytes.buff, min_len); drbg->filled = 1; /* Update amount left and shift it down. */ rand_bytes.curr -= min_len; if (rand_bytes.curr != 0) memmove(rand_bytes.buff, &rand_bytes.buff[min_len], rand_bytes.curr); } CRYPTO_THREAD_unlock(rand_bytes.lock); *pout = drbg->randomness; return min_len; }
static void RandomSeed(void) { /* 1. Seed the weak C PRNGs. */ /* Mix various stuff. */ pid_t pid = getpid(); size_t fqdn_len = strlen(VFQNAME) > 0 ? strlen(VFQNAME) : 1; time_t start_time = CFSTARTTIME; time_t now = time(NULL); srand((unsigned) pid * start_time ^ (unsigned) fqdn_len * now); srand48((long) pid * start_time ^ (long) fqdn_len * now); /* 2. Seed the strong OpenSSL PRNG. */ #ifndef __MINGW32__ /* windows may hang */ RAND_poll(); #else RAND_screen(); #endif if (RAND_status() != 1) { /* randseed file is written on deinitialization of crypto system */ char randfile[CF_BUFSIZE]; snprintf(randfile, CF_BUFSIZE, "%s%crandseed", CFWORKDIR, FILE_SEPARATOR); Log(LOG_LEVEL_VERBOSE, "Looking for a source of entropy in '%s'", randfile); if (RAND_load_file(randfile, -1) != 1024) { Log(LOG_LEVEL_CRIT, "Could not read randomness from '%s'", randfile); unlink(randfile); /* kill randseed if error reading it */ } /* If we've used the random seed, then delete */ unlink(randfile); } }
/** * Initialize Droplet global data. * * Initializes global data used by the library. Must be called once * and only once before any other Droplet library functions. The next * step after calling `dpl_init()` is probably `dpl_ctx_new()`. * * @retval DPL_SUCCESS this function cannot currently fail */ dpl_status_t dpl_init() { SSL_library_init(); SSL_load_error_strings(); ERR_load_crypto_strings(); /* RAND_seed(randbuf, strlen(randbuf)); */ int ret = RAND_status(); if (0 == ret) { DPL_LOG(NULL, DPL_WARNING, "PRNG not properly seeded, seeding it..."); RAND_poll(); ret = RAND_status(); DPL_LOG(NULL, DPL_INFO, "PRNG state after seeding: %d", ret); } else if (1 == ret) { DPL_LOG(NULL, DPL_INFO, "PRNG has been seeded with enough data"); } dpl_base64_init(); return DPL_SUCCESS; }
int LOF_CONNECTION_FetionConnection_ssl_connection_start(LOF_CONNECTION_FetionConnectionType* conn) { int ret; SSL_load_error_strings(); SSL_library_init(); conn->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if ( conn->ssl_ctx == NULL ) { LOF_debug_info("Init SSL CTX failed"); return -1; } conn->ssl = SSL_new(conn->ssl_ctx); if ( conn->ssl == NULL ) { LOF_debug_info("New SSL with created CTX failed"); return -1; } ret = SSL_set_fd(conn->ssl, conn->socketfd); if ( ret == 0 ) { LOF_debug_info("Add ssl to tcp socket failed"); return -1; } RAND_poll(); while ( RAND_status() == 0 ) { unsigned short rand_ret = rand() % 65536; RAND_seed(&rand_ret, sizeof(rand_ret)); } ret = SSL_connect(conn->ssl); if( ret != 1 ) { LOF_debug_info("SSL connection failed"); return -1; } return 0; }
static int ssleay_rand_status(void) { int ret; int do_not_lock; /* check if we already have the lock * (could happen if a RAND_poll() implementation calls RAND_status()) */ do_not_lock = crypto_lock_rand && (locking_thread == CRYPTO_thread_id()); if (!do_not_lock) { CRYPTO_w_lock(CRYPTO_LOCK_RAND); /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ crypto_lock_rand = 1; locking_thread = CRYPTO_thread_id(); } if (!initialized) { RAND_poll(); initialized = 1; } ret = entropy >= ENTROPY_NEEDED; if (!do_not_lock) { /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; locking_thread = 0; CRYPTO_w_unlock(CRYPTO_LOCK_RAND); } return ret; }
int connect_ssl_server(struct sockaddr_in *server, SSL *ssl) { int s; int ret; if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { print_line("ソケットの生成に失敗しました。"); return -1; } if(connect(s, (struct sockaddr *)server, sizeof(*server)) == -1) { print_line("connect に失敗しました。"); return -1; } /* ここからが SSL */ ret = SSL_set_fd(ssl, s); if(ret == 0) { ERR_print_errors_fp(stderr); return -1; } /* PRNG 初期化 */ RAND_poll(); while(RAND_status() == 0) { unsigned short rand_ret = rand() % 65536; RAND_seed(&rand_ret, sizeof(rand_ret)); } /* SSL で接続 */ ret = SSL_connect(ssl); if(ret != 1) { ERR_print_errors_fp(stderr); return -1; } return s; }
static void li_rand_init (void) { /* (intended to be called at init and after fork() in order to re-seed PRNG * so that forked children, grandchildren, etc do not share PRNG seed) * https://github.com/ramsey/uuid/issues/80 * https://www.agwa.name/blog/post/libressls_prng_is_unsafe_on_linux * (issue in early version of libressl has since been fixed) * https://github.com/libressl-portable/portable/commit/32d9eeeecf4e951e1566d5f4a42b36ea37b60f35 */ unsigned int u; li_rand_inited = 1; if (1 == li_rand_device_bytes((unsigned char *)xsubi, (int)sizeof(xsubi))) { u = ((unsigned int)xsubi[0] << 16) | xsubi[1]; } else { #ifdef HAVE_ARC4RANDOM_BUF u = arc4random(); arc4random_buf(xsubi, sizeof(xsubi)); #else /* NOTE: not cryptographically random !!! */ srand((unsigned int)(time(NULL) ^ getpid())); for (u = 0; u < sizeof(unsigned short); ++u) /* coverity[dont_call : FALSE] */ xsubi[u] = (unsigned short)(rand() & 0xFFFF); u = ((unsigned int)xsubi[0] << 16) | xsubi[1]; #endif } srand(u); /*(initialize just in case rand() used elsewhere)*/ #ifdef HAVE_SRANDOM srandom(u); /*(initialize just in case random() used elsewhere)*/ #endif #ifdef USE_OPENSSL_CRYPTO RAND_poll(); RAND_seed(xsubi, (int)sizeof(xsubi)); #endif }
bool tor_add_entropy (void) { return RAND_poll(); }
/* * Loop spawning up to `multi` child processes, only child processes return * from this function. The parent process loops until receiving a termination * signal, kills extant children and exits without returning. */ static void spawn_loop(void) { pid_t *kidpids = NULL; int status; int procs = 0; int i; openlog(prog, LOG_PID, LOG_DAEMON); if (setpgid(0, 0)) { syslog(LOG_ERR, "fatal: error detaching from parent process group: %s", strerror(errno)); exit(1); } kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array"); for (i = 0; i < multi; ++i) kidpids[i] = 0; signal(SIGINT, noteterm); signal(SIGTERM, noteterm); while (termsig == 0) { pid_t fpid; /* * Wait for a child to replace when we're at the limit. * Slow down if a child exited abnormally or waitpid() < 0 */ while (termsig == 0 && procs >= multi) { if ((fpid = waitpid(-1, &status, 0)) > 0) { for (i = 0; i < procs; ++i) { if (kidpids[i] == fpid) { kidpids[i] = 0; --procs; break; } } if (i >= multi) { syslog(LOG_ERR, "fatal: internal error: " "no matching child slot for pid: %ld", (long) fpid); killall(1, kidpids); } if (status != 0) { if (WIFEXITED(status)) syslog(LOG_WARNING, "child process: %ld, exit status: %d", (long)fpid, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) syslog(LOG_WARNING, "child process: %ld, term signal %d%s", (long)fpid, WTERMSIG(status), #ifdef WCOREDUMP WCOREDUMP(status) ? " (core dumped)" : #endif ""); sleep(1); } break; } else if (errno != EINTR) { syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno)); killall(1, kidpids); } } if (termsig) break; switch(fpid = fork()) { case -1: /* error */ /* System critically low on memory, pause and try again later */ sleep(30); break; case 0: /* child */ OPENSSL_free(kidpids); signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); if (termsig) _exit(0); if (RAND_poll() <= 0) { syslog(LOG_ERR, "fatal: RAND_poll() failed"); _exit(1); } return; default: /* parent */ for (i = 0; i < multi; ++i) { if (kidpids[i] == 0) { kidpids[i] = fpid; procs++; break; } } if (i >= multi) { syslog(LOG_ERR, "fatal: internal error: no free child slots"); killall(1, kidpids); } break; } } /* The loop above can only break on termsig */ syslog(LOG_INFO, "terminating on signal: %d", termsig); killall(0, kidpids); }
int main(int argc, char **argv) { int r; struct evhttp_uri *http_uri = NULL; const char *url = NULL, *data_file = NULL; const char *crt = "/etc/ssl/certs/ca-certificates.crt"; const char *scheme, *host, *path, *query; char uri[256]; int port; int retries = 0; int timeout = -1; SSL_CTX *ssl_ctx = NULL; SSL *ssl = NULL; struct bufferevent *bev; struct evhttp_connection *evcon = NULL; struct evhttp_request *req; struct evkeyvalq *output_headers; struct evbuffer *output_buffer; int i; int ret = 0; enum { HTTP, HTTPS } type = HTTP; for (i = 1; i < argc; i++) { if (!strcmp("-url", argv[i])) { if (i < argc - 1) { url = argv[i + 1]; } else { syntax(); goto error; } } else if (!strcmp("-crt", argv[i])) { if (i < argc - 1) { crt = argv[i + 1]; } else { syntax(); goto error; } } else if (!strcmp("-ignore-cert", argv[i])) { ignore_cert = 1; } else if (!strcmp("-data", argv[i])) { if (i < argc - 1) { data_file = argv[i + 1]; } else { syntax(); goto error; } } else if (!strcmp("-retries", argv[i])) { if (i < argc - 1) { retries = atoi(argv[i + 1]); } else { syntax(); goto error; } } else if (!strcmp("-timeout", argv[i])) { if (i < argc - 1) { timeout = atoi(argv[i + 1]); } else { syntax(); goto error; } } else if (!strcmp("-help", argv[i])) { syntax(); goto error; } } if (!url) { syntax(); goto error; } #ifdef _WIN32 { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { printf("WSAStartup failed with error: %d\n", err); goto error; } } #endif // _WIN32 http_uri = evhttp_uri_parse(url); if (http_uri == NULL) { err("malformed url"); goto error; } scheme = evhttp_uri_get_scheme(http_uri); if (scheme == NULL || (strcasecmp(scheme, "https") != 0 && strcasecmp(scheme, "http") != 0)) { err("url must be http or https"); goto error; } host = evhttp_uri_get_host(http_uri); if (host == NULL) { err("url must have a host"); goto error; } port = evhttp_uri_get_port(http_uri); if (port == -1) { port = (strcasecmp(scheme, "http") == 0) ? 80 : 443; } path = evhttp_uri_get_path(http_uri); if (strlen(path) == 0) { path = "/"; } query = evhttp_uri_get_query(http_uri); if (query == NULL) { snprintf(uri, sizeof(uri) - 1, "%s", path); } else { snprintf(uri, sizeof(uri) - 1, "%s?%s", path, query); } uri[sizeof(uri) - 1] = '\0'; #if OPENSSL_VERSION_NUMBER < 0x10100000L // Initialize OpenSSL SSL_library_init(); ERR_load_crypto_strings(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); #endif /* This isn't strictly necessary... OpenSSL performs RAND_poll * automatically on first use of random number generator. */ r = RAND_poll(); if (r == 0) { err_openssl("RAND_poll"); goto error; } /* Create a new OpenSSL context */ ssl_ctx = SSL_CTX_new(SSLv23_method()); if (!ssl_ctx) { err_openssl("SSL_CTX_new"); goto error; } #ifndef _WIN32 /* TODO: Add certificate loading on Windows as well */ /* Attempt to use the system's trusted root certificates. * (This path is only valid for Debian-based systems.) */ if (1 != SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL)) { err_openssl("SSL_CTX_load_verify_locations"); goto error; } /* Ask OpenSSL to verify the server certificate. Note that this * does NOT include verifying that the hostname is correct. * So, by itself, this means anyone with any legitimate * CA-issued certificate for any website, can impersonate any * other website in the world. This is not good. See "The * Most Dangerous Code in the World" article at * https://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html */ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); /* This is how we solve the problem mentioned in the previous * comment. We "wrap" OpenSSL's validation routine in our * own routine, which also validates the hostname by calling * the code provided by iSECPartners. Note that even though * the "Everything You've Always Wanted to Know About * Certificate Validation With OpenSSL (But Were Afraid to * Ask)" paper from iSECPartners says very explicitly not to * call SSL_CTX_set_cert_verify_callback (at the bottom of * page 2), what we're doing here is safe because our * cert_verify_callback() calls X509_verify_cert(), which is * OpenSSL's built-in routine which would have been called if * we hadn't set the callback. Therefore, we're just * "wrapping" OpenSSL's routine, not replacing it. */ SSL_CTX_set_cert_verify_callback(ssl_ctx, cert_verify_callback, (void *) host); #else // _WIN32 (void)crt; #endif // _WIN32 // Create event base base = event_base_new(); if (!base) { perror("event_base_new()"); goto error; } // Create OpenSSL bufferevent and stack evhttp on top of it ssl = SSL_new(ssl_ctx); if (ssl == NULL) { err_openssl("SSL_new()"); goto error; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME // Set hostname for SNI extension SSL_set_tlsext_host_name(ssl, host); #endif if (strcasecmp(scheme, "http") == 0) { bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); } else { type = HTTPS; bev = bufferevent_openssl_socket_new(base, -1, ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); } if (bev == NULL) { fprintf(stderr, "bufferevent_openssl_socket_new() failed\n"); goto error; } bufferevent_openssl_set_allow_dirty_shutdown(bev, 1); // For simplicity, we let DNS resolution block. Everything else should be // asynchronous though. evcon = evhttp_connection_base_bufferevent_new(base, NULL, bev, host, port); if (evcon == NULL) { fprintf(stderr, "evhttp_connection_base_bufferevent_new() failed\n"); goto error; } if (retries > 0) { evhttp_connection_set_retries(evcon, retries); } if (timeout >= 0) { evhttp_connection_set_timeout(evcon, timeout); } // Fire off the request req = evhttp_request_new(http_request_done, bev); if (req == NULL) { fprintf(stderr, "evhttp_request_new() failed\n"); goto error; } output_headers = evhttp_request_get_output_headers(req); evhttp_add_header(output_headers, "Host", host); evhttp_add_header(output_headers, "Connection", "close"); if (data_file) { /* NOTE: In production code, you'd probably want to use * evbuffer_add_file() or evbuffer_add_file_segment(), to * avoid needless copying. */ FILE * f = fopen(data_file, "rb"); char buf[1024]; size_t s; size_t bytes = 0; if (!f) { syntax(); goto error; } output_buffer = evhttp_request_get_output_buffer(req); while ((s = fread(buf, 1, sizeof(buf), f)) > 0) { evbuffer_add(output_buffer, buf, s); bytes += s; } evutil_snprintf(buf, sizeof(buf)-1, "%lu", (unsigned long)bytes); evhttp_add_header(output_headers, "Content-Length", buf); fclose(f); } r = evhttp_make_request(evcon, req, data_file ? EVHTTP_REQ_POST : EVHTTP_REQ_GET, uri); if (r != 0) { fprintf(stderr, "evhttp_make_request() failed\n"); goto error; } event_base_dispatch(base); goto cleanup; error: ret = 1; cleanup: if (evcon) evhttp_connection_free(evcon); if (http_uri) evhttp_uri_free(http_uri); event_base_free(base); if (ssl_ctx) SSL_CTX_free(ssl_ctx); if (type == HTTP && ssl) SSL_free(ssl); #if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); ERR_free_strings(); #ifdef EVENT__HAVE_ERR_REMOVE_THREAD_STATE ERR_remove_thread_state(NULL); #else ERR_remove_state(0); #endif CRYPTO_cleanup_all_ex_data(); sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); #endif /*OPENSSL_VERSION_NUMBER < 0x10100000L */ #ifdef _WIN32 WSACleanup(); #endif return ret; }
bool OpenSslLib::init(const char* path) { if(ssl_ctx_client_ || ssl_ctx_server_) { return true; } std::string cert_path; if(path == NULL) { cert_path = getCurrentModulePath(); } else { cert_path = path; if(cert_path.empty()) { cert_path = getCurrentModulePath(); } else if(cert_path.at(cert_path.length() - 1) != PATH_SEPARATOR) { cert_path += PATH_SEPARATOR; } } std::string server_cert_file = cert_path + "server.cer"; std::string server_key_file = cert_path + "server.key"; std::string client_cert_file;// = cert_path + "cleint.cer"; std::string client_key_file;// = cert_path + "client.key"; std::string ca_cert_file = cert_path + "ca.cer"; SSL_library_init(); //OpenSSL_add_all_algorithms(); SSL_load_error_strings(); bool server_ctx_ok = false; bool client_ctx_ok = false; do { ssl_ctx_server_ = SSL_CTX_new(SSLv23_server_method()); if(NULL == ssl_ctx_server_) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_new failed, err="<<ERR_reason_error_string(ERR_get_error())); break; } //const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION; //SSL_CTX_set_options(ssl_ctx_server_, flags); SSL_CTX_set_options(ssl_ctx_server_, SSL_OP_NO_SSLv2); SSL_CTX_set_mode(ssl_ctx_server_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_mode(ssl_ctx_server_, SSL_MODE_ENABLE_PARTIAL_WRITE); if(!server_cert_file.empty() && !server_key_file.empty()) { if(SSL_CTX_use_certificate_file(ssl_ctx_server_, server_cert_file.c_str(), SSL_FILETYPE_PEM) != 1) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_certificate_file failed, file="<<server_cert_file <<", err="<<ERR_reason_error_string(ERR_get_error())); break; } if(SSL_CTX_use_PrivateKey_file(ssl_ctx_server_, server_key_file.c_str(), SSL_FILETYPE_PEM) != 1) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_PrivateKey_file failed, file:"<<server_key_file <<", err="<<ERR_reason_error_string(ERR_get_error())); break; } if(SSL_CTX_check_private_key(ssl_ctx_server_) != 1) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_check_private_key failed, err="<<ERR_reason_error_string(ERR_get_error())); break; } } /* SSL_CTX_set_verify(ssl_ctx_client_, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyCallback); app_verify_arg arg0; SSL_CTX_set_cert_verify_callback(ssl_ctx_server_, appVerifyCallback, &arg0); int session_id_context = 1; if(SSL_CTX_set_session_id_context(ssl_ctx_server_, (unsigned char *)&session_id_context, sizeof(session_id_context)) != 1) { } */ server_ctx_ok = true; } while(0); do { ssl_ctx_client_ = SSL_CTX_new(SSLv23_client_method()); if(NULL == ssl_ctx_client_) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_new failed, err="<<ERR_reason_error_string(ERR_get_error())); break; } SSL_CTX_set_verify(ssl_ctx_client_, SSL_VERIFY_PEER, verifyCallback); //SSL_CTX_set_verify_depth(ssl_ctx_client_, 4); //app_verify_arg arg1; //SSL_CTX_set_cert_verify_callback(ssl_ctx_client_, appVerifyCallback, &arg1); //const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION; //SSL_CTX_set_options(ssl_ctx_client_, flags); SSL_CTX_set_options(ssl_ctx_client_, SSL_OP_NO_SSLv2); SSL_CTX_set_mode(ssl_ctx_client_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_mode(ssl_ctx_client_, SSL_MODE_ENABLE_PARTIAL_WRITE); // set AES256_SHA cipher for client. //if(SSL_CTX_set_cipher_list(ssl_ctx_client_,"AES256-SHA") != 1) //{ // KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_set_cipher_list failed, err="<<ERR_reason_error_string(ERR_get_error())); //} if(!client_cert_file.empty() && !client_key_file.empty()) { if(SSL_CTX_use_certificate_file(ssl_ctx_client_, client_cert_file.c_str(), SSL_FILETYPE_PEM) != 1) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_certificate_file failed, file="<<client_cert_file <<", err="<<ERR_reason_error_string(ERR_get_error())); break; } if(SSL_CTX_use_PrivateKey_file(ssl_ctx_client_, client_key_file.c_str(), SSL_FILETYPE_PEM) != 1) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_use_PrivateKey_file failed, file="<<client_key_file <<", err="<<ERR_reason_error_string(ERR_get_error())); break; } if(SSL_CTX_check_private_key(ssl_ctx_client_) != 1) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_check_private_key failed, err="<<ERR_reason_error_string(ERR_get_error())); break; } } if(!ca_cert_file.empty() && SSL_CTX_load_verify_locations(ssl_ctx_client_, ca_cert_file.c_str(), NULL) != 1) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_load_verify_locations failed, file="<<ca_cert_file <<", err="<<ERR_reason_error_string(ERR_get_error())); break; } if(SSL_CTX_set_default_verify_paths(ssl_ctx_client_) != 1) { KUMA_WARNTRACE("OpenSslLib::init, SSL_CTX_set_default_verify_paths failed, err=" <<ERR_reason_error_string(ERR_get_error())); break; } client_ctx_ok = true; } while(0); if(!server_ctx_ok && ssl_ctx_server_) { SSL_CTX_free(ssl_ctx_server_); ssl_ctx_server_ = NULL; } if(!client_ctx_ok && ssl_ctx_client_) { SSL_CTX_free(ssl_ctx_client_); ssl_ctx_client_ = NULL; } if(!server_ctx_ok && !client_ctx_ok) { return false; } ssl_locks_ = new std::mutex[CRYPTO_num_locks()]; CRYPTO_set_id_callback(threadIdCallback); CRYPTO_set_locking_callback(lockingCallback); // PRNG RAND_poll(); while(RAND_status() == 0) { unsigned short rand_ret = rand() % 65536; RAND_seed(&rand_ret, sizeof(rand_ret)); } return true; }