1d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt/*
2d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * HTTP wrapper for libcurl
36cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt * Copyright (c) 2012-2014, Qualcomm Atheros, Inc.
4d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt *
5d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * This software may be distributed under the terms of the BSD license.
6d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * See README for more details.
7d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt */
8d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
9d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "includes.h"
10d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <curl/curl.h>
11d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#ifdef EAP_TLS_OPENSSL
12d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/ssl.h>
13d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/asn1.h>
14d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/asn1t.h>
15d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/x509v3.h>
16d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
17d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#ifdef SSL_set_tlsext_status_type
18d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#ifndef OPENSSL_NO_TLSEXT
19d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define HAVE_OCSP
20d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/err.h>
21d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include <openssl/ocsp.h>
22d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#endif /* OPENSSL_NO_TLSEXT */
23d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#endif /* SSL_set_tlsext_status_type */
24d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#endif /* EAP_TLS_OPENSSL */
25d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
26d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "common.h"
27d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "xml-utils.h"
28d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "http-utils.h"
29d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#ifdef EAP_TLS_OPENSSL
30d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#include "crypto/tls_openssl.h"
31d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#endif /* EAP_TLS_OPENSSL */
32d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
33d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
34d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstruct http_ctx {
35d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	void *ctx;
36d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct xml_node_ctx *xml;
37d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	CURL *curl;
38d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct curl_slist *curl_hdr;
39d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *svc_address;
40d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *svc_ca_fname;
41d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *svc_username;
42d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *svc_password;
43d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *svc_client_cert;
44d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *svc_client_key;
45d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *curl_buf;
46d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	size_t curl_buf_len;
47d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
48d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int (*cert_cb)(void *ctx, struct http_cert *cert);
49d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	void *cert_cb_ctx;
50d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
51d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	enum {
52d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		NO_OCSP, OPTIONAL_OCSP, MANDATORY_OCSP
53d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	} ocsp;
54d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509 *peer_cert;
55d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509 *peer_issuer;
56d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509 *peer_issuer_issuer;
57d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
58d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	const char *last_err;
59d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt};
60d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
61d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
62d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void clear_curl(struct http_ctx *ctx)
63d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
64d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ctx->curl) {
65d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_cleanup(ctx->curl);
66d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->curl = NULL;
67d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
68d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ctx->curl_hdr) {
69d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_slist_free_all(ctx->curl_hdr);
70d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->curl_hdr = NULL;
71d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
72d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
73d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
74d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
75d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void clone_str(char **dst, const char *src)
76d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
77d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(*dst);
78d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (src)
79d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		*dst = os_strdup(src);
80d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	else
81d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		*dst = NULL;
82d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
83d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
84d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
85d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void debug_dump(struct http_ctx *ctx, const char *title,
86d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		       const char *buf, size_t len)
87d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
886cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt	char *txt;
896cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt	size_t i;
906cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt
916cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt	for (i = 0; i < len; i++) {
926cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt		if (buf[i] < 32 && buf[i] != '\t' && buf[i] != '\n' &&
936cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt		    buf[i] != '\r') {
946cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt			wpa_hexdump_ascii(MSG_MSGDUMP, title, buf, len);
956cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt			return;
966cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt		}
976cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt	}
986cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt
996cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt	txt = os_malloc(len + 1);
100d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (txt == NULL)
101d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
102d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_memcpy(txt, buf, len);
103d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	txt[len] = '\0';
104d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	while (len > 0) {
105d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		len--;
1066cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt		if (txt[len] == '\n' || txt[len] == '\r')
1076cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt			txt[len] = '\0';
1086cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt		else
1096cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt			break;
110d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
111d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "%s[%s]", title, txt);
112d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(txt);
113d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
114d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
115d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
116d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic int curl_cb_debug(CURL *curl, curl_infotype info, char *buf, size_t len,
117d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			 void *userdata)
118d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
119d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_ctx *ctx = userdata;
120d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	switch (info) {
121d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case CURLINFO_TEXT:
122d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		debug_dump(ctx, "CURLINFO_TEXT", buf, len);
123d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
124d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case CURLINFO_HEADER_IN:
125d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		debug_dump(ctx, "CURLINFO_HEADER_IN", buf, len);
126d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
127d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case CURLINFO_HEADER_OUT:
128d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		debug_dump(ctx, "CURLINFO_HEADER_OUT", buf, len);
129d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
130d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case CURLINFO_DATA_IN:
131d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		debug_dump(ctx, "CURLINFO_DATA_IN", buf, len);
132d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
133d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case CURLINFO_DATA_OUT:
134d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		debug_dump(ctx, "CURLINFO_DATA_OUT", buf, len);
135d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
136d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case CURLINFO_SSL_DATA_IN:
137d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "debug - CURLINFO_SSL_DATA_IN - %d",
138d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   (int) len);
139d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
140d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case CURLINFO_SSL_DATA_OUT:
141d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "debug - CURLINFO_SSL_DATA_OUT - %d",
142d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   (int) len);
143d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
144d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case CURLINFO_END:
145d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "debug - CURLINFO_END - %d",
146d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   (int) len);
147d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
148d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
149d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return 0;
150d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
151d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
152d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
153d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic size_t curl_cb_write(void *ptr, size_t size, size_t nmemb,
154d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			    void *userdata)
155d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
156d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_ctx *ctx = userdata;
157d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *n;
158d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n = os_realloc(ctx->curl_buf, ctx->curl_buf_len + size * nmemb + 1);
159d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (n == NULL)
160d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
161d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl_buf = n;
162d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_memcpy(n + ctx->curl_buf_len, ptr, size * nmemb);
163d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n[ctx->curl_buf_len + size * nmemb] = '\0';
164d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl_buf_len += size * nmemb;
165d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return size * nmemb;
166d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
167d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
168d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
169d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#ifdef EAP_TLS_OPENSSL
170d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
171d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void debug_dump_cert(const char *title, X509 *cert)
172d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
173d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO *out;
174d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *txt;
175d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	size_t rlen;
176d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
177d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	out = BIO_new(BIO_s_mem());
178d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!out)
179d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
180d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
181d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509_print_ex(out, cert, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
182d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	rlen = BIO_ctrl_pending(out);
183d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	txt = os_malloc(rlen + 1);
184d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (txt) {
185d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		int res = BIO_read(out, txt, rlen);
186d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (res > 0) {
187d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			txt[res] = '\0';
188d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			wpa_printf(MSG_MSGDUMP, "%s:\n%s", title, txt);
189d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		}
190d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_free(txt);
191d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
192d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_free(out);
193d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
194d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
195d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
196d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_alt_name_othername(struct http_ctx *ctx, struct http_cert *cert,
197d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				   OTHERNAME *o)
198d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
199d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char txt[100];
200d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int res;
201d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_othername *on;
202d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_TYPE *val;
203d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
204d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	on = os_realloc_array(cert->othername, cert->num_othername + 1,
205d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			      sizeof(struct http_othername));
206d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (on == NULL)
207d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
208d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	cert->othername = on;
209d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	on = &on[cert->num_othername];
210d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_memset(on, 0, sizeof(*on));
211d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
212d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	res = OBJ_obj2txt(txt, sizeof(txt), o->type_id, 1);
213d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (res < 0 || res >= (int) sizeof(txt))
214d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
215d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
216d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	on->oid = os_strdup(txt);
217d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (on->oid == NULL)
218d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
219d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
220d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	val = o->value;
221d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	on->data = val->value.octet_string->data;
222d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	on->len = val->value.octet_string->length;
223d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
224d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	cert->num_othername++;
225d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
226d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
227d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
228d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_alt_name_dns(struct http_ctx *ctx, struct http_cert *cert,
229d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			     ASN1_STRING *name)
230d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
231d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *buf;
232d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char **n;
233d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
234d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	buf = NULL;
235d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ASN1_STRING_to_UTF8((unsigned char **) &buf, name) < 0)
236d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
237d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
238d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n = os_realloc_array(cert->dnsname, cert->num_dnsname + 1,
239d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			     sizeof(char *));
240d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (n == NULL)
241d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
242d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
243d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	cert->dnsname = n;
244d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n[cert->num_dnsname] = buf;
245d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	cert->num_dnsname++;
246d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
247d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
248d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
249d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_alt_name(struct http_ctx *ctx, struct http_cert *cert,
250d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			 const GENERAL_NAME *name)
251d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
252d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	switch (name->type) {
253d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case GEN_OTHERNAME:
254d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		add_alt_name_othername(ctx, cert, name->d.otherName);
255d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
256d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case GEN_DNS:
257d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		add_alt_name_dns(ctx, cert, name->d.dNSName);
258d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
259d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
260d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
261d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
262d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
263d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_alt_names(struct http_ctx *ctx, struct http_cert *cert,
264d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			  GENERAL_NAMES *names)
265d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
266d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int num, i;
267d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
268d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	num = sk_GENERAL_NAME_num(names);
269d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < num; i++) {
270d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		const GENERAL_NAME *name;
271d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		name = sk_GENERAL_NAME_value(names, i);
272d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		add_alt_name(ctx, cert, name);
273d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
274d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
275d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
276d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
277d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt/* RFC 3709 */
278d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
279d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
280d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509_ALGOR *hashAlg;
281d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_OCTET_STRING *hashValue;
282d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} HashAlgAndValue;
283d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
284d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
285d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	STACK_OF(HashAlgAndValue) *refStructHash;
286d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	STACK_OF(ASN1_IA5STRING) *refStructURI;
287d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeReference;
288d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
289d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
290d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IA5STRING *mediaType;
291d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	STACK_OF(HashAlgAndValue) *logotypeHash;
292d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	STACK_OF(ASN1_IA5STRING) *logotypeURI;
293d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeDetails;
294d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
295d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
296d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int type;
297d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	union {
298d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ASN1_INTEGER *numBits;
299d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ASN1_INTEGER *tableSize;
300d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	} d;
301d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeImageResolution;
302d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
303d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
304d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_INTEGER *type; /* LogotypeImageType ::= INTEGER */
305d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_INTEGER *fileSize;
306d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_INTEGER *xSize;
307d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_INTEGER *ySize;
308d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeImageResolution *resolution;
309d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IA5STRING *language;
310d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeImageInfo;
311d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
312d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
313d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeDetails *imageDetails;
314d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeImageInfo *imageInfo;
315d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeImage;
316d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
317d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
318d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_INTEGER *fileSize;
319d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_INTEGER *playTime;
320d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_INTEGER *channels;
321d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_INTEGER *sampleRate;
322d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IA5STRING *language;
323d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeAudioInfo;
324d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
325d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
326d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeDetails *audioDetails;
327d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeAudioInfo *audioInfo;
328d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeAudio;
329d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
330d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
331d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	STACK_OF(LogotypeImage) *image;
332d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	STACK_OF(LogotypeAudio) *audio;
333d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeData;
334d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
335d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
336d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int type;
337d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	union {
338d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		LogotypeData *direct;
339d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		LogotypeReference *indirect;
340d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	} d;
341d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeInfo;
342d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
343d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
344d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_OBJECT *logotypeType;
345d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeInfo *info;
346d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} OtherLogotypeInfo;
347d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
348d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidttypedef struct {
349d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	STACK_OF(LogotypeInfo) *communityLogos;
350d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeInfo *issuerLogo;
351d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeInfo *subjectLogo;
352d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	STACK_OF(OtherLogotypeInfo) *otherLogos;
353d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} LogotypeExtn;
354d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
355d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(HashAlgAndValue) = {
356d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(HashAlgAndValue, hashAlg, X509_ALGOR),
357d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(HashAlgAndValue, hashValue, ASN1_OCTET_STRING)
358d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(HashAlgAndValue);
359d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
360d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(LogotypeReference) = {
361d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SEQUENCE_OF(LogotypeReference, refStructHash, HashAlgAndValue),
362d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SEQUENCE_OF(LogotypeReference, refStructURI, ASN1_IA5STRING)
363d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(LogotypeReference);
364d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
365d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(LogotypeDetails) = {
366d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(LogotypeDetails, mediaType, ASN1_IA5STRING),
367d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SEQUENCE_OF(LogotypeDetails, logotypeHash, HashAlgAndValue),
368d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SEQUENCE_OF(LogotypeDetails, logotypeURI, ASN1_IA5STRING)
369d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(LogotypeDetails);
370d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
371d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_CHOICE(LogotypeImageResolution) = {
372d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IMP(LogotypeImageResolution, d.numBits, ASN1_INTEGER, 1),
373d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IMP(LogotypeImageResolution, d.tableSize, ASN1_INTEGER, 2)
374d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_CHOICE_END(LogotypeImageResolution);
375d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
376d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(LogotypeImageInfo) = {
377d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IMP_OPT(LogotypeImageInfo, type, ASN1_INTEGER, 0),
378d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(LogotypeImageInfo, fileSize, ASN1_INTEGER),
379d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(LogotypeImageInfo, xSize, ASN1_INTEGER),
380d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(LogotypeImageInfo, ySize, ASN1_INTEGER),
381d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_OPT(LogotypeImageInfo, resolution, LogotypeImageResolution),
382d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IMP_OPT(LogotypeImageInfo, language, ASN1_IA5STRING, 4),
383d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(LogotypeImageInfo);
384d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
385d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(LogotypeImage) = {
386d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(LogotypeImage, imageDetails, LogotypeDetails),
387d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_OPT(LogotypeImage, imageInfo, LogotypeImageInfo)
388d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(LogotypeImage);
389d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
390d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(LogotypeAudioInfo) = {
391d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(LogotypeAudioInfo, fileSize, ASN1_INTEGER),
392d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(LogotypeAudioInfo, playTime, ASN1_INTEGER),
393d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(LogotypeAudioInfo, channels, ASN1_INTEGER),
394d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IMP_OPT(LogotypeAudioInfo, sampleRate, ASN1_INTEGER, 3),
395d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IMP_OPT(LogotypeAudioInfo, language, ASN1_IA5STRING, 4)
396d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(LogotypeAudioInfo);
397d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
398d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(LogotypeAudio) = {
399d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(LogotypeAudio, audioDetails, LogotypeDetails),
400d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_OPT(LogotypeAudio, audioInfo, LogotypeAudioInfo)
401d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(LogotypeAudio);
402d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
403d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(LogotypeData) = {
404d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SEQUENCE_OF_OPT(LogotypeData, image, LogotypeImage),
405d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IMP_SEQUENCE_OF_OPT(LogotypeData, audio, LogotypeAudio, 1)
406d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(LogotypeData);
407d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
408d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_CHOICE(LogotypeInfo) = {
409d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IMP(LogotypeInfo, d.direct, LogotypeData, 0),
410d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_IMP(LogotypeInfo, d.indirect, LogotypeReference, 1)
411d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_CHOICE_END(LogotypeInfo);
412d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
413d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(OtherLogotypeInfo) = {
414d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(OtherLogotypeInfo, logotypeType, ASN1_OBJECT),
415d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_SIMPLE(OtherLogotypeInfo, info, LogotypeInfo)
416d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(OtherLogotypeInfo);
417d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
418d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtASN1_SEQUENCE(LogotypeExtn) = {
419d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_EXP_SEQUENCE_OF_OPT(LogotypeExtn, communityLogos, LogotypeInfo, 0),
420d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_EXP_OPT(LogotypeExtn, issuerLogo, LogotypeInfo, 1),
421d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_EXP_OPT(LogotypeExtn, issuerLogo, LogotypeInfo, 2),
422d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_EXP_SEQUENCE_OF_OPT(LogotypeExtn, otherLogos, OtherLogotypeInfo, 3)
423d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} ASN1_SEQUENCE_END(LogotypeExtn);
424d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
425d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry ShmidtIMPLEMENT_ASN1_FUNCTIONS(LogotypeExtn);
426d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
427d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef OPENSSL_IS_BORINGSSL
428d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_LogotypeInfo_num(st) \
429d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_num(CHECKED_CAST(_STACK *, STACK_OF(LogotypeInfo) *, (st)))
430d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_LogotypeInfo_value(st, i) (LogotypeInfo *) \
431d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_value(CHECKED_CAST(_STACK *, const STACK_OF(LogotypeInfo) *, (st)), (i))
432d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_LogotypeImage_num(st) \
433d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_num(CHECKED_CAST(_STACK *, STACK_OF(LogotypeImage) *, (st)))
434d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_LogotypeImage_value(st, i) (LogotypeImage *) \
435d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_value(CHECKED_CAST(_STACK *, const STACK_OF(LogotypeImage) *, (st)), (i))
436d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_LogotypeAudio_num(st) \
437d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_num(CHECKED_CAST(_STACK *, STACK_OF(LogotypeAudio) *, (st)))
438d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_LogotypeAudio_value(st, i) (LogotypeAudio *) \
439d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_value(CHECK_CAST(_STACK *, const STACK_OF(LogotypeAudio) *, (st)), (i))
440d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_HashAlgAndValue_num(st) \
441d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_num(CHECKED_CAST(_STACK *, STACK_OF(HashAlgAndValue) *, (st)))
442d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_HashAlgAndValue_value(st, i) (HashAlgAndValue *) \
443d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_value(CHECKED_CAST(_STACK *, const STACK_OF(HashAlgAndValue) *, (st)), (i))
444d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_ASN1_IA5STRING_num(st) \
445d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_IA5STRING) *, (st)))
446d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#define sk_ASN1_IA5STRING_value(st, i) (ASN1_IA5STRING *) \
447d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtsk_value(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_IA5STRING) *, (st)), (i))
448d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#else /* OPENSSL_IS_BORINGSSL */
449d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_LogotypeInfo_num(st) SKM_sk_num(LogotypeInfo, (st))
450d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_LogotypeInfo_value(st, i) SKM_sk_value(LogotypeInfo, (st), (i))
451d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_LogotypeImage_num(st) SKM_sk_num(LogotypeImage, (st))
452d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_LogotypeImage_value(st, i) SKM_sk_value(LogotypeImage, (st), (i))
453d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_LogotypeAudio_num(st) SKM_sk_num(LogotypeAudio, (st))
454d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_LogotypeAudio_value(st, i) SKM_sk_value(LogotypeAudio, (st), (i))
455d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_HashAlgAndValue_num(st) SKM_sk_num(HashAlgAndValue, (st))
456d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_HashAlgAndValue_value(st, i) SKM_sk_value(HashAlgAndValue, (st), (i))
457d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_ASN1_IA5STRING_num(st) SKM_sk_num(ASN1_IA5STRING, (st))
458d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#define sk_ASN1_IA5STRING_value(st, i) SKM_sk_value(ASN1_IA5STRING, (st), (i))
459d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* OPENSSL_IS_BORINGSSL */
460d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
461d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
462d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_logo(struct http_ctx *ctx, struct http_cert *hcert,
463d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		     HashAlgAndValue *hash, ASN1_IA5STRING *uri)
464d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
465d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char txt[100];
466d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int res, len;
467d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_logo *n;
468d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
469d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (hash == NULL || uri == NULL)
470d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
471d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
472d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	res = OBJ_obj2txt(txt, sizeof(txt), hash->hashAlg->algorithm, 1);
473d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (res < 0 || res >= (int) sizeof(txt))
474d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
475d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
476d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n = os_realloc_array(hcert->logo, hcert->num_logo + 1,
477d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			     sizeof(struct http_logo));
478d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (n == NULL)
479d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
480d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	hcert->logo = n;
481d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n = &hcert->logo[hcert->num_logo];
482d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_memset(n, 0, sizeof(*n));
483d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
484d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n->alg_oid = os_strdup(txt);
485d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (n->alg_oid == NULL)
486d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
487d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
488d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n->hash_len = ASN1_STRING_length(hash->hashValue);
489d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n->hash = os_malloc(n->hash_len);
490d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (n->hash == NULL) {
491d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_free(n->alg_oid);
492d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
493d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
494d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_memcpy(n->hash, ASN1_STRING_data(hash->hashValue), n->hash_len);
495d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
496d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	len = ASN1_STRING_length(uri);
497d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n->uri = os_malloc(len + 1);
498d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (n->uri == NULL) {
499d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_free(n->alg_oid);
500d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_free(n->hash);
501d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
502d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
503d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_memcpy(n->uri, ASN1_STRING_data(uri), len);
504d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n->uri[len] = '\0';
505d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
506d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	hcert->num_logo++;
507d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
508d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
509d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
510d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_logo_direct(struct http_ctx *ctx, struct http_cert *hcert,
511d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			    LogotypeData *data)
512d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
513d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int i, num;
514d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
515d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (data->image == NULL)
516d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
517d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
518d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	num = sk_LogotypeImage_num(data->image);
519d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < num; i++) {
520d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		LogotypeImage *image;
521d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		LogotypeDetails *details;
522d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		int j, hash_num, uri_num;
523d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		HashAlgAndValue *found_hash = NULL;
524d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
525d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		image = sk_LogotypeImage_value(data->image, i);
526d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (image == NULL)
527d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			continue;
528d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
529d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		details = image->imageDetails;
530d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (details == NULL)
531d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			continue;
532d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
533d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		hash_num = sk_HashAlgAndValue_num(details->logotypeHash);
534d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		for (j = 0; j < hash_num; j++) {
535d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			HashAlgAndValue *hash;
536d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			char txt[100];
537d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			int res;
538d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			hash = sk_HashAlgAndValue_value(details->logotypeHash,
539d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt							j);
540d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			if (hash == NULL)
541d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				continue;
542d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			res = OBJ_obj2txt(txt, sizeof(txt),
543d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					  hash->hashAlg->algorithm, 1);
544d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			if (res < 0 || res >= (int) sizeof(txt))
545d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				continue;
546d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			if (os_strcmp(txt, "2.16.840.1.101.3.4.2.1") == 0) {
547d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				found_hash = hash;
548d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				break;
549d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			}
550d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		}
551d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
552d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (!found_hash) {
553d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			wpa_printf(MSG_DEBUG, "OpenSSL: No SHA256 hash found for the logo");
554d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			continue;
555d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		}
556d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
557d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		uri_num = sk_ASN1_IA5STRING_num(details->logotypeURI);
558d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		for (j = 0; j < uri_num; j++) {
559d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			ASN1_IA5STRING *uri;
560d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			uri = sk_ASN1_IA5STRING_value(details->logotypeURI, j);
561d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			add_logo(ctx, hcert, found_hash, uri);
562d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		}
563d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
564d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
565d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
566d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
567d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_logo_indirect(struct http_ctx *ctx, struct http_cert *hcert,
568d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			      LogotypeReference *ref)
569d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
570d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int j, hash_num, uri_num;
571d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
572d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	hash_num = sk_HashAlgAndValue_num(ref->refStructHash);
573d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	uri_num = sk_ASN1_IA5STRING_num(ref->refStructURI);
574d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (hash_num != uri_num) {
575d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "Unexpected LogotypeReference array size difference %d != %d",
576d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   hash_num, uri_num);
577d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
578d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
579d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
580d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (j = 0; j < hash_num; j++) {
581d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		HashAlgAndValue *hash;
582d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ASN1_IA5STRING *uri;
583d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		hash = sk_HashAlgAndValue_value(ref->refStructHash, j);
584d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		uri = sk_ASN1_IA5STRING_value(ref->refStructURI, j);
585d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		add_logo(ctx, hcert, hash, uri);
586d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
587d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
588d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
589d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
590d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void i2r_HashAlgAndValue(HashAlgAndValue *hash, BIO *out, int indent)
591d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
592d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int i;
593d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	const unsigned char *data;
594d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
595d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "%*shashAlg: ", indent, "");
596d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	i2a_ASN1_OBJECT(out, hash->hashAlg->algorithm);
597d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "\n");
598d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
599d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "%*shashValue: ", indent, "");
600d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	data = hash->hashValue->data;
601d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < hash->hashValue->length; i++)
602d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%s%02x", i > 0 ? ":" : "", data[i]);
603d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "\n");
604d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
605d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
606d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void i2r_LogotypeDetails(LogotypeDetails *details, BIO *out, int indent)
607d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
608d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int i, num;
609d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
610d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "%*sLogotypeDetails\n", indent, "");
611d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (details->mediaType) {
612d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%*smediaType: ", indent, "");
613d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ASN1_STRING_print(out, details->mediaType);
614d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "\n");
615d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
616d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
617d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	num = details->logotypeHash ?
618d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		sk_HashAlgAndValue_num(details->logotypeHash) : 0;
619d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < num; i++) {
620d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		HashAlgAndValue *hash;
621d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		hash = sk_HashAlgAndValue_value(details->logotypeHash, i);
622d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		i2r_HashAlgAndValue(hash, out, indent);
623d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
624d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
625d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	num = details->logotypeURI ?
626d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		sk_ASN1_IA5STRING_num(details->logotypeURI) : 0;
627d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < num; i++) {
628d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ASN1_IA5STRING *uri;
629d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		uri = sk_ASN1_IA5STRING_value(details->logotypeURI, i);
630d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%*slogotypeURI: ", indent, "");
631d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ASN1_STRING_print(out, uri);
632d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "\n");
633d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
634d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
635d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
636d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void i2r_LogotypeImageInfo(LogotypeImageInfo *info, BIO *out, int indent)
637d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
638d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	long val;
639d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
640d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "%*sLogotypeImageInfo\n", indent, "");
641d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (info->type) {
642d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		val = ASN1_INTEGER_get(info->type);
643d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%*stype: %ld\n", indent, "", val);
644d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	} else {
645d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%*stype: default (1)\n", indent, "");
646d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
647b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	val = ASN1_INTEGER_get(info->fileSize);
648b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	BIO_printf(out, "%*sfileSize: %ld\n", indent, "", val);
649d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	val = ASN1_INTEGER_get(info->xSize);
650d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "%*sxSize: %ld\n", indent, "", val);
651d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	val = ASN1_INTEGER_get(info->ySize);
652d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "%*sySize: %ld\n", indent, "", val);
653d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (info->resolution) {
654b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		BIO_printf(out, "%*sresolution [%d]\n", indent, "",
655b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			   info->resolution->type);
656b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		switch (info->resolution->type) {
657b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		case 0:
658b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			val = ASN1_INTEGER_get(info->resolution->d.numBits);
659b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			BIO_printf(out, "%*snumBits: %ld\n", indent, "", val);
660b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			break;
661b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		case 1:
662b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			val = ASN1_INTEGER_get(info->resolution->d.tableSize);
663b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			BIO_printf(out, "%*stableSize: %ld\n", indent, "", val);
664b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt			break;
665b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt		}
666d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
667d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (info->language) {
668d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%*slanguage: ", indent, "");
669d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ASN1_STRING_print(out, info->language);
670d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "\n");
671d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
672d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
673d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
674d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void i2r_LogotypeImage(LogotypeImage *image, BIO *out, int indent)
675d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
676d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "%*sLogotypeImage\n", indent, "");
677d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (image->imageDetails) {
678d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		i2r_LogotypeDetails(image->imageDetails, out, indent + 4);
679d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
680d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (image->imageInfo) {
681d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		i2r_LogotypeImageInfo(image->imageInfo, out, indent + 4);
682d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
683d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
684d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
685d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void i2r_LogotypeData(LogotypeData *data, const char *title, BIO *out,
686d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			     int indent)
687d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
688d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int i, num;
689d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
690d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "%*s%s - LogotypeData\n", indent, "", title);
691d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
692d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	num = data->image ? sk_LogotypeImage_num(data->image) : 0;
693d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < num; i++) {
694d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		LogotypeImage *image = sk_LogotypeImage_value(data->image, i);
695d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		i2r_LogotypeImage(image, out, indent + 4);
696d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
697d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
698d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	num = data->audio ? sk_LogotypeAudio_num(data->audio) : 0;
699d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < num; i++) {
700d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%*saudio: TODO\n", indent, "");
701d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
702d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
703d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
704d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void i2r_LogotypeReference(LogotypeReference *ref, const char *title,
705d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				  BIO *out, int indent)
706d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
707d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int i, hash_num, uri_num;
708d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
709d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_printf(out, "%*s%s - LogotypeReference\n", indent, "", title);
710d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
711d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	hash_num = ref->refStructHash ?
712d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		sk_HashAlgAndValue_num(ref->refStructHash) : 0;
713d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	uri_num = ref->refStructURI ?
714d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		sk_ASN1_IA5STRING_num(ref->refStructURI) : 0;
715d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (hash_num != uri_num) {
716d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%*sUnexpected LogotypeReference array size difference %d != %d\n",
717d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   indent, "", hash_num, uri_num);
718d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
719d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
720d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
721d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < hash_num; i++) {
722d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		HashAlgAndValue *hash;
723d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ASN1_IA5STRING *uri;
724d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
725d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		hash = sk_HashAlgAndValue_value(ref->refStructHash, i);
726d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		i2r_HashAlgAndValue(hash, out, indent);
727d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
728d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		uri = sk_ASN1_IA5STRING_value(ref->refStructURI, i);
729d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%*srefStructURI: ", indent, "");
730d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ASN1_STRING_print(out, uri);
731d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "\n");
732d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
733d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
734d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
735d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void i2r_LogotypeInfo(LogotypeInfo *info, const char *title, BIO *out,
736d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			     int indent)
737d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
738d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	switch (info->type) {
739d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case 0:
740d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		i2r_LogotypeData(info->d.direct, title, out, indent);
741d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
742d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	case 1:
743d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		i2r_LogotypeReference(info->d.indirect, title, out, indent);
744d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		break;
745d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
746d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
747d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
748d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void debug_print_logotypeext(LogotypeExtn *logo)
749d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
750d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO *out;
751d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int i, num;
752d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int indent = 0;
753d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
754d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	out = BIO_new_fp(stdout, BIO_NOCLOSE);
755d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (out == NULL)
756d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
757d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
758d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (logo->communityLogos) {
759d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		num = sk_LogotypeInfo_num(logo->communityLogos);
760d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		for (i = 0; i < num; i++) {
761d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			LogotypeInfo *info;
762d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			info = sk_LogotypeInfo_value(logo->communityLogos, i);
763d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			i2r_LogotypeInfo(info, "communityLogo", out, indent);
764d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		}
765d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
766d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
767d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (logo->issuerLogo) {
768d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		i2r_LogotypeInfo(logo->issuerLogo, "issuerLogo", out, indent );
769d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
770d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
771d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (logo->subjectLogo) {
772d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		i2r_LogotypeInfo(logo->subjectLogo, "subjectLogo", out, indent);
773d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
774d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
775d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (logo->otherLogos) {
776d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_printf(out, "%*sotherLogos - TODO\n", indent, "");
777d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
778d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
779d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_free(out);
780d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
781d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
782d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
783d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void add_logotype_ext(struct http_ctx *ctx, struct http_cert *hcert,
784d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			     X509 *cert)
785d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
786d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_OBJECT *obj;
787d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int pos;
788d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509_EXTENSION *ext;
789d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_OCTET_STRING *os;
790d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeExtn *logo;
791d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	const unsigned char *data;
792d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int i, num;
793d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
794d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	obj = OBJ_txt2obj("1.3.6.1.5.5.7.1.12", 0);
795d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (obj == NULL)
796d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
797d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
798d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	pos = X509_get_ext_by_OBJ(cert, obj, -1);
799d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (pos < 0) {
800d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "No logotype extension included");
801d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
802d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
803d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
804d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_INFO, "Parsing logotype extension");
805d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ext = X509_get_ext(cert, pos);
806d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!ext) {
807d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "Could not get logotype extension");
808d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
809d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
810d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
811d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os = X509_EXTENSION_get_data(ext);
812d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (os == NULL) {
813d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "Could not get logotype extension data");
814d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
815d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
816d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
817d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "logotypeExtn",
818d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		    ASN1_STRING_data(os), ASN1_STRING_length(os));
819d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
820d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	data = ASN1_STRING_data(os);
821d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	logo = d2i_LogotypeExtn(NULL, &data, ASN1_STRING_length(os));
822d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (logo == NULL) {
823d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "Failed to parse logotypeExtn");
824d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
825d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
826d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
827d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (wpa_debug_level < MSG_INFO)
828d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		debug_print_logotypeext(logo);
829d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
830d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!logo->communityLogos) {
831d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "No communityLogos included");
832d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		LogotypeExtn_free(logo);
833d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
834d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
835d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
836d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	num = sk_LogotypeInfo_num(logo->communityLogos);
837d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < num; i++) {
838d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		LogotypeInfo *info;
839d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		info = sk_LogotypeInfo_value(logo->communityLogos, i);
840d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		switch (info->type) {
841d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		case 0:
842d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			add_logo_direct(ctx, hcert, info->d.direct);
843d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			break;
844d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		case 1:
845d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			add_logo_indirect(ctx, hcert, info->d.indirect);
846d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			break;
847d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		}
848d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
849d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
850d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	LogotypeExtn_free(logo);
851d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
852d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
853d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
854d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void parse_cert(struct http_ctx *ctx, struct http_cert *hcert,
855d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		       X509 *cert, GENERAL_NAMES **names)
856d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
857d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_memset(hcert, 0, sizeof(*hcert));
858d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
859d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	*names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
860d5ab1b53af720d05586ccc0addabe93459f1f388Dmitry Shmidt	if (*names)
861d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		add_alt_names(ctx, hcert, *names);
862d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
863d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	add_logotype_ext(ctx, hcert, cert);
864d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
865d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
866d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
867d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void parse_cert_free(struct http_cert *hcert, GENERAL_NAMES *names)
868d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
869d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	unsigned int i;
870d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
871d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < hcert->num_dnsname; i++)
872d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OPENSSL_free(hcert->dnsname[i]);
873d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(hcert->dnsname);
874d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
875d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < hcert->num_othername; i++)
876d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_free(hcert->othername[i].oid);
877d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(hcert->othername);
878d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
879d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < hcert->num_logo; i++) {
880d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_free(hcert->logo[i].alg_oid);
881d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_free(hcert->logo[i].hash);
882d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_free(hcert->logo[i].uri);
883d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
884d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(hcert->logo);
885d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
886d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
887d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
888d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
889d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
890d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic int validate_server_cert(struct http_ctx *ctx, X509 *cert)
891d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
892d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	GENERAL_NAMES *names;
893d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_cert hcert;
894d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int ret;
895d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
896912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	if (ctx->cert_cb == NULL) {
897912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: no cert_cb configured", __func__);
898d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
899912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	}
900d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
901d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (0) {
902d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO *out;
903d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		out = BIO_new_fp(stdout, BIO_NOCLOSE);
904d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		X509_print_ex(out, cert, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
905d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_free(out);
906d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
907d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
908d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	parse_cert(ctx, &hcert, cert, &names);
909d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ret = ctx->cert_cb(ctx->cert_cb_ctx, &hcert);
910d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	parse_cert_free(&hcert, names);
911d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
912d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return ret;
913d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
914d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
915d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
916d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtvoid http_parse_x509_certificate(struct http_ctx *ctx, const char *fname)
917d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
918d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO *in, *out;
919d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509 *cert;
920d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	GENERAL_NAMES *names;
921d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_cert hcert;
922d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	unsigned int i;
923d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
924d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	in = BIO_new_file(fname, "r");
925d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (in == NULL) {
926d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "Could not read '%s'", fname);
927d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
928d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
929d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
930d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	cert = d2i_X509_bio(in, NULL);
931d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_free(in);
932d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
933d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (cert == NULL) {
934d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "Could not parse certificate");
935d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
936d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
937d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
938d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	out = BIO_new_fp(stdout, BIO_NOCLOSE);
939d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (out) {
940d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		X509_print_ex(out, cert, XN_FLAG_COMPAT,
941d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			      X509_FLAG_COMPAT);
942d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_free(out);
943d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
944d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
945d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_INFO, "Additional parsing information:");
946d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	parse_cert(ctx, &hcert, cert, &names);
947d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (i = 0; i < hcert.num_othername; i++) {
948d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (os_strcmp(hcert.othername[i].oid,
949d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			      "1.3.6.1.4.1.40808.1.1.1") == 0) {
950d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			char *name = os_zalloc(hcert.othername[i].len + 1);
951d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			if (name) {
952d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				os_memcpy(name, hcert.othername[i].data,
953d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					  hcert.othername[i].len);
954d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				wpa_printf(MSG_INFO,
955d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					   "id-wfa-hotspot-friendlyName: %s",
956d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					   name);
957d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				os_free(name);
958d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			}
959d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			wpa_hexdump_ascii(MSG_INFO,
960d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					  "id-wfa-hotspot-friendlyName",
961d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					  hcert.othername[i].data,
962d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					  hcert.othername[i].len);
963d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		} else {
964d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			wpa_printf(MSG_INFO, "subjAltName[othername]: oid=%s",
965d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				   hcert.othername[i].oid);
966d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			wpa_hexdump_ascii(MSG_INFO, "unknown othername",
967d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					  hcert.othername[i].data,
968d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					  hcert.othername[i].len);
969d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		}
970d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
971d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	parse_cert_free(&hcert, names);
972d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
973d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509_free(cert);
974d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
975d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
976d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
977d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic int curl_cb_ssl_verify(int preverify_ok, X509_STORE_CTX *x509_ctx)
978d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
979d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_ctx *ctx;
980d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509 *cert;
981d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int err, depth;
982d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char buf[256];
983d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509_NAME *name;
984d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	const char *err_str;
985d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	SSL *ssl;
986d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	SSL_CTX *ssl_ctx;
987d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
988d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
989d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					 SSL_get_ex_data_X509_STORE_CTX_idx());
990d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ssl_ctx = ssl->ctx;
991d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx = SSL_CTX_get_app_data(ssl_ctx);
992d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
993912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify, preverify_ok: %d",
994912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		   preverify_ok);
995d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
996d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	err = X509_STORE_CTX_get_error(x509_ctx);
997d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	err_str = X509_verify_cert_error_string(err);
998d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	depth = X509_STORE_CTX_get_error_depth(x509_ctx);
999d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	cert = X509_STORE_CTX_get_current_cert(x509_ctx);
1000d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!cert) {
1001d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "No server certificate available");
1002d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "No server certificate available";
1003d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1004d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1005d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1006d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (depth == 0)
1007d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->peer_cert = cert;
1008d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	else if (depth == 1)
1009d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->peer_issuer = cert;
1010d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	else if (depth == 2)
1011d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->peer_issuer_issuer = cert;
1012d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1013d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	name = X509_get_subject_name(cert);
1014d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509_NAME_oneline(name, buf, sizeof(buf));
1015d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_INFO, "Server certificate chain - depth=%d err=%d (%s) subject=%s",
1016d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		   depth, err, err_str, buf);
1017d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	debug_dump_cert("Server certificate chain - certificate", cert);
1018d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1019d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (depth == 0 && preverify_ok && validate_server_cert(ctx, cert) < 0)
1020d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1021d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1022d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#ifdef OPENSSL_IS_BORINGSSL
1023d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt	if (depth == 0 && ctx->ocsp != NO_OCSP && preverify_ok) {
1024d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		enum ocsp_result res;
1025d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt
1026d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		res = check_ocsp_resp(ssl_ctx, ssl, cert, ctx->peer_issuer,
1027d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt				      ctx->peer_issuer_issuer);
1028d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		if (res == OCSP_REVOKED) {
1029d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt			preverify_ok = 0;
1030d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt			wpa_printf(MSG_INFO, "OCSP: certificate revoked");
1031d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt			if (err == X509_V_OK)
1032d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt				X509_STORE_CTX_set_error(
1033d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt					x509_ctx, X509_V_ERR_CERT_REVOKED);
1034d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		} else if (res != OCSP_GOOD && (ctx->ocsp == MANDATORY_OCSP)) {
1035d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt			preverify_ok = 0;
1036d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt			wpa_printf(MSG_INFO,
1037d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt				   "OCSP: bad certificate status response");
1038d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		}
1039d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt	}
1040d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#endif /* OPENSSL_IS_BORINGSSL */
1041d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt
1042d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!preverify_ok)
1043d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "TLS validation failed";
1044d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1045d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return preverify_ok;
1046d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1047d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1048d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1049d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#ifdef HAVE_OCSP
1050d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1051d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
1052d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1053d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO *out;
1054d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	size_t rlen;
1055d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *txt;
1056d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int res;
1057d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1058d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	out = BIO_new(BIO_s_mem());
1059d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!out)
1060d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
1061d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1062d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	OCSP_RESPONSE_print(out, rsp, 0);
1063d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	rlen = BIO_ctrl_pending(out);
1064d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	txt = os_malloc(rlen + 1);
1065d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!txt) {
1066d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		BIO_free(out);
1067d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
1068d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1069d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1070d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	res = BIO_read(out, txt, rlen);
1071d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (res > 0) {
1072d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		txt[res] = '\0';
1073d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "OpenSSL: OCSP Response\n%s", txt);
1074d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1075d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(txt);
1076d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	BIO_free(out);
1077d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1078d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1079d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1080d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void tls_show_errors(const char *func, const char *txt)
1081d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1082d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	unsigned long err;
1083d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1084d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: %s - %s %s",
1085d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		   func, txt, ERR_error_string(ERR_get_error(), NULL));
1086d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1087d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	while ((err = ERR_get_error())) {
1088d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: pending error: %s",
1089d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   ERR_error_string(err, NULL));
1090d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1091d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1092d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1093d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1094d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic int ocsp_resp_cb(SSL *s, void *arg)
1095d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1096d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_ctx *ctx = arg;
1097d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	const unsigned char *p;
1098d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int len, status, reason;
1099d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	OCSP_RESPONSE *rsp;
1100d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	OCSP_BASICRESP *basic;
1101d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	OCSP_CERTID *id;
1102d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
1103d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	X509_STORE *store;
1104d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	STACK_OF(X509) *certs = NULL;
1105d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1106d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	len = SSL_get_tlsext_status_ocsp_resp(s, &p);
1107d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!p) {
1108d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
1109d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (ctx->ocsp == MANDATORY_OCSP)
1110d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			ctx->last_err = "No OCSP response received";
1111d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1;
1112d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1113d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1114d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
1115d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1116d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
1117d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!rsp) {
1118d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
1119d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "Failed to parse OCSP response";
1120d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1121d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1122d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1123d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ocsp_debug_print_resp(rsp);
1124d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1125d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	status = OCSP_response_status(rsp);
1126d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
1127d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
1128d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   status, OCSP_response_status_str(status));
1129d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "OCSP responder error";
1130d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1131d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1132d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1133d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	basic = OCSP_response_get1_basic(rsp);
1134d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!basic) {
1135d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
1136d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "Could not find BasicOCSPResponse";
1137d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1138d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1139d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1140d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	store = SSL_CTX_get_cert_store(s->ctx);
1141d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ctx->peer_issuer) {
1142d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Add issuer");
1143d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		debug_dump_cert("OpenSSL: Issuer certificate",
1144d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				ctx->peer_issuer);
1145d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1146d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (X509_STORE_add_cert(store, ctx->peer_issuer) != 1) {
1147d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			tls_show_errors(__func__,
11487f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt					"OpenSSL: Could not add issuer to certificate store");
1149d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		}
1150d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		certs = sk_X509_new_null();
1151d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (certs) {
1152d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			X509 *cert;
1153d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			cert = X509_dup(ctx->peer_issuer);
1154d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			if (cert && !sk_X509_push(certs, cert)) {
1155d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				tls_show_errors(
1156d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					__func__,
11577f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt					"OpenSSL: Could not add issuer to OCSP responder trust store");
1158d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				X509_free(cert);
1159d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				sk_X509_free(certs);
1160d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				certs = NULL;
1161d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			}
11627f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt			if (certs && ctx->peer_issuer_issuer) {
1163d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				cert = X509_dup(ctx->peer_issuer_issuer);
1164d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				if (cert && !sk_X509_push(certs, cert)) {
1165d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					tls_show_errors(
1166d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt						__func__,
11677f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt						"OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
1168d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					X509_free(cert);
1169d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				}
1170d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			}
1171d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		}
1172d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1173d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1174d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
1175d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	sk_X509_pop_free(certs, X509_free);
1176d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (status <= 0) {
1177d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		tls_show_errors(__func__,
1178d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				"OpenSSL: OCSP response failed verification");
1179d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_BASICRESP_free(basic);
1180d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_RESPONSE_free(rsp);
1181d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "OCSP response failed verification";
1182d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1183d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1184d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1185d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
1186d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1187d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!ctx->peer_cert) {
1188d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check");
1189d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_BASICRESP_free(basic);
1190d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_RESPONSE_free(rsp);
1191d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "Peer certificate not available for OCSP status check";
1192d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1193d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1194d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1195d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!ctx->peer_issuer) {
1196d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check");
1197d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_BASICRESP_free(basic);
1198d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_RESPONSE_free(rsp);
1199d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "Peer issuer certificate not available for OCSP status check";
1200d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1201d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1202d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1203d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	id = OCSP_cert_to_id(NULL, ctx->peer_cert, ctx->peer_issuer);
1204d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!id) {
1205d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: Could not create OCSP certificate identifier");
1206d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_BASICRESP_free(basic);
1207d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_RESPONSE_free(rsp);
1208d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "Could not create OCSP certificate identifier";
1209d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1210d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1211d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1212d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
1213d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				   &this_update, &next_update)) {
1214d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
1215d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   (ctx->ocsp == MANDATORY_OCSP) ? "" :
1216d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   " (OCSP not required)");
121757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		OCSP_CERTID_free(id);
1218d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_BASICRESP_free(basic);
1219d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_RESPONSE_free(rsp);
1220d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (ctx->ocsp == MANDATORY_OCSP)
1221d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1222d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			ctx->last_err = "Could not find current server certificate from OCSP response";
1223d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1;
1224d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
122557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	OCSP_CERTID_free(id);
1226d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1227d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
1228d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		tls_show_errors(__func__, "OpenSSL: OCSP status times invalid");
1229d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_BASICRESP_free(basic);
1230d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		OCSP_RESPONSE_free(rsp);
1231d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "OCSP status times invalid";
1232d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1233d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1234d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1235d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	OCSP_BASICRESP_free(basic);
1236d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	OCSP_RESPONSE_free(rsp);
1237d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1238d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
1239d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		   OCSP_cert_status_str(status));
1240d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1241d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (status == V_OCSP_CERTSTATUS_GOOD)
1242d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 1;
1243661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (status == V_OCSP_CERTSTATUS_REVOKED) {
1244d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "Server certificate has been revoked";
1245d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1246661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	}
1247d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ctx->ocsp == MANDATORY_OCSP) {
1248d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
1249d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "OCSP status unknown";
1250d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return 0;
1251d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1252d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue");
1253d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return 1;
1254d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1255d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1256d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1257d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic SSL_METHOD patch_ssl_method;
1258d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic const SSL_METHOD *real_ssl_method;
1259d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1260d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic int curl_patch_ssl_new(SSL *s)
1261d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1262d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	SSL_CTX *ssl = s->ctx;
1263d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int ret;
1264d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1265d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ssl->method = real_ssl_method;
1266d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	s->method = real_ssl_method;
1267d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1268d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ret = s->method->ssl_new(s);
1269d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	SSL_set_tlsext_status_type(s, TLSEXT_STATUSTYPE_ocsp);
1270d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1271d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return ret;
1272d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1273d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1274d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#endif /* HAVE_OCSP */
1275d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1276d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1277d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic CURLcode curl_cb_ssl(CURL *curl, void *sslctx, void *parm)
1278d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1279d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_ctx *ctx = parm;
1280d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	SSL_CTX *ssl = sslctx;
1281d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1282d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "curl_cb_ssl");
1283d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	SSL_CTX_set_app_data(ssl, ctx);
1284d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	SSL_CTX_set_verify(ssl, SSL_VERIFY_PEER, curl_cb_ssl_verify);
1285d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1286d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#ifdef HAVE_OCSP
1287d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ctx->ocsp != NO_OCSP) {
1288d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		SSL_CTX_set_tlsext_status_cb(ssl, ocsp_resp_cb);
1289d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		SSL_CTX_set_tlsext_status_arg(ssl, ctx);
1290d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1291d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		/*
1292d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		 * Use a temporary SSL_METHOD to get a callback on SSL_new()
1293d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		 * from libcurl since there is no proper callback registration
1294d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		 * available for this.
1295d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		 */
1296d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_memset(&patch_ssl_method, 0, sizeof(patch_ssl_method));
1297d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		patch_ssl_method.ssl_new = curl_patch_ssl_new;
1298d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		real_ssl_method = ssl->method;
1299d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ssl->method = &patch_ssl_method;
1300d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1301d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#endif /* HAVE_OCSP */
1302d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1303d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return CURLE_OK;
1304d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1305d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1306d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#endif /* EAP_TLS_OPENSSL */
1307d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1308d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1309d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic CURL * setup_curl_post(struct http_ctx *ctx, const char *address,
1310d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			      const char *ca_fname, const char *username,
1311d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			      const char *password, const char *client_cert,
1312d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			      const char *client_key)
1313d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1314d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	CURL *curl;
1315912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt#ifdef EAP_TLS_OPENSSL
1316912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	const char *extra = " tls=openssl";
1317912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt#else /* EAP_TLS_OPENSSL */
1318912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt	const char *extra = "";
1319912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt#endif /* EAP_TLS_OPENSSL */
1320d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1321d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "Start HTTP client: address=%s ca_fname=%s "
1322912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt		   "username=%s%s", address, ca_fname, username, extra);
1323d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1324d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl = curl_easy_init();
1325d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (curl == NULL)
1326d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1327d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1328d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_URL, address);
1329d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_POST, 1L);
1330d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ca_fname) {
1331d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_CAINFO, ca_fname);
1332d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
1333d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#ifdef EAP_TLS_OPENSSL
1334d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, curl_cb_ssl);
1335d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, ctx);
1336d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#ifdef OPENSSL_IS_BORINGSSL
1337d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		/* For now, using the CURLOPT_SSL_VERIFYSTATUS option only
1338d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		 * with BoringSSL since the OpenSSL specific callback hack to
1339d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		 * enable OCSP is not available with BoringSSL. The OCSP
1340d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		 * implementation within libcurl is not sufficient for the
1341d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		 * Hotspot 2.0 OSU needs, so cannot use this with OpenSSL.
1342d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		 */
1343d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		if (ctx->ocsp != NO_OCSP)
1344d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt			curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
1345d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt#endif /* OPENSSL_IS_BORINGSSL */
1346d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#endif /* EAP_TLS_OPENSSL */
1347d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	} else {
1348d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
1349d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1350d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (client_cert && client_key) {
1351d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert);
1352d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_SSLKEY, client_key);
1353d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1354d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	/* TODO: use curl_easy_getinfo() with CURLINFO_CERTINFO to fetch
1355d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	 * information about the server certificate */
1356d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
1357d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_cb_debug);
1358d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_DEBUGDATA, ctx);
1359d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_cb_write);
1360d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx);
1361d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
1362d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (username) {
1363d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
1364d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_USERNAME, username);
1365d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_PASSWORD, password);
1366d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1367d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1368d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return curl;
1369d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1370d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1371d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1372d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic int post_init_client(struct http_ctx *ctx, const char *address,
1373d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			    const char *ca_fname, const char *username,
1374d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			    const char *password, const char *client_cert,
1375d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			    const char *client_key)
1376d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1377d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *pos;
1378d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int count;
1379d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1380d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&ctx->svc_address, address);
1381d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&ctx->svc_ca_fname, ca_fname);
1382d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&ctx->svc_username, username);
1383d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&ctx->svc_password, password);
1384d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&ctx->svc_client_cert, client_cert);
1385d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&ctx->svc_client_key, client_key);
1386d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1387d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	/*
1388d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	 * Workaround for Apache "Hostname 'FOO' provided via SNI and hostname
1389d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	 * 'foo' provided via HTTP are different.
1390d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	 */
1391d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	for (count = 0, pos = ctx->svc_address; count < 3 && pos && *pos;
1392d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	     pos++) {
1393d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (*pos == '/')
1394d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			count++;
1395d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		*pos = tolower(*pos);
1396d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1397d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1398d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl = setup_curl_post(ctx, ctx->svc_address, ca_fname, username,
1399d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt				    password, client_cert, client_key);
1400d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ctx->curl == NULL)
1401d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
1402d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1403d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return 0;
1404d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1405d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1406d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1407d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtint soap_init_client(struct http_ctx *ctx, const char *address,
1408d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		     const char *ca_fname, const char *username,
1409d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		     const char *password, const char *client_cert,
1410d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		     const char *client_key)
1411d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1412d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (post_init_client(ctx, address, ca_fname, username, password,
1413d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			     client_cert, client_key) < 0)
1414d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
1415d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1416d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl_hdr = curl_slist_append(ctx->curl_hdr,
1417d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt					  "Content-Type: application/soap+xml");
1418d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl_hdr = curl_slist_append(ctx->curl_hdr, "SOAPAction: ");
1419d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl_hdr = curl_slist_append(ctx->curl_hdr, "Expect:");
1420d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(ctx->curl, CURLOPT_HTTPHEADER, ctx->curl_hdr);
1421d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1422d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return 0;
1423d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1424d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1425d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1426d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtint soap_reinit_client(struct http_ctx *ctx)
1427d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1428d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *address = NULL;
1429d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *ca_fname = NULL;
1430d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *username = NULL;
1431d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *password = NULL;
1432d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *client_cert = NULL;
1433d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *client_key = NULL;
1434d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int ret;
1435d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1436d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clear_curl(ctx);
1437d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1438d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&address, ctx->svc_address);
1439d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&ca_fname, ctx->svc_ca_fname);
1440d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&username, ctx->svc_username);
1441d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&password, ctx->svc_password);
1442d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&client_cert, ctx->svc_client_cert);
1443d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clone_str(&client_key, ctx->svc_client_key);
1444d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1445d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ret = soap_init_client(ctx, address, ca_fname, username, password,
1446d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			       client_cert, client_key);
1447d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(address);
1448d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(ca_fname);
1449c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	str_clear_free(username);
1450c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	str_clear_free(password);
1451d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(client_cert);
1452d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(client_key);
1453d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return ret;
1454d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1455d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1456d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1457d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void free_curl_buf(struct http_ctx *ctx)
1458d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1459d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(ctx->curl_buf);
1460d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl_buf = NULL;
1461d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl_buf_len = 0;
1462d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1463d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1464d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1465d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtxml_node_t * soap_send_receive(struct http_ctx *ctx, xml_node_t *node)
1466d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1467d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *str;
1468d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	xml_node_t *envelope, *ret, *resp, *n;
1469d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	CURLcode res;
1470d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	long http = 0;
1471d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1472d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->last_err = NULL;
1473d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1474d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "SOAP: Sending message");
1475d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	envelope = soap_build_envelope(ctx->xml, node);
1476d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	str = xml_node_to_str(ctx->xml, envelope);
1477d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	xml_node_free(ctx->xml, envelope);
1478d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "SOAP[%s]", str);
1479d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1480d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(ctx->curl, CURLOPT_POSTFIELDS, str);
1481d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	free_curl_buf(ctx);
1482d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1483d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	res = curl_easy_perform(ctx->curl);
1484d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (res != CURLE_OK) {
1485d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (!ctx->last_err)
1486d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			ctx->last_err = curl_easy_strerror(res);
1487d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s",
1488d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   ctx->last_err);
1489d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		os_free(str);
1490d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		free_curl_buf(ctx);
1491d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1492d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1493d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(str);
1494d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1495d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_getinfo(ctx->curl, CURLINFO_RESPONSE_CODE, &http);
1496d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "SOAP: Server response code %ld", http);
1497d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (http != 200) {
1498d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "HTTP download failed";
1499d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "HTTP download failed - code %ld", http);
1500d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		free_curl_buf(ctx);
1501d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1502d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1503d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1504d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ctx->curl_buf == NULL)
1505d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1506d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1507d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Server response:\n%s", ctx->curl_buf);
1508d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	resp = xml_node_from_buf(ctx->xml, ctx->curl_buf);
1509d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	free_curl_buf(ctx);
1510d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (resp == NULL) {
1511d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "Could not parse SOAP response");
1512d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "Could not parse SOAP response";
1513d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1514d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1515d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1516d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ret = soap_get_body(ctx->xml, resp);
1517d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ret == NULL) {
1518d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "Could not get SOAP body");
1519d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "Could not get SOAP body";
1520d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1521d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1522d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1523d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "SOAP body localname: '%s'",
1524d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		   xml_node_get_localname(ctx->xml, ret));
1525d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	n = xml_node_copy(ctx->xml, ret);
1526d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	xml_node_free(ctx->xml, resp);
1527d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1528d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return n;
1529d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1530d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1531d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1532d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstruct http_ctx * http_init_ctx(void *upper_ctx, struct xml_node_ctx *xml_ctx)
1533d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1534d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_ctx *ctx;
1535d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1536d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
1537d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ctx == NULL)
1538d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1539d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->ctx = upper_ctx;
1540d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->xml = xml_ctx;
1541d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->ocsp = OPTIONAL_OCSP;
1542d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1543d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_global_init(CURL_GLOBAL_ALL);
1544d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1545d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return ctx;
1546d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1547d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1548d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1549d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtvoid http_ocsp_set(struct http_ctx *ctx, int val)
1550d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1551d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (val == 0)
1552d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->ocsp = NO_OCSP;
1553d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	else if (val == 1)
1554d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->ocsp = OPTIONAL_OCSP;
1555d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (val == 2)
1556d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->ocsp = MANDATORY_OCSP;
1557d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1558d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1559d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1560d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtvoid http_deinit_ctx(struct http_ctx *ctx)
1561d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1562d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	clear_curl(ctx);
1563d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(ctx->curl_buf);
1564d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_global_cleanup();
1565d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1566d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(ctx->svc_address);
1567d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(ctx->svc_ca_fname);
1568c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	str_clear_free(ctx->svc_username);
1569c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	str_clear_free(ctx->svc_password);
1570d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(ctx->svc_client_cert);
1571d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(ctx->svc_client_key);
1572d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1573d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_free(ctx);
1574d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1575d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1576d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1577d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtint http_download_file(struct http_ctx *ctx, const char *url,
1578d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		       const char *fname, const char *ca_fname)
1579d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1580d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	CURL *curl;
1581d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	FILE *f;
1582d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	CURLcode res;
1583d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	long http = 0;
1584d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1585d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->last_err = NULL;
1586d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1587d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "curl: Download file from %s to %s (ca=%s)",
1588d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		   url, fname, ca_fname);
1589d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl = curl_easy_init();
1590d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (curl == NULL)
1591d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
1592d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1593d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	f = fopen(fname, "wb");
1594d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (f == NULL) {
1595d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_cleanup(curl);
1596d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
1597d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1598d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1599d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_URL, url);
1600d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ca_fname) {
1601d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_CAINFO, ca_fname);
1602d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
1603d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
1604d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	} else {
1605d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
1606d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1607d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_cb_debug);
1608d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_DEBUGDATA, ctx);
1609d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
1610d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_WRITEDATA, f);
1611d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
1612d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1613d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	res = curl_easy_perform(curl);
1614d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (res != CURLE_OK) {
1615d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (!ctx->last_err)
1616d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			ctx->last_err = curl_easy_strerror(res);
1617d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s",
1618d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   ctx->last_err);
1619d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_cleanup(curl);
1620d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		fclose(f);
1621d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
1622d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1623d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1624d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http);
1625d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "curl: Server response code %ld", http);
1626d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (http != 200) {
1627d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "HTTP download failed";
1628d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "HTTP download failed - code %ld", http);
1629d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_easy_cleanup(curl);
1630d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		fclose(f);
1631d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
1632d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1633d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1634d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_cleanup(curl);
1635d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	fclose(f);
1636d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1637d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return 0;
1638d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1639d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1640d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1641d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtchar * http_post(struct http_ctx *ctx, const char *url, const char *data,
1642d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		 const char *content_type, const char *ext_hdr,
1643d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		 const char *ca_fname,
1644d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		 const char *username, const char *password,
1645d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		 const char *client_cert, const char *client_key,
1646d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		 size_t *resp_len)
1647d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1648d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	long http = 0;
1649d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	CURLcode res;
1650d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char *ret;
1651d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	CURL *curl;
1652d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct curl_slist *curl_hdr = NULL;
1653d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1654d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->last_err = NULL;
1655d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "curl: HTTP POST to %s", url);
1656d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl = setup_curl_post(ctx, url, ca_fname, username, password,
1657d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			       client_cert, client_key);
1658d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (curl == NULL)
1659d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1660d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1661d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (content_type) {
1662d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		char ct[200];
1663d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		snprintf(ct, sizeof(ct), "Content-Type: %s", content_type);
1664d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_hdr = curl_slist_append(curl_hdr, ct);
1665d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1666d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ext_hdr)
1667d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		curl_hdr = curl_slist_append(curl_hdr, ext_hdr);
1668d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_hdr);
1669d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1670d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
1671d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	free_curl_buf(ctx);
1672d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1673d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	res = curl_easy_perform(curl);
1674d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (res != CURLE_OK) {
1675d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (!ctx->last_err)
1676d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			ctx->last_err = curl_easy_strerror(res);
1677d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s",
1678d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			   ctx->last_err);
1679d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		free_curl_buf(ctx);
1680d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1681d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1682d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1683d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http);
1684d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_DEBUG, "curl: Server response code %ld", http);
1685d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (http != 200) {
1686d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		ctx->last_err = "HTTP POST failed";
1687d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "HTTP POST failed - code %ld", http);
1688d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		free_curl_buf(ctx);
1689d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1690d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
1691d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1692d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ctx->curl_buf == NULL)
1693d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return NULL;
1694d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1695d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ret = ctx->curl_buf;
1696d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (resp_len)
1697d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		*resp_len = ctx->curl_buf_len;
1698d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl_buf = NULL;
1699d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->curl_buf_len = 0;
1700d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1701d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Server response:\n%s", ret);
1702d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1703d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return ret;
1704d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1705d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1706d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1707d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtvoid http_set_cert_cb(struct http_ctx *ctx,
1708d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		      int (*cb)(void *ctx, struct http_cert *cert),
1709d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		      void *cb_ctx)
1710d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1711d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->cert_cb = cb;
1712d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ctx->cert_cb_ctx = cb_ctx;
1713d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1714d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1715d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
1716d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtconst char * http_get_err(struct http_ctx *ctx)
1717d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
1718d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return ctx->last_err;
1719d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
1720