Author: bh
Date: 2007-10-05 16:40:35 +0200 (Fri, 05 Oct 2007)
New Revision: 409
Added:
trunk/openvas-libnasl/nasl/nasl_signature.c
trunk/openvas-libnasl/nasl/nasl_signature.h
Modified:
trunk/openvas-libnasl/ChangeLog
trunk/openvas-libnasl/nasl/Makefile
trunk/openvas-libnasl/nasl/nasl_crypto2.c
trunk/openvas-libnasl/nasl/nasl_crypto2.h
trunk/openvas-libnasl/nasl/nasl_grammar.y
Log:
Implement the GnuPG based detached signatures for nasl scripts.
* nasl/nasl_signature.c, nasl/nasl_signature.h: New. GPGME base
signature verification with the new function nasl_verify_signature
* nasl/nasl_grammar.y (init_nasl_ctx): Check detached gpg
signatures now, using nasl_verify_signature instead of the old
verify_script_signature
* nasl/nasl_crypto2.c (hexdecode, verify_script_signature):
Removed. The functions are no longer uses.
* nasl/nasl_crypto2.h (verify_script_signature): Removed.
* nasl/Makefile (NESSUS_CFLAGS, +NESSUS_LIBS): Add GPGME options
(OBJS, LO_OBJS): Add nasl_signature.
Modified: trunk/openvas-libnasl/ChangeLog
===================================================================
--- trunk/openvas-libnasl/ChangeLog 2007-10-05 14:29:19 UTC (rev 408)
+++ trunk/openvas-libnasl/ChangeLog 2007-10-05 14:40:35 UTC (rev 409)
@@ -1,5 +1,24 @@
2007-10-05 Bernhard Herzog <[EMAIL PROTECTED]>
+ Implement the GnuPG based detached signatures for nasl scripts.
+
+ * nasl/nasl_signature.c, nasl/nasl_signature.h: New. GPGME base
+ signature verification with the new function nasl_verify_signature
+
+ * nasl/nasl_grammar.y (init_nasl_ctx): Check detached gpg
+ signatures now, using nasl_verify_signature instead of the old
+ verify_script_signature
+
+ * nasl/nasl_crypto2.c (hexdecode, verify_script_signature):
+ Removed. The functions are no longer uses.
+
+ * nasl/nasl_crypto2.h (verify_script_signature): Removed.
+
+ * nasl/Makefile (NESSUS_CFLAGS, +NESSUS_LIBS): Add GPGME options
+ (OBJS, LO_OBJS): Add nasl_signature.
+
+2007-10-05 Bernhard Herzog <[EMAIL PROTECTED]>
+
Add simple support for GPGME to configure
* configure.in: Add check for GPGME
Modified: trunk/openvas-libnasl/nasl/Makefile
===================================================================
--- trunk/openvas-libnasl/nasl/Makefile 2007-10-05 14:29:19 UTC (rev 408)
+++ trunk/openvas-libnasl/nasl/Makefile 2007-10-05 14:40:35 UTC (rev 409)
@@ -23,8 +23,8 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
include ../nasl.tmpl
-NESSUS_CFLAGS= -I../include $(OPTIMIZE) `$(LIBOPENVASCONFIG) --cflags`
-DNESSUS_EXTENSIONS
-NESSUS_LIBS = $(LIBS) `$(LIBOPENVASCONFIG) --libs`
+NESSUS_CFLAGS= -I../include $(OPTIMIZE) `$(LIBOPENVASCONFIG) --cflags`
`$(GPGME_CONFIG) --cflags` -DNESSUS_EXTENSIONS
+NESSUS_LIBS = $(LIBS) `$(LIBOPENVASCONFIG) --libs` `$(GPGME_CONFIG) --libs`
NESSUS_INCLUDE=`sh ./cflags`
@@ -56,6 +56,7 @@
lfind.o \
preparse.o \
nasl_server.o \
+ nasl_signature.o \
nasl_debug.o
LO_OBJS = \
@@ -83,6 +84,7 @@
lfind.lo \
preparse.lo \
nasl_server.lo \
+ nasl_signature.lo \
nasl_debug.lo
COMPILE = $(LIBTOOL) $(CC) $(CFLAGS) $(NESSUS_INCLUDE)
@@ -130,8 +132,10 @@
nasl_cmd_exec.o: nasl_cmd_exec.c
$(COMPILE) -c -DNESSUS_STATE_DIR=\"$(localstatedir)\" nasl_cmd_exec.c
-
+nasl_signature.o: nasl_signature.c
+ $(COMPILE) -c -DOPENVAS_SYSCONFDIR=\"$(sysconfdir)\" nasl_signature.c
+
nasl_func.o: nasl_func.c nasl_var.h
nasl_var.o: nasl_var.c nasl_var.h
Modified: trunk/openvas-libnasl/nasl/nasl_crypto2.c
===================================================================
--- trunk/openvas-libnasl/nasl/nasl_crypto2.c 2007-10-05 14:29:19 UTC (rev
408)
+++ trunk/openvas-libnasl/nasl/nasl_crypto2.c 2007-10-05 14:40:35 UTC (rev
409)
@@ -1297,111 +1297,3 @@
return result;
}
-/* Decodes a sequence of hexadecimal numbers. */
-static ptrdiff_t
-hexdecode(unsigned char *to, const unsigned char * from)
-{
- char temp[3] = {0, 0, 0};
- unsigned char * start = to;
-
- while (from[0] && from[1])
- {
- temp[0] = from[0];
- temp[1] = from[1];
- *to = strtoul(temp, NULL, 16);
- to += 1;
- from += 2;
- }
-
- return to - start;
-}
-
-/*
- * Verify a script signature
- *
- * In the original OpenSSL based code the public key was stored in a
- * format that GnuTLS cannot read. The new code requires a real x509
- * certificate.
- *
- * Returns :
- * -1 : if an error occured
- * 0 : if the signature matches
- * 1 : if the signature does NOT match
- */
-int
-verify_script_signature(char * filename)
-{
- const char * pemfilename = NESSUS_STATE_DIR "/openvas/openvas_org.pem";
- char * t;
- int be_len;
- gnutls_x509_crt_t cert = NULL;
- gnutls_datum_t pem = {NULL, 0};
- gnutls_datum_t script = {NULL, 0};
- gnutls_datum_t data_to_hash;
- gnutls_datum_t signature;
- int result = -1;
- int err;
-
- pem = map_file(pemfilename);
- if (!pem.data)
- goto fail;
-
- err = gnutls_x509_crt_init(&cert);
- if (err)
- {
- print_tls_error(NULL, "gnutls_x509_crt_init", err);
- goto fail;
- }
-
- err = gnutls_x509_crt_import(cert, &pem, GNUTLS_X509_FMT_PEM);
- if (err)
- {
- print_tls_error(NULL, "gnutls_x509_crt_import", err);
- goto fail;
- }
-
- script = map_file(filename);
- if (!script.data)
- {
- goto fail;
- }
-
- /* Make room for the size of the file at the end of the script */
- script.data = erealloc(script.data, script.size + sizeof(be_len));
-
- /* split the script into the signature (first line) and the rest */
- t = strchr((char*)script.data, '\n');
- if (t == NULL)
- goto fail;
- t[0] = '\0'; t++;
-
- /* The data to hash is the rest with the size of the rest appended */
- data_to_hash.data = (unsigned char*)t;
- data_to_hash.size = script.size - (data_to_hash.data - script.data);
- be_len = htonl(data_to_hash.size);
- memcpy(data_to_hash.data + data_to_hash.size, &be_len, sizeof(be_len));
- data_to_hash.size += sizeof(be_len);
-
- /* decode the hex signature. We can do it in place because the binary
- * signature is always shorter than it's hexadecimal
- * representation. Also, the caller has already checked that the
- * script starts with "#TRUSTED", so we can simply skip it here */
- signature.data = script.data;
- signature.size = hexdecode(signature.data, script.data + strlen("#TRUSTED
"));
-
- err = gnutls_x509_crt_verify_data(cert, 0, &data_to_hash, &signature);
- if (err < 0)
- {
- print_tls_error(NULL, "gnutls_x509_crt_verify_data", err);
- goto fail;
- }
-
- result = err == 1 ? 0 : 1;
-
- fail:
- gnutls_x509_crt_deinit(cert);
- efree(&script.data);
- efree(&pem);
-
- return result;
-}
Modified: trunk/openvas-libnasl/nasl/nasl_crypto2.h
===================================================================
--- trunk/openvas-libnasl/nasl/nasl_crypto2.h 2007-10-05 14:29:19 UTC (rev
408)
+++ trunk/openvas-libnasl/nasl/nasl_crypto2.h 2007-10-05 14:40:35 UTC (rev
409)
@@ -44,6 +44,5 @@
tree_cell * nasl_dsa_do_sign(lex_ctxt* lexic);
-int verify_script_signature(char *);
int generate_script_signature(char *);
#endif
Modified: trunk/openvas-libnasl/nasl/nasl_grammar.y
===================================================================
--- trunk/openvas-libnasl/nasl/nasl_grammar.y 2007-10-05 14:29:19 UTC (rev
408)
+++ trunk/openvas-libnasl/nasl/nasl_grammar.y 2007-10-05 14:40:35 UTC (rev
409)
@@ -30,7 +30,7 @@
#include "nasl_var.h"
#include "nasl_lex_ctxt.h"
#include "nasl_debug.h"
-#include "nasl_crypto2.h"
+#include "nasl_signature.h"
static void naslerror(const char *);
#define YYERROR_VERBOSE
@@ -476,7 +476,6 @@
int
init_nasl_ctx(naslctxt* pc, const char* name)
{
- char line[1024];
char full_name[MAXPATHLEN];
#ifdef MULTIPLE_INCLUDE_DIRS
static const char* inc_dirs[] = { ".", "/tmp" }; /* TBD */
@@ -521,32 +520,26 @@
pc->authenticated = 1;
else
{
- fgets(line, sizeof(line) - 1, pc->fp);
- line[sizeof(line) - 1] = '\0';
- if (strncmp(line, "#TRUSTED", strlen("#TRUSTED")) == 0)
- {
- int sig;
- full_name[sizeof(full_name) - 1] = '\0';
- sig = verify_script_signature(full_name);
- if (sig == 0)
- pc->authenticated = 1;
- else
- pc->authenticated = 0;
+ int sig;
+ full_name[sizeof(full_name) - 1] = '\0';
+ sig = nasl_verify_signature(full_name);
+ if (sig == 0)
+ pc->authenticated = 1;
+ else
+ pc->authenticated = 0;
- if (sig > 0)
- {
- fprintf(stderr, "%s: bad signature."
- " Will not execute this script\n", full_name);
- fclose(pc->fp);
- pc->fp = NULL;
- return -1;
- }
- else if (sig < 0)
- fprintf(stderr, "%s: Could not verify the signature -"
- " this script will be run in non-authenticated mode\n",
- full_name);
+ if (sig > 0)
+ {
+ fprintf(stderr, "%s: bad signature."
+ " Will not execute this script\n", full_name);
+ fclose(pc->fp);
+ pc->fp = NULL;
+ return -1;
}
- rewind(pc->fp);
+ else if (sig < 0)
+ fprintf(stderr, "%s: Could not verify the signature -"
+ " this script will be run in non-authenticated mode\n",
+ full_name);
}
return 0;
}
Added: trunk/openvas-libnasl/nasl/nasl_signature.c
===================================================================
--- trunk/openvas-libnasl/nasl/nasl_signature.c 2007-10-05 14:29:19 UTC (rev
408)
+++ trunk/openvas-libnasl/nasl/nasl_signature.c 2007-10-05 14:40:35 UTC (rev
409)
@@ -0,0 +1,205 @@
+/* OpenVAS-LibNASL
+ *
+ * Authors:
+ * Bernhard Herzog <[EMAIL PROTECTED]>
+ *
+ * Copyright:
+ * Copyright (C) 2007 Intevation GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * or, at your option, any later version as published by the Free
+ * Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <gpgme.h>
+
+#include <includes.h>
+#include "nasl_tree.h"
+#include "nasl_var.h"
+#include "nasl_func.h"
+#include "nasl_lex_ctxt.h"
+#include "nasl_debug.h"
+
+
+/*
+ * Prints an error message for errors returned by gpgme.
+ */
+static void
+print_gpgme_error(char *function, gpgme_error_t err)
+{
+ nasl_perror(NULL, "%s failed: %s/%s\n",
+ function, gpgme_strsource(err), gpgme_strerror(err));
+}
+
+/*
+ * Checks whether the signature verification result has at least one
+ * signature and whether all signatures are fully valid. The function
+ * returns 1 if all signatures are fully valid and 0 otherwise.
+ */
+static int
+examine_signatures(gpgme_verify_result_t result)
+{
+ int num_sigs = 0;
+ int num_valid = 0;
+ gpgme_signature_t sig;
+
+ nasl_trace(NULL, "examine_signatures\n");
+
+ sig = result->signatures;
+ while (sig)
+ {
+ num_sigs += 1;
+
+ if (nasl_trace_enabled())
+ {
+ nasl_trace(NULL, "examine_signatures: signature #%d:\n", num_sigs);
+ nasl_trace(NULL, "examine_signatures: summary: %d\n",
+ sig->summary);
+ nasl_trace(NULL, "examine_signatures: validity: %d\n",
+ sig->validity);
+ nasl_trace(NULL, "examine_signatures: status: %s\n",
+ gpg_strerror(sig->status));
+ nasl_trace(NULL, "examine_signatures: timestamp: %ld\n",
+ sig->timestamp);
+ nasl_trace(NULL, "examine_signatures: exp_timestamp: %ld\n",
+ sig->exp_timestamp);
+ nasl_trace(NULL, "examine_signatures: fpr: %s\n", sig->fpr);
+ }
+
+ if (sig->summary & GPGME_SIGSUM_VALID)
+ {
+ nasl_trace(NULL, "examine_signatures: signature is valid\n");
+ num_valid += 1;
+ }
+ else
+ {
+ nasl_trace(NULL, "examine_signatures: signature is invalid\n");
+ }
+ sig = sig->next;
+ }
+
+ return num_sigs > 0 && num_sigs == num_valid;
+}
+
+/*
+ * Returns the name of the GnuPG home directory to use when checking
+ * GnuPG signatures. The return value is the value of the environment
+ * variable OPENVAS_GPGHOME if it is set. Otherwise it is the directory
+ * openvas/gnupg under the sysconfdir that was set by configure (usually
+ * $prefix/etc). The return value has been created by estrdup and must
+ * be deallocated by efree.
+ */
+static char *
+determine_gpghome()
+{
+ char * default_dir = OPENVAS_SYSCONFDIR "/openvas/gnupg";
+ char * envdir = getenv("OPENVAS_GPGHOME");
+
+ return estrdup(envdir ? envdir : default_dir);
+}
+
+/*
+ * Checks the detached OpenPGP signature of the file given by FILENAME.
+ * The name of the signature file is derived from FILENAME by appending
+ * ".asc".
+ *
+ * If a signature file exists and it contains only fully valid
+ * signatures, the function returns 0. If any of the signatures is not
+ * valid or was made by an unknown or untrusted key, the function
+ * returns 1. If an error occurs or the file does not have a
+ * corresponding detached signature the function returns -1.
+ */
+int
+nasl_verify_signature(const char* filename)
+{
+ int retcode = -1;
+ char * sigfilename = NULL;
+ gpgme_error_t err;
+ gpgme_ctx_t ctx = NULL;
+ gpgme_data_t sig = NULL, text = NULL;
+ char * gpghome = determine_gpghome();
+
+ err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
+ if (err)
+ {
+ print_gpgme_error("gpgme_engine_check_version", err);
+ goto fail;
+ }
+ err = gpgme_new(&ctx);
+ if (err)
+ {
+ print_gpgme_error("gpgme_new", err);
+ goto fail;
+ }
+
+ nasl_trace(NULL, "nasl_verify_signature: setting homedir '%s'\n", gpghome);
+ err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, NULL,
+ gpghome);
+ if (err)
+ {
+ print_gpgme_error("gpgme_ctx_set_engine_info", err);
+ goto fail;
+ }
+
+ nasl_trace(NULL, "nasl_verify_signature: loading scriptfile '%s'\n",
+ filename);
+ err = gpgme_data_new_from_file(&text, filename, 1);
+ if (err)
+ {
+ print_gpgme_error("gpgme_data_new_from_file", err);
+ goto fail;
+ }
+
+ sigfilename = emalloc(strlen(filename) + 4 + 1);
+ strcpy(sigfilename, filename);
+ strcat(sigfilename, ".asc");
+ nasl_trace(NULL, "nasl_verify_signature: loading signature file '%s'\n",
+ sigfilename);
+ err = gpgme_data_new_from_file(&sig, sigfilename, 1);
+ if (err)
+ {
+ /* If the file doesn't exist, fail without an error message
+ * because an unsigned file is a very common and expected
+ * condition */
+ if (gpgme_err_code(err) != GPG_ERR_ENOENT)
+ print_gpgme_error("gpgme_data_new_from_file", err);
+ else
+ nasl_trace(NULL, "nasl_verify_signature: %s: %s\n",
+ sigfilename, gpgme_strerror(err));
+ goto fail;
+ }
+
+ err = gpgme_op_verify(ctx, sig, text, NULL);
+ nasl_trace(NULL, "nasl_verify_signature: gpgme_op_verify -> '%d'\n", err);
+ if (err)
+ {
+ print_gpgme_error("gpgme_op_verify", err);
+ goto fail;
+ }
+
+ if (examine_signatures(gpgme_op_verify_result(ctx)))
+ retcode = 0;
+ else
+ retcode = 1;
+
+ fail:
+ gpgme_data_release(sig);
+ gpgme_data_release(text);
+ gpgme_release(ctx);
+ efree(&sigfilename);
+ efree(&gpghome);
+
+ return retcode;
+}
Property changes on: trunk/openvas-libnasl/nasl/nasl_signature.c
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Added: trunk/openvas-libnasl/nasl/nasl_signature.h
===================================================================
--- trunk/openvas-libnasl/nasl/nasl_signature.h 2007-10-05 14:29:19 UTC (rev
408)
+++ trunk/openvas-libnasl/nasl/nasl_signature.h 2007-10-05 14:40:35 UTC (rev
409)
@@ -0,0 +1,30 @@
+/* OpenVAS-LibNASL
+ *
+ * Authors:
+ * Bernhard Herzog <[EMAIL PROTECTED]>
+ *
+ * Copyright:
+ * Copyright (C) 2007 Intevation GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * or, at your option, any later version as published by the Free
+ * Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef NASL_SIGNATURE_H
+#define NASL_SIGNATURE_H
+
+int nasl_verify_signature(const char* filename);
+
+
+#endif
Property changes on: trunk/openvas-libnasl/nasl/nasl_signature.h
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
_______________________________________________
Openvas-commits mailing list
[email protected]
http://lists.wald.intevation.org/mailman/listinfo/openvas-commits