Add pathfinder support for certificate validation
authorpixdamix <pixdamix@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>
Thu, 5 Nov 2009 08:46:33 +0000 (08:46 +0000)
committerpixdamix <pixdamix@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>
Thu, 5 Nov 2009 08:46:33 +0000 (08:46 +0000)
  From http://code.google.com/p/pathfinder-pki/

       PathFinder is designed to provide a mechanism for any program to
       perform RFC3280-compliant path validation of X509 certificates,
       even when some of the intermediate certificates are not present
       on the local machine. By design, Pathfinder automatically
       downloads any such certificates from the Internet as needed using
       the AIA and CRL distribution point extensions of the certificates
       it is processing. It has the ability to do revocation status
       checking either using CRL or OCSP, or both. And, given the recent
       vulnerabilities that have rendered the MD5 algorithm highly
       suspect, it allows the administrator to choose to not validate
       certificates using that algorithm anywhere in the trust path.

git-svn-id: http://opkg.googlecode.com/svn/trunk@261 e8e0d7a0-c8d9-11dd-a880-a1081c7ac358

Makefile.am
configure.ac
libopkg/Makefile.am
libopkg/opkg_download.c
libopkg/opkg_pathfinder.c [new file with mode: 0644]
libopkg/opkg_pathfinder.h [new file with mode: 0644]

index a746e60..b1980bf 100644 (file)
@@ -5,6 +5,9 @@ BUILD_CPU=@build_cpu@
 OPKGLIBDIR=@opkglibdir@ 
 ALL_CFLAGS=-g -O -Wall -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DDATADIR=\"@datadir@\"
 
+PATHFINDER_CFLAGS = @PATHFINDER_CFLAGS@
+PATHFINDER_LIBS   = @PATHFINDER_LIBS@
+
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libopkg.pc
 
index 95233b5..df58817 100644 (file)
@@ -29,6 +29,22 @@ AC_PROG_LIBTOOL
 
 # Checks for libraries
 
+dnl extra argument: --with-pathfinder
+AC_ARG_ENABLE(pathfinder,
+              AC_HELP_STRING([--with-pathfinder], [With libpathfinder support.
+      [[default=no]] ]),
+    [want_pathfinder="$enableval"], [want_pathfinder="no"])
+dnl Check for libpathfinder
+if test "x$want_pathfinder" = "xyes"; then
+  PKG_CHECK_MODULES([PATHFINDER], [pathfinder-openssl dbus-1 openssl])
+  if test -n "$PATHFINDER_CFLAGS$PATHFINDER_LIBS"; then
+    AC_DEFINE(HAVE_PATHFINDER, 1, [we have pathfinder])
+  fi
+  AC_SUBST(PATHFINDER_CFLAGS)
+  AC_SUBST(PATHFINDER_LIBS)
+fi
+AM_CONDITIONAL(HAVE_PATHFINDER, test "x$want_pathfinder" = "xyes")
+
 # check for libcurl
 AC_ARG_ENABLE(curl,
               AC_HELP_STRING([--enable-curl], [Enable downloading with curl
@@ -36,7 +52,7 @@ AC_ARG_ENABLE(curl,
     [want_curl="$enableval"], [want_curl="yes"])
 
 if test "x$want_curl" = "xyes"; then
-  PKG_CHECK_MODULES(CURL, libcurl)
+  PKG_CHECK_MODULES(CURL, [libcurl])
   AC_DEFINE(HAVE_CURL, 1, [Define if you want CURL support])
 fi
 
@@ -65,7 +81,7 @@ fi
 # check for libssl-curl
 AC_ARG_ENABLE(ssl-curl,
               AC_HELP_STRING([--enable-ssl-curl], [Enable certificate authentication with curl
-                              [[default="$default_sslcurl"]] ]),
+                              [[default="yes"]] ]),
                               [want_sslcurl="$enableval"], [want_sslcurl="yes"])
 
 if test "x$want_curl" = "xyes" -a "x$want_sslcurl" = "xyes"; then
index 5aee171..067d867 100644 (file)
@@ -1,5 +1,5 @@
 
-AM_CFLAGS=-Wall -Werror -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS)
+AM_CFLAGS=-Wall -Werror -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS) $(PATHFINDER_CFLAGS)
 
 libopkg_includedir=$(includedir)/libopkg
 libopkg_include_HEADERS= opkg.h
@@ -29,7 +29,9 @@ opkg_list_sources = conffile.c conffile.h conffile_list.c conffile_list.h \
 opkg_util_sources = file_util.c file_util.h opkg_message.h opkg_message.c md5.c md5.h \
                    sprintf_alloc.c sprintf_alloc.h str_util.c str_util.h \
                    xregex.c xregex.h xsystem.c xsystem.h
-
+if HAVE_PATHFINDER
+opkg_util_sources += opkg_pathfinder.c opkg_pathfinder.h
+endif
 if HAVE_SHA256
 opkg_util_sources += sha256.c sha256.h
 endif
@@ -40,7 +42,8 @@ libopkg_la_SOURCES = \
        $(opkg_cmd_sources) $(opkg_db_sources) \
        $(opkg_util_sources) $(opkg_list_sources)
 
-libopkg_la_LIBADD = $(top_builddir)/libbb/libbb.la $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS)
+libopkg_la_LIBADD = $(top_builddir)/libbb/libbb.la $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS)
+
 # make sure we only export symbols that are for public use
 libopkg_la_LDFLAGS = -export-symbols-regex "^opkg_.*"
 
index 77dc8e4..0e67927 100644 (file)
@@ -26,6 +26,7 @@
 #include <openssl/conf.h>
 #include <openssl/evp.h>
 #include <openssl/err.h>
