static const char *done_handshake(struct Worker *w) { int res; size_t outlen = 0; const char *emsg; emsg = check_fp(w, "sha1", w->peer_fingerprint_sha1, 20); if (emsg) return emsg; emsg = check_fp(w, "sha256", w->peer_fingerprint_sha256, 32); if (emsg) return emsg; if (w->show) { if (strcmp(w->show, "ciphers") == 0) { tls_get_connection_info(w->ctx, w->showbuf, sizeof w->showbuf); } else if (strcmp(w->show, "peer-cert") == 0) { struct tls_cert *cert = NULL; tls_get_peer_cert(w->ctx, &cert, NULL); show_cert(cert, w->showbuf, sizeof w->showbuf); tls_cert_free(cert); } else { snprintf(w->showbuf, sizeof w->showbuf, "bad kw: show=%s", w->show); } } if (!w->is_server) { res = tls_write(w->ctx, "PKT", 3, &outlen); if (res != 0 && outlen != 3) return "write!=3"; } return wait_for_event(w, EV_READ); }
static const char *done_handshake(struct Worker *w) { int res; const char *emsg; emsg = check_fp(w, "sha1", w->peer_fingerprint_sha1, 20); if (emsg) return emsg; emsg = check_fp(w, "sha256", w->peer_fingerprint_sha256, 32); if (emsg) return emsg; if (w->show) { if (strcmp(w->show, "ciphers") == 0) { tls_get_connection_info(w->ctx, w->showbuf, sizeof w->showbuf); } else if (strcmp(w->show, "peer-cert") == 0) { struct tls_cert *cert = NULL; tls_get_peer_cert(w->ctx, &cert, NULL); show_cert(cert, w->showbuf, sizeof w->showbuf); tls_cert_free(cert); } else { snprintf(w->showbuf, sizeof w->showbuf, "bad kw: show=%s", w->show); } } if (w->aggressive_close) { close(w->socket); tls_close(w->ctx); w->wstate = CLOSED; return "OK"; } if (!w->is_server) { res = tls_write(w->ctx, "PKT", 3); if (res < 0) { return tls_error(w->ctx); } else if (res == 0) { return "write==0"; } else if (res != 3) { return "write!=3"; } } return wait_for_event(w, EV_READ); }
BIO * httpsGetFileDesc(char * hostname, int port, char * remotename, char *extraHeaders, int *errorcode, char **returnedHeaders) { char *buf; char headers[4096]; char *nextChar = headers; char *hstr; int sock; int rc; int checkedCode; int headerslen; int bufsize; int byteswritten; struct loaderData_s * loaderData; SSL_CTX *ssl_context; SSL *ssl; BIO *sbio = 0; X509 *server_cert; *errorcode = 0; sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (sock < 0) { logMessage(ERROR, "ROCKS:httpsGetFileDesc:Could not get a socket"); *errorcode = FTPERR_FAILED_CONNECT; return NULL; } /* OpenSSL_add_all_algorithms(); */ SSLeay_add_ssl_algorithms(); ssl_context = SSL_CTX_new(SSLv23_client_method()); if (!ssl_context) { logMessage(ERROR, "Could not create SSLv2,3 context"); *errorcode = FTPERR_FAILED_CONNECT; goto error; } /* Pull in the Global Loader Data structure. */ loaderData = rocks_global_loaderData; /* I have a Certificate */ if (loaderData->cert_filename) { rc = SSL_CTX_use_certificate_file(ssl_context, loaderData->cert_filename, SSL_FILETYPE_PEM); if (!rc) { logMessage(ERROR, "Could not read Cluster Certificate"); *errorcode = FTPERR_CLIENT_SECURITY; goto error; } rc = SSL_CTX_use_PrivateKey_file(ssl_context, loaderData->priv_filename, SSL_FILETYPE_PEM); if (!rc) { logMessage(ERROR, "Could not read Cluster cert private key"); *errorcode = FTPERR_CLIENT_SECURITY; goto error; } /* Only connect to servers that have certs signed by * our trusted CA. */ if (loaderData->authParent) { rc = SSL_CTX_load_verify_locations(ssl_context, loaderData->ca_filename, 0); if (!rc) { logMessage(ERROR, "Could not read Server CA cert"); *errorcode = FTPERR_CLIENT_SECURITY; goto error; } SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, 0); SSL_CTX_set_verify_depth(ssl_context, 1); } } sbio = BIO_new_ssl_connect(ssl_context); if (!sbio) { logMessage(ERROR, "Could not create SSL object"); *errorcode = FTPERR_CLIENT_SECURITY; goto error; } BIO_get_ssl(sbio, &ssl); if (!ssl) { logMessage(ERROR, "Could not find ssl pointer."); *errorcode = FTPERR_CLIENT_SECURITY; goto error; } SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); BIO_set_conn_hostname(sbio, hostname); BIO_set_conn_port(sbio, "https"); rc = BIO_do_connect(sbio); if (rc<=0) { rc = SSL_get_verify_result(ssl); if (rc) { logMessage(ERROR, "Could not verify %s's identity", hostname); *errorcode = FTPERR_REFUSED; goto error; } logMessage(ERROR, "Could not connect to %s:https", hostname); *errorcode = FTPERR_FAILED_CONNECT; goto error; } rc = BIO_do_handshake(sbio); if (rc<=0) { logMessage(ERROR, "Could not establish HTTPS connection with %s", hostname); *errorcode = FTPERR_FAILED_CONNECT; goto error; } server_cert = SSL_get_peer_certificate(ssl); /* Show credentials if appropriate. */ /* Don't Show Credentials */ if ( (0 == 1) && !loaderData->cert_filename && !loaderData->ekv && !loaderData->dropCert) { rc = show_cert(server_cert); if (rc != 1) { *errorcode = FTPERR_REFUSED; goto error; } } if (extraHeaders) hstr = extraHeaders; else hstr = ""; bufsize = strlen(remotename) + strlen(hostname) + strlen(hstr) + 30; if ((buf = malloc(bufsize)) == NULL) { logMessage(ERROR, "ROCKS:httpsGetFileDesc:malloc failed"); *errorcode = FTPERR_FAILED_CONNECT; goto error; } sprintf(buf, "GET %s HTTP/1.0\r\nHost: %s\r\n%s\r\n", remotename, hostname, hstr); byteswritten = BIO_puts(sbio, buf); logMessage(INFO, "ROCKS:httpsGetFileDesc:byteswritten(%d)", byteswritten); logMessage(INFO, "ROCKS:httpsGetFileDesc:bufsize(%d)", (int)strlen(buf)); free(buf); /* This is fun; read the response a character at a time until we: 1) Get our first \r\n; which lets us check the return code 2) Get a \r\n\r\n, which means we're done */ *nextChar = '\0'; checkedCode = 0; headerslen = 0; while (!strstr(headers, "\r\n\r\n")) { if (BIO_read(sbio, nextChar, 1) != 1) { *errorcode = FTPERR_SERVER_SECURITY; goto error; } nextChar++; *nextChar = '\0'; ++headerslen; if (nextChar - headers == sizeof(headers)) { goto error; } if (!checkedCode && strstr(headers, "\r\n")) { char * start, * end; checkedCode = 1; start = headers; while (!isspace(*start) && *start) start++; if (!*start) { goto error; } while (isspace(*start) && *start) start++; end = start; while (!isspace(*end) && *end) end++; if (!*end) { goto error; } logMessage(INFO, "ROCKS:httpsGetFileDesc:status %s.", start); *end = '\0'; if (!strcmp(start, "404")) goto error; else if (!strcmp(start, "403")) { *errorcode = FTPERR_SERVER_SECURITY; goto error; } else if (!strcmp(start, "503")) { /* A server nack - busy */ logMessage(WARNING, "ROCKS:server busy"); watchdog_reset(); *errorcode = FTPERR_FAILED_DATA_CONNECT; goto error; } else if (strcmp(start, "200")) { *errorcode = FTPERR_BAD_SERVER_RESPONSE; goto error; } *end = ' '; } } if ((*returnedHeaders = (char *)malloc(headerslen + 1)) != NULL) { memcpy(*returnedHeaders, headers, headerslen + 1); } return sbio; error: close(sock); if (sbio) BIO_free_all(sbio); if (!*errorcode) *errorcode = FTPERR_SERVER_IO_ERROR; logMessage(ERROR, "ROCKS:httpsGetFileDesc:Error %s", ftpStrerror(*errorcode, URL_METHOD_HTTP)); return NULL; }