NetSurf
about.c
Go to the documentation of this file.
1 /*
2  * Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
3  *
4  * This file is part of NetSurf.
5  *
6  * NetSurf is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * NetSurf is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /**
20  * \file
21  *
22  * URL handling for the "about" scheme.
23  *
24  * Based on the data fetcher by Rob Kendrick
25  * This fetcher provides a simple scheme for the user to access
26  * information from the browser from a known, fixed URL.
27  */
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 
34 #include "netsurf/inttypes.h"
35 #include "netsurf/plot_style.h"
36 
37 #include "utils/log.h"
38 #include "testament.h"
39 #include "utils/corestrings.h"
40 #include "utils/nscolour.h"
41 #include "utils/nsoption.h"
42 #include "utils/utils.h"
43 #include "utils/messages.h"
44 #include "utils/ring.h"
45 
46 #include "content/fetch.h"
47 #include "content/fetchers.h"
48 #include "content/fetchers/about.h"
49 #include "image/image_cache.h"
50 
51 #include "desktop/system_colour.h"
52 
53 struct fetch_about_context;
54 
55 typedef bool (*fetch_about_handler)(struct fetch_about_context *);
56 
57 /**
58  * Context for an about fetch
59  */
62 
63  struct fetch *fetchh; /**< Handle for this fetch */
64 
65  bool aborted; /**< Flag indicating fetch has been aborted */
66  bool locked; /**< Flag indicating entry is already entered */
67 
68  nsurl *url; /**< The full url the fetch refers to */
69 
70  const struct fetch_multipart_data *multipart; /**< post data */
71 
73 };
74 
75 static struct fetch_about_context *ring = NULL;
76 
77 /**
78  * handler info for about scheme
79  */
81  const char *name; /**< name to match in url */
82  int name_len;
83  lwc_string *lname; /**< Interned name */
84  fetch_about_handler handler; /**< handler for the url */
85  bool hidden; /**< If entry should be hidden in listing */
86 };
87 
88 
89 /**
90  * issue fetch callbacks with locking
91  */
92 static inline bool
94 {
95  ctx->locked = true;
96  fetch_send_callback(msg, ctx->fetchh);
97  ctx->locked = false;
98 
99  return ctx->aborted;
100 }
101 
102 static inline bool
104 {
105  fetch_msg msg;
106  msg.type = FETCH_FINISHED;
107  return fetch_about_send_callback(&msg, ctx);
108 }
109 
110 static bool
111 fetch_about_send_header(struct fetch_about_context *ctx, const char *fmt, ...)
112 {
113  char header[64];
114  fetch_msg msg;
115  va_list ap;
116 
117  va_start(ap, fmt);
118 
119  vsnprintf(header, sizeof header, fmt, ap);
120 
121  va_end(ap);
122 
123  msg.type = FETCH_HEADER;
124  msg.data.header_or_data.buf = (const uint8_t *) header;
125  msg.data.header_or_data.len = strlen(header);
126 
127  return fetch_about_send_callback(&msg, ctx);
128 }
129 
130 /**
131  * send formatted data on a fetch
132  */
133 static nserror ssenddataf(struct fetch_about_context *ctx, const char *fmt, ...)
134 {
135  char buffer[1024];
136  char *dbuff;
137  fetch_msg msg;
138  va_list ap;
139  int slen;
140 
141  va_start(ap, fmt);
142 
143  slen = vsnprintf(buffer, sizeof(buffer), fmt, ap);
144 
145  va_end(ap);
146 
147  if (slen < (int)sizeof(buffer)) {
148  msg.type = FETCH_DATA;
149  msg.data.header_or_data.buf = (const uint8_t *) buffer;
150  msg.data.header_or_data.len = slen;
151 
152  if (fetch_about_send_callback(&msg, ctx)) {
153  return NSERROR_INVALID;
154  }
155 
156  return NSERROR_OK;
157  }
158 
159  dbuff = malloc(slen + 1);
160  if (dbuff == NULL) {
161  return NSERROR_NOSPACE;
162  }
163 
164  va_start(ap, fmt);
165 
166  slen = vsnprintf(dbuff, slen + 1, fmt, ap);
167 
168  va_end(ap);
169 
170  msg.type = FETCH_DATA;
171  msg.data.header_or_data.buf = (const uint8_t *)dbuff;
172  msg.data.header_or_data.len = slen;
173 
174  if (fetch_about_send_callback(&msg, ctx)) {
175  free(dbuff);
176  return NSERROR_INVALID;
177  }
178 
179  free(dbuff);
180  return NSERROR_OK;
181 }
182 
183 
184 /**
185  * Generate a 500 server error respnse
186  *
187  * \param ctx The fetcher context.
188  * \return true if handled false if aborted.
189  */
191 {
192  nserror res;
193 
194  fetch_set_http_code(ctx->fetchh, 500);
195 
196  /* content type */
197  if (fetch_about_send_header(ctx, "Content-Type: text/plain"))
198  return false;
199 
200  res = ssenddataf(ctx, "Server error 500");
201  if (res != NSERROR_OK) {
202  return false;
203  }
204 
206 
207  return true;
208 }
209 
210 
211 /**
212  * Handler to generate about scheme cache page.
213  *
214  * \param ctx The fetcher context.
215  * \return true if handled false if aborted.
216  */
218 {
219  fetch_msg msg;
220  const char buffer[2] = { ' ', '\0' };
221 
222  /* content is going to return ok */
223  fetch_set_http_code(ctx->fetchh, 200);
224 
225  /* content type */
226  if (fetch_about_send_header(ctx, "Content-Type: text/html"))
227  goto fetch_about_blank_handler_aborted;
228 
229  msg.type = FETCH_DATA;
230  msg.data.header_or_data.buf = (const uint8_t *) buffer;
231  msg.data.header_or_data.len = strlen(buffer);
232 
233  if (fetch_about_send_callback(&msg, ctx))
234  goto fetch_about_blank_handler_aborted;
235 
236  msg.type = FETCH_FINISHED;
237 
238  fetch_about_send_callback(&msg, ctx);
239 
240  return true;
241 
242 fetch_about_blank_handler_aborted:
243  return false;
244 }
245 
246 
247 /**
248  * Handler to generate about scheme credits page.
249  *
250  * \param ctx The fetcher context.
251  * \return true if handled false if aborted.
252  */
254 {
255  fetch_msg msg;
256 
257  /* content is going to return redirect */
258  fetch_set_http_code(ctx->fetchh, 302);
259 
260  msg.type = FETCH_REDIRECT;
261  msg.data.redirect = "resource:credits.html";
262 
263  fetch_about_send_callback(&msg, ctx);
264 
265  return true;
266 }
267 
268 
269 /**
270  * Handler to generate about scheme licence page.
271  *
272  * \param ctx The fetcher context.
273  * \return true if handled false if aborted.
274  */
276 {
277  fetch_msg msg;
278 
279  /* content is going to return redirect */
280  fetch_set_http_code(ctx->fetchh, 302);
281 
282  msg.type = FETCH_REDIRECT;
283  msg.data.redirect = "resource:licence.html";
284 
285  fetch_about_send_callback(&msg, ctx);
286 
287  return true;
288 }
289 
290 
291 /**
292  * Handler to generate about:imagecache page.
293  *
294  * Shows details of current image cache.
295  *
296  * \param ctx The fetcher context.
297  * \return true if handled false if aborted.
298  */
300 {
301  fetch_msg msg;
302  char buffer[2048]; /* output buffer */
303  int code = 200;
304  int slen;
305  unsigned int cent_loop = 0;
306  int elen = 0; /* entry length */
307  nserror res;
308  bool even = false;
309 
310  /* content is going to return ok */
311  fetch_set_http_code(ctx->fetchh, code);
312 
313  /* content type */
314  if (fetch_about_send_header(ctx, "Content-Type: text/html"))
315  goto fetch_about_imagecache_handler_aborted;
316 
317  /* page head */
318  res = ssenddataf(ctx,
319  "<html>\n<head>\n"
320  "<title>Image Cache Status</title>\n"
321  "<link rel=\"stylesheet\" type=\"text/css\" "
322  "href=\"resource:internal.css\">\n"
323  "</head>\n"
324  "<body id =\"cachelist\" class=\"ns-even-bg ns-even-fg ns-border\">\n"
325  "<h1 class=\"ns-border\">Image Cache Status</h1>\n");
326  if (res != NSERROR_OK) {
327  goto fetch_about_imagecache_handler_aborted;
328  }
329 
330  /* image cache summary */
331  slen = image_cache_snsummaryf(buffer, sizeof(buffer),
332  "<p>Configured limit of %a hysteresis of %b</p>\n"
333  "<p>Total bitmap size in use %c (in %d)</p>\n"
334  "<p>Age %es</p>\n"
335  "<p>Peak size %f (in %g)</p>\n"
336  "<p>Peak image count %h (size %i)</p>\n"
337  "<p>Cache total/hit/miss/fail (counts) %j/%k/%l/%m "
338  "(%pj%%/%pk%%/%pl%%/%pm%%)</p>\n"
339  "<p>Cache total/hit/miss/fail (size) %n/%o/%q/%r "
340  "(%pn%%/%po%%/%pq%%/%pr%%)</p>\n"
341  "<p>Total images never rendered: %s "
342  "(includes %t that were converted)</p>\n"
343  "<p>Total number of excessive conversions: %u "
344  "(from %v images converted more than once)"
345  "</p>\n"
346  "<p>Bitmap of size %w had most (%x) conversions</p>\n"
347  "<h2 class=\"ns-border\">Current contents</h2>\n");
348  if (slen >= (int) (sizeof(buffer))) {
349  goto fetch_about_imagecache_handler_aborted; /* overflow */
350  }
351 
352  /* send image cache summary */
353  msg.type = FETCH_DATA;
354  msg.data.header_or_data.buf = (const uint8_t *) buffer;
355  msg.data.header_or_data.len = slen;
356  if (fetch_about_send_callback(&msg, ctx)) {
357  goto fetch_about_imagecache_handler_aborted;
358  }
359 
360  /* image cache entry table */
361  res = ssenddataf(ctx, "<p class=\"imagecachelist\">\n"
362  "<strong>"
363  "<span>Entry</span>"
364  "<span>Content Key</span>"
365  "<span>Redraw Count</span>"
366  "<span>Conversion Count</span>"
367  "<span>Last Redraw</span>"
368  "<span>Bitmap Age</span>"
369  "<span>Bitmap Size</span>"
370  "<span>Source</span>"
371  "</strong>\n");
372  if (res != NSERROR_OK) {
373  goto fetch_about_imagecache_handler_aborted;
374  }
375 
376  slen = 0;
377  do {
378  if (even) {
379  elen = image_cache_snentryf(buffer + slen,
380  sizeof buffer - slen,
381  cent_loop,
382  "<a href=\"%U\">"
383  "<span class=\"ns-border\">%e</span>"
384  "<span class=\"ns-border\">%k</span>"
385  "<span class=\"ns-border\">%r</span>"
386  "<span class=\"ns-border\">%c</span>"
387  "<span class=\"ns-border\">%a</span>"
388  "<span class=\"ns-border\">%g</span>"
389  "<span class=\"ns-border\">%s</span>"
390  "<span class=\"ns-border\">%o</span>"
391  "</a>\n");
392  } else {
393  elen = image_cache_snentryf(buffer + slen,
394  sizeof buffer - slen,
395  cent_loop,
396  "<a class=\"ns-odd-bg\" href=\"%U\">"
397  "<span class=\"ns-border\">%e</span>"
398  "<span class=\"ns-border\">%k</span>"
399  "<span class=\"ns-border\">%r</span>"
400  "<span class=\"ns-border\">%c</span>"
401  "<span class=\"ns-border\">%a</span>"
402  "<span class=\"ns-border\">%g</span>"
403  "<span class=\"ns-border\">%s</span>"
404  "<span class=\"ns-border\">%o</span>"
405  "</a>\n");
406  }
407  if (elen <= 0)
408  break; /* last option */
409 
410  if (elen >= (int) (sizeof buffer - slen)) {
411  /* last entry would not fit in buffer, submit buffer */
412  msg.data.header_or_data.len = slen;
413  if (fetch_about_send_callback(&msg, ctx))
414  goto fetch_about_imagecache_handler_aborted;
415  slen = 0;
416  } else {
417  /* normal addition */
418  slen += elen;
419  cent_loop++;
420  even = !even;
421  }
422  } while (elen > 0);
423 
424  slen += snprintf(buffer + slen, sizeof buffer - slen,
425  "</p>\n</body>\n</html>\n");
426 
427  msg.data.header_or_data.len = slen;
428  if (fetch_about_send_callback(&msg, ctx))
429  goto fetch_about_imagecache_handler_aborted;
430 
432 
433  return true;
434 
435 fetch_about_imagecache_handler_aborted:
436  return false;
437 }
438 
439 /**
440  * certificate name parameters
441  */
442 struct ns_cert_name {
443  char *common_name;
446  char *locality;
447  char *province;
448  char *country;
449 };
450 
451 /**
452  * Certificate public key parameters
453  */
454 struct ns_cert_pkey {
455  char *algor;
456  int size;
457  char *modulus;
458  char *exponent;
459  char *curve;
460  char *public;
461 };
462 
463 /**
464  * Certificate subject alternative name
465  */
466 struct ns_cert_san {
467  struct ns_cert_san *next;
468  char *name;
469 };
470 
471 /**
472  * certificate information for certificate chain
473  */
474 struct ns_cert_info {
475  struct ns_cert_name subject_name; /**< Subject details */
476  struct ns_cert_name issuer_name; /**< Issuer details */
477  struct ns_cert_pkey public_key; /**< public key details */
478  long version; /**< Certificate version */
479  char *not_before; /**< Valid from date */
480  char *not_after; /**< Valid to date */
481  int sig_type; /**< Signature type */
482  char *sig_algor; /**< Signature Algorithm */
483  char *serialnum; /**< Serial number */
484  char *sha1fingerprint; /**< fingerprint shar1 encoded */
485  char *sha256fingerprint; /**< fingerprint shar256 encoded */
486  struct ns_cert_san *san; /**< subject alternative names */
487  ssl_cert_err err; /**< Whatever is wrong with this certificate */
488 };
489 
490 /**
491  * free all resources associated with a certificate information structure
492  */
494 {
495  struct ns_cert_san *san;
496 
497  free(cinfo->subject_name.common_name);
498  free(cinfo->subject_name.organisation);
499  free(cinfo->subject_name.organisation_unit);
500  free(cinfo->subject_name.locality);
501  free(cinfo->subject_name.province);
502  free(cinfo->subject_name.country);
503  free(cinfo->issuer_name.common_name);
504  free(cinfo->issuer_name.organisation);
505  free(cinfo->issuer_name.organisation_unit);
506  free(cinfo->issuer_name.locality);
507  free(cinfo->issuer_name.province);
508  free(cinfo->issuer_name.country);
509  free(cinfo->public_key.algor);
510  free(cinfo->public_key.modulus);
511  free(cinfo->public_key.exponent);
512  free(cinfo->public_key.curve);
513  free(cinfo->public_key.public);
514  free(cinfo->not_before);
515  free(cinfo->not_after);
516  free(cinfo->sig_algor);
517  free(cinfo->serialnum);
518 
519  /* free san list avoiding use after free */
520  san = cinfo->san;
521  while (san != NULL) {
522  struct ns_cert_san *next;
523  next = san->next;
524  free(san);
525  san = next;
526  }
527 
528  free(cinfo);
529 
530  return NSERROR_OK;
531 }
532 
533 #ifdef WITH_OPENSSL
534 
535 #include <openssl/ssl.h>
536 #include <openssl/x509v3.h>
537 
538 /* OpenSSL 1.0.x, 1.0.2, 1.1.0 and 1.1.1 API all changed
539  * LibreSSL declares its OpenSSL version as 2.1 but only supports 1.0.x API
540  */
541 #if (defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x1010000fL))
542 /* 1.0.x */
543 
544 #if (defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x1000200fL))
545 /* pre 1.0.2 */
546 static int ns_X509_get_signature_nid(X509 *cert)
547 {
548  return OBJ_obj2nid(cert->cert_info->key->algor->algorithm);
549 }
550 #else
551 #define ns_X509_get_signature_nid X509_get_signature_nid
552 #endif
553 
554 static const unsigned char *ns_ASN1_STRING_get0_data(ASN1_STRING *asn1str)
555 {
556  return (const unsigned char *)ASN1_STRING_data(asn1str);
557 }
558 
559 static const BIGNUM *ns_RSA_get0_n(const RSA *d)
560 {
561  return d->n;
562 }
563 
564 static const BIGNUM *ns_RSA_get0_e(const RSA *d)
565 {
566  return d->e;
567 }
568 
569 static int ns_RSA_bits(const RSA *rsa)
570 {
571  return RSA_size(rsa) * 8;
572 }
573 
574 static int ns_DSA_bits(const DSA *dsa)
575 {
576  return DSA_size(dsa) * 8;
577 }
578 
579 static int ns_DH_bits(const DH *dh)
580 {
581  return DH_size(dh) * 8;
582 }
583 
584 #elif (OPENSSL_VERSION_NUMBER < 0x1010100fL)
585 /* 1.1.0 */
586 #define ns_X509_get_signature_nid X509_get_signature_nid
587 #define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
588 
589 static const BIGNUM *ns_RSA_get0_n(const RSA *r)
590 {
591  const BIGNUM *n;
592  const BIGNUM *e;
593  const BIGNUM *d;
594  RSA_get0_key(r, &n, &e, &d);
595  return n;
596 }
597 
598 static const BIGNUM *ns_RSA_get0_e(const RSA *r)
599 {
600  const BIGNUM *n;
601  const BIGNUM *e;
602  const BIGNUM *d;
603  RSA_get0_key(r, &n, &e, &d);
604  return e;
605 }
606 
607 #define ns_RSA_bits RSA_bits
608 #define ns_DSA_bits DSA_bits
609 #define ns_DH_bits DH_bits
610 
611 #else
612 /* 1.1.1 and later */
613 #define ns_X509_get_signature_nid X509_get_signature_nid
614 #define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
615 #define ns_RSA_get0_n RSA_get0_n
616 #define ns_RSA_get0_e RSA_get0_e
617 #define ns_RSA_bits RSA_bits
618 #define ns_DSA_bits DSA_bits
619 #define ns_DH_bits DH_bits
620 #endif
621 
622 /**
623  * extract certificate name information
624  *
625  * \param xname The X509 name to convert. The reference is borrowed so is not freeed
626  * \param iname The info structure to recive the extracted parameters.
627  * \return NSERROR_OK on success else error code
628  */
629 static nserror
630 xname_to_info(X509_NAME *xname, struct ns_cert_name *iname)
631 {
632  int entryidx;
633  int entrycnt;
634  X509_NAME_ENTRY *entry; /* current name entry */
635  ASN1_STRING *value;
636  const unsigned char *value_str;
637  ASN1_OBJECT *name;
638  int name_nid;
639  char **field;
640 
641  entrycnt = X509_NAME_entry_count(xname);
642 
643  for (entryidx = 0; entryidx < entrycnt; entryidx++) {
644  entry = X509_NAME_get_entry(xname, entryidx);
645  name = X509_NAME_ENTRY_get_object(entry);
646  name_nid = OBJ_obj2nid(name);
647  value = X509_NAME_ENTRY_get_data(entry);
648  value_str = ns_ASN1_STRING_get0_data(value);
649  switch (name_nid) {
650  case NID_commonName:
651  field = &iname->common_name;
652  break;
653  case NID_countryName:
654  field = &iname->country;
655  break;
656  case NID_localityName:
657  field = &iname->locality;
658  break;
659  case NID_stateOrProvinceName:
660  field = &iname->province;
661  break;
662  case NID_organizationName:
663  field = &iname->organisation;
664  break;
665  case NID_organizationalUnitName:
666  field = &iname->organisation_unit;
667  break;
668  default :
669  field = NULL;
670  break;
671  }
672  if (field != NULL) {
673  *field = strdup((const char *)value_str);
674  NSLOG(netsurf, DEEPDEBUG,
675  "NID:%d value: %s", name_nid, *field);
676  } else {
677  NSLOG(netsurf, DEEPDEBUG, "NID:%d", name_nid);
678  }
679  }
680 
681  /*
682  * ensure the common name is set to something, this being
683  * missing means the certificate is broken but this should be
684  * robust in the face of bad data
685  */
686  if (iname->common_name == NULL) {
687  iname->common_name = strdup("Unknown");
688  }
689 
690  return NSERROR_OK;
691 }
692 
693 
694 /**
695  * duplicate a hex formatted string inserting the colons
696  *
697  * \todo only uses html entity as separator because netsurfs line breaking
698  * fails otherwise.
699  */
700 static char *hexdup(const char *hex)
701 {
702  int hexlen;
703  char *dst;
704  char *out;
705  int cn = 0;
706 
707  hexlen = strlen(hex);
708  /* allow space fox XXYY to XX&#58;YY&#58; */
709  dst = malloc(((hexlen * 7) + 6) / 2);
710 
711  if (dst != NULL) {
712  for (out = dst; *hex != 0; hex++) {
713  if (cn == 2) {
714  cn = 0;
715  *out++ = '&';
716  *out++ = '#';
717  *out++ = '5';
718  *out++ = '8';
719  *out++ = ';';
720  }
721  *out++ = *hex;
722  cn++;
723  }
724  *out = 0;
725  }
726  return dst;
727 }
728 
729 
730 /**
731  * create a hex formatted string inserting the colons from binary data
732  *
733  * \todo only uses html entity as separator because netsurfs line breaking
734  * fails otherwise.
735  */
736 static char *bindup(unsigned char *bin, unsigned int binlen)
737 {
738  char *dst;
739  char *out;
740  unsigned int idx;
741  const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
742  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
743 
744  /* allow space fox XY to expand to XX&#58;YY&#58; */
745  dst = malloc(binlen * 7);
746 
747  if (dst != NULL) {
748  out = dst;
749  for (idx = 0; idx < binlen; idx++) {
750  *out++ = hex[(bin[idx] & 0xf0) >> 4];
751  *out++ = hex[bin[idx] & 0xf];
752 
753  *out++ = '&';
754  *out++ = '#';
755  *out++ = '5';
756  *out++ = '8';
757  *out++ = ';';
758  }
759  out -= 5;
760  *out = 0;
761  }
762  return dst;
763 }
764 
765 
766 /**
767  * extract RSA key information to info structure
768  *
769  * \param rsa The RSA key to examine. The reference is dropped on return
770  * \param ikey The public key info structure to fill
771  * \rerun NSERROR_OK on success else error code.
772  */
773 static nserror
774 rsa_to_info(RSA *rsa, struct ns_cert_pkey *ikey)
775 {
776  char *tmp;
777 
778  if (rsa == NULL) {
779  return NSERROR_BAD_PARAMETER;
780  }
781 
782  ikey->algor = strdup("RSA");
783 
784  ikey->size = ns_RSA_bits(rsa);
785 
786  tmp = BN_bn2hex(ns_RSA_get0_n(rsa));
787  if (tmp != NULL) {
788  ikey->modulus = hexdup(tmp);
789  OPENSSL_free(tmp);
790  }
791 
792  tmp = BN_bn2dec(ns_RSA_get0_e(rsa));
793  if (tmp != NULL) {
794  ikey->exponent = strdup(tmp);
795  OPENSSL_free(tmp);
796  }
797 
798  RSA_free(rsa);
799 
800  return NSERROR_OK;
801 }
802 
803 
804 /**
805  * extract DSA key information to info structure
806  *
807  * \param dsa The RSA key to examine. The reference is dropped on return
808  * \param ikey The public key info structure to fill
809  * \rerun NSERROR_OK on success else error code.
810  */
811 static nserror
812 dsa_to_info(DSA *dsa, struct ns_cert_pkey *ikey)
813 {
814  if (dsa == NULL) {
815  return NSERROR_BAD_PARAMETER;
816  }
817 
818  ikey->algor = strdup("DSA");
819 
820  ikey->size = ns_DSA_bits(dsa);
821 
822  DSA_free(dsa);
823 
824  return NSERROR_OK;
825 }
826 
827 
828 /**
829  * extract DH key information to info structure
830  *
831  * \param dsa The RSA key to examine. The reference is dropped on return
832  * \param ikey The public key info structure to fill
833  * \rerun NSERROR_OK on success else error code.
834  */
835 static nserror
836 dh_to_info(DH *dh, struct ns_cert_pkey *ikey)
837 {
838  if (dh == NULL) {
839  return NSERROR_BAD_PARAMETER;
840  }
841 
842  ikey->algor = strdup("Diffie Hellman");
843 
844  ikey->size = ns_DH_bits(dh);
845 
846  DH_free(dh);
847 
848  return NSERROR_OK;
849 }
850 
851 
852 /**
853  * extract EC key information to info structure
854  *
855  * \param ec The EC key to examine. The reference is dropped on return
856  * \param ikey The public key info structure to fill
857  * \rerun NSERROR_OK on success else error code.
858  */
859 static nserror
860 ec_to_info(EC_KEY *ec, struct ns_cert_pkey *ikey)
861 {
862  const EC_GROUP *ecgroup;
863  const EC_POINT *ecpoint;
864  BN_CTX *bnctx;
865  char *ecpoint_hex;
866 
867  if (ec == NULL) {
868  return NSERROR_BAD_PARAMETER;
869  }
870 
871  ikey->algor = strdup("Elliptic Curve");
872 
873  ecgroup = EC_KEY_get0_group(ec);
874 
875  if (ecgroup != NULL) {
876  ikey->size = EC_GROUP_get_degree(ecgroup);
877 
878  ikey->curve = strdup(OBJ_nid2ln(EC_GROUP_get_curve_name(ecgroup)));
879 
880  ecpoint = EC_KEY_get0_public_key(ec);
881  if (ecpoint != NULL) {
882  bnctx = BN_CTX_new();
883  ecpoint_hex = EC_POINT_point2hex(ecgroup,
884  ecpoint,
885  POINT_CONVERSION_UNCOMPRESSED,
886  bnctx);
887  ikey->public = hexdup(ecpoint_hex);
888  OPENSSL_free(ecpoint_hex);
889  BN_CTX_free(bnctx);
890  }
891  }
892  EC_KEY_free(ec);
893 
894  return NSERROR_OK;
895 }
896 
897 
898 /**
899  * extract public key information to info structure
900  *
901  * \param pkey the public key to examine. The reference is dropped on return
902  * \param ikey The public key info structure to fill
903  * \rerun NSERROR_OK on success else error code.
904  */
905 static nserror
906 pkey_to_info(EVP_PKEY *pkey, struct ns_cert_pkey *ikey)
907 {
908  nserror res;
909 
910  if (pkey == NULL) {
911  return NSERROR_BAD_PARAMETER;
912  }
913 
914  switch (EVP_PKEY_base_id(pkey)) {
915  case EVP_PKEY_RSA:
916  res = rsa_to_info(EVP_PKEY_get1_RSA(pkey), ikey);
917  break;
918 
919  case EVP_PKEY_DSA:
920  res = dsa_to_info(EVP_PKEY_get1_DSA(pkey), ikey);
921  break;
922 
923  case EVP_PKEY_DH:
924  res = dh_to_info(EVP_PKEY_get1_DH(pkey), ikey);
925  break;
926 
927  case EVP_PKEY_EC:
928  res = ec_to_info(EVP_PKEY_get1_EC_KEY(pkey), ikey);
929  break;
930 
931  default:
933  break;
934  }
935 
936  EVP_PKEY_free(pkey);
937 
938  return res;
939 }
940 
941 static nserror san_to_info(X509 *cert, struct ns_cert_san **prev_next)
942 {
943  int idx;
944  int san_names_nb = -1;
945  const GENERAL_NAME *current_name;
946  const unsigned char *dns_name;
947  struct ns_cert_san *isan;
948 
949  STACK_OF(GENERAL_NAME) *san_names = NULL;
950 
951  san_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
952  if (san_names == NULL) {
953  return NSERROR_OK;
954  }
955 
956  san_names_nb = sk_GENERAL_NAME_num(san_names);
957 
958  /* Check each name within the extension */
959  for (idx = 0; idx < san_names_nb; idx++) {
960  current_name = sk_GENERAL_NAME_value(san_names, idx);
961 
962  if (current_name->type == GEN_DNS) {
963  /* extract DNS name into info structure */
964  dns_name = ns_ASN1_STRING_get0_data(current_name->d.dNSName);
965 
966  isan = malloc(sizeof(struct ns_cert_san));
967  if (isan != NULL) {
968  isan->name = strdup((const char *)dns_name);
969  isan->next = NULL;
970  *prev_next = isan;
971  prev_next = &isan->next;
972  }
973  }
974  }
975 
976  /* AmiSSL can't cope with the "correct" mechanism of freeing
977  * the GENERAL_NAME stack, which is:
978  * sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
979  * So instead we do this open-coded loop which does the same:
980  */
981  for (idx = 0; idx < san_names_nb; idx++) {
982  GENERAL_NAME *entry = sk_GENERAL_NAME_pop(san_names);
983  GENERAL_NAME_free(entry);
984  }
985  sk_GENERAL_NAME_free(san_names);
986 
987  return NSERROR_OK;
988 }
989 
990 static nserror
991 der_to_certinfo(const uint8_t *der,
992  size_t der_length,
993  struct ns_cert_info *info)
994 {
995  BIO *mem;
996  BUF_MEM *buf;
997  const ASN1_INTEGER *asn1_num;
998  BIGNUM *bignum;
999  X509 *cert; /**< Pointer to certificate */
1000 
1001  if (der == NULL) {
1002  return NSERROR_OK;
1003  }
1004 
1005  cert = d2i_X509(NULL, &der, der_length);
1006  if (cert == NULL) {
1007  return NSERROR_INVALID;
1008  }
1009 
1010  /*
1011  * get certificate version
1012  *
1013  * \note this is defined by standards (X.509 et al) to be one
1014  * less than the certificate version.
1015  */
1016  info->version = X509_get_version(cert) + 1;
1017 
1018  /* not before date */
1019  mem = BIO_new(BIO_s_mem());
1020  ASN1_TIME_print(mem, X509_get_notBefore(cert));
1021  BIO_get_mem_ptr(mem, &buf);
1022  (void) BIO_set_close(mem, BIO_NOCLOSE);
1023  BIO_free(mem);
1024  info->not_before = calloc(1, buf->length + 1);
1025  if (info->not_before != NULL) {
1026  memcpy(info->not_before, buf->data, (unsigned)buf->length);
1027  }
1028  BUF_MEM_free(buf);
1029 
1030  /* not after date */
1031  mem = BIO_new(BIO_s_mem());
1032  ASN1_TIME_print(mem,
1033  X509_get_notAfter(cert));
1034  BIO_get_mem_ptr(mem, &buf);
1035  (void) BIO_set_close(mem, BIO_NOCLOSE);
1036  BIO_free(mem);
1037  info->not_after = calloc(1, buf->length + 1);
1038  if (info->not_after != NULL) {
1039  memcpy(info->not_after, buf->data, (unsigned)buf->length);
1040  }
1041  BUF_MEM_free(buf);
1042 
1043  /* signature type */
1044  info->sig_type = X509_get_signature_type(cert);
1045 
1046  /* signature algorithm */
1047  int pkey_nid = ns_X509_get_signature_nid(cert);
1048  if (pkey_nid != NID_undef) {
1049  const char* sslbuf = OBJ_nid2ln(pkey_nid);
1050  if (sslbuf != NULL) {
1051  info->sig_algor = strdup(sslbuf);
1052  }
1053  }
1054 
1055  /* serial number */
1056  asn1_num = X509_get_serialNumber(cert);
1057  if (asn1_num != NULL) {
1058  bignum = ASN1_INTEGER_to_BN(asn1_num, NULL);
1059  if (bignum != NULL) {
1060  char *tmp = BN_bn2hex(bignum);
1061  if (tmp != NULL) {
1062  info->serialnum = hexdup(tmp);
1063  OPENSSL_free(tmp);
1064  }
1065  BN_free(bignum);
1066  bignum = NULL;
1067  }
1068  }
1069 
1070  /* fingerprints */
1071  const EVP_MD *digest;
1072  unsigned int dig_len;
1073  unsigned char *buff;
1074  int rc;
1075 
1076  digest = EVP_sha1();
1077  buff = malloc(EVP_MD_size(digest));
1078  if (buff != NULL) {
1079  rc = X509_digest(cert, digest, buff, &dig_len);
1080  if ((rc == 1) && (dig_len == (unsigned int)EVP_MD_size(digest))) {
1081  info->sha1fingerprint = bindup(buff, dig_len);
1082  }
1083  free(buff);
1084  }
1085 
1086  digest = EVP_sha256();
1087  buff = malloc(EVP_MD_size(digest));
1088  if (buff != NULL) {
1089  rc = X509_digest(cert, digest, buff, &dig_len);
1090  if ((rc == 1) && (dig_len == (unsigned int)EVP_MD_size(digest))) {
1091  info->sha256fingerprint = bindup(buff, dig_len);
1092  }
1093  free(buff);
1094  }
1095 
1096  /* subject alternative names */
1097  san_to_info(cert, &info->san);
1098 
1099  /* issuer name */
1100  xname_to_info(X509_get_issuer_name(cert), &info->issuer_name);
1101 
1102  /* subject */
1103  xname_to_info(X509_get_subject_name(cert), &info->subject_name);
1104 
1105  /* public key */
1106  pkey_to_info(X509_get_pubkey(cert), &info->public_key);
1107 
1108  X509_free(cert);
1109 
1110  return NSERROR_OK;
1111 }
1112 
1113 /* copy certificate data */
1114 static nserror
1115 convert_chain_to_cert_info(const struct cert_chain *chain,
1116  struct ns_cert_info **cert_info_out)
1117 {
1118  struct ns_cert_info *certs;
1119  size_t depth;
1120  nserror res;
1121 
1122  certs = calloc(chain->depth, sizeof(struct ns_cert_info));
1123  if (certs == NULL) {
1124  return NSERROR_NOMEM;
1125  }
1126 
1127  for (depth = 0; depth < chain->depth;depth++) {
1128  res = der_to_certinfo(chain->certs[depth].der,
1129  chain->certs[depth].der_length,
1130  certs + depth);
1131  if (res != NSERROR_OK) {
1132  free(certs);
1133  return res;
1134  }
1135  certs[depth].err = chain->certs[depth].err;
1136  }
1137 
1138  *cert_info_out = certs;
1139  return NSERROR_OK;
1140 }
1141 
1142 #else
1143 static nserror
1145  struct ns_cert_info **cert_info_out)
1146 {
1147  return NSERROR_NOT_IMPLEMENTED;
1148 }
1149 #endif
1150 
1151 
1152 static nserror
1154  struct ns_cert_name *cert_name)
1155 {
1156  nserror res;
1157  res = ssenddataf(ctx,
1158  "<tr><th>Common Name</th><td>%s</td></tr>\n",
1159  cert_name->common_name);
1160  if (res != NSERROR_OK) {
1161  return res;
1162  }
1163 
1164  if (cert_name->organisation != NULL) {
1165  res = ssenddataf(ctx,
1166  "<tr><th>Organisation</th><td>%s</td></tr>\n",
1167  cert_name->organisation);
1168  if (res != NSERROR_OK) {
1169  return res;
1170  }
1171  }
1172 
1173  if (cert_name->organisation_unit != NULL) {
1174  res = ssenddataf(ctx,
1175  "<tr><th>Organisation Unit</th><td>%s</td></tr>\n",
1176  cert_name->organisation_unit);
1177  if (res != NSERROR_OK) {
1178  return res;
1179  }
1180  }
1181 
1182  if (cert_name->locality != NULL) {
1183  res = ssenddataf(ctx,
1184  "<tr><th>Locality</th><td>%s</td></tr>\n",
1185  cert_name->locality);
1186  if (res != NSERROR_OK) {
1187  return res;
1188  }
1189  }
1190 
1191  if (cert_name->province != NULL) {
1192  res = ssenddataf(ctx,
1193  "<tr><th>Privince</th><td>%s</td></tr>\n",
1194  cert_name->province);
1195  if (res != NSERROR_OK) {
1196  return res;
1197  }
1198  }
1199 
1200  if (cert_name->country != NULL) {
1201  res = ssenddataf(ctx,
1202  "<tr><th>Country</th><td>%s</td></tr>\n",
1203  cert_name->country);
1204  if (res != NSERROR_OK) {
1205  return res;
1206  }
1207  }
1208 
1209  return res;
1210 }
1211 
1212 /**
1213  * output formatted certificate subject alternate names
1214  */
1215 static nserror
1217  struct ns_cert_san *san)
1218 {
1219  nserror res;
1220 
1221  if (san == NULL) {
1222  return NSERROR_OK;
1223  }
1224 
1225  res = ssenddataf(ctx,
1226  "<table class=\"info\">\n"
1227  "<tr><th>Alternative Names</th><td><hr></td></tr>\n");
1228  if (res != NSERROR_OK) {
1229  return res;
1230  }
1231 
1232  while (san != NULL) {
1233  res = ssenddataf(ctx,
1234  "<tr><th>DNS Name</th><td>%s</td></tr>\n",
1235  san->name);
1236  if (res != NSERROR_OK) {
1237  return res;
1238  }
1239 
1240  san = san->next;
1241  }
1242 
1243  res = ssenddataf(ctx, "</table>\n");
1244 
1245  return res;
1246 
1247 }
1248 
1249 
1250 static nserror
1252  struct ns_cert_pkey *public_key)
1253 {
1254  nserror res;
1255 
1256  if (public_key->algor == NULL) {
1257  /* skip the table if no algorithm name */
1258  return NSERROR_OK;
1259  }
1260 
1261  res = ssenddataf(ctx,
1262  "<table class=\"info\">\n"
1263  "<tr><th>Public Key</th><td><hr></td></tr>\n"
1264  "<tr><th>Algorithm</th><td>%s</td></tr>\n"
1265  "<tr><th>Key Size</th><td>%d</td></tr>\n",
1266  public_key->algor,
1267  public_key->size);
1268  if (res != NSERROR_OK) {
1269  return res;
1270  }
1271 
1272 
1273  if (public_key->exponent != NULL) {
1274  res = ssenddataf(ctx,
1275  "<tr><th>Exponent</th><td>%s</td></tr>\n",
1276  public_key->exponent);
1277  if (res != NSERROR_OK) {
1278  return res;
1279  }
1280  }
1281 
1282  if (public_key->modulus != NULL) {
1283  res = ssenddataf(ctx,
1284  "<tr><th>Modulus</th><td class=\"data\">%s</td></tr>\n",
1285  public_key->modulus);
1286  if (res != NSERROR_OK) {
1287  return res;
1288  }
1289  }
1290 
1291  if (public_key->curve != NULL) {
1292  res = ssenddataf(ctx,
1293  "<tr><th>Curve</th><td>%s</td></tr>\n",
1294  public_key->curve);
1295  if (res != NSERROR_OK) {
1296  return res;
1297  }
1298  }
1299 
1300  if (public_key->public != NULL) {
1301  res = ssenddataf(ctx,
1302  "<tr><th>Public Value</th><td>%s</td></tr>\n",
1303  public_key->public);
1304  if (res != NSERROR_OK) {
1305  return res;
1306  }
1307  }
1308 
1309  res = ssenddataf(ctx, "</table>\n");
1310 
1311  return res;
1312 }
1313 
1314 static nserror
1316  struct ns_cert_info *cert_info)
1317 {
1318  nserror res;
1319 
1320  if ((cert_info->sha1fingerprint == NULL) &&
1321  (cert_info->sha256fingerprint == NULL)) {
1322  /* skip the table if no fingerprints */
1323  return NSERROR_OK;
1324  }
1325 
1326 
1327  res = ssenddataf(ctx,
1328  "<table class=\"info\">\n"
1329  "<tr><th>Fingerprints</th><td><hr></td></tr>\n");
1330  if (res != NSERROR_OK) {
1331  return res;
1332  }
1333 
1334  if (cert_info->sha256fingerprint != NULL) {
1335  res = ssenddataf(ctx,
1336  "<tr><th>SHA-256</th><td class=\"data\">%s</td></tr>\n",
1337  cert_info->sha256fingerprint);
1338  if (res != NSERROR_OK) {
1339  return res;
1340  }
1341  }
1342 
1343  if (cert_info->sha1fingerprint != NULL) {
1344  res = ssenddataf(ctx,
1345  "<tr><th>SHA-1</th><td class=\"data\">%s</td></tr>\n",
1346  cert_info->sha1fingerprint);
1347  if (res != NSERROR_OK) {
1348  return res;
1349  }
1350  }
1351 
1352  res = ssenddataf(ctx, "</table>\n");
1353 
1354  return res;
1355 }
1356 
1357 static nserror
1359  struct ns_cert_info *cert_info,
1360  size_t depth)
1361 {
1362  nserror res;
1363 
1364  res = ssenddataf(ctx,
1365  "<h2 id=\"%"PRIsizet"\" class=\"ns-border\">%s</h2>\n",
1366  depth, cert_info->subject_name.common_name);
1367  if (res != NSERROR_OK) {
1368  return res;
1369  }
1370 
1371  if (cert_info->err != SSL_CERT_ERR_OK) {
1372  res = ssenddataf(ctx,
1373  "<table class=\"info\">\n"
1374  "<tr class=\"ns-even-fg-bad\">"
1375  "<th>Fault</th>"
1376  "<td>%s</td>"
1377  "</tr>"
1378  "</table>\n",
1379  messages_get_sslcode(cert_info->err));
1380  if (res != NSERROR_OK) {
1381  return res;
1382  }
1383  }
1384 
1385  res = ssenddataf(ctx,
1386  "<table class=\"info\">\n"
1387  "<tr><th>Issued To</th><td><hr></td></tr>\n");
1388  if (res != NSERROR_OK) {
1389  return res;
1390  }
1391 
1392  res = format_certificate_name(ctx, &cert_info->subject_name);
1393  if (res != NSERROR_OK) {
1394  return res;
1395  }
1396 
1397  res = ssenddataf(ctx,
1398  "</table>\n");
1399  if (res != NSERROR_OK) {
1400  return res;
1401  }
1402 
1403  res = ssenddataf(ctx,
1404  "<table class=\"info\">\n"
1405  "<tr><th>Issued By</th><td><hr></td></tr>\n");
1406  if (res != NSERROR_OK) {
1407  return res;
1408  }
1409 
1410  res = format_certificate_name(ctx, &cert_info->issuer_name);
1411  if (res != NSERROR_OK) {
1412  return res;
1413  }
1414 
1415  res = ssenddataf(ctx,
1416  "</table>\n");
1417  if (res != NSERROR_OK) {
1418  return res;
1419  }
1420 
1421  res = ssenddataf(ctx,
1422  "<table class=\"info\">\n"
1423  "<tr><th>Validity</th><td><hr></td></tr>\n"
1424  "<tr><th>Valid From</th><td>%s</td></tr>\n"
1425  "<tr><th>Valid Until</th><td>%s</td></tr>\n"
1426  "</table>\n",
1427  cert_info->not_before,
1428  cert_info->not_after);
1429  if (res != NSERROR_OK) {
1430  return res;
1431  }
1432 
1433  res = format_certificate_san(ctx, cert_info->san);
1434  if (res != NSERROR_OK) {
1435  return res;
1436  }
1437 
1438  res = format_certificate_public_key(ctx, &cert_info->public_key);
1439  if (res != NSERROR_OK) {
1440  return res;
1441  }
1442 
1443  res = ssenddataf(ctx,
1444  "<table class=\"info\">\n"
1445  "<tr><th>Miscellaneous</th><td><hr></td></tr>\n");
1446  if (res != NSERROR_OK) {
1447  return res;
1448  }
1449 
1450  if (cert_info->serialnum != NULL) {
1451  res = ssenddataf(ctx,
1452  "<tr><th>Serial Number</th><td>%s</td></tr>\n",
1453  cert_info->serialnum);
1454  if (res != NSERROR_OK) {
1455  return res;
1456  }
1457  }
1458 
1459  if (cert_info->sig_algor != NULL) {
1460  res = ssenddataf(ctx,
1461  "<tr><th>Signature Algorithm</th>"
1462  "<td>%s</td></tr>\n",
1463  cert_info->sig_algor);
1464  if (res != NSERROR_OK) {
1465  return res;
1466  }
1467  }
1468 
1469  res = ssenddataf(ctx,
1470  "<tr><th>Version</th><td>%ld</td></tr>\n"
1471  "</table>\n",
1472  cert_info->version);
1473  if (res != NSERROR_OK) {
1474  return res;
1475  }
1476 
1477  res = format_certificate_fingerprint(ctx, cert_info);
1478  if (res != NSERROR_OK) {
1479  return res;
1480  }
1481 
1482  return res;
1483 }
1484 
1485 /**
1486  * Handler to generate about:certificate page.
1487  *
1488  * Shows details of a certificate chain
1489  *
1490  * \param ctx The fetcher context.
1491  * \return true if handled false if aborted.
1492  */
1494 {
1495  int code = 200;
1496  nserror res;
1497  struct cert_chain *chain = NULL;
1498 
1499  /* content is going to return ok */
1500  fetch_set_http_code(ctx->fetchh, code);
1501 
1502  /* content type */
1503  if (fetch_about_send_header(ctx, "Content-Type: text/html"))
1504  goto fetch_about_certificate_handler_aborted;
1505 
1506  /* page head */
1507  res = ssenddataf(ctx,
1508  "<html>\n<head>\n"
1509  "<title>NetSurf Browser Certificate Viewer</title>\n"
1510  "<link rel=\"stylesheet\" type=\"text/css\" "
1511  "href=\"resource:internal.css\">\n"
1512  "</head>\n"
1513  "<body id=\"certificate\" class=\"ns-even-bg ns-even-fg ns-border\">\n"
1514  "<h1 class=\"ns-border\">Certificate</h1>\n");
1515  if (res != NSERROR_OK) {
1516  goto fetch_about_certificate_handler_aborted;
1517  }
1518 
1519  res = cert_chain_from_query(ctx->url, &chain);
1520  if (res != NSERROR_OK) {
1521  res = ssenddataf(ctx, "<p>Could not process that</p>\n");
1522  if (res != NSERROR_OK) {
1523  goto fetch_about_certificate_handler_aborted;
1524  }
1525  } else {
1526  struct ns_cert_info *cert_info;
1527  res = convert_chain_to_cert_info(chain, &cert_info);
1528  if (res == NSERROR_OK) {
1529  size_t depth;
1530  res = ssenddataf(ctx, "<ul>\n");
1531  if (res != NSERROR_OK) {
1532  free_ns_cert_info(cert_info);
1533  goto fetch_about_certificate_handler_aborted;
1534  }
1535 
1536  for (depth = 0; depth < chain->depth; depth++) {
1537  res = ssenddataf(ctx, "<li><a href=\"#%"PRIsizet"\">%s</a></li>\n",
1538  depth, (cert_info + depth)
1539  ->subject_name
1540  .common_name);
1541  if (res != NSERROR_OK) {
1542  free_ns_cert_info(cert_info);
1543  goto fetch_about_certificate_handler_aborted;
1544  }
1545 
1546  }
1547 
1548  res = ssenddataf(ctx, "</ul>\n");
1549  if (res != NSERROR_OK) {
1550  free_ns_cert_info(cert_info);
1551  goto fetch_about_certificate_handler_aborted;
1552  }
1553 
1554  for (depth = 0; depth < chain->depth; depth++) {
1555  res = format_certificate(ctx, cert_info + depth,
1556  depth);
1557  if (res != NSERROR_OK) {
1558  free_ns_cert_info(cert_info);
1559  goto fetch_about_certificate_handler_aborted;
1560  }
1561 
1562  }
1563  free_ns_cert_info(cert_info);
1564 
1565  } else {
1566  res = ssenddataf(ctx,
1567  "<p>Invalid certificate data</p>\n");
1568  if (res != NSERROR_OK) {
1569  goto fetch_about_certificate_handler_aborted;
1570  }
1571  }
1572  }
1573 
1574 
1575  /* page footer */
1576  res = ssenddataf(ctx, "</body>\n</html>\n");
1577  if (res != NSERROR_OK) {
1578  goto fetch_about_certificate_handler_aborted;
1579  }
1580 
1582 
1583  cert_chain_free(chain);
1584 
1585  return true;
1586 
1587 fetch_about_certificate_handler_aborted:
1588  cert_chain_free(chain);
1589  return false;
1590 }
1591 
1592 
1593 /**
1594  * Handler to generate about scheme config page
1595  *
1596  * \param ctx The fetcher context.
1597  * \return true if handled false if aborted.
1598  */
1600 {
1601  fetch_msg msg;
1602  char buffer[1024];
1603  int slen = 0;
1604  unsigned int opt_loop = 0;
1605  int elen = 0; /* entry length */
1606  nserror res;
1607  bool even = false;
1608 
1609  /* content is going to return ok */
1610  fetch_set_http_code(ctx->fetchh, 200);
1611 
1612  /* content type */
1613  if (fetch_about_send_header(ctx, "Content-Type: text/html")) {
1614  goto fetch_about_config_handler_aborted;
1615  }
1616 
1617  res = ssenddataf(ctx,
1618  "<html>\n<head>\n"
1619  "<title>NetSurf Browser Config</title>\n"
1620  "<link rel=\"stylesheet\" type=\"text/css\" "
1621  "href=\"resource:internal.css\">\n"
1622  "</head>\n"
1623  "<body "
1624  "id =\"configlist\" "
1625  "class=\"ns-even-bg ns-even-fg ns-border\" "
1626  "style=\"overflow: hidden;\">\n"
1627  "<h1 class=\"ns-border\">NetSurf Browser Config</h1>\n"
1628  "<table class=\"config\">\n"
1629  "<tr><th>Option</th>"
1630  "<th>Type</th>"
1631  "<th>Provenance</th>"
1632  "<th>Setting</th></tr>\n");
1633  if (res != NSERROR_OK) {
1634  goto fetch_about_config_handler_aborted;
1635  }
1636 
1637  msg.type = FETCH_DATA;
1638  msg.data.header_or_data.buf = (const uint8_t *) buffer;
1639 
1640  do {
1641  if (even) {
1642  elen = nsoption_snoptionf(buffer + slen,
1643  sizeof buffer - slen,
1644  opt_loop,
1645  "<tr class=\"ns-even-bg\">"
1646  "<th class=\"ns-border\">%k</th>"
1647  "<td class=\"ns-border\">%t</td>"
1648  "<td class=\"ns-border\">%p</td>"
1649  "<td class=\"ns-border\">%V</td>"
1650  "</tr>\n");
1651  } else {
1652  elen = nsoption_snoptionf(buffer + slen,
1653  sizeof buffer - slen,
1654  opt_loop,
1655  "<tr class=\"ns-odd-bg\">"
1656  "<th class=\"ns-border\">%k</th>"
1657  "<td class=\"ns-border\">%t</td>"
1658  "<td class=\"ns-border\">%p</td>"
1659  "<td class=\"ns-border\">%V</td>"
1660  "</tr>\n");
1661  }
1662  if (elen <= 0)
1663  break; /* last option */
1664 
1665  if (elen >= (int) (sizeof buffer - slen)) {
1666  /* last entry would not fit in buffer, submit buffer */
1667  msg.data.header_or_data.len = slen;
1668  if (fetch_about_send_callback(&msg, ctx))
1669  goto fetch_about_config_handler_aborted;
1670  slen = 0;
1671  } else {
1672  /* normal addition */
1673  slen += elen;
1674  opt_loop++;
1675  even = !even;
1676  }
1677  } while (elen > 0);
1678 
1679  slen += snprintf(buffer + slen, sizeof buffer - slen,
1680  "</table>\n</body>\n</html>\n");
1681 
1682  msg.data.header_or_data.len = slen;
1683  if (fetch_about_send_callback(&msg, ctx))
1684  goto fetch_about_config_handler_aborted;
1685 
1687 
1688  return true;
1689 
1690 fetch_about_config_handler_aborted:
1691  return false;
1692 }
1693 
1694 
1695 /**
1696  * Handler to generate the nscolours stylesheet
1697  *
1698  * \param ctx The fetcher context.
1699  * \return true if handled false if aborted.
1700  */
1702 {
1703  nserror res;
1704  const char *stylesheet;
1705 
1706  /* content is going to return ok */
1707  fetch_set_http_code(ctx->fetchh, 200);
1708 
1709  /* content type */
1710  if (fetch_about_send_header(ctx, "Content-Type: text/css; charset=utf-8")) {
1711  goto aborted;
1712  }
1713 
1714  res = nscolour_get_stylesheet(&stylesheet);
1715  if (res != NSERROR_OK) {
1716  goto aborted;
1717  }
1718 
1719  res = ssenddataf(ctx,
1720  "html {\n"
1721  "\tbackground-color: #%06x;\n"
1722  "}\n"
1723  "%s",
1725  stylesheet);
1726  if (res != NSERROR_OK) {
1727  goto aborted;
1728  }
1729 
1731 
1732  return true;
1733 
1734 aborted:
1735 
1736  return false;
1737 }
1738 
1739 
1740 /**
1741  * Generate the text of a Choices file which represents the current
1742  * in use options.
1743  *
1744  * \param ctx The fetcher context.
1745  * \return true if handled false if aborted.
1746  */
1748 {
1749  fetch_msg msg;
1750  char buffer[1024];
1751  int code = 200;
1752  int slen;
1753  unsigned int opt_loop = 0;
1754  int res = 0;
1755 
1756  /* content is going to return ok */
1757  fetch_set_http_code(ctx->fetchh, code);
1758 
1759  /* content type */
1760  if (fetch_about_send_header(ctx, "Content-Type: text/plain"))
1761  goto fetch_about_choices_handler_aborted;
1762 
1763  msg.type = FETCH_DATA;
1764  msg.data.header_or_data.buf = (const uint8_t *) buffer;
1765 
1766  slen = snprintf(buffer, sizeof buffer,
1767  "# Automatically generated current NetSurf browser Choices\n");
1768 
1769  do {
1770  res = nsoption_snoptionf(buffer + slen,
1771  sizeof buffer - slen,
1772  opt_loop,
1773  "%k:%v\n");
1774  if (res <= 0)
1775  break; /* last option */
1776 
1777  if (res >= (int) (sizeof buffer - slen)) {
1778  /* last entry would not fit in buffer, submit buffer */
1779  msg.data.header_or_data.len = slen;
1780  if (fetch_about_send_callback(&msg, ctx))
1781  goto fetch_about_choices_handler_aborted;
1782  slen = 0;
1783  } else {
1784  /* normal addition */
1785  slen += res;
1786  opt_loop++;
1787  }
1788  } while (res > 0);
1789 
1790  msg.data.header_or_data.len = slen;
1791  if (fetch_about_send_callback(&msg, ctx))
1792  goto fetch_about_choices_handler_aborted;
1793 
1795 
1796  return true;
1797 
1798 fetch_about_choices_handler_aborted:
1799  return false;
1800 }
1801 
1802 
1803 typedef struct {
1804  const char *leaf;
1805  const char *modtype;
1806 } modification_t;
1807 
1808 /**
1809  * Generate the text of an svn testament which represents the current
1810  * build-tree status
1811  *
1812  * \param ctx The fetcher context.
1813  * \return true if handled false if aborted.
1814  */
1816 {
1817  nserror res;
1818  static modification_t modifications[] = WT_MODIFICATIONS;
1819  int modidx; /* midification index */
1820 
1821  /* content is going to return ok */
1822  fetch_set_http_code(ctx->fetchh, 200);
1823 
1824  /* content type */
1825  if (fetch_about_send_header(ctx, "Content-Type: text/plain"))
1826  goto fetch_about_testament_handler_aborted;
1827 
1828  res = ssenddataf(ctx,
1829  "# Automatically generated by NetSurf build system\n\n");
1830  if (res != NSERROR_OK) {
1831  goto fetch_about_testament_handler_aborted;
1832  }
1833 
1834  res = ssenddataf(ctx,
1835 #if defined(WT_BRANCHISTRUNK) || defined(WT_BRANCHISMASTER)
1836  "# This is a *DEVELOPMENT* build from the main line.\n\n"
1837 #elif defined(WT_BRANCHISTAG) && (WT_MODIFIED == 0)
1838  "# This is a tagged build of NetSurf\n"
1839 #ifdef WT_TAGIS
1840  "# The tag used was '" WT_TAGIS "'\n\n"
1841 #else
1842  "\n"
1843 #endif
1844 #elif defined(WT_NO_SVN) || defined(WT_NO_GIT)
1845  "# This NetSurf was built outside of our revision "
1846  "control environment.\n"
1847  "# This testament is therefore not very useful.\n\n"
1848 #else
1849  "# This NetSurf was built from a branch (" WT_BRANCHPATH ").\n\n"
1850 #endif
1851 #if defined(CI_BUILD)
1852  "# This build carries the CI build number '" CI_BUILD "'\n\n"
1853 #endif
1854  );
1855  if (res != NSERROR_OK) {
1856  goto fetch_about_testament_handler_aborted;
1857  }
1858 
1859  res = ssenddataf(ctx,
1860  "Built by %s (%s) from %s at revision %s on %s\n\n",
1861  GECOS, USERNAME, WT_BRANCHPATH, WT_REVID, WT_COMPILEDATE);
1862  if (res != NSERROR_OK) {
1863  goto fetch_about_testament_handler_aborted;
1864  }
1865 
1866  res = ssenddataf(ctx, "Built on %s in %s\n\n", WT_HOSTNAME, WT_ROOT);
1867  if (res != NSERROR_OK) {
1868  goto fetch_about_testament_handler_aborted;
1869  }
1870 
1871  if (WT_MODIFIED > 0) {
1872  res = ssenddataf(ctx,
1873  "Working tree has %d modification%s\n\n",
1874  WT_MODIFIED, WT_MODIFIED == 1 ? "" : "s");
1875  } else {
1876  res = ssenddataf(ctx, "Working tree is not modified.\n");
1877  }
1878  if (res != NSERROR_OK) {
1879  goto fetch_about_testament_handler_aborted;
1880  }
1881 
1882  for (modidx = 0; modidx < WT_MODIFIED; ++modidx) {
1883  res = ssenddataf(ctx,
1884  " %s %s\n",
1885  modifications[modidx].modtype,
1886  modifications[modidx].leaf);
1887  if (res != NSERROR_OK) {
1888  goto fetch_about_testament_handler_aborted;
1889  }
1890  }
1891 
1893 
1894  return true;
1895 
1896 fetch_about_testament_handler_aborted:
1897  return false;
1898 }
1899 
1900 
1901 /**
1902  * Handler to generate about scheme logo page
1903  *
1904  * \param ctx The fetcher context.
1905  * \return true if handled false if aborted.
1906  */
1908 {
1909  fetch_msg msg;
1910 
1911  /* content is going to return redirect */
1912  fetch_set_http_code(ctx->fetchh, 302);
1913 
1914  msg.type = FETCH_REDIRECT;
1915  msg.data.redirect = "resource:netsurf.png";
1916 
1917  fetch_about_send_callback(&msg, ctx);
1918 
1919  return true;
1920 }
1921 
1922 
1923 /**
1924  * Handler to generate about scheme welcome page
1925  *
1926  * \param ctx The fetcher context.
1927  * \return true if handled false if aborted.
1928  */
1930 {
1931  fetch_msg msg;
1932 
1933  /* content is going to return redirect */
1934  fetch_set_http_code(ctx->fetchh, 302);
1935 
1936  msg.type = FETCH_REDIRECT;
1937  msg.data.redirect = "resource:welcome.html";
1938 
1939  fetch_about_send_callback(&msg, ctx);
1940 
1941  return true;
1942 }
1943 
1944 
1945 /**
1946  * generate the description of the login query
1947  */
1948 static nserror
1950  const char *realm,
1951  const char *username,
1952  const char *password,
1953  char **out_str)
1954 {
1955  nserror res;
1956  char *url_s;
1957  size_t url_l;
1958  char *str = NULL;
1959  const char *key;
1960 
1961  res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
1962  if (res != NSERROR_OK) {
1963  return res;
1964  }
1965 
1966  if ((*username == 0) && (*password == 0)) {
1967  key = "LoginDescription";
1968  } else {
1969  key = "LoginAgain";
1970  }
1971 
1972  str = messages_get_buff(key, url_s, realm);
1973  if (str != NULL) {
1974  NSLOG(netsurf, INFO,
1975  "key:%s url:%s realm:%s str:%s",
1976  key, url_s, realm, str);
1977  *out_str = str;
1978  } else {
1979  res = NSERROR_NOMEM;
1980  }
1981 
1982  free(url_s);
1983 
1984  return res;
1985 }
1986 
1987 
1988 /**
1989  * generate a generic query description
1990  */
1991 static nserror
1993  const char *key,
1994  char **out_str)
1995 {
1996  nserror res;
1997  char *url_s;
1998  size_t url_l;
1999  char *str = NULL;
2000 
2001  /* get the host in question */
2002  res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
2003  if (res != NSERROR_OK) {
2004  return res;
2005  }
2006 
2007  /* obtain the description with the url substituted */
2008  str = messages_get_buff(key, url_s);
2009  if (str == NULL) {
2010  res = NSERROR_NOMEM;
2011  } else {
2012  *out_str = str;
2013  }
2014 
2015  free(url_s);
2016 
2017  return res;
2018 }
2019 
2020 
2021 /**
2022  * Handler to generate about scheme authentication query page
2023  *
2024  * \param ctx The fetcher context.
2025  * \return true if handled false if aborted.
2026  */
2028 {
2029  nserror res;
2030  char *url_s;
2031  size_t url_l;
2032  const char *realm = "";
2033  const char *username = "";
2034  const char *password = "";
2035  const char *title;
2036  char *description = NULL;
2037  struct nsurl *siteurl = NULL;
2038  const struct fetch_multipart_data *curmd; /* mutipart data iterator */
2039 
2040  /* extract parameters from multipart post data */
2041  curmd = ctx->multipart;
2042  while (curmd != NULL) {
2043  if (strcmp(curmd->name, "siteurl") == 0) {
2044  res = nsurl_create(curmd->value, &siteurl);
2045  if (res != NSERROR_OK) {
2046  return fetch_about_srverror(ctx);
2047  }
2048  } else if (strcmp(curmd->name, "realm") == 0) {
2049  realm = curmd->value;
2050  } else if (strcmp(curmd->name, "username") == 0) {
2051  username = curmd->value;
2052  } else if (strcmp(curmd->name, "password") == 0) {
2053  password = curmd->value;
2054  }
2055  curmd = curmd->next;
2056  }
2057 
2058  if (siteurl == NULL) {
2059  return fetch_about_srverror(ctx);
2060  }
2061 
2062  /* content is going to return ok */
2063  fetch_set_http_code(ctx->fetchh, 200);
2064 
2065  /* content type */
2066  if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
2067  goto fetch_about_query_auth_handler_aborted;
2068  }
2069 
2070  title = messages_get("LoginTitle");
2071  res = ssenddataf(ctx,
2072  "<html>\n<head>\n"
2073  "<title>%s</title>\n"
2074  "<link rel=\"stylesheet\" type=\"text/css\" "
2075  "href=\"resource:internal.css\">\n"
2076  "</head>\n"
2077  "<body class=\"ns-even-bg ns-even-fg ns-border\" id =\"authentication\">\n"
2078  "<h1 class=\"ns-border\">%s</h1>\n",
2079  title, title);
2080  if (res != NSERROR_OK) {
2081  goto fetch_about_query_auth_handler_aborted;
2082  }
2083 
2084  res = ssenddataf(ctx,
2085  "<form method=\"post\""
2086  " enctype=\"multipart/form-data\">");
2087  if (res != NSERROR_OK) {
2088  goto fetch_about_query_auth_handler_aborted;
2089  }
2090 
2091  res = get_authentication_description(siteurl,
2092  realm,
2093  username,
2094  password,
2095  &description);
2096  if (res == NSERROR_OK) {
2097  res = ssenddataf(ctx, "<p>%s</p>", description);
2098  free(description);
2099  if (res != NSERROR_OK) {
2100  goto fetch_about_query_auth_handler_aborted;
2101  }
2102  }
2103 
2104  res = ssenddataf(ctx, "<table>");
2105  if (res != NSERROR_OK) {
2106  goto fetch_about_query_auth_handler_aborted;
2107  }
2108 
2109  res = ssenddataf(ctx,
2110  "<tr>"
2111  "<th><label for=\"name\">%s:</label></th>"
2112  "<td><input type=\"text\" id=\"username\" "
2113  "name=\"username\" value=\"%s\"></td>"
2114  "</tr>",
2115  messages_get("Username"), username);
2116  if (res != NSERROR_OK) {
2117  goto fetch_about_query_auth_handler_aborted;
2118  }
2119 
2120  res = ssenddataf(ctx,
2121  "<tr>"
2122  "<th><label for=\"password\">%s:</label></th>"
2123  "<td><input type=\"password\" id=\"password\" "
2124  "name=\"password\" value=\"%s\"></td>"
2125  "</tr>",
2126  messages_get("Password"), password);
2127  if (res != NSERROR_OK) {
2128  goto fetch_about_query_auth_handler_aborted;
2129  }
2130 
2131  res = ssenddataf(ctx, "</table>");
2132  if (res != NSERROR_OK) {
2133  goto fetch_about_query_auth_handler_aborted;
2134  }
2135 
2136  res = ssenddataf(ctx,
2137  "<div id=\"buttons\">"
2138  "<input type=\"submit\" id=\"login\" name=\"login\" "
2139  "value=\"%s\" class=\"default-action\">"
2140  "<input type=\"submit\" id=\"cancel\" name=\"cancel\" "
2141  "value=\"%s\">"
2142  "</div>",
2143  messages_get("Login"),
2144  messages_get("Cancel"));
2145  if (res != NSERROR_OK) {
2146  goto fetch_about_query_auth_handler_aborted;
2147  }
2148 
2149  res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
2150  if (res != NSERROR_OK) {
2151  url_s = strdup("");
2152  }
2153  res = ssenddataf(ctx,
2154  "<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
2155  url_s);
2156  free(url_s);
2157  if (res != NSERROR_OK) {
2158  goto fetch_about_query_auth_handler_aborted;
2159  }
2160 
2161  res = ssenddataf(ctx,
2162  "<input type=\"hidden\" name=\"realm\" value=\"%s\">",
2163  realm);
2164  if (res != NSERROR_OK) {
2165  goto fetch_about_query_auth_handler_aborted;
2166  }
2167 
2168  res = ssenddataf(ctx, "</form></body>\n</html>\n");
2169  if (res != NSERROR_OK) {
2170  goto fetch_about_query_auth_handler_aborted;
2171  }
2172 
2174 
2175  nsurl_unref(siteurl);
2176 
2177  return true;
2178 
2179 fetch_about_query_auth_handler_aborted:
2180 
2181  nsurl_unref(siteurl);
2182 
2183  return false;
2184 }
2185 
2186 
2187 /**
2188  * Handler to generate about scheme privacy query page
2189  *
2190  * \param ctx The fetcher context.
2191  * \return true if handled false if aborted.
2192  */
2194 {
2195  nserror res;
2196  char *url_s;
2197  size_t url_l;
2198  const char *reason = "";
2199  const char *title;
2200  struct nsurl *siteurl = NULL;
2201  char *description = NULL;
2202  const char *chainurl = NULL;
2203  const struct fetch_multipart_data *curmd; /* mutipart data iterator */
2204 
2205  /* extract parameters from multipart post data */
2206  curmd = ctx->multipart;
2207  while (curmd != NULL) {
2208  if (strcmp(curmd->name, "siteurl") == 0) {
2209  res = nsurl_create(curmd->value, &siteurl);
2210  if (res != NSERROR_OK) {
2211  return fetch_about_srverror(ctx);
2212  }
2213  } else if (strcmp(curmd->name, "reason") == 0) {
2214  reason = curmd->value;
2215  } else if (strcmp(curmd->name, "chainurl") == 0) {
2216  chainurl = curmd->value;
2217  }
2218  curmd = curmd->next;
2219  }
2220 
2221  if (siteurl == NULL) {
2222  return fetch_about_srverror(ctx);
2223  }
2224 
2225  /* content is going to return ok */
2226  fetch_set_http_code(ctx->fetchh, 200);
2227 
2228  /* content type */
2229  if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
2230  goto fetch_about_query_ssl_handler_aborted;
2231  }
2232 
2233  title = messages_get("PrivacyTitle");
2234  res = ssenddataf(ctx,
2235  "<html>\n<head>\n"
2236  "<title>%s</title>\n"
2237  "<link rel=\"stylesheet\" type=\"text/css\" "
2238  "href=\"resource:internal.css\">\n"
2239  "</head>\n"
2240  "<body class=\"ns-even-bg ns-even-fg ns-border\" id =\"privacy\">\n"
2241  "<h1 class=\"ns-border ns-odd-fg-bad\">%s</h1>\n",
2242  title, title);
2243  if (res != NSERROR_OK) {
2244  goto fetch_about_query_ssl_handler_aborted;
2245  }
2246 
2247  res = ssenddataf(ctx,
2248  "<form method=\"post\""
2249  " enctype=\"multipart/form-data\">");
2250  if (res != NSERROR_OK) {
2251  goto fetch_about_query_ssl_handler_aborted;
2252  }
2253 
2254  res = get_query_description(siteurl,
2255  "PrivacyDescription",
2256  &description);
2257  if (res == NSERROR_OK) {
2258  res = ssenddataf(ctx, "<div><p>%s</p></div>", description);
2259  free(description);
2260  if (res != NSERROR_OK) {
2261  goto fetch_about_query_ssl_handler_aborted;
2262  }
2263  }
2264 
2265  if (chainurl == NULL) {
2266  res = ssenddataf(ctx,
2267  "<div><p>%s</p></div>"
2268  "<div><p>%s</p></div>",
2269  reason,
2270  messages_get("ViewCertificatesNotPossible"));
2271  } else {
2272  res = ssenddataf(ctx,
2273  "<div><p>%s</p></div>"
2274  "<div><p><a href=\"%s\" target=\"_blank\">%s</a></p></div>",
2275  reason,
2276  chainurl,
2277  messages_get("ViewCertificates"));
2278  }
2279  if (res != NSERROR_OK) {
2280  goto fetch_about_query_ssl_handler_aborted;
2281  }
2282  res = ssenddataf(ctx,
2283  "<div id=\"buttons\">"
2284  "<input type=\"submit\" id=\"back\" name=\"back\" "
2285  "value=\"%s\" class=\"default-action\">"
2286  "<input type=\"submit\" id=\"proceed\" name=\"proceed\" "
2287  "value=\"%s\">"
2288  "</div>",
2289  messages_get("Backtosafety"),
2290  messages_get("Proceed"));
2291  if (res != NSERROR_OK) {
2292  goto fetch_about_query_ssl_handler_aborted;
2293  }
2294 
2295  res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
2296  if (res != NSERROR_OK) {
2297  url_s = strdup("");
2298  }
2299  res = ssenddataf(ctx,
2300  "<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
2301  url_s);
2302  free(url_s);
2303  if (res != NSERROR_OK) {
2304  goto fetch_about_query_ssl_handler_aborted;
2305  }
2306 
2307  res = ssenddataf(ctx, "</form></body>\n</html>\n");
2308  if (res != NSERROR_OK) {
2309  goto fetch_about_query_ssl_handler_aborted;
2310  }
2311 
2313 
2314  nsurl_unref(siteurl);
2315 
2316  return true;
2317 
2318 fetch_about_query_ssl_handler_aborted:
2319  nsurl_unref(siteurl);
2320 
2321  return false;
2322 }
2323 
2324 
2325 /**
2326  * Handler to generate about scheme timeout query page
2327  *
2328  * \param ctx The fetcher context.
2329  * \return true if handled false if aborted.
2330  */
2332 {
2333  nserror res;
2334  char *url_s;
2335  size_t url_l;
2336  const char *reason = "";
2337  const char *title;
2338  struct nsurl *siteurl = NULL;
2339  char *description = NULL;
2340  const struct fetch_multipart_data *curmd; /* mutipart data iterator */
2341 
2342  /* extract parameters from multipart post data */
2343  curmd = ctx->multipart;
2344  while (curmd != NULL) {
2345  if (strcmp(curmd->name, "siteurl") == 0) {
2346  res = nsurl_create(curmd->value, &siteurl);
2347  if (res != NSERROR_OK) {
2348  return fetch_about_srverror(ctx);
2349  }
2350  } else if (strcmp(curmd->name, "reason") == 0) {
2351  reason = curmd->value;
2352  }
2353  curmd = curmd->next;
2354  }
2355 
2356  if (siteurl == NULL) {
2357  return fetch_about_srverror(ctx);
2358  }
2359 
2360  /* content is going to return ok */
2361  fetch_set_http_code(ctx->fetchh, 200);
2362 
2363  /* content type */
2364  if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
2365  goto fetch_about_query_timeout_handler_aborted;
2366  }
2367 
2368  title = messages_get("TimeoutTitle");
2369  res = ssenddataf(ctx,
2370  "<html>\n<head>\n"
2371  "<title>%s</title>\n"
2372  "<link rel=\"stylesheet\" type=\"text/css\" "
2373  "href=\"resource:internal.css\">\n"
2374  "</head>\n"
2375  "<body class=\"ns-even-bg ns-even-fg ns-border\" id =\"timeout\">\n"
2376  "<h1 class=\"ns-border ns-odd-fg-bad\">%s</h1>\n",
2377  title, title);
2378  if (res != NSERROR_OK) {
2379  goto fetch_about_query_timeout_handler_aborted;
2380  }
2381 
2382  res = ssenddataf(ctx,
2383  "<form method=\"post\""
2384  " enctype=\"multipart/form-data\">");
2385  if (res != NSERROR_OK) {
2386  goto fetch_about_query_timeout_handler_aborted;
2387  }
2388 
2389  res = get_query_description(siteurl,
2390  "TimeoutDescription",
2391  &description);
2392  if (res == NSERROR_OK) {
2393  res = ssenddataf(ctx, "<div><p>%s</p></div>", description);
2394  free(description);
2395  if (res != NSERROR_OK) {
2396  goto fetch_about_query_timeout_handler_aborted;
2397  }
2398  }
2399  res = ssenddataf(ctx, "<div><p>%s</p></div>", reason);
2400  if (res != NSERROR_OK) {
2401  goto fetch_about_query_timeout_handler_aborted;
2402  }
2403 
2404  res = ssenddataf(ctx,
2405  "<div id=\"buttons\">"
2406  "<input type=\"submit\" id=\"back\" name=\"back\" "
2407  "value=\"%s\" class=\"default-action\">"
2408  "<input type=\"submit\" id=\"retry\" name=\"retry\" "
2409  "value=\"%s\">"
2410  "</div>",
2411  messages_get("Backtoprevious"),
2412  messages_get("TryAgain"));
2413  if (res != NSERROR_OK) {
2414  goto fetch_about_query_timeout_handler_aborted;
2415  }
2416 
2417  res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
2418  if (res != NSERROR_OK) {
2419  url_s = strdup("");
2420  }
2421  res = ssenddataf(ctx,
2422  "<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
2423  url_s);
2424  free(url_s);
2425  if (res != NSERROR_OK) {
2426  goto fetch_about_query_timeout_handler_aborted;
2427  }
2428 
2429  res = ssenddataf(ctx, "</form></body>\n</html>\n");
2430  if (res != NSERROR_OK) {
2431  goto fetch_about_query_timeout_handler_aborted;
2432  }
2433 
2435 
2436  nsurl_unref(siteurl);
2437 
2438  return true;
2439 
2440 fetch_about_query_timeout_handler_aborted:
2441  nsurl_unref(siteurl);
2442 
2443  return false;
2444 }
2445 
2446 
2447 /**
2448  * Handler to generate about scheme fetch error query page
2449  *
2450  * \param ctx The fetcher context.
2451  * \return true if handled false if aborted.
2452  */
2453 static bool
2455 {
2456  nserror res;
2457  char *url_s;
2458  size_t url_l;
2459  const char *reason = "";
2460  const char *title;
2461  struct nsurl *siteurl = NULL;
2462  char *description = NULL;
2463  const struct fetch_multipart_data *curmd; /* mutipart data iterator */
2464 
2465  /* extract parameters from multipart post data */
2466  curmd = ctx->multipart;
2467  while (curmd != NULL) {
2468  if (strcmp(curmd->name, "siteurl") == 0) {
2469  res = nsurl_create(curmd->value, &siteurl);
2470  if (res != NSERROR_OK) {
2471  return fetch_about_srverror(ctx);
2472  }
2473  } else if (strcmp(curmd->name, "reason") == 0) {
2474  reason = curmd->value;
2475  }
2476  curmd = curmd->next;
2477  }
2478 
2479  if (siteurl == NULL) {
2480  return fetch_about_srverror(ctx);
2481  }
2482 
2483  /* content is going to return ok */
2484  fetch_set_http_code(ctx->fetchh, 200);
2485 
2486  /* content type */
2487  if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
2488  goto fetch_about_query_fetcherror_handler_aborted;
2489  }
2490 
2491  title = messages_get("FetchErrorTitle");
2492  res = ssenddataf(ctx,
2493  "<html>\n<head>\n"
2494  "<title>%s</title>\n"
2495  "<link rel=\"stylesheet\" type=\"text/css\" "
2496  "href=\"resource:internal.css\">\n"
2497  "</head>\n"
2498  "<body class=\"ns-even-bg ns-even-fg ns-border\" id =\"fetcherror\">\n"
2499  "<h1 class=\"ns-border ns-odd-fg-bad\">%s</h1>\n",
2500  title, title);
2501  if (res != NSERROR_OK) {
2502  goto fetch_about_query_fetcherror_handler_aborted;
2503  }
2504 
2505  res = ssenddataf(ctx,
2506  "<form method=\"post\""
2507  " enctype=\"multipart/form-data\">");
2508  if (res != NSERROR_OK) {
2509  goto fetch_about_query_fetcherror_handler_aborted;
2510  }
2511 
2512  res = get_query_description(siteurl,
2513  "FetchErrorDescription",
2514  &description);
2515  if (res == NSERROR_OK) {
2516  res = ssenddataf(ctx, "<div><p>%s</p></div>", description);
2517  free(description);
2518  if (res != NSERROR_OK) {
2519  goto fetch_about_query_fetcherror_handler_aborted;
2520  }
2521  }
2522  res = ssenddataf(ctx, "<div><p>%s</p></div>", reason);
2523  if (res != NSERROR_OK) {
2524  goto fetch_about_query_fetcherror_handler_aborted;
2525  }
2526 
2527  res = ssenddataf(ctx,
2528  "<div id=\"buttons\">"
2529  "<input type=\"submit\" id=\"back\" name=\"back\" "
2530  "value=\"%s\" class=\"default-action\">"
2531  "<input type=\"submit\" id=\"retry\" name=\"retry\" "
2532  "value=\"%s\">"
2533  "</div>",
2534  messages_get("Backtoprevious"),
2535  messages_get("TryAgain"));
2536  if (res != NSERROR_OK) {
2537  goto fetch_about_query_fetcherror_handler_aborted;
2538  }
2539 
2540  res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
2541  if (res != NSERROR_OK) {
2542  url_s = strdup("");
2543  }
2544  res = ssenddataf(ctx,
2545  "<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
2546  url_s);
2547  free(url_s);
2548  if (res != NSERROR_OK) {
2549  goto fetch_about_query_fetcherror_handler_aborted;
2550  }
2551 
2552  res = ssenddataf(ctx, "</form></body>\n</html>\n");
2553  if (res != NSERROR_OK) {
2554  goto fetch_about_query_fetcherror_handler_aborted;
2555  }
2556 
2558 
2559  nsurl_unref(siteurl);
2560 
2561  return true;
2562 
2563 fetch_about_query_fetcherror_handler_aborted:
2564  nsurl_unref(siteurl);
2565 
2566  return false;
2567 }
2568 
2569 
2570 /* Forward declaration because this handler requires the handler table. */
2571 static bool fetch_about_about_handler(struct fetch_about_context *ctx);
2572 
2573 /**
2574  * List of about paths and their handlers
2575  */
2577  {
2578  "credits",
2579  SLEN("credits"),
2580  NULL,
2582  false
2583  },
2584  {
2585  "licence",
2586  SLEN("licence"),
2587  NULL,
2589  false
2590  },
2591  {
2592  "license",
2593  SLEN("license"),
2594  NULL,
2596  true
2597  },
2598  {
2599  "welcome",
2600  SLEN("welcome"),
2601  NULL,
2603  false
2604  },
2605  {
2606  "config",
2607  SLEN("config"),
2608  NULL,
2610  false
2611  },
2612  {
2613  "Choices",
2614  SLEN("Choices"),
2615  NULL,
2617  false
2618  },
2619  {
2620  "testament",
2621  SLEN("testament"),
2622  NULL,
2624  false
2625  },
2626  {
2627  "about",
2628  SLEN("about"),
2629  NULL,
2631  true
2632  },
2633  {
2634  "nscolours.css",
2635  SLEN("nscolours.css"),
2636  NULL,
2638  true
2639  },
2640  {
2641  "logo",
2642  SLEN("logo"),
2643  NULL,
2645  true
2646  },
2647  {
2648  /* details about the image cache */
2649  "imagecache",
2650  SLEN("imagecache"),
2651  NULL,
2653  true
2654  },
2655  {
2656  /* The default blank page */
2657  "blank",
2658  SLEN("blank"),
2659  NULL,
2661  true
2662  },
2663  {
2664  /* details about a certificate */
2665  "certificate",
2666  SLEN("certificate"),
2667  NULL,
2669  true
2670  },
2671  {
2672  "query/auth",
2673  SLEN("query/auth"),
2674  NULL,
2676  true
2677  },
2678  {
2679  "query/ssl",
2680  SLEN("query/ssl"),
2681  NULL,
2683  true
2684  },
2685  {
2686  "query/timeout",
2687  SLEN("query/timeout"),
2688  NULL,
2690  true
2691  },
2692  {
2693  "query/fetcherror",
2694  SLEN("query/fetcherror"),
2695  NULL,
2697  true
2698  }
2699 };
2700 
2701 #define about_handler_list_len \
2702  (sizeof(about_handler_list) / sizeof(struct about_handlers))
2703 
2704 /**
2705  * List all the valid about: paths available
2706  *
2707  * \param ctx The fetch context.
2708  * \return true for sucess or false to generate an error.
2709  */
2711 {
2712  nserror res;
2713  unsigned int abt_loop = 0;
2714 
2715  /* content is going to return ok */
2716  fetch_set_http_code(ctx->fetchh, 200);
2717 
2718  /* content type */
2719  if (fetch_about_send_header(ctx, "Content-Type: text/html"))
2720  goto fetch_about_config_handler_aborted;
2721 
2722  res = ssenddataf(ctx,
2723  "<html>\n<head>\n"
2724  "<title>List of NetSurf pages</title>\n"
2725  "<link rel=\"stylesheet\" type=\"text/css\" "
2726  "href=\"resource:internal.css\">\n"
2727  "</head>\n"
2728  "<body class=\"ns-even-bg ns-even-fg ns-border\">\n"
2729  "<h1 class =\"ns-border\">List of NetSurf pages</h1>\n"
2730  "<ul>\n");
2731  if (res != NSERROR_OK) {
2732  goto fetch_about_config_handler_aborted;
2733  }
2734 
2735  for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
2736 
2737  /* Skip over hidden entries */
2738  if (about_handler_list[abt_loop].hidden)
2739  continue;
2740 
2741  res = ssenddataf(ctx,
2742  "<li><a href=\"about:%s\">about:%s</a></li>\n",
2743  about_handler_list[abt_loop].name,
2744  about_handler_list[abt_loop].name);
2745  if (res != NSERROR_OK) {
2746  goto fetch_about_config_handler_aborted;
2747  }
2748  }
2749 
2750  res = ssenddataf(ctx, "</ul>\n</body>\n</html>\n");
2751  if (res != NSERROR_OK) {
2752  goto fetch_about_config_handler_aborted;
2753  }
2754 
2756 
2757  return true;
2758 
2759 fetch_about_config_handler_aborted:
2760  return false;
2761 }
2762 
2763 static bool
2765 {
2766  nserror res;
2767 
2768  /* content is going to return 404 */
2769  fetch_set_http_code(ctx->fetchh, 404);
2770 
2771  /* content type */
2772  if (fetch_about_send_header(ctx, "Content-Type: text/plain; charset=utf-8")) {
2773  return false;
2774  }
2775 
2776  res = ssenddataf(ctx, "Unknown page: %s", nsurl_access(ctx->url));
2777  if (res != NSERROR_OK) {
2778  return false;
2779  }
2780 
2782 
2783  return true;
2784 }
2785 
2786 /**
2787  * callback to initialise the about scheme fetcher.
2788  */
2789 static bool fetch_about_initialise(lwc_string *scheme)
2790 {
2791  unsigned int abt_loop = 0;
2792  lwc_error error;
2793 
2794  for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
2795  error = lwc_intern_string(about_handler_list[abt_loop].name,
2796  about_handler_list[abt_loop].name_len,
2797  &about_handler_list[abt_loop].lname);
2798  if (error != lwc_error_ok) {
2799  while (abt_loop-- != 0) {
2800  lwc_string_unref(about_handler_list[abt_loop].lname);
2801  }
2802  return false;
2803  }
2804  }
2805 
2806  return true;
2807 }
2808 
2809 
2810 /**
2811  * callback to finalise the about scheme fetcher.
2812  */
2813 static void fetch_about_finalise(lwc_string *scheme)
2814 {
2815  unsigned int abt_loop = 0;
2816  for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
2817  lwc_string_unref(about_handler_list[abt_loop].lname);
2818  }
2819 }
2820 
2821 
2822 static bool fetch_about_can_fetch(const nsurl *url)
2823 {
2824  return true;
2825 }
2826 
2827 
2828 /**
2829  * callback to set up a about scheme fetch.
2830  *
2831  * \param post_urlenc post data in urlenc format, owned by the llcache object
2832  * hence valid the entire lifetime of the fetch.
2833  * \param post_multipart post data in multipart format, owned by the llcache
2834  * object hence valid the entire lifetime of the fetch.
2835  */
2836 static void *
2838  nsurl *url,
2839  bool only_2xx,
2840  bool downgrade_tls,
2841  const char *post_urlenc,
2842  const struct fetch_multipart_data *post_multipart,
2843  const char **headers)
2844 {
2845  struct fetch_about_context *ctx;
2846  unsigned int handler_loop;
2847  lwc_string *path;
2848  bool match;
2849 
2850  ctx = calloc(1, sizeof(*ctx));
2851  if (ctx == NULL)
2852  return NULL;
2853 
2854  path = nsurl_get_component(url, NSURL_PATH);
2855 
2856  for (handler_loop = 0;
2857  handler_loop < about_handler_list_len;
2858  handler_loop++) {
2859  if (lwc_string_isequal(path,
2860  about_handler_list[handler_loop].lname,
2861  &match) == lwc_error_ok && match) {
2862  ctx->handler = about_handler_list[handler_loop].handler;
2863  break;
2864  }
2865  }
2866 
2867  if (path != NULL)
2868  lwc_string_unref(path);
2869 
2870  ctx->fetchh = fetchh;
2871  ctx->url = nsurl_ref(url);
2872  ctx->multipart = post_multipart;
2873 
2874  RING_INSERT(ring, ctx);
2875 
2876  return ctx;
2877 }
2878 
2879 
2880 /**
2881  * callback to free a about scheme fetch
2882  */
2883 static void fetch_about_free(void *ctx)
2884 {
2885  struct fetch_about_context *c = ctx;
2886  nsurl_unref(c->url);
2887  free(ctx);
2888 }
2889 
2890 
2891 /**
2892  * callback to start an about scheme fetch
2893  */
2894 static bool fetch_about_start(void *ctx)
2895 {
2896  return true;
2897 }
2898 
2899 
2900 /**
2901  * callback to abort a about fetch
2902  */
2903 static void fetch_about_abort(void *ctx)
2904 {
2905  struct fetch_about_context *c = ctx;
2906 
2907  /* To avoid the poll loop having to deal with the fetch context
2908  * disappearing from under it, we simply flag the abort here.
2909  * The poll loop itself will perform the appropriate cleanup.
2910  */
2911  c->aborted = true;
2912 }
2913 
2914 
2915 /**
2916  * callback to poll for additional about fetch contents
2917  */
2918 static void fetch_about_poll(lwc_string *scheme)
2919 {
2920  struct fetch_about_context *c, *save_ring = NULL;
2921 
2922  /* Iterate over ring, processing each pending fetch */
2923  while (ring != NULL) {
2924  /* Take the first entry from the ring */
2925  c = ring;
2926  RING_REMOVE(ring, c);
2927 
2928  /* Ignore fetches that have been flagged as locked.
2929  * This allows safe re-entrant calls to this function.
2930  * Re-entrancy can occur if, as a result of a callback,
2931  * the interested party causes fetch_poll() to be called
2932  * again.
2933  */
2934  if (c->locked == true) {
2935  RING_INSERT(save_ring, c);
2936  continue;
2937  }
2938 
2939  /* Only process non-aborted fetches */
2940  if (c->aborted == false) {
2941  /* about fetches can be processed in one go */
2942  if (c->handler == NULL) {
2944  } else {
2945  c->handler(c);
2946  }
2947  }
2948 
2949  /* And now finish */
2951  fetch_free(c->fetchh);
2952  }
2953 
2954  /* Finally, if we saved any fetches which were locked, put them back
2955  * into the ring for next time
2956  */
2957  ring = save_ring;
2958 }
2959 
2960 
2962 {
2963  lwc_string *scheme = lwc_string_ref(corestring_lwc_about);
2964  const struct fetcher_operation_table fetcher_ops = {
2966  .acceptable = fetch_about_can_fetch,
2967  .setup = fetch_about_setup,
2968  .start = fetch_about_start,
2969  .abort = fetch_about_abort,
2970  .free = fetch_about_free,
2971  .poll = fetch_about_poll,
2972  .finalise = fetch_about_finalise
2973  };
2974 
2975  return fetcher_add(scheme, &fetcher_ops);
2976 }
int name_len
Definition: about.c:82
static bool fetch_about_testament_handler(struct fetch_about_context *ctx)
Generate the text of an svn testament which represents the current build-tree status.
Definition: about.c:1815
nserror fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *ops)
Register a fetcher for a scheme.
Definition: fetch.c:358
struct fetch_multipart_data * next
Next in linked list.
Definition: fetch.h:100
struct cert_chain::@57 certs[MAX_CERT_DEPTH]
static void fetch_about_free(void *ctx)
callback to free a about scheme fetch
Definition: about.c:2883
static bool fetch_about_start(void *ctx)
callback to start an about scheme fetch
Definition: about.c:2894
static void fetch_about_abort(void *ctx)
callback to abort a about fetch
Definition: about.c:2903
static nserror get_authentication_description(struct nsurl *url, const char *realm, const char *username, const char *password, char **out_str)
generate the description of the login query
Definition: about.c:1949
static void fetch_about_finalise(lwc_string *scheme)
callback to finalise the about scheme fetcher.
Definition: about.c:2813
bool hidden
If entry should be hidden in listing.
Definition: about.c:85
Interface to utility string handling.
char * locality
Definition: about.c:446
Functionality is not implemented.
Definition: errors.h:61
Localised message support (interface).
Certificate public key parameters.
Definition: about.c:454
char * organisation
Definition: about.c:444
Memory exhaustion.
Definition: errors.h:32
lwc_string * lname
Interned name.
Definition: about.c:83
char * not_after
Valid to date.
Definition: about.c:480
const char * leaf
Definition: about.c:1804
certificate information for certificate chain
Definition: about.c:474
const char * redirect
Definition: fetch.h:86
const char * modtype
Definition: about.c:1805
nserror nsurl_get(const nsurl *url, nsurl_component parts, char **url_s, size_t *url_l)
Get URL (section) as a string, from a NetSurf URL object.
size_t depth
the number of certificates in the chain
Definition: ssl_certs.h:63
Fetch POST multipart data.
Definition: fetch.h:99
char * public
Definition: about.c:460
char * name
Definition: about.c:468
char * name
Name of item.
Definition: fetch.h:102
static bool fetch_about_logo_handler(struct fetch_about_context *ctx)
Handler to generate about scheme logo page.
Definition: about.c:1907
#define RING_INSERT(ring, element)
Insert the given item into the specified ring.
Definition: ring.h:40
static bool fetch_about_imagecache_handler(struct fetch_about_context *ctx)
Handler to generate about:imagecache page.
Definition: about.c:299
Option reading and saving interface.
const char * messages_get_sslcode(ssl_cert_err code)
lookup of a message by SSL error code from the standard Messages hash.
Definition: messages.c:405
char * country
Definition: about.c:448
Ring list structure.
static bool fetch_about_welcome_handler(struct fetch_about_context *ctx)
Handler to generate about scheme welcome page.
Definition: about.c:1929
Invalid data.
Definition: errors.h:49
#define SLEN(x)
Calculate length of constant C string.
Definition: utils.h:84
plotter style interfaces, generic styles and style colour helpers.
nserror
Enumeration of error codes.
Definition: errors.h:29
static bool fetch_about_srverror(struct fetch_about_context *ctx)
Generate a 500 server error respnse.
Definition: about.c:190
void fetch_remove_from_queues(struct fetch *fetch)
remove a queued fetch
Definition: fetch.c:808
static nserror ssenddataf(struct fetch_about_context *ctx, const char *fmt,...)
send formatted data on a fetch
Definition: about.c:133
static bool fetch_about_send_header(struct fetch_about_context *ctx, const char *fmt,...)
Definition: about.c:111
long version
Certificate version.
Definition: about.c:478
char * algor
Definition: about.c:455
char * province
Definition: about.c:447
nserror nsurl_create(const char *const url_s, nsurl **url)
Create a NetSurf URL object from a URL string.
Useful interned string pointers (interface).
const struct fetch_multipart_data * multipart
post data
Definition: about.c:70
Fetcher operations API.
Definition: fetchers.h:49
static nserror format_certificate_san(struct fetch_about_context *ctx, struct ns_cert_san *san)
output formatted certificate subject alternate names
Definition: about.c:1216
struct ns_cert_san * next
Definition: about.c:467
fetch_about_handler handler
handler for the url
Definition: about.c:84
static nserror format_certificate_name(struct fetch_about_context *ctx, struct ns_cert_name *cert_name)
Definition: about.c:1153
#define colour_rb_swap(c)
Definition: plot_style.h:221
static bool fetch_about_send_finished(struct fetch_about_context *ctx)
Definition: about.c:103
char * sha256fingerprint
fingerprint shar256 encoded
Definition: about.c:485
int image_cache_snentryf(char *string, size_t size, unsigned int entryn, const char *fmt)
Fill a buffer with information about a cache entry using a format.
Definition: image_cache.c:692
No error.
Definition: errors.h:30
#define PRIsizet
c99 standard printf formatting for size_t type
Definition: inttypes.h:53
struct fetch_about_context * r_prev
Definition: about.c:61
bool(* initialise)(lwc_string *scheme)
The initialiser for the fetcher.
Definition: fetchers.h:55
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:115
uint8_t * der
data in Distinguished Encoding Rules (DER) format
Definition: ssl_certs.h:73
#define RING_REMOVE(ring, element)
Remove the given element from the specified ring.
Definition: ring.h:53
fetch_about_handler handler
Definition: about.c:72
union fetch_msg::@118 data
void fetch_set_http_code(struct fetch *fetch, long http_code)
set the http code of a fetch
Definition: fetch.c:835
struct about_handlers about_handler_list[]
List of about paths and their handlers.
Definition: about.c:2576
void fetch_free(struct fetch *f)
Free a fetch structure and associated resources.
Definition: fetch.c:589
struct ns_cert_pkey public_key
public key details
Definition: about.c:477
bool locked
Flag indicating entry is already entered.
Definition: about.c:66
static nserror free_ns_cert_info(struct ns_cert_info *cinfo)
free all resources associated with a certificate information structure
Definition: about.c:493
static struct fetch_about_context * ring
Definition: about.c:75
lwc_string * nsurl_get_component(const nsurl *url, nsurl_component part)
Get part of a URL as a lwc_string, from a NetSurf URL object.
bool aborted
Flag indicating fetch has been aborted.
Definition: about.c:65
static osspriteop_area * buffer
The buffer characteristics.
Definition: buffer.c:55
static nserror format_certificate(struct fetch_about_context *ctx, struct ns_cert_info *cert_info, size_t depth)
Definition: about.c:1358
Bad Parameter.
Definition: errors.h:48
static bool fetch_about_query_fetcherror_handler(struct fetch_about_context *ctx)
Handler to generate about scheme fetch error query page.
Definition: about.c:2454
struct ns_cert_name issuer_name
Issuer details.
Definition: about.c:476
int image_cache_snsummaryf(char *string, size_t size, const char *fmt)
Fill a buffer with information about the image cache using a format.
Definition: image_cache.c:585
struct ns_cert_san * san
subject alternative names
Definition: about.c:486
char * exponent
Definition: about.c:458
char * serialnum
Serial number.
Definition: about.c:483
static bool fetch_about_certificate_handler(struct fetch_about_context *ctx)
Handler to generate about:certificate page.
Definition: about.c:1493
static bool fetch_about_choices_handler(struct fetch_about_context *ctx)
Generate the text of a Choices file which represents the current in use options.
Definition: about.c:1747
static bool fetch_about_credits_handler(struct fetch_about_context *ctx)
Handler to generate about scheme credits page.
Definition: about.c:253
char * value
Item value.
Definition: fetch.h:103
char X509
Definition: curl.c:116
handler info for about scheme
Definition: about.c:80
static bool fetch_about_query_auth_handler(struct fetch_about_context *ctx)
Handler to generate about scheme authentication query page.
Definition: about.c:2027
X509 certificate chain.
Definition: ssl_certs.h:59
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
static nserror format_certificate_fingerprint(struct fetch_about_context *ctx, struct ns_cert_info *cert_info)
Definition: about.c:1315
char * not_before
Valid from date.
Definition: about.c:479
Netsurf additional integer type formatting macros.
bool(* fetch_about_handler)(struct fetch_about_context *)
Definition: about.c:55
ssl_cert_err err
Whatever is wrong with this certificate.
Definition: ssl_certs.h:68
static bool fetch_about_licence_handler(struct fetch_about_context *ctx)
Handler to generate about scheme licence page.
Definition: about.c:275
nserror cert_chain_free(struct cert_chain *chain)
free a certificate chain
Definition: ssl_certs.c:296
ssl_cert_err err
Whatever is wrong with this certificate.
Definition: about.c:487
colour nscolours[NSCOLOUR__COUNT]
NetSurf UI colour table.
Definition: nscolour.c:37
static nserror get_query_description(struct nsurl *url, const char *key, char **out_str)
generate a generic query description
Definition: about.c:1992
ssl_cert_err
ssl certificate error status
Definition: ssl_certs.h:36
int sig_type
Signature type.
Definition: about.c:481
Interface to system colour values.
static bool fetch_about_404_handler(struct fetch_about_context *ctx)
Definition: about.c:2764
nsurl * url
The full url the fetch refers to.
Definition: about.c:68
static bool fetch_about_nscolours_handler(struct fetch_about_context *ctx)
Handler to generate the nscolours stylesheet.
Definition: about.c:1701
static bool fetch_about_initialise(lwc_string *scheme)
callback to initialise the about scheme fetcher.
Definition: about.c:2789
Interface for fetchers factory.
nsurl * nsurl_ref(nsurl *url)
Increment the reference count to a NetSurf URL object.
size_t der_length
DER length.
Definition: ssl_certs.h:78
Context for an about fetch.
Definition: about.c:60
static nserror format_certificate_public_key(struct fetch_about_context *ctx, struct ns_cert_pkey *public_key)
Definition: about.c:1251
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plot.c:821
Certificate subject alternative name.
Definition: about.c:466
nserror fetch_about_register(void)
Register about scheme handler.
Definition: about.c:2961
static nserror convert_chain_to_cert_info(const struct cert_chain *chain, struct ns_cert_info **cert_info_out)
Definition: about.c:1144
struct fetch_about_context * r_next
Definition: about.c:61
Interface to a number of general purpose functionality.
Insufficient space.
Definition: errors.h:59
char * sha1fingerprint
fingerprint shar1 encoded
Definition: about.c:484
nserror nscolour_get_stylesheet(const char **stylesheet_out)
Get a pointer to a stylesheet for nscolours.
Definition: nscolour.c:205
Information for a single fetch.
Definition: fetch.c:89
char * sig_algor
Signature Algorithm.
Definition: about.c:482
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
Fetcher message data.
Definition: fetch.h:72
Fetching of data from a URL (interface).
char * curve
Definition: about.c:459
static bool fetch_about_blank_handler(struct fetch_about_context *ctx)
Handler to generate about scheme cache page.
Definition: about.c:217
static bool fetch_about_can_fetch(const nsurl *url)
Definition: about.c:2822
fetch_msg_type type
Definition: fetch.h:73
about: URL method handler
void fetch_send_callback(const fetch_msg *msg, struct fetch *fetch)
send message to fetch
Definition: fetch.c:798
struct fetch * fetchh
Handle for this fetch.
Definition: about.c:63
int size
Definition: about.c:456
char * messages_get_buff(const char *key,...)
Formatted message from a key in the global message hash.
Definition: messages.c:205
char * modulus
Definition: about.c:457
struct ns_cert_name subject_name
Subject details.
Definition: about.c:475
#define about_handler_list_len
Definition: about.c:2701
static void * fetch_about_setup(struct fetch *fetchh, nsurl *url, bool only_2xx, bool downgrade_tls, const char *post_urlenc, const struct fetch_multipart_data *post_multipart, const char **headers)
callback to set up a about scheme fetch.
Definition: about.c:2837
static bool fetch_about_query_timeout_handler(struct fetch_about_context *ctx)
Handler to generate about scheme timeout query page.
Definition: about.c:2331
struct fetch_msg::@118::@119 header_or_data
Nothing wrong with this certificate.
Definition: ssl_certs.h:37
char * common_name
Definition: about.c:443
nserror cert_chain_from_query(struct nsurl *url, struct cert_chain **chain_out)
create a certificate chain from a fetch query string
Definition: ssl_certs.c:169
certificate name parameters
Definition: about.c:442
int nsoption_snoptionf(char *string, size_t size, enum nsoption_e option_idx, const char *fmt)
Fill a buffer with an option using a format.
Definition: nsoption.c:897
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
static bool fetch_about_query_privacy_handler(struct fetch_about_context *ctx)
Handler to generate about scheme privacy query page.
Definition: about.c:2193
SSL certificate info.
Definition: curl.c:214
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
NetSurf UI colours (interface).
static bool fetch_about_config_handler(struct fetch_about_context *ctx)
Handler to generate about scheme config page.
Definition: about.c:1599
The image content handler intermediate image cache.
static void fetch_about_poll(lwc_string *scheme)
callback to poll for additional about fetch contents
Definition: about.c:2918
static bool fetch_about_send_callback(const fetch_msg *msg, struct fetch_about_context *ctx)
issue fetch callbacks with locking
Definition: about.c:93
static bool fetch_about_about_handler(struct fetch_about_context *ctx)
List all the valid about: paths available.
Definition: about.c:2710
const char * name
name to match in url
Definition: about.c:81
char * organisation_unit
Definition: about.c:445