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