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