OpenVAS Scanner  7.0.1~git
nasl_cert.c
Go to the documentation of this file.
1 /* Copyright (C) 2012-2019 Greenbone Networks GmbH
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program 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, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
29 #ifdef HAVE_LIBKSBA
30 #include "nasl_cert.h"
31 
32 #include "nasl_debug.h"
33 #include "nasl_func.h"
34 #include "nasl_global_ctxt.h"
35 #include "nasl_lex_ctxt.h"
36 #include "nasl_tree.h"
37 #include "nasl_var.h"
38 
39 #include <errno.h>
40 #include <gcrypt.h>
41 #include <glib.h>
42 #include <glib/gstdio.h>
43 #include <gnutls/gnutls.h>
44 #include <gnutls/x509.h>
45 #include <gvm/base/logging.h>
46 #include <ksba.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 
52 #undef G_LOG_DOMAIN
53 
56 #define G_LOG_DOMAIN "lib nasl"
57 
58 #ifndef DIM
59 #define DIM(v) (sizeof (v) / sizeof ((v)[0]))
60 #define DIMof(type, member) DIM (((type *) 0)->member)
61 #endif
62 
63 /* Useful helper macros to avoid problems with locales. */
64 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
65 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
66 #define hexdigitp(a) \
67  (digitp (a) || (*(a) >= 'A' && *(a) <= 'F') || (*(a) >= 'a' && *(a) <= 'f'))
68 
69 /* The atoi macros assume that the buffer has only valid digits. */
70 #define atoi_1(p) (*(p) - '0')
71 #define atoi_2(p) ((atoi_1 (p) * 10) + atoi_1 ((p) + 1))
72 #define atoi_4(p) ((atoi_2 (p) * 100) + atoi_2 ((p) + 2))
73 #define xtoi_1(p) \
74  (*(p) <= '9' ? (*(p) - '0') \
75  : *(p) <= 'F' ? (*(p) - 'A' + 10) : (*(p) - 'a' + 10))
76 #define xtoi_2(p) \
77  ((xtoi_1 ((const unsigned char *) (p)) * 16) \
78  + xtoi_1 ((const unsigned char *) (p) + 1))
79 
80 /* Convert N to a hex digit. N must be in the range 0..15. */
81 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) -10) + 'A'))
82 
83 /* This object is used to keep track of KSBA certificate objects.
84  Because they are pointers they can't be mapped easily to the NASL
85  type system. Our solution is to track those objects here and clean
86  up any left over context at the end of a script run. We could use
87  the undocumented "on_exit" feature but that one is not well
88  implemented; thus we use explicit code in the interpreter for the
89  cleanup. The scripts are expected to close the objects, but as
90  long as they don't open too many of them, the system will take care
91  of it at script termination time.
92 
93  We associate each object with an object id, which is a global
94  counter of this process. An object id of 0 marks an unused table
95  entry.
96  */
97 struct object_desc_s;
98 typedef struct object_desc_s *object_desc_t;
99 struct object_desc_s
100 {
101  object_desc_t next;
102  int object_id;
103  ksba_cert_t cert;
104 };
105 
106 /* A linked list of all used certificate objects. */
107 static object_desc_t object_list;
108 
109 /* Return the next object id. */
110 static int
111 next_object_id (void)
112 {
113  static int last;
114  static int wrapped;
115 
116 again:
117  last++;
118  /* Because we don't have an unsigned type, it is better to avoid
119  negative values. Thus if LAST turns negative we wrap around to
120  the 1; this also avoids the verboten zero. */
121  if (last <= 0)
122  {
123  last = 1;
124  wrapped = 1;
125  }
126 
127  /* If the counter wrapped we need to check that we do not return an
128  object id still in use. We use a stupid simple retry algorithm;
129  this could be improved, for example, by remembering gaps in the
130  list of used ids. This code part is anyway not easy to test
131  unless we implement a test feature for this function. */
132  if (wrapped)
133  {
134  object_desc_t obj;
135 
136  for (obj = object_list; obj; obj = obj->next)
137  if (obj->object_id == last)
138  goto again;
139  }
140  return last;
141 }
142 
171 tree_cell *
172 nasl_cert_open (lex_ctxt *lexic)
173 {
174  gpg_error_t err;
175  tree_cell *retc;
176  const char *data;
177  int datalen;
178  ksba_reader_t reader;
179  ksba_cert_t cert;
180  object_desc_t obj;
181 
182  data = get_str_var_by_num (lexic, 0);
183  if (!data || !(datalen = get_var_size_by_num (lexic, 0)))
184  {
185  g_message ("No certificate passed to cert_open");
186  return NULL;
187  }
188 
189  err = ksba_reader_new (&reader);
190  if (err)
191  {
192  g_message ("Opening reader object failed: %s", gpg_strerror (err));
193  return NULL;
194  }
195  err = ksba_reader_set_mem (reader, data, datalen);
196  if (err)
197  {
198  g_message ("ksba_reader_set_mem failed: %s", gpg_strerror (err));
199  ksba_reader_release (reader);
200  return NULL;
201  }
202 
203  err = ksba_cert_new (&cert);
204  if (err)
205  {
206  g_message ("ksba_cert_new failed: %s", gpg_strerror (err));
207  ksba_reader_release (reader);
208  return NULL;
209  }
210 
211  err = ksba_cert_read_der (cert, reader);
212  if (err)
213  {
214  g_message ("Certificate parsing failed: %s", gpg_strerror (err));
215  /* FIXME: Try again this time assuming a PEM certificate. */
216  ksba_reader_release (reader);
217  ksba_cert_release (cert);
218  return NULL;
219  }
220  ksba_reader_release (reader);
221 
222  obj = g_try_malloc (sizeof *obj);
223  if (!obj)
224  {
225  g_message ("malloc failed in %s", __FUNCTION__);
226  ksba_cert_release (cert);
227  return NULL;
228  }
229  obj->object_id = next_object_id ();
230  obj->cert = cert;
231  obj->next = object_list;
232  object_list = obj;
233 
234  /* Return the session id. */
235  retc = alloc_typed_cell (CONST_INT);
236  retc->x.i_val = obj->object_id;
237  return retc;
238 }
239 
257 tree_cell *
258 nasl_cert_close (lex_ctxt *lexic)
259 {
260  int object_id;
261  object_desc_t prevobj, obj;
262 
263  object_id = get_int_var_by_num (lexic, 0, -1);
264  if (!object_id)
265  return FAKE_CELL;
266  if (object_id < 0)
267  {
268  g_message ("Bad object id %d passed to cert_close", object_id);
269  return FAKE_CELL;
270  }
271 
272  for (prevobj = NULL, obj = object_list; obj; prevobj = obj, obj = obj->next)
273  if (obj->object_id == object_id)
274  break;
275  if (!obj)
276  {
277  g_message ("Unused object id %d passed to cert_close", object_id);
278  return FAKE_CELL;
279  }
280 
281  if (prevobj)
282  prevobj->next = obj->next;
283  else
284  object_list = obj->next;
285 
286  ksba_cert_release (obj->cert);
287  g_free (obj);
288 
289  return FAKE_CELL;
290 }
291 
292 /* Helper to get the value of the Common Name part. */
293 static const char *
294 parse_dn_part_for_CN (const char *string, char **r_value)
295 {
296  const char *s, *s1;
297  size_t n;
298  char *p = NULL;
299  int found;
300 
301  *r_value = NULL;
302 
303  /* Parse attributeType */
304  for (s = string + 1; *s && *s != '='; s++)
305  ;
306  if (!*s)
307  return NULL; /* Error */
308  n = s - string;
309  if (!n)
310  return NULL; /* Empty key */
311 
312  found = (n == 2 && string[0] == 'C' && string[1] == 'N');
313  string = s + 1;
314 
315  if (*string == '#') /* Hex encoded value. */
316  {
317  string++;
318  for (s = string; hexdigitp (s); s++)
319  s++;
320  n = s - string;
321  if (!n || (n & 1))
322  return NULL; /* No or odd number of digits. */
323  n /= 2;
324  if (found)
325  *r_value = p = g_malloc0 (n + 1);
326 
327  for (s1 = string; n; s1 += 2, n--, p++)
328  {
329  if (found)
330  {
331  *(unsigned char *) p = xtoi_2 (s1);
332  if (!*p)
333  *p = 0x01; /* Better return a wrong value than
334  truncate the string. */
335  }
336  }
337  if (found)
338  *p = 0;
339  }
340  else /* Regular V3 quoted string */
341  {
342  for (n = 0, s = string; *s; s++)
343  {
344  if (*s == '\\') /* Pair */
345  {
346  s++;
347  if (*s == ',' || *s == '=' || *s == '+' || *s == '<' || *s == '>'
348  || *s == '#' || *s == ';' || *s == '\\' || *s == '\"'
349  || *s == ' ')
350  n++;
351  else if (hexdigitp (s) && hexdigitp (s + 1))
352  {
353  s++;
354  n++;
355  }
356  else
357  return NULL; /* Invalid escape sequence. */
358  }
359  else if (*s == '\"')
360  return NULL; /* Invalid encoding. */
361  else if (*s == ',' || *s == '=' || *s == '+' || *s == '<' || *s == '>'
362  || *s == ';')
363  break; /* End of that part. */
364  else
365  n++;
366  }
367 
368  if (found)
369  *r_value = p = g_malloc0 (n + 1);
370 
371  for (s = string; n; s++, n--)
372  {
373  if (*s == '\\')
374  {
375  s++;
376  if (hexdigitp (s))
377  {
378  if (found)
379  {
380  *(unsigned char *) p = xtoi_2 (s);
381  if (!*p)
382  *p = 0x01; /* Better return a wrong value than
383  truncate the string. */
384  p++;
385  }
386  s++;
387  }
388  else if (found)
389  *p++ = *s;
390  }
391  else if (found)
392  *p++ = *s;
393  }
394  if (found)
395  *p = 0;
396  }
397  return s;
398 }
399 
400 /* Parse a DN and return the value of the CommonName. Note that this
401  is not a validating parser and it does not support any old-stylish
402  syntax; this is not a problem because KSBA will always return
403  RFC-2253 compatible strings. The caller must use free to free the
404  returned value. */
405 static char *
406 parse_dn_for_CN (const char *string)
407 {
408  char *value = NULL;
409 
410  while (*string && !value)
411  {
412  while (*string == ' ')
413  string++;
414  if (!*string)
415  break; /* ready */
416  string = parse_dn_part_for_CN (string, &value);
417  if (!string)
418  goto failure;
419  while (*string == ' ')
420  string++;
421  if (*string && *string != ',' && *string != ';' && *string != '+')
422  goto failure; /* Invalid delimiter. */
423  if (*string == '+')
424  goto failure; /* A multivalued CN is not supported. */
425  if (*string)
426  string++;
427  }
428  return value;
429 
430 failure:
431  g_free (value);
432  return NULL;
433 }
434 
435 /* Given a CERT object, build an array with all hostnames identified
436  by the certifciate. */
437 static tree_cell *
438 build_hostname_list (ksba_cert_t cert)
439 {
440  tree_cell *retc;
441  char *name, *value;
442  int arridx;
443  int idx;
444  nasl_array *a;
445  anon_nasl_var v;
446 
447  name = ksba_cert_get_subject (cert, 0);
448  if (!name)
449  return NULL; /* No valid subject. */
450 
451  retc = alloc_typed_cell (DYN_ARRAY);
452  retc->x.ref_val = a = g_malloc0 (sizeof *a);
453  arridx = 0;
454 
455  value = parse_dn_for_CN (name);
456  ksba_free (name);
457 
458  /* Add the CN to the array even if it doesn't look like a hostname. */
459  if (value)
460  {
461  memset (&v, 0, sizeof v);
462  v.var_type = VAR2_DATA;
463  v.v.v_str.s_val = (unsigned char *) value;
464  v.v.v_str.s_siz = strlen (value);
465  add_var_to_list (a, arridx++, &v);
466  }
467  g_free (value);
468  value = NULL;
469 
470  for (idx = 1; (name = ksba_cert_get_subject (cert, idx)); idx++)
471  {
472  /* Poor man's s-expression parser. Despite it simple code, it
473  is correct in this case because ksba will always return a
474  valid s-expression. */
475  if (*name == '(' && name[1] == '8' && name[2] == ':'
476  && !memcmp (name + 3, "dns-name", 8))
477  {
478  char *endp;
479  unsigned long n = strtoul (name + 11, &endp, 10);
480 
481  if (*endp != ':')
482  {
483  ksba_free (name);
484  return NULL;
485  }
486  endp++;
487  memset (&v, 0, sizeof v);
488  v.var_type = VAR2_DATA;
489  v.v.v_str.s_val = (unsigned char *) endp;
490  v.v.v_str.s_siz = n;
491  add_var_to_list (a, arridx++, &v);
492  }
493  ksba_free (name);
494  }
495 
496  return retc;
497 }
498 
503 static tree_cell *
504 make_hexstring (const void *buffer, size_t length)
505 {
506  const unsigned char *s;
507  tree_cell *retc;
508  char *p;
509 
510  retc = alloc_typed_cell (CONST_STR);
511  retc->size = length * 2;
512  retc->x.str_val = p = g_malloc0 (length * 2 + 1);
513 
514  for (s = buffer; length; length--, s++)
515  {
516  *p++ = tohex ((*s >> 4) & 15);
517  *p++ = tohex (*s & 15);
518  }
519  *p = 0;
520 
521  return retc;
522 }
523 
533 static tree_cell *
534 get_fingerprint (ksba_cert_t cert, int algo)
535 {
536  int dlen;
537  const unsigned char *der;
538  size_t derlen;
539  unsigned char digest[32];
540 
541  dlen = gcry_md_get_algo_dlen (algo);
542  if (dlen != 20 && dlen != 32)
543  return NULL; /* We only support SHA-1 and SHA-256. */
544 
545  der = ksba_cert_get_image (cert, &derlen);
546  if (!der)
547  return NULL;
548  gcry_md_hash_buffer (algo, digest, der, derlen);
549 
550  return make_hexstring (digest, dlen);
551 }
552 
553 /*
554  * @brief Return algorithm name from its OID.
555  *
556  * param[in] oid Algorithm ID.
557  *
558  * @return Algorithm name or NULL.
559  */
560 static const char *
561 get_oid_name (const char *oid)
562 {
563  /* Initial list from Wireshark. See epan/dissectors/packet-pkcs1.c */
564  if (!strcmp ("1.2.840.10040.4.1", oid))
565  return "id-dsa";
566  else if (!strcmp ("1.2.840.10046.2.1", oid))
567  return "dhpublicnumber";
568  else if (!strcmp ("2.16.840.1.101.2.1.1.22", oid))
569  return "id-keyExchangeAlgorithm";
570  else if (!strcmp ("1.2.840.10045.2.1", oid))
571  return "id-ecPublicKey";
572  else if (!strcmp ("1.3.132.1.12", oid))
573  return "id-ecDH";
574  else if (!strcmp ("1.2.840.10045.2.13", oid))
575  return "id-ecMQV";
576  else if (!strcmp ("1.2.840.113549.1.1.10", oid))
577  return "id-RSASSA-PSS";
578  else if (!strcmp ("1.2.840.113549.1.1.11", oid))
579  return "sha256WithRSAEncryption";
580  else if (!strcmp ("1.2.840.113549.1.1.12", oid))
581  return "sha384WithRSAEncryption";
582  else if (!strcmp ("1.2.840.113549.1.1.13", oid))
583  return "sha512WithRSAEncryption";
584  else if (!strcmp ("1.2.840.113549.1.1.14", oid))
585  return "sha224WithRSAEncryption";
586  else if (!strcmp ("1.2.840.113549.1.1.8", oid))
587  return "id-mgf1";
588  else if (!strcmp ("1.2.840.113549.2.2", oid))
589  return "md2";
590  else if (!strcmp ("1.2.840.113549.2.4", oid))
591  return "md4";
592  else if (!strcmp ("1.2.840.113549.2.5", oid))
593  return "md5";
594  else if (!strcmp ("1.2.840.113549.1.1.1", oid))
595  return "rsaEncryption";
596  else if (!strcmp ("1.2.840.113549.1.1.2", oid))
597  return "md2WithRSAEncryption";
598  else if (!strcmp ("1.2.840.113549.1.1.3", oid))
599  return "md4WithRSAEncryption";
600  else if (!strcmp ("1.2.840.113549.1.1.4", oid))
601  return "md5WithRSAEncryption";
602  else if (!strcmp ("1.2.840.113549.1.1.5", oid))
603  return "sha1WithRSAEncryption";
604  else if (!strcmp ("1.2.840.113549.1.1.6", oid))
605  return "rsaOAEPEncryptionSET";
606  else if (!strcmp ("1.2.840.10045.3.1.1", oid))
607  return "secp192r1";
608  else if (!strcmp ("1.3.132.0.1", oid))
609  return "sect163k1";
610  else if (!strcmp ("1.3.132.0.15", oid))
611  return "sect163r2";
612  else if (!strcmp ("1.3.132.0.33", oid))
613  return "secp224r1";
614  else if (!strcmp ("1.3.132.0.26", oid))
615  return "sect233k1";
616  else if (!strcmp ("1.3.132.0.27", oid))
617  return "sect233r1";
618  else if (!strcmp ("1.2.840.10045.3.1.7", oid))
619  return "secp256r1";
620  else if (!strcmp ("1.3.132.0.16", oid))
621  return "sect283k1";
622  else if (!strcmp ("1.3.132.0.17", oid))
623  return "sect283r1";
624  else if (!strcmp ("1.3.132.0.34", oid))
625  return "secp384r1";
626  else if (!strcmp ("1.3.132.0.36", oid))
627  return "sect409k1";
628  else if (!strcmp ("1.3.132.0.37", oid))
629  return "sect409r1";
630  else if (!strcmp ("1.3.132.0.35", oid))
631  return "sect521r1";
632  else if (!strcmp ("1.3.132.0.38", oid))
633  return "sect571k1";
634  else if (!strcmp ("1.3.132.0.39", oid))
635  return "sect571r1";
636  else
637  return NULL;
638 }
639 
646 static tree_cell *
647 get_name (const char *string)
648 {
649  tree_cell *retc;
650 
651  if (*string == '(')
652  {
653  /* This is an s-expression in canonical format. We convert it
654  to advanced format. */
655  gcry_sexp_t sexp;
656  size_t len;
657  char *buffer;
658 
659  len = gcry_sexp_canon_len ((const unsigned char *) string, 0, NULL, NULL);
660  if (gcry_sexp_sscan (&sexp, NULL, string, len))
661  return NULL; /* Invalid encoding. */
662  len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
663  if (!len)
664  return NULL;
665  buffer = g_malloc0 (len);
666  len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, buffer, len);
667  if (!len)
668  return NULL;
669  len = strlen (buffer);
670  /* Strip a trailing linefeed. */
671  if (len && buffer[len - 1] == '\n')
672  buffer[--len] = 0;
673  gcry_sexp_release (sexp);
674  retc = alloc_typed_cell (CONST_STR);
675  retc->x.str_val = buffer;
676  retc->size = len;
677  }
678  else
679  {
680  /* RFC-2822 style mailboxes or RFC-2253 strings are returned
681  verbatim. */
682  retc = alloc_typed_cell (CONST_STR);
683  retc->x.str_val = g_strdup (string);
684  retc->size = strlen (retc->x.str_val);
685  }
686 
687  return retc;
688 }
689 
757 tree_cell *
758 nasl_cert_query (lex_ctxt *lexic)
759 {
760  int object_id;
761  object_desc_t obj;
762  const char *command;
763  int cmdidx;
764  char *result;
765  ksba_isotime_t isotime;
766  ksba_sexp_t sexp;
767  tree_cell *retc;
768 
769  object_id = get_int_var_by_num (lexic, 0, -1);
770  if (object_id <= 0)
771  {
772  g_message ("Bad object id %d passed to cert_query", object_id);
773  return NULL;
774  }
775 
776  for (obj = object_list; obj; obj = obj->next)
777  if (obj->object_id == object_id)
778  break;
779  if (!obj)
780  {
781  g_message ("Unused object id %d passed to cert_query", object_id);
782  return NULL;
783  }
784 
785  /* Check that the command is a string. */
786  command = get_str_var_by_num (lexic, 1);
787  if (!command || get_var_type_by_num (lexic, 1) != VAR2_STRING)
788  {
789  g_message ("No proper command passed to cert_query");
790  return NULL;
791  }
792 
793  /* Get the index which defaults to 0. */
794  cmdidx = get_int_var_by_name (lexic, "idx", 0);
795 
796  /* Command dispatcher. */
797  retc = NULL;
798  if (!strcmp (command, "serial"))
799  {
800  const unsigned char *s;
801  char *endp;
802  unsigned long n;
803 
804  sexp = ksba_cert_get_serial (obj->cert);
805  s = sexp;
806  if (!s || *s != '(')
807  return NULL; /* Ooops. */
808  s++;
809  n = strtoul ((const char *) s, &endp, 10);
810  s = (const unsigned char *) endp;
811  if (*s == ':')
812  {
813  s++;
814  retc = make_hexstring (s, n);
815  }
816  ksba_free (sexp);
817  }
818  else if (!strcmp (command, "issuer"))
819  {
820  result = ksba_cert_get_issuer (obj->cert, cmdidx);
821  if (!result)
822  return NULL;
823 
824  retc = get_name (result);
825  ksba_free (result);
826  }
827  else if (!strcmp (command, "subject"))
828  {
829  result = ksba_cert_get_subject (obj->cert, cmdidx);
830  if (!result)
831  return NULL;
832 
833  retc = get_name (result);
834  ksba_free (result);
835  }
836  else if (!strcmp (command, "not-before"))
837  {
838  ksba_cert_get_validity (obj->cert, 0, isotime);
839  retc = alloc_typed_cell (CONST_STR);
840  retc->x.str_val = g_strdup (isotime);
841  retc->size = strlen (isotime);
842  }
843  else if (!strcmp (command, "not-after"))
844  {
845  ksba_cert_get_validity (obj->cert, 1, isotime);
846  retc = alloc_typed_cell (CONST_STR);
847  retc->x.str_val = g_strdup (isotime);
848  retc->size = strlen (isotime);
849  }
850  else if (!strcmp (command, "fpr-sha-256"))
851  {
852  retc = get_fingerprint (obj->cert, GCRY_MD_SHA256);
853  }
854  else if (!strcmp (command, "fpr-sha-1"))
855  {
856  retc = get_fingerprint (obj->cert, GCRY_MD_SHA1);
857  }
858  else if (!strcmp (command, "all"))
859  {
860  /* FIXME */
861  }
862  else if (!strcmp (command, "hostnames"))
863  {
864  retc = build_hostname_list (obj->cert);
865  }
866  else if (!strcmp (command, "image"))
867  {
868  const unsigned char *der;
869  size_t derlen;
870 
871  der = ksba_cert_get_image (obj->cert, &derlen);
872  if (der && derlen)
873  {
874  retc = alloc_typed_cell (CONST_DATA);
875  retc->size = derlen;
876  retc->x.str_val = g_malloc0 (derlen);
877  memcpy (retc->x.str_val, der, derlen);
878  }
879  }
880  else if (!strcmp (command, "algorithm-name"))
881  {
882  const char *digest = ksba_cert_get_digest_algo (obj->cert);
883  if (digest)
884  {
885  const char *name = get_oid_name (digest);
886  if (!name)
887  name = digest;
888  retc = alloc_typed_cell (CONST_STR);
889  retc->x.str_val = g_strdup (name);
890  retc->size = strlen (name);
891  }
892  }
893  else if (!strcmp (command, "modulus"))
894  {
895  gnutls_datum_t datum, m, e;
896  gnutls_x509_crt_t cert = NULL;
897 
898  datum.data =
899  (void *) ksba_cert_get_image (obj->cert, (size_t *) &datum.size);
900  if (!datum.data)
901  return NULL;
902  if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS)
903  return NULL;
904  if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER)
905  != GNUTLS_E_SUCCESS)
906  return NULL;
907  if (gnutls_x509_crt_get_pk_rsa_raw (cert, &m, &e) != GNUTLS_E_SUCCESS)
908  return NULL;
909 
910  retc = alloc_typed_cell (CONST_DATA);
911  retc->size = m.size;
912  retc->x.str_val = g_memdup (m.data, m.size);
913  gnutls_free (m.data);
914  gnutls_free (e.data);
915  gnutls_x509_crt_deinit (cert);
916  }
917  else if (!strcmp (command, "exponent"))
918  {
919  gnutls_datum_t datum, m, e;
920  gnutls_x509_crt_t cert = NULL;
921 
922  datum.data =
923  (void *) ksba_cert_get_image (obj->cert, (size_t *) &datum.size);
924  if (!datum.data)
925  return NULL;
926  if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS)
927  return NULL;
928  if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER)
929  != GNUTLS_E_SUCCESS)
930  return NULL;
931  if (gnutls_x509_crt_get_pk_rsa_raw (cert, &m, &e) != GNUTLS_E_SUCCESS)
932  return NULL;
933 
934  retc = alloc_typed_cell (CONST_DATA);
935  retc->size = e.size;
936  retc->x.str_val = g_memdup (e.data, e.size);
937  gnutls_free (m.data);
938  gnutls_free (e.data);
939  gnutls_x509_crt_deinit (cert);
940  }
941  else if (!strcmp (command, "key-size"))
942  {
943  gnutls_datum_t datum;
944  gnutls_x509_crt_t cert = NULL;
945  unsigned int bits = 0;
946 
947  datum.data =
948  (void *) ksba_cert_get_image (obj->cert, (size_t *) &datum.size);
949  if (!datum.data)
950  return NULL;
951  if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS)
952  return NULL;
953  if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER)
954  != GNUTLS_E_SUCCESS)
955  return NULL;
956  gnutls_x509_crt_get_pk_algorithm (cert, &bits);
957  gnutls_free (datum.data);
958  gnutls_x509_crt_deinit (cert);
959 
960  retc = alloc_typed_cell (CONST_INT);
961  retc->x.i_val = bits;
962  }
963  else
964  {
965  g_message ("Unknown command '%s' passed to cert_query", command);
966  }
967 
968  return retc;
969 }
970 
971 #endif /* HAVE_LIBKSBA */
Protos and data structures for CERT functions used by NASL scripts.
tree_cell * nasl_cert_open(lex_ctxt *lexic)
#define FAKE_CELL
Definition: nasl_tree.h:119
tree_cell * nasl_cert_query(lex_ctxt *lexic)
char * str_val
Definition: nasl_tree.h:112
const char * oid
void * ref_val
Definition: nasl_tree.h:114
nasl_string_t v_str
Definition: nasl_var.h:58
int add_var_to_list(nasl_array *a, int i, const anon_nasl_var *v)
Definition: nasl_var.c:1254
tree_cell * alloc_typed_cell(int typ)
Definition: nasl_tree.c:40
int var_type
Definition: nasl_var.h:52
Definition: nasl_tree.h:104
int get_var_size_by_num(lex_ctxt *, int)
Definition: nasl_var.c:1154
union TC::@2 x
tree_cell * nasl_cert_close(lex_ctxt *lexic)
const char * name
Definition: nasl_init.c:377
long int get_int_var_by_num(lex_ctxt *, int, int)
Definition: nasl_var.c:1106
char * get_str_var_by_num(lex_ctxt *, int)
Definition: nasl_var.c:1120
long int get_int_var_by_name(lex_ctxt *, const char *, int)
Definition: nasl_var.c:1113
union st_a_nasl_var::@4 v
long int i_val
Definition: nasl_tree.h:113
unsigned char * s_val
Definition: nasl_var.h:37
int get_var_type_by_num(lex_ctxt *, int)
Returns NASL variable/cell type, VAR2_UNDEF if value is NULL.
Definition: nasl_var.c:1164
int size
Definition: nasl_tree.h:109