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 struct 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 *curl_buf;
41 	size_t curl_buf_len;
42 
43 	enum {
44 		NO_OCSP, OPTIONAL_OCSP, MANDATORY_OCSP
45 	} ocsp;
46 	X509 *peer_cert;
47 	X509 *peer_issuer;
48 	X509 *peer_issuer_issuer;
49 
50 	const char *last_err;
51 	const char *url;
52 };
53 
54 
clear_curl(struct http_ctx * ctx)55 static void clear_curl(struct http_ctx *ctx)
56 {
57 	if (ctx->curl) {
58 		curl_easy_cleanup(ctx->curl);
59 		ctx->curl = NULL;
60 	}
61 	if (ctx->curl_hdr) {
62 		curl_slist_free_all(ctx->curl_hdr);
63 		ctx->curl_hdr = NULL;
64 	}
65 }
66 
67 
debug_dump(struct http_ctx * ctx,const char * title,const char * buf,size_t len)68 static void debug_dump(struct http_ctx *ctx, const char *title,
69 		       const char *buf, size_t len)
70 {
71 	char *txt;
72 	size_t i;
73 
74 	for (i = 0; i < len; i++) {
75 		if (buf[i] < 32 && buf[i] != '\t' && buf[i] != '\n' &&
76 		    buf[i] != '\r') {
77 			wpa_hexdump_ascii(MSG_MSGDUMP, title, buf, len);
78 			return;
79 		}
80 	}
81 
82 	txt = os_malloc(len + 1);
83 	if (txt == NULL)
84 		return;
85 	os_memcpy(txt, buf, len);
86 	txt[len] = '\0';
87 	while (len > 0) {
88 		len--;
89 		if (txt[len] == '\n' || txt[len] == '\r')
90 			txt[len] = '\0';
91 		else
92 			break;
93 	}
94 	wpa_printf(MSG_MSGDUMP, "%s[%s]", title, txt);
95 	os_free(txt);
96 }
97 
98 
curl_cb_debug(CURL * curl,curl_infotype info,char * buf,size_t len,void * userdata)99 static int curl_cb_debug(CURL *curl, curl_infotype info, char *buf, size_t len,
100 			 void *userdata)
101 {
102 	struct http_ctx *ctx = userdata;
103 	switch (info) {
104 	case CURLINFO_TEXT:
105 		debug_dump(ctx, "CURLINFO_TEXT", buf, len);
106 		break;
107 	case CURLINFO_HEADER_IN:
108 		debug_dump(ctx, "CURLINFO_HEADER_IN", buf, len);
109 		break;
110 	case CURLINFO_HEADER_OUT:
111 		debug_dump(ctx, "CURLINFO_HEADER_OUT", buf, len);
112 		break;
113 	case CURLINFO_DATA_IN:
114 		debug_dump(ctx, "CURLINFO_DATA_IN", buf, len);
115 		break;
116 	case CURLINFO_DATA_OUT:
117 		debug_dump(ctx, "CURLINFO_DATA_OUT", buf, len);
118 		break;
119 	case CURLINFO_SSL_DATA_IN:
120 		wpa_printf(MSG_DEBUG, "debug - CURLINFO_SSL_DATA_IN - %d",
121 			   (int) len);
122 		break;
123 	case CURLINFO_SSL_DATA_OUT:
124 		wpa_printf(MSG_DEBUG, "debug - CURLINFO_SSL_DATA_OUT - %d",
125 			   (int) len);
126 		break;
127 	case CURLINFO_END:
128 		wpa_printf(MSG_DEBUG, "debug - CURLINFO_END - %d",
129 			   (int) len);
130 		break;
131 	}
132 	return 0;
133 }
134 
135 
curl_cb_write(void * ptr,size_t size,size_t nmemb,void * userdata)136 static size_t curl_cb_write(void *ptr, size_t size, size_t nmemb,
137 			    void *userdata)
138 {
139 	struct http_ctx *ctx = userdata;
140 	char *n;
141 	n = os_realloc(ctx->curl_buf, ctx->curl_buf_len + size * nmemb + 1);
142 	if (n == NULL)
143 		return 0;
144 	ctx->curl_buf = n;
145 	os_memcpy(n + ctx->curl_buf_len, ptr, size * nmemb);
146 	n[ctx->curl_buf_len + size * nmemb] = '\0';
147 	ctx->curl_buf_len += size * nmemb;
148 	return size * nmemb;
149 }
150 
151 
152 #ifdef EAP_TLS_OPENSSL
153 
debug_dump_cert(const char * title,X509 * cert)154 static void debug_dump_cert(const char *title, X509 *cert)
155 {
156 	BIO *out;
157 	char *txt;
158 	size_t rlen;
159 
160 	out = BIO_new(BIO_s_mem());
161 	if (!out)
162 		return;
163 
164 	X509_print_ex(out, cert, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
165 	rlen = BIO_ctrl_pending(out);
166 	txt = os_malloc(rlen + 1);
167 	if (txt) {
168 		int res = BIO_read(out, txt, rlen);
169 		if (res > 0) {
170 			txt[res] = '\0';
171 			wpa_printf(MSG_MSGDUMP, "%s:\n%s", title, txt);
172 		}
173 		os_free(txt);
174 	}
175 	BIO_free(out);
176 }
177 
178 
curl_cb_ssl_verify(int preverify_ok,X509_STORE_CTX * x509_ctx)179 static int curl_cb_ssl_verify(int preverify_ok, X509_STORE_CTX *x509_ctx)
180 {
181 	struct http_ctx *ctx;
182 	X509 *cert;
183 	int err, depth;
184 	char buf[256];
185 	X509_NAME *name;
186 	const char *err_str;
187 	SSL *ssl;
188 	SSL_CTX *ssl_ctx;
189 
190 	ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
191 					 SSL_get_ex_data_X509_STORE_CTX_idx());
192 	ssl_ctx = SSL_get_SSL_CTX(ssl);
193 	ctx = SSL_CTX_get_app_data(ssl_ctx);
194 
195 	wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify, preverify_ok: %d",
196 		   preverify_ok);
197 
198 	err = X509_STORE_CTX_get_error(x509_ctx);
199 	err_str = X509_verify_cert_error_string(err);
200 	depth = X509_STORE_CTX_get_error_depth(x509_ctx);
201 	cert = X509_STORE_CTX_get_current_cert(x509_ctx);
202 	if (!cert) {
203 		wpa_printf(MSG_INFO, "No server certificate available");
204 		ctx->last_err = "No server certificate available";
205 		return 0;
206 	}
207 
208 	if (depth == 0)
209 		ctx->peer_cert = cert;
210 	else if (depth == 1)
211 		ctx->peer_issuer = cert;
212 	else if (depth == 2)
213 		ctx->peer_issuer_issuer = cert;
214 
215 	name = X509_get_subject_name(cert);
216 	X509_NAME_oneline(name, buf, sizeof(buf));
217 	wpa_printf(MSG_INFO, "Server certificate chain - depth=%d err=%d (%s) subject=%s",
218 		   depth, err, err_str, buf);
219 	debug_dump_cert("Server certificate chain - certificate", cert);
220 
221 #ifdef OPENSSL_IS_BORINGSSL
222 	if (depth == 0 && ctx->ocsp != NO_OCSP && preverify_ok) {
223 		enum ocsp_result res;
224 
225 		res = check_ocsp_resp(ssl_ctx, ssl, cert, ctx->peer_issuer,
226 				      ctx->peer_issuer_issuer);
227 		if (res == OCSP_REVOKED) {
228 			preverify_ok = 0;
229 			wpa_printf(MSG_INFO, "OCSP: certificate revoked");
230 			if (err == X509_V_OK)
231 				X509_STORE_CTX_set_error(
232 					x509_ctx, X509_V_ERR_CERT_REVOKED);
233 		} else if (res != OCSP_GOOD && (ctx->ocsp == MANDATORY_OCSP)) {
234 			preverify_ok = 0;
235 			wpa_printf(MSG_INFO,
236 				   "OCSP: bad certificate status response");
237 		}
238 	}
239 #endif /* OPENSSL_IS_BORINGSSL */
240 
241 	if (!preverify_ok)
242 		ctx->last_err = "TLS validation failed";
243 
244 	return preverify_ok;
245 }
246 
247 
248 #ifdef HAVE_OCSP
249 
ocsp_debug_print_resp(OCSP_RESPONSE * rsp)250 static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
251 {
252 	BIO *out;
253 	size_t rlen;
254 	char *txt;
255 	int res;
256 
257 	out = BIO_new(BIO_s_mem());
258 	if (!out)
259 		return;
260 
261 	OCSP_RESPONSE_print(out, rsp, 0);
262 	rlen = BIO_ctrl_pending(out);
263 	txt = os_malloc(rlen + 1);
264 	if (!txt) {
265 		BIO_free(out);
266 		return;
267 	}
268 
269 	res = BIO_read(out, txt, rlen);
270 	if (res > 0) {
271 		txt[res] = '\0';
272 		wpa_printf(MSG_MSGDUMP, "OpenSSL: OCSP Response\n%s", txt);
273 	}
274 	os_free(txt);
275 	BIO_free(out);
276 }
277 
278 
tls_show_errors(const char * func,const char * txt)279 static void tls_show_errors(const char *func, const char *txt)
280 {
281 	unsigned long err;
282 
283 	wpa_printf(MSG_DEBUG, "OpenSSL: %s - %s %s",
284 		   func, txt, ERR_error_string(ERR_get_error(), NULL));
285 
286 	while ((err = ERR_get_error())) {
287 		wpa_printf(MSG_DEBUG, "OpenSSL: pending error: %s",
288 			   ERR_error_string(err, NULL));
289 	}
290 }
291 
292 
ocsp_resp_cb(SSL * s,void * arg)293 static int ocsp_resp_cb(SSL *s, void *arg)
294 {
295 	struct http_ctx *ctx = arg;
296 	const unsigned char *p;
297 	int len, status, reason, res;
298 	OCSP_RESPONSE *rsp;
299 	OCSP_BASICRESP *basic;
300 	OCSP_CERTID *id;
301 	ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
302 	X509_STORE *store;
303 	STACK_OF(X509) *certs = NULL;
304 
305 	len = SSL_get_tlsext_status_ocsp_resp(s, &p);
306 	if (!p) {
307 		wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
308 		if (ctx->ocsp == MANDATORY_OCSP)
309 			ctx->last_err = "No OCSP response received";
310 		return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1;
311 	}
312 
313 	wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
314 
315 	rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
316 	if (!rsp) {
317 		wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
318 		ctx->last_err = "Failed to parse OCSP response";
319 		return 0;
320 	}
321 
322 	ocsp_debug_print_resp(rsp);
323 
324 	status = OCSP_response_status(rsp);
325 	if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
326 		wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
327 			   status, OCSP_response_status_str(status));
328 		ctx->last_err = "OCSP responder error";
329 		return 0;
330 	}
331 
332 	basic = OCSP_response_get1_basic(rsp);
333 	if (!basic) {
334 		wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
335 		ctx->last_err = "Could not find BasicOCSPResponse";
336 		return 0;
337 	}
338 
339 	store = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s));
340 	if (ctx->peer_issuer) {
341 		wpa_printf(MSG_DEBUG, "OpenSSL: Add issuer");
342 		debug_dump_cert("OpenSSL: Issuer certificate",
343 				ctx->peer_issuer);
344 
345 		if (X509_STORE_add_cert(store, ctx->peer_issuer) != 1) {
346 			tls_show_errors(__func__,
347 					"OpenSSL: Could not add issuer to certificate store");
348 		}
349 		certs = sk_X509_new_null();
350 		if (certs) {
351 			X509 *cert;
352 			cert = X509_dup(ctx->peer_issuer);
353 			if (cert && !sk_X509_push(certs, cert)) {
354 				tls_show_errors(
355 					__func__,
356 					"OpenSSL: Could not add issuer to OCSP responder trust store");
357 				X509_free(cert);
358 				sk_X509_free(certs);
359 				certs = NULL;
360 			}
361 			if (certs && ctx->peer_issuer_issuer) {
362 				cert = X509_dup(ctx->peer_issuer_issuer);
363 				if (cert && !sk_X509_push(certs, cert)) {
364 					tls_show_errors(
365 						__func__,
366 						"OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
367 					X509_free(cert);
368 				}
369 			}
370 		}
371 	}
372 
373 	status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
374 	sk_X509_pop_free(certs, X509_free);
375 	if (status <= 0) {
376 		tls_show_errors(__func__,
377 				"OpenSSL: OCSP response failed verification");
378 		OCSP_BASICRESP_free(basic);
379 		OCSP_RESPONSE_free(rsp);
380 		ctx->last_err = "OCSP response failed verification";
381 		return 0;
382 	}
383 
384 	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
385 
386 	if (!ctx->peer_cert) {
387 		wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check");
388 		OCSP_BASICRESP_free(basic);
389 		OCSP_RESPONSE_free(rsp);
390 		ctx->last_err = "Peer certificate not available for OCSP status check";
391 		return 0;
392 	}
393 
394 	if (!ctx->peer_issuer) {
395 		wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check");
396 		OCSP_BASICRESP_free(basic);
397 		OCSP_RESPONSE_free(rsp);
398 		ctx->last_err = "Peer issuer certificate not available for OCSP status check";
399 		return 0;
400 	}
401 
402 	id = OCSP_cert_to_id(EVP_sha256(), ctx->peer_cert, ctx->peer_issuer);
403 	if (!id) {
404 		wpa_printf(MSG_DEBUG,
405 			   "OpenSSL: Could not create OCSP certificate identifier (SHA256)");
406 		OCSP_BASICRESP_free(basic);
407 		OCSP_RESPONSE_free(rsp);
408 		ctx->last_err = "Could not create OCSP certificate identifier";
409 		return 0;
410 	}
411 
412 	res = OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
413 				    &this_update, &next_update);
414 	if (!res) {
415 		id = OCSP_cert_to_id(NULL, ctx->peer_cert, ctx->peer_issuer);
416 		if (!id) {
417 			wpa_printf(MSG_DEBUG,
418 				   "OpenSSL: Could not create OCSP certificate identifier (SHA1)");
419 			OCSP_BASICRESP_free(basic);
420 			OCSP_RESPONSE_free(rsp);
421 			ctx->last_err =
422 				"Could not create OCSP certificate identifier";
423 			return 0;
424 		}
425 
426 		res = OCSP_resp_find_status(basic, id, &status, &reason,
427 					    &produced_at, &this_update,
428 					    &next_update);
429 	}
430 
431 	if (!res) {
432 		wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
433 			   (ctx->ocsp == MANDATORY_OCSP) ? "" :
434 			   " (OCSP not required)");
435 		OCSP_CERTID_free(id);
436 		OCSP_BASICRESP_free(basic);
437 		OCSP_RESPONSE_free(rsp);
438 		if (ctx->ocsp == MANDATORY_OCSP)
439 
440 			ctx->last_err = "Could not find current server certificate from OCSP response";
441 		return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1;
442 	}
443 	OCSP_CERTID_free(id);
444 
445 	if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
446 		tls_show_errors(__func__, "OpenSSL: OCSP status times invalid");
447 		OCSP_BASICRESP_free(basic);
448 		OCSP_RESPONSE_free(rsp);
449 		ctx->last_err = "OCSP status times invalid";
450 		return 0;
451 	}
452 
453 	OCSP_BASICRESP_free(basic);
454 	OCSP_RESPONSE_free(rsp);
455 
456 	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
457 		   OCSP_cert_status_str(status));
458 
459 	if (status == V_OCSP_CERTSTATUS_GOOD)
460 		return 1;
461 	if (status == V_OCSP_CERTSTATUS_REVOKED) {
462 		ctx->last_err = "Server certificate has been revoked";
463 		return 0;
464 	}
465 	if (ctx->ocsp == MANDATORY_OCSP) {
466 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
467 		ctx->last_err = "OCSP status unknown";
468 		return 0;
469 	}
470 	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue");
471 	return 1;
472 }
473 
474 
475 #if OPENSSL_VERSION_NUMBER < 0x10100000L
476 static SSL_METHOD patch_ssl_method;
477 static const SSL_METHOD *real_ssl_method;
478 
curl_patch_ssl_new(SSL * s)479 static int curl_patch_ssl_new(SSL *s)
480 {
481 	SSL_CTX *ssl = SSL_get_SSL_CTX(s);
482 	int ret;
483 
484 	ssl->method = real_ssl_method;
485 	s->method = real_ssl_method;
486 
487 	ret = s->method->ssl_new(s);
488 	SSL_set_tlsext_status_type(s, TLSEXT_STATUSTYPE_ocsp);
489 
490 	return ret;
491 }
492 #endif /* OpenSSL < 1.1.0 */
493 
494 #endif /* HAVE_OCSP */
495 
496 
curl_cb_ssl(CURL * curl,void * sslctx,void * parm)497 static CURLcode curl_cb_ssl(CURL *curl, void *sslctx, void *parm)
498 {
499 	struct http_ctx *ctx = parm;
500 	SSL_CTX *ssl = sslctx;
501 
502 	wpa_printf(MSG_DEBUG, "curl_cb_ssl");
503 	SSL_CTX_set_app_data(ssl, ctx);
504 	SSL_CTX_set_verify(ssl, SSL_VERIFY_PEER, curl_cb_ssl_verify);
505 
506 #ifdef HAVE_OCSP
507 	if (ctx->ocsp != NO_OCSP) {
508 		SSL_CTX_set_tlsext_status_cb(ssl, ocsp_resp_cb);
509 		SSL_CTX_set_tlsext_status_arg(ssl, ctx);
510 
511 #if OPENSSL_VERSION_NUMBER < 0x10100000L
512 		/*
513 		 * Use a temporary SSL_METHOD to get a callback on SSL_new()
514 		 * from libcurl since there is no proper callback registration
515 		 * available for this.
516 		 */
517 		os_memset(&patch_ssl_method, 0, sizeof(patch_ssl_method));
518 		patch_ssl_method.ssl_new = curl_patch_ssl_new;
519 		real_ssl_method = ssl->method;
520 		ssl->method = &patch_ssl_method;
521 #endif /* OpenSSL < 1.1.0 */
522 	}
523 #endif /* HAVE_OCSP */
524 
525 	return CURLE_OK;
526 }
527 
528 #endif /* EAP_TLS_OPENSSL */
529 
530 
setup_curl_post(struct http_ctx * ctx,const char * address,const char * ca_fname,const char * username,const char * password,const char * client_cert,const char * client_key)531 static CURL * setup_curl_post(struct http_ctx *ctx, const char *address,
532 			      const char *ca_fname, const char *username,
533 			      const char *password, const char *client_cert,
534 			      const char *client_key)
535 {
536 	CURL *curl;
537 #ifdef EAP_TLS_OPENSSL
538 	const char *extra = " tls=openssl";
539 #else /* EAP_TLS_OPENSSL */
540 	const char *extra = "";
541 #endif /* EAP_TLS_OPENSSL */
542 
543 	wpa_printf(MSG_DEBUG, "Start HTTP client: address=%s ca_fname=%s "
544 		   "username=%s%s", address, ca_fname, username, extra);
545 
546 	curl = curl_easy_init();
547 	if (curl == NULL)
548 		return NULL;
549 
550 	curl_easy_setopt(curl, CURLOPT_URL, address);
551 	curl_easy_setopt(curl, CURLOPT_POST, 1L);
552 	if (ca_fname) {
553 		curl_easy_setopt(curl, CURLOPT_CAINFO, ca_fname);
554 		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
555 #ifdef EAP_TLS_OPENSSL
556 		curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, curl_cb_ssl);
557 		curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, ctx);
558 #if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10100000L)
559 		/* For now, using the CURLOPT_SSL_VERIFYSTATUS option only
560 		 * with BoringSSL since the OpenSSL specific callback hack to
561 		 * enable OCSP is not available with BoringSSL. The OCSP
562 		 * implementation within libcurl is not sufficient for the
563 		 * Hotspot 2.0 OSU needs, so cannot use this with OpenSSL.
564 		 */
565 		if (ctx->ocsp != NO_OCSP)
566 			curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
567 #endif /* OPENSSL_IS_BORINGSSL */
568 #endif /* EAP_TLS_OPENSSL */
569 	} else {
570 		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
571 	}
572 	if (client_cert && client_key) {
573 		curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert);
574 		curl_easy_setopt(curl, CURLOPT_SSLKEY, client_key);
575 	}
576 	/* TODO: use curl_easy_getinfo() with CURLINFO_CERTINFO to fetch
577 	 * information about the server certificate */
578 	curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
579 	curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_cb_debug);
580 	curl_easy_setopt(curl, CURLOPT_DEBUGDATA, ctx);
581 	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_cb_write);
582 	curl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx);
583 	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
584 	if (username) {
585 		curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
586 		curl_easy_setopt(curl, CURLOPT_USERNAME, username);
587 		curl_easy_setopt(curl, CURLOPT_PASSWORD, password);
588 	}
589 
590 	return curl;
591 }
592 
593 
free_curl_buf(struct http_ctx * ctx)594 static void free_curl_buf(struct http_ctx *ctx)
595 {
596 	os_free(ctx->curl_buf);
597 	ctx->curl_buf = NULL;
598 	ctx->curl_buf_len = 0;
599 }
600 
601 
http_init_ctx(void * upper_ctx,struct xml_node_ctx * xml_ctx)602 struct http_ctx * http_init_ctx(void *upper_ctx, struct xml_node_ctx *xml_ctx)
603 {
604 	struct http_ctx *ctx;
605 
606 	ctx = os_zalloc(sizeof(*ctx));
607 	if (ctx == NULL)
608 		return NULL;
609 	ctx->ctx = upper_ctx;
610 	ctx->xml = xml_ctx;
611 	ctx->ocsp = OPTIONAL_OCSP;
612 
613 	curl_global_init(CURL_GLOBAL_ALL);
614 
615 	return ctx;
616 }
617 
618 
http_ocsp_set(struct http_ctx * ctx,int val)619 void http_ocsp_set(struct http_ctx *ctx, int val)
620 {
621 	if (val == 0)
622 		ctx->ocsp = NO_OCSP;
623 	else if (val == 1)
624 		ctx->ocsp = OPTIONAL_OCSP;
625 	if (val == 2)
626 		ctx->ocsp = MANDATORY_OCSP;
627 }
628 
629 
http_deinit_ctx(struct http_ctx * ctx)630 void http_deinit_ctx(struct http_ctx *ctx)
631 {
632 	clear_curl(ctx);
633 	os_free(ctx->curl_buf);
634 	curl_global_cleanup();
635 
636 	os_free(ctx->svc_address);
637 
638 	os_free(ctx);
639 }
640 
641 
http_download_file(struct http_ctx * ctx,const char * url,const char * fname,const char * ca_fname)642 int http_download_file(struct http_ctx *ctx, const char *url,
643 		       const char *fname, const char *ca_fname)
644 {
645 	CURL *curl;
646 	FILE *f = NULL;
647 	CURLcode res;
648 	long http = 0;
649 	int ret = -1;
650 
651 	ctx->last_err = NULL;
652 	ctx->url = url;
653 
654 	wpa_printf(MSG_DEBUG, "curl: Download file from %s to %s (ca=%s)",
655 		   url, fname, ca_fname);
656 	curl = curl_easy_init();
657 	if (curl == NULL)
658 		goto fail;
659 
660 	f = fopen(fname, "wb");
661 	if (!f)
662 		goto fail;
663 
664 	curl_easy_setopt(curl, CURLOPT_URL, url);
665 	if (ca_fname) {
666 		curl_easy_setopt(curl, CURLOPT_CAINFO, ca_fname);
667 		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
668 		curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
669 	} else {
670 		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
671 	}
672 	curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_cb_debug);
673 	curl_easy_setopt(curl, CURLOPT_DEBUGDATA, ctx);
674 	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
675 	curl_easy_setopt(curl, CURLOPT_WRITEDATA, f);
676 	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
677 
678 	res = curl_easy_perform(curl);
679 	if (res != CURLE_OK) {
680 		if (!ctx->last_err)
681 			ctx->last_err = curl_easy_strerror(res);
682 		wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s",
683 			   ctx->last_err);
684 		goto fail;
685 	}
686 
687 	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http);
688 	wpa_printf(MSG_DEBUG, "curl: Server response code %ld", http);
689 	if (http != 200) {
690 		ctx->last_err = "HTTP download failed";
691 		wpa_printf(MSG_INFO, "HTTP download failed - code %ld", http);
692 		goto fail;
693 	}
694 
695 	ret = 0;
696 
697 fail:
698 	ctx->url = NULL;
699 	if (curl)
700 		curl_easy_cleanup(curl);
701 	if (f)
702 		fclose(f);
703 
704 	return ret;
705 }
706 
707 
http_post(struct http_ctx * ctx,const char * url,const char * data,const char * content_type,const char * ext_hdr,const char * ca_fname,const char * username,const char * password,const char * client_cert,const char * client_key,size_t * resp_len)708 char * http_post(struct http_ctx *ctx, const char *url, const char *data,
709 		 const char *content_type, const char *ext_hdr,
710 		 const char *ca_fname,
711 		 const char *username, const char *password,
712 		 const char *client_cert, const char *client_key,
713 		 size_t *resp_len)
714 {
715 	long http = 0;
716 	CURLcode res;
717 	char *ret = NULL;
718 	CURL *curl;
719 	struct curl_slist *curl_hdr = NULL;
720 
721 	ctx->last_err = NULL;
722 	ctx->url = url;
723 	wpa_printf(MSG_DEBUG, "curl: HTTP POST to %s", url);
724 	curl = setup_curl_post(ctx, url, ca_fname, username, password,
725 			       client_cert, client_key);
726 	if (curl == NULL)
727 		goto fail;
728 
729 	if (content_type) {
730 		char ct[200];
731 		snprintf(ct, sizeof(ct), "Content-Type: %s", content_type);
732 		curl_hdr = curl_slist_append(curl_hdr, ct);
733 	}
734 	if (ext_hdr)
735 		curl_hdr = curl_slist_append(curl_hdr, ext_hdr);
736 	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_hdr);
737 
738 	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
739 	free_curl_buf(ctx);
740 
741 	res = curl_easy_perform(curl);
742 	if (res != CURLE_OK) {
743 		if (!ctx->last_err)
744 			ctx->last_err = curl_easy_strerror(res);
745 		wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s",
746 			   ctx->last_err);
747 		goto fail;
748 	}
749 
750 	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http);
751 	wpa_printf(MSG_DEBUG, "curl: Server response code %ld", http);
752 	if (http != 200) {
753 		ctx->last_err = "HTTP POST failed";
754 		wpa_printf(MSG_INFO, "HTTP POST failed - code %ld", http);
755 		goto fail;
756 	}
757 
758 	if (ctx->curl_buf == NULL)
759 		goto fail;
760 
761 	ret = ctx->curl_buf;
762 	if (resp_len)
763 		*resp_len = ctx->curl_buf_len;
764 	ctx->curl_buf = NULL;
765 	ctx->curl_buf_len = 0;
766 
767 	wpa_printf(MSG_MSGDUMP, "Server response:\n%s", ret);
768 
769 fail:
770 	free_curl_buf(ctx);
771 	ctx->url = NULL;
772 	return ret;
773 }
774 
775 
http_get_err(struct http_ctx * ctx)776 const char * http_get_err(struct http_ctx *ctx)
777 {
778 	return ctx->last_err;
779 }
780