Line data Source code
1 : /* t-http.c
2 : * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010,
3 : * 2011 Free Software Foundation, Inc.
4 : * Copyright (C) 2014 Werner Koch
5 : *
6 : * This file is part of GnuPG.
7 : *
8 : * This file is free software; you can redistribute it and/or modify
9 : * it under the terms of either
10 : *
11 : * - the GNU Lesser General Public License as published by the Free
12 : * Software Foundation; either version 3 of the License, or (at
13 : * your option) any later version.
14 : *
15 : * or
16 : *
17 : * - the GNU General Public License as published by the Free
18 : * Software Foundation; either version 2 of the License, or (at
19 : * your option) any later version.
20 : *
21 : * or both in parallel, as here.
22 : *
23 : * This file is distributed in the hope that it will be useful,
24 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 : * GNU General Public License for more details.
27 : *
28 : * You should have received a copy of the GNU General Public License
29 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
30 : */
31 :
32 : #include <config.h>
33 : #include <stdlib.h>
34 : #include <stdio.h>
35 : #include <string.h>
36 : #include <sys/types.h>
37 : #include <sys/stat.h>
38 : #include <unistd.h>
39 : #include <assuan.h>
40 :
41 : #include "util.h"
42 : #include "logging.h"
43 : #include "http.h"
44 :
45 :
46 : #if HTTP_USE_NTBTLS
47 : # include <ntbtls.h>
48 : #elif HTTP_USE_GNUTLS
49 : # include <gnutls/gnutls.h> /* For init, logging, and deinit. */
50 : #endif /*HTTP_USE_GNUTLS*/
51 :
52 : #define PGM "t-http"
53 :
54 : static int verbose;
55 : static int debug;
56 : static int no_verify;
57 :
58 : /* static void */
59 : /* read_dh_params (const char *fname) */
60 : /* { */
61 : /* gpg_error_t err; */
62 : /* int rc; */
63 : /* FILE *fp; */
64 : /* struct stat st; */
65 : /* char *buf; */
66 : /* size_t buflen; */
67 : /* gnutls_datum_t datum; */
68 :
69 : /* fp = fopen (fname, "rb"); */
70 : /* if (!fp) */
71 : /* { */
72 : /* err = gpg_error_from_syserror (); */
73 : /* log_fatal ("can't open '%s': %s\n", fname, gpg_strerror (err)); */
74 : /* } */
75 :
76 : /* if (fstat (fileno(fp), &st)) */
77 : /* { */
78 : /* err = gpg_error_from_syserror (); */
79 : /* log_fatal ("can't stat '%s': %s\n", fname, gpg_strerror (err)); */
80 : /* } */
81 :
82 : /* buflen = st.st_size; */
83 : /* buf = xmalloc (buflen+1); */
84 : /* if (fread (buf, buflen, 1, fp) != 1) */
85 : /* { */
86 : /* err = gpg_error_from_syserror (); */
87 : /* log_fatal ("error reading '%s': %s\n", fname, gpg_strerror (err)); */
88 : /* } */
89 : /* fclose (fp); */
90 :
91 : /* datum.size = buflen; */
92 : /* datum.data = buf; */
93 :
94 : /* rc = gnutls_dh_params_import_pkcs3 (dh_params, &datum, GNUTLS_X509_FMT_PEM); */
95 : /* if (rc < 0) */
96 : /* log_fatal ("gnutls_dh_param_import failed: %s\n", gnutls_strerror (rc)); */
97 :
98 : /* xfree (buf); */
99 : /* } */
100 :
101 :
102 :
103 : #if HTTP_USE_GNUTLS
104 : static gpg_error_t
105 0 : verify_callback (http_t hd, http_session_t session, int reserved)
106 : {
107 : (void)hd;
108 : (void)reserved;
109 0 : return no_verify? 0 : http_verify_server_credentials (session);
110 : }
111 : #endif
112 :
113 : #if HTTP_USE_GNUTLS
114 : static void
115 0 : my_gnutls_log (int level, const char *text)
116 : {
117 0 : fprintf (stderr, "gnutls:L%d: %s", level, text);
118 0 : }
119 : #endif
120 :
121 : /* Prepend FNAME with the srcdir environment variable's value and
122 : return an allocated filename. */
123 : static char *
124 0 : prepend_srcdir (const char *fname)
125 : {
126 : static const char *srcdir;
127 : char *result;
128 :
129 0 : if (!srcdir && !(srcdir = getenv ("srcdir")))
130 0 : srcdir = ".";
131 :
132 0 : result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
133 0 : strcpy (result, srcdir);
134 0 : strcat (result, "/");
135 0 : strcat (result, fname);
136 0 : return result;
137 : }
138 :
139 :
140 : int
141 0 : main (int argc, char **argv)
142 : {
143 0 : int last_argc = -1;
144 : gpg_error_t err;
145 : int rc;
146 : parsed_uri_t uri;
147 : uri_tuple_t r;
148 : http_t hd;
149 : int c;
150 0 : unsigned int my_http_flags = 0;
151 0 : int no_out = 0;
152 0 : int tls_dbg = 0;
153 0 : const char *cafile = NULL;
154 0 : http_session_t session = NULL;
155 :
156 0 : gpgrt_init ();
157 0 : log_set_prefix (PGM, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_PID);
158 0 : if (argc)
159 0 : { argc--; argv++; }
160 0 : while (argc && last_argc != argc )
161 : {
162 0 : last_argc = argc;
163 0 : if (!strcmp (*argv, "--"))
164 : {
165 0 : argc--; argv++;
166 0 : break;
167 : }
168 0 : else if (!strcmp (*argv, "--help"))
169 : {
170 0 : fputs ("usage: " PGM " URL\n"
171 : "Options:\n"
172 : " --verbose print timings etc.\n"
173 : " --debug flyswatter\n"
174 : " --gnutls-debug N use GNUTLS debug level N\n"
175 : " --cacert FNAME expect CA certificate in file FNAME\n"
176 : " --no-verify do not verify the certificate\n"
177 : " --force-tls use HTTP_FLAG_FORCE_TLS\n"
178 : " --force-tor use HTTP_FLAG_FORCE_TOR\n"
179 : " --no-out do not print the content\n",
180 : stdout);
181 0 : exit (0);
182 : }
183 0 : else if (!strcmp (*argv, "--verbose"))
184 : {
185 0 : verbose++;
186 0 : argc--; argv++;
187 : }
188 0 : else if (!strcmp (*argv, "--debug"))
189 : {
190 0 : verbose += 2;
191 0 : debug++;
192 0 : argc--; argv++;
193 : }
194 0 : else if (!strcmp (*argv, "--gnutls-debug"))
195 : {
196 0 : argc--; argv++;
197 0 : if (argc)
198 : {
199 0 : tls_dbg = atoi (*argv);
200 0 : argc--; argv++;
201 : }
202 : }
203 0 : else if (!strcmp (*argv, "--cacert"))
204 : {
205 0 : argc--; argv++;
206 0 : if (argc)
207 : {
208 0 : cafile = *argv;
209 0 : argc--; argv++;
210 : }
211 : }
212 0 : else if (!strcmp (*argv, "--no-verify"))
213 : {
214 0 : no_verify = 1;
215 0 : argc--; argv++;
216 : }
217 0 : else if (!strcmp (*argv, "--force-tls"))
218 : {
219 0 : my_http_flags |= HTTP_FLAG_FORCE_TLS;
220 0 : argc--; argv++;
221 : }
222 0 : else if (!strcmp (*argv, "--force-tor"))
223 : {
224 0 : my_http_flags |= HTTP_FLAG_FORCE_TOR;
225 0 : argc--; argv++;
226 : }
227 0 : else if (!strcmp (*argv, "--no-out"))
228 : {
229 0 : no_out = 1;
230 0 : argc--; argv++;
231 : }
232 0 : else if (!strncmp (*argv, "--", 2))
233 : {
234 0 : fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
235 0 : exit (1);
236 : }
237 : }
238 0 : if (argc != 1)
239 : {
240 0 : fprintf (stderr, PGM ": no or too many URLS given\n");
241 0 : exit (1);
242 : }
243 :
244 0 : if (!cafile)
245 0 : cafile = prepend_srcdir ("tls-ca.pem");
246 :
247 : /* http.c makes use of the assuan socket wrapper. */
248 0 : assuan_sock_init ();
249 :
250 : #if HTTP_USE_NTBTLS
251 :
252 : (void)err;
253 :
254 : ntbtls_set_debug (tls_dbg, NULL, NULL);
255 :
256 : #elif HTTP_USE_GNUTLS
257 :
258 0 : rc = gnutls_global_init ();
259 0 : if (rc)
260 0 : log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
261 :
262 0 : http_register_tls_callback (verify_callback);
263 0 : http_register_tls_ca (cafile);
264 :
265 0 : err = http_session_new (&session, NULL, NULL, HTTP_FLAG_TRUST_DEF);
266 0 : if (err)
267 0 : log_error ("http_session_new failed: %s\n", gpg_strerror (err));
268 :
269 : /* rc = gnutls_dh_params_init(&dh_params); */
270 : /* if (rc) */
271 : /* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */
272 : /* read_dh_params ("dh_param.pem"); */
273 :
274 : /* rc = gnutls_certificate_set_x509_trust_file */
275 : /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
276 : /* if (rc) */
277 : /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
278 : /* gnutls_strerror (rc)); */
279 :
280 : /* gnutls_certificate_set_dh_params (certcred, dh_params); */
281 :
282 0 : gnutls_global_set_log_function (my_gnutls_log);
283 0 : if (tls_dbg)
284 0 : gnutls_global_set_log_level (tls_dbg);
285 :
286 : #endif /*HTTP_USE_GNUTLS*/
287 :
288 0 : rc = http_parse_uri (&uri, *argv, 1);
289 0 : if (rc)
290 : {
291 0 : log_error ("'%s': %s\n", *argv, gpg_strerror (rc));
292 0 : return 1;
293 : }
294 :
295 0 : printf ("Scheme: %s\n", uri->scheme);
296 0 : if (uri->opaque)
297 0 : printf ("Value : %s\n", uri->path);
298 : else
299 : {
300 0 : printf ("Auth : %s\n", uri->auth? uri->auth:"[none]");
301 0 : printf ("Host : %s\n", uri->host);
302 0 : printf ("Port : %u\n", uri->port);
303 0 : printf ("Path : %s\n", uri->path);
304 0 : for (r = uri->params; r; r = r->next)
305 : {
306 0 : printf ("Params: %s", r->name);
307 0 : if (!r->no_value)
308 : {
309 0 : printf ("=%s", r->value);
310 0 : if (strlen (r->value) != r->valuelen)
311 0 : printf (" [real length=%d]", (int) r->valuelen);
312 : }
313 0 : putchar ('\n');
314 : }
315 0 : for (r = uri->query; r; r = r->next)
316 : {
317 0 : printf ("Query : %s", r->name);
318 0 : if (!r->no_value)
319 : {
320 0 : printf ("=%s", r->value);
321 0 : if (strlen (r->value) != r->valuelen)
322 0 : printf (" [real length=%d]", (int) r->valuelen);
323 : }
324 0 : putchar ('\n');
325 : }
326 0 : printf ("Flags :%s%s%s%s\n",
327 0 : uri->is_http? " http":"",
328 0 : uri->opaque? " opaque":"",
329 0 : uri->v6lit? " v6lit":"",
330 0 : uri->onion? " onion":"");
331 0 : printf ("TLS : %s\n",
332 0 : uri->use_tls? "yes":
333 0 : (my_http_flags&HTTP_FLAG_FORCE_TLS)? "forced" : "no");
334 0 : printf ("Tor : %s\n",
335 0 : (my_http_flags&HTTP_FLAG_FORCE_TOR)? "yes" : "no");
336 :
337 : }
338 0 : fflush (stdout);
339 0 : http_release_parsed_uri (uri);
340 0 : uri = NULL;
341 :
342 0 : rc = http_open_document (&hd, *argv, NULL, my_http_flags,
343 : NULL, session, NULL, NULL);
344 0 : if (rc)
345 : {
346 0 : log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc));
347 0 : return 1;
348 : }
349 0 : log_info ("open_http_document succeeded; status=%u\n",
350 : http_get_status_code (hd));
351 :
352 : {
353 : const char **names;
354 : int i;
355 :
356 0 : names = http_get_header_names (hd);
357 0 : if (!names)
358 0 : log_fatal ("http_get_header_names failed: %s\n",
359 : gpg_strerror (gpg_error_from_syserror ()));
360 0 : for (i = 0; names[i]; i++)
361 0 : printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i]));
362 0 : xfree (names);
363 : }
364 0 : fflush (stdout);
365 :
366 0 : switch (http_get_status_code (hd))
367 : {
368 : case 200:
369 : case 400:
370 : case 401:
371 : case 403:
372 : case 404:
373 : {
374 0 : unsigned long count = 0;
375 0 : while ((c = es_getc (http_get_read_ptr (hd))) != EOF)
376 : {
377 0 : count++;
378 0 : if (!no_out)
379 0 : putchar (c);
380 : }
381 0 : log_info ("Received bytes: %lu\n", count);
382 : }
383 0 : break;
384 : case 301:
385 : case 302:
386 : case 307:
387 0 : log_info ("Redirected to: %s\n", http_get_header (hd, "Location"));
388 0 : break;
389 : }
390 0 : http_close (hd, 0);
391 :
392 0 : http_session_release (session);
393 : #ifdef HTTP_USE_GNUTLS
394 0 : gnutls_global_deinit ();
395 : #endif /*HTTP_USE_GNUTLS*/
396 :
397 0 : return 0;
398 : }
|