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