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