OpenVAS Scanner  22.7.9
nasl_signature.c
Go to the documentation of this file.
1 /* SPDX-FileCopyrightText: 2023 Greenbone AG
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  */
5 
6 #include "nasl_signature.h"
7 
8 #include "nasl_debug.h"
9 #include "nasl_func.h"
10 #include "nasl_lex_ctxt.h"
11 #include "nasl_tree.h"
12 #include "nasl_var.h"
13 
14 #include <gvm/util/gpgmeutils.h>
15 #include <locale.h> /* for LC_CTYPE */
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h> /* for strlen */
19 
26 static void
27 print_gpgme_error (char *function, gpgme_error_t err)
28 {
29  nasl_perror (NULL, "%s failed: %s/%s\n", function, gpgme_strsource (err),
30  gpgme_strerror (err));
31 }
32 
43 static int
44 examine_signatures (gpgme_verify_result_t result, int sig_count)
45 {
46  gpgme_signature_t sig;
47 
48  nasl_trace (NULL, "examine_signatures\n");
49 
50  sig = result->signatures;
51 
52  if (nasl_trace_enabled ())
53  {
54  nasl_trace (NULL, "examine_signatures: signature #%d:\n", sig_count);
55  nasl_trace (NULL, "examine_signatures: summary: %d\n", sig->summary);
56  nasl_trace (NULL, "examine_signatures: validity: %d\n", sig->validity);
57  nasl_trace (NULL, "examine_signatures: status: %s\n",
58  gpg_strerror (sig->status));
59  nasl_trace (NULL, "examine_signatures: timestamp: %ld\n",
60  sig->timestamp);
61  nasl_trace (NULL, "examine_signatures: exp_timestamp: %ld\n",
62  sig->exp_timestamp);
63  nasl_trace (NULL, "examine_signatures: fpr: %s\n", sig->fpr);
64  }
65 
66  if (sig->summary & GPGME_SIGSUM_VALID)
67  {
68  nasl_trace (NULL, "examine_signatures: signature is valid\n");
69  return 1;
70  }
71  else
72  {
73  nasl_trace (NULL, "examine_signatures: signature is invalid\n");
74  }
75 
76  return 0;
77 }
78 
97 int
98 nasl_verify_signature (const char *filename, const char *fcontent, size_t flen)
99 {
100  int retcode = -1, sig_count = 0;
101  char *sigfilename = NULL;
102  gsize siglen = 0;
103  gchar *scontent = NULL;
104  gchar *offset = NULL;
105  gchar *endpos = NULL;
106  gchar *path = g_build_filename (OPENVAS_GPG_BASE_DIR, "gnupg", NULL);
107  gboolean success;
108  gpgme_error_t err;
109  gpgme_ctx_t ctx = gvm_init_gpgme_ctx_from_dir (path);
110  gpgme_data_t sig = NULL, text = NULL;
111 
112  g_free (path);
113  if (ctx == NULL)
114  {
115  nasl_trace (NULL, "gpgme context could not be initialized.\n");
116  goto fail;
117  }
118 
119  /* Signatures file is buffered. */
120  sigfilename = g_malloc0 (strlen (filename) + 4 + 1);
121  strcpy (sigfilename, filename);
122  strcat (sigfilename, ".asc");
123  nasl_trace (NULL, "nasl_verify_signature: loading signature file '%s'\n",
124  sigfilename);
125 
126  success = g_file_get_contents (sigfilename, &scontent, NULL, NULL);
127  /* If the signature file doesn't exist, fail without an error message
128  * because an unsigned file is a very common and expected
129  * condition */
130  if (!success)
131  goto fail;
132 
133  /* Start to parse the signature file to find signatures. */
134  offset = g_strstr_len (scontent, strlen (scontent), "-----B");
135  if (!offset)
136  {
137  nasl_trace (NULL, "nasl_verify_signature: No signature in '%s'\n",
138  sigfilename);
139  goto fail;
140  }
141  endpos = g_strstr_len (offset, -1, "-----E");
142  if (endpos)
143  siglen = strlen (offset) - strlen (endpos) + 17;
144  else
145  {
146  nasl_trace (NULL, "nasl_verify_signature: No signature in '%s'\n",
147  sigfilename);
148  goto fail;
149  }
150 
151  do
152  {
153  sig_count++;
154 
155  /* Load file in memory. */
156  err = gpgme_data_new_from_mem (&text, fcontent, flen, 1);
157  if (err)
158  {
159  print_gpgme_error ("gpgme_data_new_from_file", err);
160  goto fail;
161  }
162 
163  /* Load a founded signature in memory. */
164  err = gpgme_data_new_from_mem (&sig, offset, siglen, 1);
165  if (err)
166  nasl_trace (NULL, "nasl_verify_signature: %s: %s\n", sigfilename,
167  gpgme_strerror (err));
168 
169  /* Verify the signature. */
170  err = gpgme_op_verify (ctx, sig, text, NULL);
171  nasl_trace (NULL,
172  "nasl_verify_signature: gpgme_op_verify "
173  "-> '%d'\n",
174  err);
175  if (err)
176  print_gpgme_error ("gpgme_op_verify", err);
177  else
178  {
179  if (examine_signatures (gpgme_op_verify_result (ctx), sig_count))
180  {
181  retcode = 0;
182  goto fail;
183  }
184  else
185  retcode = 1;
186  }
187 
188  /* Search a new signature. */
189  offset = g_strstr_len (offset + 1, strlen (offset), "-----B");
190  if (offset)
191  {
192  if ((endpos = g_strstr_len (offset, strlen (offset), "-----E")))
193  siglen = (strlen (offset) - strlen (endpos) + 17);
194  else
195  {
196  nasl_trace (NULL, "nasl_verify_signature: No signature in '%s'\n",
197  sigfilename);
198  goto fail;
199  }
200  }
201 
202  gpgme_data_release (sig);
203  sig = NULL;
204  gpgme_data_release (text);
205  text = NULL;
206  }
207  while (offset);
208 
209 fail:
210  g_free (scontent);
211  if (sig)
212  gpgme_data_release (sig);
213  if (text)
214  gpgme_data_release (text);
215  if (ctx != NULL)
216  gpgme_release (ctx);
217  g_free (sigfilename);
218 
219  return retcode;
220 }
nasl_trace
void nasl_trace(lex_ctxt *lexic, char *msg,...)
Prints debug message in printf fashion to nasl_trace_fp if it exists.
Definition: nasl_debug.c:175
nasl_signature.h
nasl_debug.h
nasl_perror
void nasl_perror(lex_ctxt *lexic, char *msg,...)
Definition: nasl_debug.c:111
nasl_trace_enabled
int nasl_trace_enabled(void)
Checks if the nasl_trace_fp is set.
Definition: nasl_debug.c:161
nasl_lex_ctxt.h
nasl_func.h
nasl_var.h
examine_signatures
static int examine_signatures(gpgme_verify_result_t result, int sig_count)
Checks whether the signature verification result contains one.
Definition: nasl_signature.c:44
nasl_verify_signature
int nasl_verify_signature(const char *filename, const char *fcontent, size_t flen)
Definition: nasl_signature.c:98
print_gpgme_error
static void print_gpgme_error(char *function, gpgme_error_t err)
Prints an error message for errors returned by gpgme.
Definition: nasl_signature.c:27
nasl_tree.h