Handle NULL return from os_zalloc() in sta_track_add()
[mech_eap.git] / src / utils / http_curl.c
index 3a042f9..a06aae8 100644 (file)
@@ -26,6 +26,9 @@
 #include "common.h"
 #include "xml-utils.h"
 #include "http-utils.h"
+#ifdef EAP_TLS_OPENSSL
+#include "crypto/tls_openssl.h"
+#endif /* EAP_TLS_OPENSSL */
 
 
 struct http_ctx {
@@ -421,6 +424,28 @@ ASN1_SEQUENCE(LogotypeExtn) = {
 
 IMPLEMENT_ASN1_FUNCTIONS(LogotypeExtn);
 
+#ifdef OPENSSL_IS_BORINGSSL
+#define sk_LogotypeInfo_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(LogotypeInfo) *, (st)))
+#define sk_LogotypeInfo_value(st, i) (LogotypeInfo *) \
+sk_value(CHECKED_CAST(_STACK *, const STACK_OF(LogotypeInfo) *, (st)), (i))
+#define sk_LogotypeImage_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(LogotypeImage) *, (st)))
+#define sk_LogotypeImage_value(st, i) (LogotypeImage *) \
+sk_value(CHECKED_CAST(_STACK *, const STACK_OF(LogotypeImage) *, (st)), (i))
+#define sk_LogotypeAudio_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(LogotypeAudio) *, (st)))
+#define sk_LogotypeAudio_value(st, i) (LogotypeAudio *) \
+sk_value(CHECK_CAST(_STACK *, const STACK_OF(LogotypeAudio) *, (st)), (i))
+#define sk_HashAlgAndValue_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(HashAlgAndValue) *, (st)))
+#define sk_HashAlgAndValue_value(st, i) (HashAlgAndValue *) \
+sk_value(CHECKED_CAST(_STACK *, const STACK_OF(HashAlgAndValue) *, (st)), (i))
+#define sk_ASN1_IA5STRING_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_IA5STRING) *, (st)))
+#define sk_ASN1_IA5STRING_value(st, i) (ASN1_IA5STRING *) \
+sk_value(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_IA5STRING) *, (st)), (i))
+#else /* OPENSSL_IS_BORINGSSL */
 #define sk_LogotypeInfo_num(st) SKM_sk_num(LogotypeInfo, (st))
 #define sk_LogotypeInfo_value(st, i) SKM_sk_value(LogotypeInfo, (st), (i))
 #define sk_LogotypeImage_num(st) SKM_sk_num(LogotypeImage, (st))
@@ -431,6 +456,7 @@ IMPLEMENT_ASN1_FUNCTIONS(LogotypeExtn);
 #define sk_HashAlgAndValue_value(st, i) SKM_sk_value(HashAlgAndValue, (st), (i))
 #define sk_ASN1_IA5STRING_num(st) SKM_sk_num(ASN1_IA5STRING, (st))
 #define sk_ASN1_IA5STRING_value(st, i) SKM_sk_value(ASN1_IA5STRING, (st), (i))
+#endif /* OPENSSL_IS_BORINGSSL */
 
 
 static void add_logo(struct http_ctx *ctx, struct http_cert *hcert,
@@ -618,13 +644,25 @@ static void i2r_LogotypeImageInfo(LogotypeImageInfo *info, BIO *out, int indent)
        } else {
                BIO_printf(out, "%*stype: default (1)\n", indent, "");
        }
