/* Get the key from URL which is expected to specify a http style scheme. On success R_FP has an open stream to read the data. */ gpg_error_t ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp) { gpg_error_t err; http_session_t session = NULL; http_t http = NULL; int redirects_left = MAX_REDIRECTS; estream_t fp = NULL; char *request_buffer = NULL; err = http_session_new (&session, NULL); if (err) goto leave; http_session_set_log_cb (session, cert_log_cb); *r_fp = NULL; once_more: err = http_open (&http, HTTP_REQ_GET, url, /* httphost */ NULL, /* fixme: AUTH */ NULL, 0, /* fixme: proxy*/ NULL, session, NULL, /*FIXME curl->srvtag*/NULL); if (!err) { fp = http_get_write_ptr (http); /* Avoid caches to get the most recent copy of the key. We set both the Pragma and Cache-Control versions of the header, so we're good with both HTTP 1.0 and 1.1. */ es_fputs ("Pragma: no-cache\r\n" "Cache-Control: no-cache\r\n", fp); http_start_data (http); if (es_ferror (fp)) err = gpg_error_from_syserror (); } if (err) { /* Fixme: After a redirection we show the old host name. */ log_error (_("error connecting to '%s': %s\n"), url, gpg_strerror (err)); goto leave; } /* Wait for the response. */ dirmngr_tick (ctrl); err = http_wait_response (http); if (err) { log_error (_("error reading HTTP response for '%s': %s\n"), url, gpg_strerror (err)); goto leave; } switch (http_get_status_code (http)) { case 200: err = 0; break; /* Success. */ case 301: case 302: case 307: { const char *s = http_get_header (http, "Location"); log_info (_("URL '%s' redirected to '%s' (%u)\n"), url, s?s:"[none]", http_get_status_code (http)); if (s && *s && redirects_left-- ) { xfree (request_buffer); request_buffer = xtrystrdup (s); if (request_buffer) { url = request_buffer; http_close (http, 0); http = NULL; goto once_more; } err = gpg_error_from_syserror (); } else err = gpg_error (GPG_ERR_NO_DATA); log_error (_("too many redirections\n")); } goto leave; default: log_error (_("error accessing '%s': http status %u\n"), url, http_get_status_code (http)); err = gpg_error (GPG_ERR_NO_DATA); goto leave; } fp = http_get_read_ptr (http); if (!fp) { err = gpg_error (GPG_ERR_BUG); goto leave; } /* Return the read stream and close the HTTP context. */ *r_fp = fp; http_close (http, 1); http = NULL; leave: http_close (http, 0); http_session_release (session); xfree (request_buffer); return err; }
int main (int argc, char **argv) { int last_argc = -1; gpg_error_t err; int rc; parsed_uri_t uri; uri_tuple_t r; http_t hd; int c; unsigned int my_http_flags = 0; int no_out = 0; int tls_dbg = 0; const char *cafile = NULL; http_session_t session = NULL; gpgrt_init (); log_set_prefix (PGM, 1 | 4); if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " URL\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --gnutls-debug N use GNUTLS debug level N\n" " --cacert FNAME expect CA certificate in file FNAME\n" " --no-verify do not verify the certificate\n" " --force-tls use HTTP_FLAG_FORCE_TLS\n" " --no-out do not print the content\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--gnutls-debug")) { argc--; argv++; if (argc) { tls_dbg = atoi (*argv); argc--; argv++; } } else if (!strcmp (*argv, "--cacert")) { argc--; argv++; if (argc) { cafile = *argv; argc--; argv++; } } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--force-tls")) { my_http_flags |= HTTP_FLAG_FORCE_TLS; argc--; argv++; } else if (!strcmp (*argv, "--no-out")) { no_out = 1; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) { fprintf (stderr, PGM ": unknown option '%s'\n", *argv); exit (1); } } if (argc != 1) { fprintf (stderr, PGM ": no or too many URLS given\n"); exit (1); } if (!cafile) cafile = prepend_srcdir ("tls-ca.pem"); #if HTTP_USE_NTBTLS (void)err; ntbtls_set_debug (tls_dbg, NULL, NULL); #elif HTTP_USE_GNUTLS rc = gnutls_global_init (); if (rc) log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); http_register_tls_callback (verify_callback); http_register_tls_ca (cafile); err = http_session_new (&session, NULL); if (err) log_error ("http_session_new failed: %s\n", gpg_strerror (err)); /* rc = gnutls_dh_params_init(&dh_params); */ /* if (rc) */ /* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */ /* read_dh_params ("dh_param.pem"); */ /* rc = gnutls_certificate_set_x509_trust_file */ /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ /* if (rc) */ /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ /* gnutls_strerror (rc)); */ /* gnutls_certificate_set_dh_params (certcred, dh_params); */ gnutls_global_set_log_function (my_gnutls_log); if (tls_dbg) gnutls_global_set_log_level (tls_dbg); #endif /*HTTP_USE_GNUTLS*/ rc = http_parse_uri (&uri, *argv, 1); if (rc) { log_error ("'%s': %s\n", *argv, gpg_strerror (rc)); return 1; } printf ("Scheme: %s\n", uri->scheme); if (uri->opaque) printf ("Value : %s\n", uri->path); else { printf ("Auth : %s\n", uri->auth? uri->auth:"[none]"); printf ("Host : %s\n", uri->host); printf ("Port : %u\n", uri->port); printf ("Path : %s\n", uri->path); for (r = uri->params; r; r = r->next) { printf ("Params: %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } for (r = uri->query; r; r = r->next) { printf ("Query : %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } printf ("TLS : %s\n", uri->use_tls? "yes": (my_http_flags&HTTP_FLAG_FORCE_TLS)? "forced" : "no"); } fflush (stdout); http_release_parsed_uri (uri); uri = NULL; rc = http_open_document (&hd, *argv, NULL, my_http_flags, NULL, session, NULL, NULL); if (rc) { log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); return 1; } log_info ("open_http_document succeeded; status=%u\n", http_get_status_code (hd)); { const char **names; int i; names = http_get_header_names (hd); if (!names) log_fatal ("http_get_header_names failed: %s\n", gpg_strerror (gpg_error_from_syserror ())); for (i = 0; names[i]; i++) printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i])); xfree (names); } fflush (stdout); switch (http_get_status_code (hd)) { case 200: case 400: case 401: case 403: case 404: { unsigned long count = 0; while ((c = es_getc (http_get_read_ptr (hd))) != EOF) { count++; if (!no_out) putchar (c); } log_info ("Received bytes: %lu\n", count); } break; case 301: case 302: case 307: log_info ("Redirected to: %s\n", http_get_header (hd, "Location")); break; } http_close (hd, 0); http_session_release (session); #ifdef HTTP_USE_GNUTLS gnutls_global_deinit (); #endif /*HTTP_USE_GNUTLS*/ return 0; }
/* Send an HTTP request. On success returns an estream object at R_FP. HOSTPORTSTR is only used for diagnostics. If HTTPHOST is not NULL it will be used as HTTP "Host" header. If POST_CB is not NULL a post request is used and that callback is called to allow writing the post data. */ static gpg_error_t send_request (ctrl_t ctrl, const char *request, const char *hostportstr, const char *httphost, unsigned int httpflags, gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value, estream_t *r_fp) { gpg_error_t err; http_session_t session = NULL; http_t http = NULL; int redirects_left = MAX_REDIRECTS; estream_t fp = NULL; char *request_buffer = NULL; *r_fp = NULL; err = http_session_new (&session, NULL); if (err) goto leave; http_session_set_log_cb (session, cert_log_cb); once_more: err = http_open (&http, post_cb? HTTP_REQ_POST : HTTP_REQ_GET, request, httphost, /* fixme: AUTH */ NULL, (httpflags | (opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)), ctrl->http_proxy, session, NULL, /*FIXME curl->srvtag*/NULL); if (!err) { fp = http_get_write_ptr (http); /* Avoid caches to get the most recent copy of the key. We set both the Pragma and Cache-Control versions of the header, so we're good with both HTTP 1.0 and 1.1. */ es_fputs ("Pragma: no-cache\r\n" "Cache-Control: no-cache\r\n", fp); if (post_cb) err = post_cb (post_cb_value, http); if (!err) { http_start_data (http); if (es_ferror (fp)) err = gpg_error_from_syserror (); } } if (err) { /* Fixme: After a redirection we show the old host name. */ log_error (_("error connecting to '%s': %s\n"), hostportstr, gpg_strerror (err)); goto leave; } /* Wait for the response. */ dirmngr_tick (ctrl); err = http_wait_response (http); if (err) { log_error (_("error reading HTTP response for '%s': %s\n"), hostportstr, gpg_strerror (err)); goto leave; } if (http_get_tls_info (http, NULL)) { /* Update the httpflags so that a redirect won't fallback to an unencrypted connection. */ httpflags |= HTTP_FLAG_FORCE_TLS; } switch (http_get_status_code (http)) { case 200: err = 0; break; /* Success. */ case 301: case 302: case 307: { const char *s = http_get_header (http, "Location"); log_info (_("URL '%s' redirected to '%s' (%u)\n"), request, s?s:"[none]", http_get_status_code (http)); if (s && *s && redirects_left-- ) { xfree (request_buffer); request_buffer = xtrystrdup (s); if (request_buffer) { request = request_buffer; http_close (http, 0); http = NULL; goto once_more; } err = gpg_error_from_syserror (); } else err = gpg_error (GPG_ERR_NO_DATA); log_error (_("too many redirections\n")); } goto leave; default: log_error (_("error accessing '%s': http status %u\n"), request, http_get_status_code (http)); err = gpg_error (GPG_ERR_NO_DATA); goto leave; } /* FIXME: We should register a permanent redirection and whether a host has ever used TLS so that future calls will always use TLS. */ fp = http_get_read_ptr (http); if (!fp) { err = gpg_error (GPG_ERR_BUG); goto leave; } /* Return the read stream and close the HTTP context. */ *r_fp = fp; http_close (http, 1); http = NULL; leave: http_close (http, 0); http_session_release (session); xfree (request_buffer); return err; }
/* Construct an OCSP request, send it to the configured OCSP responder and parse the response. On success the OCSP context may be used to further process the reponse. */ static gpg_error_t do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md, const char *url, ksba_cert_t cert, ksba_cert_t issuer_cert) { gpg_error_t err; unsigned char *request, *response; size_t requestlen, responselen; http_t http; ksba_ocsp_response_status_t response_status; const char *t; int redirects_left = 2; char *free_this = NULL; (void)ctrl; if (opt.disable_http) { log_error (_("OCSP request not possible due to disabled HTTP\n")); return gpg_error (GPG_ERR_NOT_SUPPORTED); } err = ksba_ocsp_add_target (ocsp, cert, issuer_cert); if (err) { log_error (_("error setting OCSP target: %s\n"), gpg_strerror (err)); return err; } { size_t n; unsigned char nonce[32]; n = ksba_ocsp_set_nonce (ocsp, NULL, 0); if (n > sizeof nonce) n = sizeof nonce; gcry_create_nonce (nonce, n); ksba_ocsp_set_nonce (ocsp, nonce, n); } err = ksba_ocsp_build_request (ocsp, &request, &requestlen); if (err) { log_error (_("error building OCSP request: %s\n"), gpg_strerror (err)); return err; } once_more: err = http_open (&http, HTTP_REQ_POST, url, NULL, (opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0), opt.http_proxy, NULL, NULL, NULL); if (err) { log_error (_("error connecting to '%s': %s\n"), url, gpg_strerror (err)); xfree (free_this); return err; } es_fprintf (http_get_write_ptr (http), "Content-Type: application/ocsp-request\r\n" "Content-Length: %lu\r\n", (unsigned long)requestlen ); http_start_data (http); if (es_fwrite (request, requestlen, 1, http_get_write_ptr (http)) != 1) { err = gpg_error_from_errno (errno); log_error ("error sending request to '%s': %s\n", url, strerror (errno)); http_close (http, 0); xfree (request); xfree (free_this); return err; } xfree (request); request = NULL; err = http_wait_response (http); if (err || http_get_status_code (http) != 200) { if (err) log_error (_("error reading HTTP response for '%s': %s\n"), url, gpg_strerror (err)); else { switch (http_get_status_code (http)) { case 301: case 302: { const char *s = http_get_header (http, "Location"); log_info (_("URL '%s' redirected to '%s' (%u)\n"), url, s?s:"[none]", http_get_status_code (http)); if (s && *s && redirects_left-- ) { xfree (free_this); url = NULL; free_this = xtrystrdup (s); if (!free_this) err = gpg_error_from_errno (errno); else { url = free_this; http_close (http, 0); goto once_more; } } else err = gpg_error (GPG_ERR_NO_DATA); log_error (_("too many redirections\n")); } break; default: log_error (_("error accessing '%s': http status %u\n"), url, http_get_status_code (http)); err = gpg_error (GPG_ERR_NO_DATA); break; } } http_close (http, 0); xfree (free_this); return err; } err = read_response (http_get_read_ptr (http), &response, &responselen); http_close (http, 0); if (err) { log_error (_("error reading HTTP response for '%s': %s\n"), url, gpg_strerror (err)); xfree (free_this); return err; } err = ksba_ocsp_parse_response (ocsp, response, responselen, &response_status); if (err) { log_error (_("error parsing OCSP response for '%s': %s\n"), url, gpg_strerror (err)); xfree (response); xfree (free_this); return err; } switch (response_status) { case KSBA_OCSP_RSPSTATUS_SUCCESS: t = "success"; break; case KSBA_OCSP_RSPSTATUS_MALFORMED: t = "malformed"; break; case KSBA_OCSP_RSPSTATUS_INTERNAL: t = "internal error"; break; case KSBA_OCSP_RSPSTATUS_TRYLATER: t = "try later"; break; case KSBA_OCSP_RSPSTATUS_SIGREQUIRED: t = "must sign request"; break; case KSBA_OCSP_RSPSTATUS_UNAUTHORIZED: t = "unauthorized"; break; case KSBA_OCSP_RSPSTATUS_REPLAYED: t = "replay detected"; break; case KSBA_OCSP_RSPSTATUS_OTHER: t = "other (unknown)"; break; case KSBA_OCSP_RSPSTATUS_NONE: t = "no status"; break; default: t = "[unknown status]"; break; } if (response_status == KSBA_OCSP_RSPSTATUS_SUCCESS) { if (opt.verbose) log_info (_("OCSP responder at '%s' status: %s\n"), url, t); err = ksba_ocsp_hash_response (ocsp, response, responselen, HASH_FNC, md); if (err) log_error (_("hashing the OCSP response for '%s' failed: %s\n"), url, gpg_strerror (err)); } else { log_error (_("OCSP responder at '%s' status: %s\n"), url, t); err = gpg_error (GPG_ERR_GENERAL); } xfree (response); xfree (free_this); return err; }
CURLcode curl_easy_perform(CURL *curl) { int rc; CURLcode err=CURLE_OK; const char *errstr=NULL; char *proxy=NULL; struct http_srv srv; memset(&srv,0,sizeof(srv)); /* Emulate the libcurl proxy behavior. If the calling program set a proxy, use it. If it didn't set a proxy or set it to NULL, check for one in the environment. If the calling program explicitly set a null-string proxy the http code doesn't use a proxy at all. */ if(curl->proxy) proxy=curl->proxy; else proxy=getenv(HTTP_PROXY_ENV); if(curl->srvtag) srv.srvtag=curl->srvtag; if(curl->flags.verbose) { fprintf(curl->errors,"* HTTP proxy is \"%s\"\n",proxy?proxy:"null"); fprintf(curl->errors,"* HTTP URL is \"%s\"\n",curl->url); if(srv.srvtag) fprintf(curl->errors, "* SRV tag is \"%s\": host and port may be overridden\n", srv.srvtag); fprintf(curl->errors,"* HTTP auth is \"%s\"\n", curl->auth?curl->auth:"null"); fprintf(curl->errors,"* HTTP method is %s\n", curl->flags.post?"POST":"GET"); } if(curl->flags.post) { rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, curl->auth, 0, proxy, NULL, &srv, curl->headers?curl->headers->list:NULL); if (!rc) { unsigned int post_len = strlen(curl->postfields); if(curl->flags.verbose && srv.used_server && srv.used_port) fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n", srv.used_server, srv.used_port); es_fprintf (http_get_write_ptr (curl->hd), "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %u\r\n", post_len); http_start_data (curl->hd); es_write (http_get_write_ptr (curl->hd), curl->postfields, post_len, NULL); rc = http_wait_response (curl->hd); curl->status = http_get_status_code (curl->hd); if (!rc && curl->flags.failonerror && curl->status>=300) err = CURLE_HTTP_RETURNED_ERROR; http_close (curl->hd, 0); curl->hd = NULL; } } else { rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, curl->auth, 0, proxy, NULL, &srv, curl->headers?curl->headers->list:NULL); if (!rc) { if(curl->flags.verbose && srv.used_server && srv.used_port) fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n", srv.used_server, srv.used_port); rc = http_wait_response (curl->hd); curl->status = http_get_status_code (curl->hd); if (!rc) { if (curl->flags.failonerror && curl->status>=300) err = CURLE_HTTP_RETURNED_ERROR; else { size_t maxlen = 1024; size_t buflen; unsigned int len; char *line = NULL; while ((len = es_read_line (http_get_read_ptr (curl->hd), &line, &buflen, &maxlen))) { size_t ret; maxlen=1024; ret=(curl->writer)(line,len,1,curl->file); if(ret!=len) { err=CURLE_WRITE_ERROR; break; } } es_free (line); http_close(curl->hd, 0); curl->hd = NULL; } } else { http_close (curl->hd, 0); curl->hd = NULL; } } } xfree(srv.used_server); switch(gpg_err_code (rc)) { case 0: break; case GPG_ERR_INV_URI: err=CURLE_UNSUPPORTED_PROTOCOL; break; default: errstr=gpg_strerror (rc); err=CURLE_COULDNT_CONNECT; break; } return handle_error(curl,err,errstr); }
int main (int argc, char **argv) { int last_argc = -1; gpg_error_t err; int rc; parsed_uri_t uri; uri_tuple_t r; http_t hd; int c; unsigned int my_http_flags = 0; int no_out = 0; int tls_dbg = 0; int no_crl = 0; const char *cafile = NULL; http_session_t session = NULL; unsigned int timeout = 0; gpgrt_init (); log_set_prefix (PGM, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_PID); if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " URL\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --tls-debug N use TLS debug level N\n" " --cacert FNAME expect CA certificate in file FNAME\n" " --timeout MS timeout for connect in MS\n" " --no-verify do not verify the certificate\n" " --force-tls use HTTP_FLAG_FORCE_TLS\n" " --force-tor use HTTP_FLAG_FORCE_TOR\n" " --no-out do not print the content\n" " --no-crl do not consuilt a CRL\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--tls-debug")) { argc--; argv++; if (argc) { tls_dbg = atoi (*argv); argc--; argv++; } } else if (!strcmp (*argv, "--cacert")) { argc--; argv++; if (argc) { cafile = *argv; argc--; argv++; } } else if (!strcmp (*argv, "--timeout")) { argc--; argv++; if (argc) { timeout = strtoul (*argv, NULL, 10); argc--; argv++; } } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--force-tls")) { my_http_flags |= HTTP_FLAG_FORCE_TLS; argc--; argv++; } else if (!strcmp (*argv, "--force-tor")) { my_http_flags |= HTTP_FLAG_FORCE_TOR; argc--; argv++; } else if (!strcmp (*argv, "--no-out")) { no_out = 1; argc--; argv++; } else if (!strcmp (*argv, "--no-crl")) { no_crl = 1; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) { fprintf (stderr, PGM ": unknown option '%s'\n", *argv); exit (1); } } if (argc != 1) { fprintf (stderr, PGM ": no or too many URLS given\n"); exit (1); } if (!cafile) cafile = prepend_srcdir ("tls-ca.pem"); if (verbose) my_http_flags |= HTTP_FLAG_LOG_RESP; if (verbose || debug) http_set_verbose (verbose, debug); /* http.c makes use of the assuan socket wrapper. */ assuan_sock_init (); if ((my_http_flags & HTTP_FLAG_FORCE_TOR)) { enable_dns_tormode (1); if (assuan_sock_set_flag (ASSUAN_INVALID_FD, "tor-mode", 1)) { log_error ("error enabling Tor mode: %s\n", strerror (errno)); log_info ("(is your Libassuan recent enough?)\n"); } } #if HTTP_USE_NTBTLS log_info ("new session.\n"); err = http_session_new (&session, NULL, ((no_crl? HTTP_FLAG_NO_CRL : 0) | HTTP_FLAG_TRUST_DEF), my_http_tls_verify_cb, NULL); if (err) log_error ("http_session_new failed: %s\n", gpg_strerror (err)); ntbtls_set_debug (tls_dbg, NULL, NULL); #elif HTTP_USE_GNUTLS rc = gnutls_global_init (); if (rc) log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); http_register_tls_callback (verify_callback); http_register_tls_ca (cafile); err = http_session_new (&session, NULL, ((no_crl? HTTP_FLAG_NO_CRL : 0) | HTTP_FLAG_TRUST_DEF), NULL, NULL); if (err) log_error ("http_session_new failed: %s\n", gpg_strerror (err)); /* rc = gnutls_dh_params_init(&dh_params); */ /* if (rc) */ /* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */ /* read_dh_params ("dh_param.pem"); */ /* rc = gnutls_certificate_set_x509_trust_file */ /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ /* if (rc) */ /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ /* gnutls_strerror (rc)); */ /* gnutls_certificate_set_dh_params (certcred, dh_params); */ gnutls_global_set_log_function (my_gnutls_log); if (tls_dbg) gnutls_global_set_log_level (tls_dbg); #else (void)err; (void)tls_dbg; (void)no_crl; #endif /*HTTP_USE_GNUTLS*/ rc = http_parse_uri (&uri, *argv, 1); if (rc) { log_error ("'%s': %s\n", *argv, gpg_strerror (rc)); return 1; } printf ("Scheme: %s\n", uri->scheme); if (uri->opaque) printf ("Value : %s\n", uri->path); else { printf ("Auth : %s\n", uri->auth? uri->auth:"[none]"); printf ("Host : %s\n", uri->host); printf ("Port : %u\n", uri->port); printf ("Path : %s\n", uri->path); for (r = uri->params; r; r = r->next) { printf ("Params: %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } for (r = uri->query; r; r = r->next) { printf ("Query : %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } printf ("Flags :%s%s%s%s\n", uri->is_http? " http":"", uri->opaque? " opaque":"", uri->v6lit? " v6lit":"", uri->onion? " onion":""); printf ("TLS : %s\n", uri->use_tls? "yes": (my_http_flags&HTTP_FLAG_FORCE_TLS)? "forced" : "no"); printf ("Tor : %s\n", (my_http_flags&HTTP_FLAG_FORCE_TOR)? "yes" : "no"); } fflush (stdout); http_release_parsed_uri (uri); uri = NULL; if (session) http_session_set_timeout (session, timeout); rc = http_open_document (NULL, &hd, *argv, NULL, my_http_flags, NULL, session, NULL, NULL); if (rc) { log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); return 1; } log_info ("open_http_document succeeded; status=%u\n", http_get_status_code (hd)); { const char **names; int i; names = http_get_header_names (hd); if (!names) log_fatal ("http_get_header_names failed: %s\n", gpg_strerror (gpg_error_from_syserror ())); for (i = 0; names[i]; i++) printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i])); xfree (names); } fflush (stdout); switch (http_get_status_code (hd)) { case 200: case 400: case 401: case 403: case 404: { unsigned long count = 0; while ((c = es_getc (http_get_read_ptr (hd))) != EOF) { count++; if (!no_out) putchar (c); } log_info ("Received bytes: %lu\n", count); } break; case 301: case 302: case 307: log_info ("Redirected to: %s\n", http_get_header (hd, "Location")); break; } http_close (hd, 0); http_session_release (session); #ifdef HTTP_USE_GNUTLS gnutls_global_deinit (); #endif /*HTTP_USE_GNUTLS*/ return 0; }
int main (int argc, char **argv) { gpg_error_t err; int rc; parsed_uri_t uri; uri_tuple_t r; http_t hd; int c; http_session_t session = NULL; gpgrt_init (); log_set_prefix ("t-http", 1 | 4); if (argc != 2) { fprintf (stderr, "usage: t-http uri\n"); return 1; } argc--; argv++; #ifdef HTTP_USE_GNUTLS rc = gnutls_global_init (); if (rc) log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); http_register_tls_callback (verify_callback); http_register_tls_ca ("tls-ca.pem"); err = http_session_new (&session, NULL); if (err) log_error ("http_session_new failed: %s\n", gpg_strerror (err)); /* rc = gnutls_dh_params_init(&dh_params); */ /* if (rc) */ /* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */ /* read_dh_params ("dh_param.pem"); */ /* rc = gnutls_certificate_set_x509_trust_file */ /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ /* if (rc) */ /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ /* gnutls_strerror (rc)); */ /* gnutls_certificate_set_dh_params (certcred, dh_params); */ gnutls_global_set_log_function (my_gnutls_log); /* gnutls_global_set_log_level (2); */ #endif /*HTTP_USE_GNUTLS*/ rc = http_parse_uri (&uri, *argv, 1); if (rc) { log_error ("'%s': %s\n", *argv, gpg_strerror (rc)); return 1; } printf ("Scheme: %s\n", uri->scheme); if (uri->opaque) printf ("Value : %s\n", uri->path); else { printf ("Auth : %s\n", uri->auth? uri->auth:"[none]"); printf ("Host : %s\n", uri->host); printf ("Port : %u\n", uri->port); printf ("Path : %s\n", uri->path); for (r = uri->params; r; r = r->next) { printf ("Params: %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } for (r = uri->query; r; r = r->next) { printf ("Query : %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } } http_release_parsed_uri (uri); uri = NULL; rc = http_open_document (&hd, *argv, NULL, 0, NULL, session, NULL, NULL); if (rc) { log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); return 1; } log_info ("open_http_document succeeded; status=%u\n", http_get_status_code (hd)); { const char **names; int i; names = http_get_header_names (hd); if (!names) log_fatal ("http_get_header_names failed: %s\n", gpg_strerror (gpg_error_from_syserror ())); for (i = 0; names[i]; i++) printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i])); xfree (names); } switch (http_get_status_code (hd)) { case 200: case 400: case 401: case 403: case 404: while ((c = es_getc (http_get_read_ptr (hd))) != EOF) putchar (c); break; case 301: case 302: printf ("Redirected to '%s'\n", http_get_header (hd, "Location")); break; } http_close (hd, 0); http_session_release (session); #ifdef HTTP_USE_GNUTLS gnutls_global_deinit (); #endif /*HTTP_USE_GNUTLS*/ return 0; }