+#include <openssl/ssl.h>
 #endif
 
 #if defined(HAVE_GPGME)
 #include "opkg_defines.h"
 #include "libbb/libbb.h"
 
+#ifdef HAVE_PATHFINDER
+#include "opkg_pathfinder.h"
+#endif
+
 #if defined(HAVE_OPENSSL) || defined(HAVE_SSLCURL)
 static void openssl_init(void);
 #endif
@@ -413,6 +418,13 @@ opkg_verify_file (opkg_conf_t *conf, char *text_file, char *sig_file)
                 "Can't read signature file (Corrupted ?)\n");
         goto verify_file_end;
     }
+#if defined(HAVE_PATHFINDER)
+    if(!pkcs7_pathfinder_verify_signers(p7)){
+       opkg_message(conf,  OPKG_ERROR, "pkcs7_pathfinder_verify_signers: "
+               "Path verification failed\n");
+    }
+
+#endif
 
     // Open the Package file to authenticate
     if (!(indata = BIO_new_file(text_file, "rb"))){
@@ -595,6 +607,16 @@ static CURL *opkg_curl_init(opkg_conf_t *conf, curl_progress_func cb, void *data
             * CURLOPT_SSL_VERIFYPEER default is nonzero (curl => 7.10)
             */
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+       }else{
+#ifdef HAVE_PATHFINDER
+           if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, curl_ssl_ctx_function) != CURLE_OK){
+               opkg_message(conf, OPKG_DEBUG, "Failed to set ssl path verification callback\n");
+           }else{
+               curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, NULL);
+           }
+
+           //curl_easy_setopt(curl, CURLOPT_SSL_CERT_VERIFY_FUNCTION, curlcb_pathfinder);
+#endif
        }
 
        /* certification authority file and/or path */
diff --git a/libopkg/opkg_pathfinder.c b/libopkg/opkg_pathfinder.c
new file mode 100644 (file)
index 0000000..793c3a4
--- /dev/null
@@ -0,0 +1,99 @@
+/* vi: set noexpandtab sw=4 sts=4: */
+/* opkg_download.c - the opkg package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+   Copyright (C) 2008 OpenMoko Inc
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   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.
+*/
+#include "config.h"
+
+#include <openssl/ssl.h>
+#include <libpathfinder.h>
+#include "includes.h"
+#include "opkg_message.h"
+
+#if defined(HAVE_SSLCURL)
+#include <curl/curl.h>
+#endif
+
+#if defined(HAVE_SSLCURL) || defined(HAVE_OPENSSL)
+/*
+ *      This callback is called instead of X509_verify_cert to perform path
+ *      validation on a certificate using pathfinder.
+ *
+ */
+static int pathfinder_verify_callback(X509_STORE_CTX *ctx, void *arg)
+{
+    char *errmsg;
+    const char *hex = "0123456789ABCDEF";
+    size_t size = i2d_X509(ctx->cert, NULL);
+    unsigned char *keybuf, *iend;
+    iend = keybuf = malloc(size);
+    i2d_X509(ctx->cert, &iend);
+    char *certdata_str = malloc(size * 2 + 1);
+    unsigned char *cp = keybuf;
+    char *certdata_str_i = certdata_str;
+    while (cp < iend)
+    {
+        unsigned char ch = *cp++;
+        *certdata_str_i++ = hex[(ch >> 4) & 0xf];
+        *certdata_str_i++ = hex[ch & 0xf];
+    }
+    *certdata_str_i = 0;
+    free(keybuf);
+
+    const char *policy = "2.5.29.32.0"; // anyPolicy
+    int validated = pathfinder_dbus_verify(certdata_str, policy, 0, 0, &errmsg);
+
+    if (!validated)
+        fprintf(stderr, "curlcb_pathfinder: Path verification failed: %s", errmsg);
+
+    free(certdata_str);
+    free(errmsg);
+
+    return validated;
+}
+#endif
+
+
+#if defined(HAVE_OPENSSL)
+int pkcs7_pathfinder_verify_signers(PKCS7* p7)
+{
+    STACK_OF(X509) *signers;
+    int i;
+
+    signers = PKCS7_get0_signers(p7, NULL, 0);
+
+    for(i = 0; i < sk_X509_num(signers); i++){
+       X509_STORE_CTX ctx = {
+           .cert = sk_X509_value(signers, i),
+       };
+
+       if(!pathfinder_verify_callback(&ctx, NULL))
+           return 0;
+    }
+
+    return 1;
+}
+#endif
+
+#if defined(HAVE_SSLCURL)
+CURLcode curl_ssl_ctx_function(CURL * curl, void * sslctx, void * parm) {
+
+  SSL_CTX * ctx = (SSL_CTX *) sslctx;
+  SSL_CTX_set_cert_verify_callback(ctx, pathfinder_verify_callback, parm);
+
+  return CURLE_OK ;
+}
+#endif
diff --git a/libopkg/opkg_pathfinder.h b/libopkg/opkg_pathfinder.h
new file mode 100644 (file)
index 0000000..446d861
--- /dev/null
@@ -0,0 +1,32 @@
+/* opkg_download.h - the opkg package management system
+
+   Camille Moncelier <moncelier@devlife.org>
+
+   Copyright (C) 2009 Camille Moncelier
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   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.
+*/
+
+#ifndef OPKG_PATHFINDER_H
+#define OPKG_PATHFINDER_H
+
+#include "config.h"
+
+#if defined(HAVE_OPENSSL)
+int pkcs7_pathfinder_verify_signers(PKCS7* p7);
+#endif
+
+#if defined(HAVE_SSLCURL)
+CURLcode curl_ssl_ctx_function(CURL * curl, void * sslctx, void * parm);
+#endif
+
+
+#endif