int ssl_open(http_t *client, char *msg) { char buf[256]; const char *sn; X509 *cert; if (!client->ssl_enabled) return tcp_init(&client->tcp, msg); tcp_set_port(&client->tcp, HTTPS_DEFAULT_PORT); DO(tcp_init(&client->tcp, msg)); logit(LOG_INFO, "%s, initiating HTTPS ...", msg); client->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if (!client->ssl_ctx) return RC_HTTPS_OUT_OF_MEMORY; /* POODLE, only allow TLSv1.x or later */ SSL_CTX_set_options(client->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); SSL_CTX_set_verify(client->ssl_ctx, SSL_VERIFY_PEER, verify_callback); SSL_CTX_set_verify_depth(client->ssl_ctx, 150); /* Try to figure out location of trusted CA certs on system */ if (ssl_set_ca_location(client)) return RC_HTTPS_NO_TRUSTED_CA_STORE; client->ssl = SSL_new(client->ssl_ctx); if (!client->ssl) return RC_HTTPS_OUT_OF_MEMORY; /* SSL SNI support: tell the servername we want to speak to */ http_get_remote_name(client, &sn); if (!SSL_set_tlsext_host_name(client->ssl, sn)) return RC_HTTPS_SNI_ERROR; SSL_set_fd(client->ssl, client->tcp.ip.socket); if (-1 == SSL_connect(client->ssl)) return RC_HTTPS_FAILED_CONNECT; logit(LOG_INFO, "SSL connection using %s", SSL_get_cipher(client->ssl)); cert = SSL_get_peer_certificate(client->ssl); if (!cert) return RC_HTTPS_FAILED_GETTING_CERT; if (SSL_get_verify_result(client->ssl) == X509_V_OK) logit(LOG_DEBUG, "Certificate OK"); X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); logit(LOG_INFO, "SSL server cert subject: %s", buf); X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); logit(LOG_INFO, "SSL server cert issuer: %s", buf); X509_free(cert); return 0; }
int ssl_open(http_t *client, char *msg) { char buf[256]; const char *sn; const X509 *cert; if (!client->ssl_enabled) return tcp_init(&client->tcp, msg); tcp_set_port(&client->tcp, 443); DO(tcp_init(&client->tcp, msg)); logit(LOG_INFO, "%s, initiating HTTPS ...", msg); client->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if (!client->ssl_ctx) return RC_HTTPS_OUT_OF_MEMORY; client->ssl = SSL_new(client->ssl_ctx); if (!client->ssl) return RC_HTTPS_OUT_OF_MEMORY; /* SSL SNI support: tell the servername we want to speak to */ http_get_remote_name(client, &sn); if (gnutls_server_name_set(client->ssl->gnutls_state, GNUTLS_NAME_DNS, sn, strlen(sn))) return RC_HTTPS_SNI_ERROR; SSL_set_fd(client->ssl, client->tcp.ip.socket); if (-1 == SSL_connect(client->ssl)) return RC_HTTPS_FAILED_CONNECT; logit(LOG_INFO, "SSL connection using %s", SSL_get_cipher(client->ssl)); /* Get server's certificate (note: beware of dynamic allocation) - opt */ cert = SSL_get_peer_certificate(client->ssl); if (!cert) return RC_HTTPS_FAILED_GETTING_CERT; /* Logging some cert details. Please note: X509_NAME_oneline doesn't work when giving NULL instead of a buffer. */ X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); logit(LOG_INFO, "SSL server cert subject: %s", buf); X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); logit(LOG_INFO, "SSL server cert issuer: %s", buf); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free(cert); return 0; }
int ssl_init(http_t *client, char *msg) { #ifndef ENABLE_SSL (void)client; (void)msg; return 0; #else int err, err_ssl, rc = 0; char buf[256]; const char *sn; X509 *cert; if (client->verbose > 1) logit(LOG_INFO, "%s, initiating HTTPS ...", msg); do { client->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if (!client->ssl_ctx) return RC_HTTPS_OUT_OF_MEMORY; #if defined(CONFIG_OPENSSL) /* POODLE, only allow TLSv1.x or later */ SSL_CTX_set_options(client->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); #endif client->ssl = SSL_new(client->ssl_ctx); if (!client->ssl) { rc = RC_HTTPS_OUT_OF_MEMORY; break; } http_get_remote_name(client, &sn); if (set_server_name(client->ssl, sn)) { rc = RC_HTTPS_SNI_ERROR; break; } SSL_set_fd(client->ssl, client->tcp.ip.socket); err = SSL_connect(client->ssl); if (err <= 0) { err_ssl = SSL_get_error(client->ssl, err); logit(LOG_ERR, "SSL_connect %s! (err: %d)", "FAILED", err_ssl); rc = RC_HTTPS_FAILED_CONNECT; break; } if (client->verbose > 0) logit(LOG_INFO, "SSL connection using %s", SSL_get_cipher(client->ssl)); /* Get server's certificate (note: beware of dynamic allocation) - opt */ cert = SSL_get_peer_certificate(client->ssl); if (!cert) { logit(LOG_ERR, "SSL_get_peer_certificate %s!", "FAILED"); rc = RC_HTTPS_FAILED_GETTING_CERT; break; } /* Logging some cert details. Please note: X509_NAME_oneline doesn't work when giving NULL instead of a buffer. */ buf[0] = 0; X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); if (client->verbose > 1) logit(LOG_INFO, "SSL server cert subject: %s", buf); buf[0] = 0; X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); if (client->verbose > 1) logit(LOG_INFO, "SSL server cert issuer: %s", buf); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free(cert); } while (0); if (rc) { ssl_exit(client); return rc; } return 0; #endif }
int ssl_open(http_t *client, char *msg) { int ret; char buf[256]; size_t len; const char *sn, *err; const gnutls_datum_t *cert_list; unsigned int cert_list_size = 0; gnutls_x509_crt_t cert; if (!client->ssl_enabled) return tcp_init(&client->tcp, msg); /* Initialize TLS session */ logit(LOG_INFO, "%s, initiating HTTPS ...", msg); gnutls_init(&client->ssl, GNUTLS_CLIENT); /* SSL SNI support: tell the servername we want to speak to */ http_get_remote_name(client, &sn); gnutls_session_set_ptr(client->ssl, (void *)sn); if (gnutls_server_name_set(client->ssl, GNUTLS_NAME_DNS, sn, strlen(sn))) return RC_HTTPS_SNI_ERROR; /* Use default priorities */ ret = gnutls_priority_set_direct(client->ssl, "NORMAL", &err); if (ret < 0) { if (ret == GNUTLS_E_INVALID_REQUEST) logit(LOG_ERR, "Syntax error at: %s", err); return RC_HTTPS_INVALID_REQUEST; } /* put the x509 credentials to the current session */ gnutls_credentials_set(client->ssl, GNUTLS_CRD_CERTIFICATE, xcred); /* connect to the peer */ tcp_set_port(&client->tcp, HTTPS_DEFAULT_PORT); DO(tcp_init(&client->tcp, msg)); /* Forward TCP socket to GnuTLS, the set_int() API is perhaps too new still ... since 3.1.9 */ // gnutls_transport_set_int(client->ssl, client->tcp.ip.socket); gnutls_transport_set_ptr(client->ssl, (gnutls_transport_ptr_t)(intptr_t)client->tcp.ip.socket); /* Perform the TLS handshake, ignore non-fatal errors. */ do { ret = gnutls_handshake(client->ssl); } while (ret != 0 && !gnutls_error_is_fatal(ret)); if (gnutls_error_is_fatal(ret)) { logit(LOG_ERR, "SSL handshake with %s failed: %s", sn, gnutls_strerror(ret)); return RC_HTTPS_FAILED_CONNECT; } ssl_get_info(client); /* Get server's certificate (note: beware of dynamic allocation) - opt */ cert_list = gnutls_certificate_get_peers(client->ssl, &cert_list_size); if (cert_list_size > 0) { if (gnutls_x509_crt_init(&cert)) return RC_HTTPS_FAILED_GETTING_CERT; gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); len = sizeof(buf); gnutls_x509_crt_get_dn(cert, buf, &len); logit(LOG_INFO, "SSL server cert subject: %s", buf); len = sizeof(buf); gnutls_x509_crt_get_issuer_dn(cert, buf, &len); logit(LOG_INFO, "SSL server cert issuer: %s", buf); gnutls_x509_crt_deinit(cert); } return 0; }