[Openvas-commits] r409 - in trunk/openvas-libnasl: . nasl

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Oct 5 16:40:35 CEST 2007


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  <bh at intevation.de>
 
+	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  <bh at intevation.de>
+
 	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 <bernhard.herzog at intevation.de>
+ *
+ * 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 <bernhard.herzog at intevation.de>
+ *
+ * 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



More information about the Openvas-commits mailing list