PUBLIC int sslOpen() { RandBuf randBuf; trace(7, "Initializing SSL"); randBuf.now = time(0); randBuf.pid = getpid(); RAND_seed((void*) &randBuf, sizeof(randBuf)); #if BIT_UNIX_LIKE trace(6, "OpenSsl: Before calling RAND_load_file"); RAND_load_file("/dev/urandom", 256); trace(6, "OpenSsl: After calling RAND_load_file"); #endif CRYPTO_malloc_init(); #if !BIT_WIN_LIKE OpenSSL_add_all_algorithms(); #endif SSL_library_init(); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) { error("Unable to create SSL context"); return -1; } /* Set the client certificate verification locations */ if (*BIT_GOAHEAD_CA) { if ((!SSL_CTX_load_verify_locations(sslctx, BIT_GOAHEAD_CA, NULL)) || (!SSL_CTX_set_default_verify_paths(sslctx))) { error("Unable to read cert verification locations"); sslClose(); return -1; } } /* Set the server certificate and key files */ if (*BIT_GOAHEAD_KEY && sslSetKeyFile(BIT_GOAHEAD_KEY) < 0) { sslClose(); return -1; } if (*BIT_GOAHEAD_CERTIFICATE && sslSetCertFile(BIT_GOAHEAD_CERTIFICATE) < 0) { sslClose(); return -1; } SSL_CTX_set_tmp_rsa_callback(sslctx, rsaCallback); #if VERIFY_CLIENT if (verifyPeer) { SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyX509Certificate); #if FUTURE && KEEP SSL_CTX_set_verify_depth(context, VERIFY_DEPTH); #endif } else { SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyX509Certificate); } #else SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyX509Certificate); #endif /* Set the certificate authority list for the client */ if (BIT_GOAHEAD_CA && *BIT_GOAHEAD_CA) { SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(BIT_GOAHEAD_CA)); } SSL_CTX_set_cipher_list(sslctx, BIT_GOAHEAD_CIPHERS); SSL_CTX_set_options(sslctx, SSL_OP_ALL); SSL_CTX_sess_set_cache_size(sslctx, 128); #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET); #endif #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_CTX_set_options(sslctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif SSL_CTX_set_mode(sslctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2); /* Ensure we generate a new private key for each connection */ SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE); return 0; }
// ssl host port url // ssl host port url file // ssl host port url key file // ssl host port url key file dir sec int main(int ac, char *av[]) { bool dbg; SSL_CTX *ctx; SSL *ssl; int n, sec, getLen, lenLen, fd, sd; DIR *dp; struct dirent *p; struct stat st; char get[1024], buf[4096], nm[4096], len[64]; if (dbg = strcmp(av[ac-1], "+") == 0) --ac; if (!(ac >= 4 && ac <= 6 || ac == 8)) giveup("host port url [[key] file] | host port url key file dir sec"); if (strlen(Get)+strlen(av[1])+strlen(av[2])+strlen(av[3]) >= sizeof(get)) giveup("Names too long"); getLen = sprintf(get, Get, av[3], av[1], av[2]); SSL_library_init(); SSL_load_error_strings(); if (!(ctx = SSL_CTX_new(SSLv23_client_method()))) { ERR_print_errors_fp(stderr); giveup("SSL init"); } SSL_CTX_set_cipher_list(ctx, Ciphers); ssl = SSL_new(ctx); if (ac <= 6) { if (sslConnect(ssl, av[1], av[2]) < 0) { ERR_print_errors_fp(stderr); giveup("Can't connect"); } if (SSL_write(ssl, get, getLen) < 0) { ERR_print_errors_fp(stderr); giveup("SSL GET"); } if (ac > 4) { if (*av[4] && !sslFile(ssl,av[4])) giveup(av[4]); if (ac > 5 && *av[5] && !sslFile(ssl,av[5])) giveup(av[5]); } while ((n = SSL_read(ssl, buf, sizeof(buf))) > 0) write(STDOUT_FILENO, buf, n); if (dbg) ERR_print_errors_fp(stderr); return 0; } if (!dbg) { signal(SIGCHLD,SIG_IGN); /* Prevent zombies */ if ((n = fork()) < 0) giveup("detach"); if (n) return 0; setsid(); } File = av[5]; Dir = av[6]; sec = atoi(av[7]); signal(SIGINT, doSigTerm); signal(SIGTERM, doSigTerm); signal(SIGPIPE, SIG_IGN); signal(SIGALRM, SIG_IGN); for (;;) { if (*File && (fd = open(File, O_RDWR)) >= 0) { if (fstat(fd,&st) < 0 || st.st_size == 0) close(fd); else { lockFile(fd); if (fstat(fd,&st) < 0 || (Size = st.st_size) == 0) giveup("Can't access"); lenLen = sprintf(len, "%ld\n", Size); if ((Data = malloc(Size)) == NULL) giveup("Can't alloc"); if (read(fd, Data, Size) != Size) giveup("Can't read"); Hot = YES; if (ftruncate(fd,0) < 0) giveup("Can't truncate"); close(fd); for (;;) { if ((sd = sslConnect(ssl, av[1], av[2])) >= 0) { alarm(420); if (SSL_write(ssl, get, getLen) == getLen && (!*av[4] || sslFile(ssl,av[4])) && // key SSL_write(ssl, len, lenLen) == lenLen && // length SSL_write(ssl, Data, Size) == Size && // data SSL_write(ssl, "T", 1) == 1 && // ack SSL_read(ssl, buf, 1) == 1 && buf[0] == 'T' ) { Hot = NO; alarm(0); sslClose(ssl,sd); break; } alarm(0); sslClose(ssl,sd); } if (dbg) ERR_print_errors_fp(stderr); sleep(sec); } free(Data); } } if (*Dir && (dp = opendir(Dir))) { while (p = readdir(dp)) { if (p->d_name[0] != '.') { snprintf(nm, sizeof(nm), "%s%s", Dir, p->d_name); if ((n = readlink(nm, buf, sizeof(buf))) > 0 && (sd = sslConnect(ssl, av[1], av[2])) >= 0 ) { if (SSL_write(ssl, get, getLen) == getLen && (!*av[4] || sslFile(ssl,av[4])) && // key SSL_write(ssl, buf, n) == n && // path SSL_write(ssl, "\n", 1) == 1 && // nl sslFile(ssl, nm) ) // file unlink(nm); sslClose(ssl,sd); } if (dbg) ERR_print_errors_fp(stderr); } } closedir(dp); } sleep(sec); } }
/* Open the SSL module */ PUBLIC int sslOpen() { RandBuf randBuf; X509_STORE *store; uchar resume[16]; char *ciphers; trace(7, "Initializing SSL"); randBuf.now = time(0); randBuf.pid = getpid(); RAND_seed((void*) &randBuf, sizeof(randBuf)); #if ME_UNIX_LIKE trace(6, "OpenSsl: Before calling RAND_load_file"); RAND_load_file("/dev/urandom", 256); trace(6, "OpenSsl: After calling RAND_load_file"); #endif CRYPTO_malloc_init(); #if !ME_WIN_LIKE OpenSSL_add_all_algorithms(); #endif SSL_library_init(); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) { error("Unable to create SSL context"); return -1; } /* Set the server certificate and key files */ if (*ME_GOAHEAD_SSL_KEY && sslSetKeyFile(ME_GOAHEAD_SSL_KEY) < 0) { sslClose(); return -1; } if (*ME_GOAHEAD_SSL_CERTIFICATE && sslSetCertFile(ME_GOAHEAD_SSL_CERTIFICATE) < 0) { sslClose(); return -1; } if (ME_GOAHEAD_SSL_VERIFY_PEER) { SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyClientCertificate); SSL_CTX_set_verify_depth(sslctx, VERIFY_DEPTH); } else { SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyClientCertificate); } /* Set the client certificate verification locations */ if (ME_GOAHEAD_SSL_AUTHORITY && *ME_GOAHEAD_SSL_AUTHORITY) { if ((!SSL_CTX_load_verify_locations(sslctx, ME_GOAHEAD_SSL_AUTHORITY, NULL)) || (!SSL_CTX_set_default_verify_paths(sslctx))) { error("Unable to read cert verification locations"); sslClose(); return -1; } /* Define the list of CA certificates to send to the client before they send their client certificate for validation */ SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(ME_GOAHEAD_SSL_AUTHORITY)); } if (ME_GOAHEAD_SSL_REVOKE && *ME_GOAHEAD_SSL_REVOKE) { store = SSL_CTX_get_cert_store(sslctx); if (!X509_STORE_load_locations(store, ME_GOAHEAD_SSL_REVOKE, 0)) { error("Cannot load certificate revoke list: %s", ME_GOAHEAD_SSL_REVOKE); sslClose(); return -1; } } /* Configure DH parameters */ dhKey = getDhKey(); SSL_CTX_set_tmp_dh_callback(sslctx, dhcallback); /* Configure cipher suite */ if (ME_GOAHEAD_SSL_CIPHERS && *ME_GOAHEAD_SSL_CIPHERS) { ciphers = ME_GOAHEAD_SSL_CIPHERS; } else { ciphers = OPENSSL_DEFAULT_CIPHERS; } ciphers = mapCipherNames(ciphers); trace(5, "Using OpenSSL ciphers: %s", ciphers); if (SSL_CTX_set_cipher_list(sslctx, ciphers) != 1) { error("Unable to set cipher list \"%s\"", ciphers); sslClose(); wfree(ciphers); return -1; } wfree(ciphers); /* Define default OpenSSL options */ SSL_CTX_set_options(sslctx, SSL_OP_ALL); /* Ensure we generate a new private key for each connection */ SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE); /* Define a session reuse context */ RAND_bytes(resume, sizeof(resume)); SSL_CTX_set_session_id_context(sslctx, resume, sizeof(resume)); /* Elliptic Curve initialization */ #if SSL_OP_SINGLE_ECDH_USE #ifdef SSL_CTX_set_ecdh_auto SSL_CTX_set_ecdh_auto(sslctx, 1); #else { EC_KEY *ecdh; cchar *name; int nid; name = ME_GOAHEAD_SSL_CURVE; if ((nid = OBJ_sn2nid(name)) == 0) { error("Unknown curve name \"%s\"", name); sslClose(); return -1; } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) { error("Unable to create curve \"%s\"", name); sslClose(); return -1; } SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_ECDH_USE); SSL_CTX_set_tmp_ecdh(sslctx, ecdh); EC_KEY_free(ecdh); } #endif #endif SSL_CTX_set_mode(sslctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING SSL_CTX_set_options(sslctx, SSL_OP_MSIE_SSLV2_RSA_PADDING); #endif #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(sslctx, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_mode(sslctx, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif /* Select the required protocols Disable both SSLv2 and SSLv3 by default - they are insecure */ SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3); #if defined(SSL_OP_NO_TLSv1) && ME_GOAHEAD_SSL_NO_V1 SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1); #endif #if defined(SSL_OP_NO_TLSv1_1) && ME_GOAHEAD_SSL_NO_V1_1 SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1); #endif #if defined(SSL_OP_NO_TLSv1_2) && ME_GOAHEAD_SSL_NO_V1_2 SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2); #endif #if defined(SSL_OP_NO_TICKET) /* Ticket based session reuse is enabled by default */ #if defined(ME_GOAHEAD_SSL_TICKET) if (ME_GOAHEAD_SSL_TICKET) { SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET); } else { SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET); } #else SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET); #endif #endif #if defined(SSL_OP_NO_COMPRESSION) /* CRIME attack targets compression */ SSL_CTX_clear_options(sslctx, SSL_OP_NO_COMPRESSION); #endif #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) /* Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers. Defaults to true. */ #if defined(ME_GOAHEAD_SSL_EMPTY_FRAGMENTS) if (ME_GOAHEAD_SSL_EMPTY_FRAGMENTS) { /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */ SSL_CTX_clear_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } else { SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } #else SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); #endif #endif #if defined(ME_GOAHEAD_SSL_CACHE) /* Set the number of sessions supported. Default in OpenSSL is 20K. */ SSL_CTX_sess_set_cache_size(sslctx, ME_GOAHEAD_SSL_CACHE); #else SSL_CTX_sess_set_cache_size(sslctx, 256); #endif return 0; }
//WARNING!!! //The function you are about to read is TERRIBLE. //Please wash your eyes with acid after reading it. //Thanks. static bool httpGetRequest(const char *loc, char **content, bool forceNa = false) { *g_log << "RiotAPI query: " << loc << "; Force NA: " << forceNa << std::endl; //Step one: resolve hostname struct addrinfo hints; struct addrinfo *result; ZeroMemory(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if(getaddrinfo(forceNa ? "na.api.pvp.net" : g_apiHost.c_str(), NULL, &hints, &result) != 0) return false; if(result->ai_addr == NULL || result->ai_addrlen != sizeof(sockaddr_in)) { freeaddrinfo(result); return false; } sockaddr_in addr; memcpy(&addr, result->ai_addr, sizeof(sockaddr_in)); freeaddrinfo(result); addr.sin_port = htons(443); //Step two: create socket SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sock == INVALID_SOCKET) return false; if(connect(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr_in)) == SOCKET_ERROR) { closesocket(sock); return false; } //SSL STUFF SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method()); SSL *ssl = SSL_new(ctx); SSL_set_fd(ssl, sock); SSL_connect(ssl); //Step three: send request std::string req("GET "); req += loc; req += " HTTP/1.1\r\nHost: "; req += (forceNa ? std::string("na.api.pvp.net") : g_apiHost); req += "\r\nUser-Agent: LoL Mana\r\n\r\n"; if(SSL_write(ssl, req.c_str(), req.length()) != req.length()) { sslClose(sock, ssl, ctx); return false; } //Step four: read response char buf[8192]; int read = SSL_read(ssl, buf, 8192); if(read <= 0) { sslClose(sock, ssl, ctx); return false; } char *response = buf; int num = 0; bool wasEmpty = false; int retCode = -1; int contentLength = -1; while(!wasEmpty) { char *ptr = nextLine(response, read); int len = ptr - response; if(ptr == NULL) //End!! break; read -= len; len -= 2; if(len <= 0) //Only CRLF; skip wasEmpty = true; else if(num == 0 || contentLength < 0) { char *line = new char[len + 1]; memcpy(line, response, len); line[len] = 0; std::istringstream iss(line); delete[] line; if(num == 0) { std::string dontcare; iss >> dontcare; iss >> retCode; } else if(contentLength < 0) {