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