+       val = ASN1_INTEGER_get(info->fileSize);
+       BIO_printf(out, "%*sfileSize: %ld\n", indent, "", val);
        val = ASN1_INTEGER_get(info->xSize);
        BIO_printf(out, "%*sxSize: %ld\n", indent, "", val);
        val = ASN1_INTEGER_get(info->ySize);
        BIO_printf(out, "%*sySize: %ld\n", indent, "", val);
        if (info->resolution) {
-               BIO_printf(out, "%*sresolution\n", indent, "");
-               /* TODO */
+               BIO_printf(out, "%*sresolution [%d]\n", indent, "",
+                          info->resolution->type);
+               switch (info->resolution->type) {
+               case 0:
+                       val = ASN1_INTEGER_get(info->resolution->d.numBits);
+                       BIO_printf(out, "%*snumBits: %ld\n", indent, "", val);
+                       break;
+               case 1:
+                       val = ASN1_INTEGER_get(info->resolution->d.tableSize);
+                       BIO_printf(out, "%*stableSize: %ld\n", indent, "", val);
+                       break;
+               }
        }
        if (info->language) {
                BIO_printf(out, "%*slanguage: ", indent, "");
@@ -855,8 +893,10 @@ static int validate_server_cert(struct http_ctx *ctx, X509 *cert)
        struct http_cert hcert;
        int ret;
 
-       if (ctx->cert_cb == NULL)
+       if (ctx->cert_cb == NULL) {
+               wpa_printf(MSG_DEBUG, "%s: no cert_cb configured", __func__);
                return 0;
+       }
 
        if (0) {
                BIO *out;
@@ -950,7 +990,8 @@ static int curl_cb_ssl_verify(int preverify_ok, X509_STORE_CTX *x509_ctx)
        ssl_ctx = ssl->ctx;
        ctx = SSL_CTX_get_app_data(ssl_ctx);
 
-       wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify");
+       wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify, preverify_ok: %d",
+                  preverify_ok);
 
        err = X509_STORE_CTX_get_error(x509_ctx);
        err_str = X509_verify_cert_error_string(err);
@@ -978,6 +1019,26 @@ static int curl_cb_ssl_verify(int preverify_ok, X509_STORE_CTX *x509_ctx)
        if (depth == 0 && preverify_ok && validate_server_cert(ctx, cert) < 0)
                return 0;
 
+#ifdef OPENSSL_IS_BORINGSSL
+       if (depth == 0 && ctx->ocsp != NO_OCSP && preverify_ok) {
+               enum ocsp_result res;
+
+               res = check_ocsp_resp(ssl_ctx, ssl, cert, ctx->peer_issuer,
+                                     ctx->peer_issuer_issuer);
+               if (res == OCSP_REVOKED) {
+                       preverify_ok = 0;
+                       wpa_printf(MSG_INFO, "OCSP: certificate revoked");
+                       if (err == X509_V_OK)
+                               X509_STORE_CTX_set_error(
+                                       x509_ctx, X509_V_ERR_CERT_REVOKED);
+               } else if (res != OCSP_GOOD && (ctx->ocsp == MANDATORY_OCSP)) {
+                       preverify_ok = 0;
+                       wpa_printf(MSG_INFO,
+                                  "OCSP: bad certificate status response");
+               }
+       }
+#endif /* OPENSSL_IS_BORINGSSL */
+
        if (!preverify_ok)
                ctx->last_err = "TLS validation failed";
 
@@ -1084,7 +1145,7 @@ static int ocsp_resp_cb(SSL *s, void *arg)
 
                if (X509_STORE_add_cert(store, ctx->peer_issuer) != 1) {
                        tls_show_errors(__func__,
-                                       "OpenSSL: Could not add issuer to certificate store\n");
+                                       "OpenSSL: Could not add issuer to certificate store");
                }
                certs = sk_X509_new_null();
                if (certs) {
@@ -1093,7 +1154,7 @@ static int ocsp_resp_cb(SSL *s, void *arg)
                        if (cert && !sk_X509_push(certs, cert)) {
                                tls_show_errors(
                                        __func__,
-                                       "OpenSSL: Could not add issuer to OCSP responder trust store\n");
+                                       "OpenSSL: Could not add issuer to OCSP responder trust store");
                                X509_free(cert);
                                sk_X509_free(certs);
                                certs = NULL;
@@ -1103,7 +1164,7 @@ static int ocsp_resp_cb(SSL *s, void *arg)
                                if (cert && !sk_X509_push(certs, cert)) {
                                        tls_show_errors(
                                                __func__,
-                                               "OpenSSL: Could not add issuer to OCSP responder trust store\n");
+                                               "OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
                                        X509_free(cert);
                                }
                        }
@@ -1153,6 +1214,7 @@ static int ocsp_resp_cb(SSL *s, void *arg)
                wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
                           (ctx->ocsp == MANDATORY_OCSP) ? "" :
                           " (OCSP not required)");
+               OCSP_CERTID_free(id);
                OCSP_BASICRESP_free(basic);
                OCSP_RESPONSE_free(rsp);
                if (ctx->ocsp == MANDATORY_OCSP)
@@ -1160,6 +1222,7 @@ static int ocsp_resp_cb(SSL *s, void *arg)
                        ctx->last_err = "Could not find current server certificate from OCSP response";
                return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1;
        }
+       OCSP_CERTID_free(id);
 
        if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
                tls_show_errors(__func__, "OpenSSL: OCSP status times invalid");
@@ -1249,9 +1312,14 @@ static CURL * setup_curl_post(struct http_ctx *ctx, const char *address,
                              const char *client_key)
 {
        CURL *curl;
+#ifdef EAP_TLS_OPENSSL
+       const char *extra = " tls=openssl";
+#else /* EAP_TLS_OPENSSL */
+       const char *extra = "";
+#endif /* EAP_TLS_OPENSSL */
 
        wpa_printf(MSG_DEBUG, "Start HTTP client: address=%s ca_fname=%s "
-                  "username=%s", address, ca_fname, username);
+                  "username=%s%s", address, ca_fname, username, extra);
 
        curl = curl_easy_init();
        if (curl == NULL)
@@ -1265,6 +1333,16 @@ static CURL * setup_curl_post(struct http_ctx *ctx, const char *address,
 #ifdef EAP_TLS_OPENSSL
                curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, curl_cb_ssl);
                curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, ctx);
+#ifdef OPENSSL_IS_BORINGSSL
+               /* For now, using the CURLOPT_SSL_VERIFYSTATUS option only
+                * with BoringSSL since the OpenSSL specific callback hack to
+                * enable OCSP is not available with BoringSSL. The OCSP
+                * implementation within libcurl is not sufficient for the
+                * Hotspot 2.0 OSU needs, so cannot use this with OpenSSL.
+                */
+               if (ctx->ocsp != NO_OCSP)
+                       curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
+#endif /* OPENSSL_IS_BORINGSSL */
 #endif /* EAP_TLS_OPENSSL */
        } else {
                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);