Commit c775f93c authored by Patrick Griffis's avatar Patrick Griffis Committed by Carlos Garcia Campos
Browse files

ssl-test: Add tests for PKCS#11 pin protected cert

parent dac4665a
......@@ -304,7 +304,9 @@ if python.found()
endif
message('Python module quart found: @0@'.format(quart_found.to_string('YES', 'NO')))
if not have_apache or not quart_found or not have_autobahn
gnutls_dep = dependency('gnutls', required : get_option('tests'))
if not have_apache or not quart_found or not have_autobahn or not gnutls_dep.found()
warning('Some regression tests will not be compiled due to missing libraries or modules. Please check the logs for more details.')
endif
......@@ -433,6 +435,7 @@ summary({
'Tests requiring Quart' : quart_found,
'Fuzzing tests' : get_option('fuzzing').enabled(),
'Autobahn tests' : have_autobahn,
'PKCS#11 tests' : gnutls_dep.found(),
'Install tests': get_option('installed_tests'),
'Unix sockets' : unix_socket_dep.found(),
},
......
......@@ -23,6 +23,23 @@ test_resources = gnome.compile_resources('soup-tests',
install_dir : installed_tests_execdir,
)
if gnutls_dep.found()
mock_pkcs11_module = shared_module('mock-pkcs11',
sources: 'mock-pkcs11.c',
name_prefix: '',
gnu_symbol_visibility: 'hidden',
include_directories: include_directories('pkcs11'),
dependencies: [
gio_dep,
gnutls_dep,
],
install: installed_tests_enabled,
install_dir: installed_tests_execdir
)
else
mock_pkcs11_module = []
endif
configure_file(input : 'index.txt',
output : 'index.txt',
copy : true)
......@@ -50,37 +67,42 @@ endif
# ['name', is_parallel, extra_deps]
tests = [
['cache', true, []],
['chunk-io', true, []],
['coding', true, []],
['context', true, []],
['continue', true, []],
['cookies', true, []],
['date', true, []],
['forms', true, []],
['header-parsing', true, []],
['http2-body-stream', true, []],
['hsts', true, []],
['hsts-db', true, []],
['logger', true, []],
['misc', true, []],
['multipart', true, []],
['no-ssl', true, []],
['ntlm', true, []],
['redirect', true, []],
['request-body', true, []],
['samesite', true, []],
['session', true, []],
['server-auth', true, []],
['server', true, []],
['sniffing', true, []],
['socket', true, []],
['ssl', true, []],
['streaming', true, []],
['timeout', true, []],
['tld', true, []],
['uri-parsing', true, []],
['websocket', true, [libz_dep]]
{'name': 'cache'},
{'name': 'chunk-io'},
{'name': 'coding'},
{'name': 'context'},
{'name': 'continue'},
{'name': 'cookies'},
{'name': 'date'},
{'name': 'forms'},
{'name': 'header-parsing'},
{'name': 'http2-body-stream'},
{'name': 'hsts'},
{'name': 'hsts-db'},
{'name': 'logger'},
{'name': 'misc'},
{'name': 'multipart'},
{'name': 'no-ssl'},
{'name': 'ntlm'},
{'name': 'redirect'},
{'name': 'request-body'},
{'name': 'samesite'},
{'name': 'session'},
{'name': 'server-auth'},
{'name': 'server'},
{'name': 'sniffing'},
{'name': 'socket'},
{'name': 'ssl',
'dependencies': [gnutls_dep],
'depends': mock_pkcs11_module,
'c_args': '-DHAVE_GNUTLS=@0@'.format(gnutls_dep.found() ? 1 : 0),
},
{'name': 'streaming'},
{'name': 'timeout'},
{'name': 'tld'},
{'name': 'uri-parsing'},
{'name': 'websocket',
'dependencies': [libz_dep]},
]
if quart_found
......@@ -88,15 +110,11 @@ if quart_found
output : 'http2-server.py',
copy : true)
tests += [
['http2', true, []],
]
tests += [{'name': 'http2'}]
endif
if brotlidec_dep.found()
tests += [
['brotli-decompressor', true, []],
]
tests += [{'name': 'brotli-decompressor'}]
if installed_tests_enabled
install_data(
......@@ -109,17 +127,18 @@ if brotlidec_dep.found()
endif
if unix_socket_dep.found()
tests += [
['unix-socket', true, [ unix_socket_dep ]],
]
tests += [{
'name': 'unix-socket',
'dependencies': [unix_socket_dep],
}]
endif
if have_apache
tests += [
['auth', false, []],
['connection', false, []],
['range', false, []],
['proxy', false, []],
{'name': 'auth', 'parallel': false},
{'name': 'connection', 'parallel': false},
{'name': 'range', 'parallel': false},
{'name': 'proxy', 'parallel': false},
]
configure_file(output : 'httpd.conf',
......@@ -164,14 +183,14 @@ if have_autobahn
endif
foreach test: tests
test_name = '@0@-test'.format(test[0])
test_name = '@0@-test'.format(test['name'])
if installed_tests_enabled
test_conf = configuration_data()
test_conf.set('installed_tests_dir', abs_installed_tests_execdir)
test_conf.set('program', test_name)
test_conf.set('env', '')
test_conf.set('type', test[1] ? 'session' : 'session-exclusive')
test_conf.set('type', test.get('parallel', true) ? 'session' : 'session-exclusive')
configure_file(
input : installed_tests_template_tap,
output : test_name + '.test',
......@@ -180,9 +199,11 @@ foreach test: tests
)
endif
test_deps = [ libsoup_static_dep ] + test[2]
test_deps = [ libsoup_static_dep ] + test.get('dependencies', [])
test_target = executable(test_name,
sources : [ test_name + '.c', test_resources ],
c_args : test.get('c_args', []),
include_directories : test.get('includes', []),
link_with : test_utils,
dependencies : test_deps,
install : installed_tests_enabled,
......@@ -194,7 +215,8 @@ foreach test: tests
test(test_name, test_target,
args : ['--debug'],
env : env,
is_parallel : test[1],
is_parallel : test.get('parallel', true),
depends : test.get('depends', []),
timeout : 60,
protocol : 'tap',
)
......
This diff is collapsed.
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
* is granted provided that it is identified as "RSA Security In.c Public-Key
* Cryptography Standards (PKCS)" in all material mentioning or referencing
* this document.
*
* The latest version of this header can be found at:
* http://www.rsalabs.com/pkcs/pkcs-11/index.html
*/
#ifndef _PKCS11_H_
#define _PKCS11_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/* Before including this file (pkcs11.h) (or pkcs11t.h by
* itself), 6 platform-specific macros must be defined. These
* macros are described below, and typical definitions for them
* are also given. Be advised that these definitions can depend
* on both the platform and the compiler used (and possibly also
* on whether a PKCS #11 library is linked statically or
* dynamically).
*
* In addition to defining these 6 macros, the packing convention
* for PKCS #11 structures should be set. The PKCS #11
* convention on packing is that structures should be 1-byte
* aligned.
*
* In a Win32 environment, this might be done by using the
* following preprocessor directive before including pkcs11.h
* or pkcs11t.h:
*
* #pragma pack(push, cryptoki, 1)
*
* and using the following preprocessor directive after including
* pkcs11.h or pkcs11t.h:
*
* #pragma pack(pop, cryptoki)
*
* In a UNIX environment, you're on your own here. You might
* not need to do anything.
*
*
* Now for the macros:
*
*
* 1. CK_PTR: The indirection string for making a pointer to an
* object. It can be used like this:
*
* typedef CK_BYTE CK_PTR CK_BYTE_PTR;
*
* In a Win32 environment, it might be defined by
*
* #define CK_PTR *
*
* In a UNIX environment, it might be defined by
*
* #define CK_PTR *
*
*
* 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
* an exportable PKCS #11 library function definition out of a
* return type and a function name. It should be used in the
* following fashion to define the exposed PKCS #11 functions in
* a PKCS #11 library:
*
* CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
* CK_VOID_PTR pReserved
* )
* {
* ...
* }
*
* For defining a function in a Win32 PKCS #11 .dll, it might be
* defined by
*
* #define CK_DEFINE_FUNCTION(returnType, name) \
* returnType __declspec(dllexport) name
*
* In a UNIX environment, it might be defined by
*
* #define CK_DEFINE_FUNCTION(returnType, name) \
* returnType name
*
*
* 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
* an importable PKCS #11 library function declaration out of a
* return type and a function name. It should be used in the
* following fashion:
*
* extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
* CK_VOID_PTR pReserved
* );
*
* For declaring a function in a Win32 PKCS #11 .dll, it might
* be defined by
*
* #define CK_DECLARE_FUNCTION(returnType, name) \
* returnType __declspec(dllimport) name
*
* In a UNIX environment, it might be defined by
*
* #define CK_DECLARE_FUNCTION(returnType, name) \
* returnType name
*
*
* 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
* which makes a PKCS #11 API function pointer declaration or
* function pointer type declaration out of a return type and a
* function name. It should be used in the following fashion:
*
* // Define funcPtr to be a pointer to a PKCS #11 API function
* // taking arguments args and returning CK_RV.
* CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
*
* or
*
* // Define funcPtrType to be the type of a pointer to a
* // PKCS #11 API function taking arguments args and returning
* // CK_RV, and then define funcPtr to be a variable of type
* // funcPtrType.
* typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
* funcPtrType funcPtr;
*
* For accessing functions in a Win32 PKCS #11 .dll, in might be
* defined by
*
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
* returnType __declspec(dllimport) (* name)
*
* In a UNIX environment, it might be defined by
*
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
* returnType (* name)
*
*
* 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
* a function pointer type for an application callback out of
* a return type for the callback and a name for the callback.
* It should be used in the following fashion:
*
* CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
*
* to declare a function pointer, myCallback, to a callback
* which takes arguments args and returns a CK_RV. It can also
* be used like this:
*
* typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
* myCallbackType myCallback;
*
* In a Win32 environment, it might be defined by
*
* #define CK_CALLBACK_FUNCTION(returnType, name) \
* returnType (* name)
*
* In a UNIX environment, it might be defined by
*
* #define CK_CALLBACK_FUNCTION(returnType, name) \
* returnType (* name)
*
*
* 6. NULL_PTR: This macro is the value of a NULL pointer.
*
* In any ANSI/ISO C environment (and in many others as well),
* this should be defined by
*
* #ifndef NULL_PTR
* #define NULL_PTR 0
* #endif
*/
/* All the various PKCS #11 types and #define'd values are in the
* file pkcs11t.h. */
#include "pkcs11t.h"
#define __PASTE(x, y) x##y
/* packing defines */
#include "pkcs11p.h"
/* ==============================================================
* Define the "extern" form of all the entry points.
* ==============================================================
*/
#define CK_NEED_ARG_LIST 1
#define CK_PKCS11_FUNCTION_INFO(name) \
CK_DECLARE_FUNCTION(CK_RV, name)
/* pkcs11f.h has all the information about the PKCS #11
* function prototypes. */
#include "pkcs11f.h"
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
/* ==============================================================
* Define the typedef form of all the entry points. That is, for
* each PKCS #11 function C_XXX, define a type CK_C_XXX which is
* a pointer to that kind of function.
* ==============================================================
*/
#define CK_NEED_ARG_LIST 1
#define CK_PKCS11_FUNCTION_INFO(name) \
typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_, name))
/* pkcs11f.h has all the information about the PKCS #11
* function prototypes. */
#include "pkcs11f.h"
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
/* ==============================================================
* Define structed vector of entry points. A CK_FUNCTION_LIST
* contains a CK_VERSION indicating a library's PKCS #11 version
* and then a whole slew of function pointers to the routines in
* the library. This type was declared, but not defined, in
* pkcs11t.h.
* ==============================================================
*/
#define CK_PKCS11_FUNCTION_INFO(name) \
__PASTE(CK_, name) \
name;
struct CK_FUNCTION_LIST {
CK_VERSION version; /* PKCS #11 version */
/* Pile all the function pointers into the CK_FUNCTION_LIST. */
/* pkcs11f.h has all the information about the PKCS #11
* function prototypes. */
#include "pkcs11f.h"
};
#undef CK_PKCS11_FUNCTION_INFO
#undef __PASTE
/* unpack */
#include "pkcs11u.h"
#ifdef __cplusplus
}
#endif
#endif
\ No newline at end of file
This diff is collapsed.
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
* is granted provided that it is identified as "RSA Security Inc. Public-Key
* Cryptography Standards (PKCS)" in all material mentioning or referencing
* this document.
*/
/* these data types are platform/implementation dependent. */
/*
* Packing was removed from the shipped RSA header files, even
* though it's still needed. put in a central file to help merging..
*/
#if defined(_WIN32) || defined(_WINDOWS)
#ifdef __clang__
#pragma clang diagnostic ignored "-Wpragma-pack"
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4103)
#endif
#pragma pack(push, cryptoki, 1)
#endif
This diff is collapsed.
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
* is granted provided that it is identified as "RSA Security Inc. Public-Key
* Cryptography Standards (PKCS)" in all material mentioning or referencing
* this document.
*/
/*
* reset any packing set by pkcs11p.h
*/
#if defined(_WIN32) || defined(_WINDOWS)
#ifdef __clang__
#pragma clang diagnostic ignored "-Wpragma-pack"
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4103)
#endif
#pragma pack(pop, cryptoki)
#endif
\ No newline at end of file
......@@ -3,6 +3,11 @@
#include "test-utils.h"
#include "soup-server-message-private.h"
#if HAVE_GNUTLS
#include <gnutls/gnutls.h>
#include <gnutls/pkcs11.h>
#endif
GUri *uri;
typedef struct {
......@@ -217,8 +222,17 @@ request_certificate_cb (SoupMessage *msg,
typedef struct {
SoupMessage *msg;
GTlsCertificate *certificate;
GTlsPassword *tls_password;
const guchar *password;
} SetCertificateAsyncData;
static void
set_certificate_async_data_free (SetCertificateAsyncData *data)
{
g_clear_object (&data->tls_password);
g_free (data);
}
static gboolean
set_certificate_idle_cb (SetCertificateAsyncData *data)
{
......@@ -234,12 +248,41 @@ request_certificate_async_cb (SoupMessage *msg,
{
SetCertificateAsyncData *data;
data = g_new (SetCertificateAsyncData, 1);
data = g_new0 (SetCertificateAsyncData, 1);
data->msg = msg;
data->certificate = certificate;
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
(GSourceFunc)set_certificate_idle_cb,
data, g_free);
data,
(GDestroyNotify)set_certificate_async_data_free);
return TRUE;
}
static gboolean
set_certificate_password_idle_cb (SetCertificateAsyncData *data)
{
g_tls_password_set_value (data->tls_password, data->password, -1);
soup_message_tls_client_certificate_password_request_complete (data->msg);
return FALSE;
}
static gboolean
request_certificate_password_async_cb (SoupMessage *msg,
GTlsPassword *password,
const guchar *pin)
{
SetCertificateAsyncData *data;
data = g_new (SetCertificateAsyncData, 1);
data->msg = msg;
data->tls_password = g_object_ref (password);
data->password = pin;
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
(GSourceFunc)set_certificate_password_idle_cb,
data,
(GDestroyNotify)set_certificate_async_data_free);
return TRUE;
}
......@@ -252,7 +295,7 @@ do_tls_interaction_msg_test (gconstpointer data)
SoupMessage *msg;
GBytes *body;
GTlsDatabase *tls_db;
GTlsCertificate *certificate, *wrong_certificate;
GTlsCertificate *certificate, *wrong_certificate, *pkcs11_certificate;
GError *error = NULL;
SOUP_TEST_SKIP_IF_NO_TLS;
......@@ -348,11 +391,35 @@ do_tls_interaction_msg_test (gconstpointer data)
g_clear_error (&error);
g_object_unref (msg);
/* Using PKCS#11 works, and asks for a PIN */
pkcs11_certificate = g_tls_certificate_new_from_pkcs11_uris (
"pkcs11:model=mock;serial=1;token=Mock%20Certificate;id=%4D%6F%63%6B%20%43%65%72%74%69%66%69%63%61%74%65;object=Mock%20Certificate;type=cert",
"pkcs11:model=mock;serial=1;token=Mock%20Certificate;id=%4D%6F%63%6B%20%50%72%69%76%61%74%65%20%4B%65%79;object=Mock%20Private%20Key;type=private",
&error
);
g_assert_no_error (error);
g_assert_nonnull (pkcs11_certificate);
g_assert_true (G_IS_TLS_CERTIFICATE (pkcs11_certificate));
msg = soup_message_new_from_uri ("GET", uri);
soup_message_add_flags (msg, SOUP_MESSAGE_NEW_CONNECTION);
g_signal_connect (msg, "request-certificate",
G_CALLBACK (request_certificate_async_cb),
pkcs11_certificate);
g_signal_connect (msg, "request-certificate-password",
G_CALLBACK (request_certificate_password_async_cb),
"ABC123");
body = soup_test_session_async_send (session, msg, NULL, &error);
g_assert_no_error (error);
g_clear_error (&error);
g_bytes_unref (body);
g_object_unref (msg);
g_signal_handlers_disconnect_by_data (server, tls_db);
soup_test_session_abort_unref (session);
g_object_unref (certificate);
g_object_unref (wrong_certificate);
g_object_unref (pkcs11_certificate);
}
static void
......@@ -376,6 +443,15 @@ main (int argc, char **argv)
test_init (argc, argv, NULL);
#if HAVE_GNUTLS
char *module_path = soup_test_build_filename_abs (G_TEST_BUILT, "mock-pkcs11.so", NULL);
g_assert_true (g_file_test (module_path, G_FILE_TEST_EXISTS));
g_assert (gnutls_pkcs11_init (GNUTLS_PKCS11_FLAG_MANUAL, NULL) == GNUTLS_E_SUCCESS);
g_assert (gnutls_pkcs11_add_provider (module_path, NULL) == GNUTLS_E_SUCCESS);
g_free (module_path);
#endif
if (tls_available) {
server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment