From 45d6529dbe1b69f3a838d01a83f0688e91696377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Trojnara?= Date: Wed, 29 Aug 2018 21:35:48 +0200 Subject: [PATCH 07/23] Expose check_fork internal API --- src/Makefile.am | 2 +- src/atfork.c | 93 ------------------- src/libp11-int.h | 7 ++ src/p11_atfork.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++ src/p11_front.c | 138 ---------------------------- 5 files changed, 239 insertions(+), 232 deletions(-) delete mode 100644 src/atfork.c create mode 100644 src/p11_atfork.c diff --git a/src/Makefile.am b/src/Makefile.am index 3cdbce1..2ca250e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,7 +14,7 @@ SHARED_EXT=@SHARED_EXT@ libp11_la_SOURCES = libpkcs11.c p11_attr.c p11_cert.c p11_err.c p11_ckr.c \ p11_key.c p11_load.c p11_misc.c p11_rsa.c p11_ec.c p11_pkey.c \ - p11_slot.c p11_front.c atfork.c libp11.exports + p11_slot.c p11_front.c p11_atfork.c libp11.exports if WIN32 libp11_la_SOURCES += libp11.rc else diff --git a/src/atfork.c b/src/atfork.c deleted file mode 100644 index 04691fb..0000000 --- a/src/atfork.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2010-2012 Free Software Foundation, Inc. - * Copyright (C) 2014 Red Hat - * - * Author: Nikos Mavrogiannopoulos - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see - * - */ - -#include "libp11-int.h" -#if defined(_WIN32) && !defined(__CYGWIN__) -#include -#else -#include -#endif -#include -#include -#include -#include -#include - -#ifdef __sun -# pragma fini(lib_deinit) -# pragma init(lib_init) -# define _CONSTRUCTOR -# define _DESTRUCTOR -#else -# define _CONSTRUCTOR __attribute__((constructor)) -# define _DESTRUCTOR __attribute__((destructor)) -#endif - -unsigned int P11_forkid = 0; - -#ifndef _WIN32 - -# ifdef HAVE_ATFORK -static void fork_handler(void) -{ - P11_forkid++; -} -# endif - -# if defined(HAVE___REGISTER_ATFORK) -extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *); -extern void *__dso_handle; - -_CONSTRUCTOR -int _P11_register_fork_handler(void) -{ - if (__register_atfork(0, 0, fork_handler, __dso_handle) != 0) - return -1; - return 0; -} - -# else - -unsigned int _P11_get_forkid(void) -{ - return getpid(); -} - -int _P11_detect_fork(unsigned int forkid) -{ - if (getpid() == forkid) - return 0; - return 1; -} - -/* we have to detect fork manually */ -_CONSTRUCTOR -int _P11_register_fork_handler(void) -{ - P11_forkid = getpid(); - return 0; -} - -# endif - -#endif /* !_WIN32 */ - -/* vim: set noexpandtab: */ diff --git a/src/libp11-int.h b/src/libp11-int.h index b62a13e..411f2b0 100644 --- a/src/libp11-int.h +++ b/src/libp11-int.h @@ -323,6 +323,13 @@ extern int pkcs11_store_certificate(PKCS11_TOKEN * token, X509 * x509, extern int pkcs11_seed_random(PKCS11_SLOT *, const unsigned char *s, unsigned int s_len); extern int pkcs11_generate_random(PKCS11_SLOT *, unsigned char *r, unsigned int r_len); +/* Reinitialize the module afer fork if needed */ +extern int check_fork(PKCS11_CTX *ctx); +extern int check_slot_fork(PKCS11_SLOT *slot); +extern int check_token_fork(PKCS11_TOKEN *token); +extern int check_key_fork(PKCS11_KEY *key); +extern int check_cert_fork(PKCS11_CERT *cert); + /* Internal implementation of deprecated features */ /* Generate and store a private key on the token */ diff --git a/src/p11_atfork.c b/src/p11_atfork.c new file mode 100644 index 0000000..fce87c6 --- /dev/null +++ b/src/p11_atfork.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2010-2012 Free Software Foundation, Inc. + * Copyright (C) 2014 Red Hat + * + * Author: Nikos Mavrogiannopoulos + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + */ + +#include "libp11-int.h" +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#else +#include +#endif +#include +#include +#include +#include +#include + +#ifdef __sun +# pragma fini(lib_deinit) +# pragma init(lib_init) +# define _CONSTRUCTOR +# define _DESTRUCTOR +#else +# define _CONSTRUCTOR __attribute__((constructor)) +# define _DESTRUCTOR __attribute__((destructor)) +#endif + +unsigned int P11_forkid = 0; + +#ifndef _WIN32 + +# ifdef HAVE_ATFORK +static void fork_handler(void) +{ + P11_forkid++; +} +# endif + +# if defined(HAVE___REGISTER_ATFORK) +extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *); +extern void *__dso_handle; + +_CONSTRUCTOR +int _P11_register_fork_handler(void) +{ + if (__register_atfork(0, 0, fork_handler, __dso_handle) != 0) + return -1; + return 0; +} + +# else + +unsigned int _P11_get_forkid(void) +{ + return getpid(); +} + +int _P11_detect_fork(unsigned int forkid) +{ + if (getpid() == forkid) + return 0; + return 1; +} + +/* we have to detect fork manually */ +_CONSTRUCTOR +int _P11_register_fork_handler(void) +{ + P11_forkid = getpid(); + return 0; +} + +# endif + +#endif /* !_WIN32 */ + +/* + * PKCS#11 reinitialization after fork + * It wipes out the internal state of the PKCS#11 library + * Any libp11 references to this state are no longer valid + */ +static int check_fork_int(PKCS11_CTX *ctx) +{ + PKCS11_CTX_private *cpriv = PRIVCTX(ctx); + + if (_P11_detect_fork(cpriv->forkid)) { + if (pkcs11_CTX_reload(ctx) < 0) + return -1; + cpriv->forkid = _P11_get_forkid(); + } + return 0; +} + +/* + * PKCS#11 reinitialization after fork + * Also relogins and reopens the session if needed + */ +static int check_slot_fork_int(PKCS11_SLOT *slot) +{ + PKCS11_SLOT_private *spriv = PRIVSLOT(slot); + PKCS11_CTX *ctx = SLOT2CTX(slot); + PKCS11_CTX_private *cpriv = PRIVCTX(ctx); + + if (check_fork_int(SLOT2CTX(slot)) < 0) + return -1; + if (spriv->forkid != cpriv->forkid) { + if (spriv->loggedIn) { + int saved = spriv->haveSession; + spriv->haveSession = 0; + spriv->loggedIn = 0; + if (pkcs11_relogin(slot) < 0) + return -1; + spriv->haveSession = saved; + } + if (spriv->haveSession) { + spriv->haveSession = 0; + if (pkcs11_reopen_session(slot) < 0) + return -1; + } + spriv->forkid = cpriv->forkid; + } + return 0; +} + +/* + * PKCS#11 reinitialization after fork + * Also reloads the key + */ +static int check_key_fork_int(PKCS11_KEY *key) +{ + PKCS11_SLOT *slot = KEY2SLOT(key); + PKCS11_KEY_private *kpriv = PRIVKEY(key); + PKCS11_SLOT_private *spriv = PRIVSLOT(slot); + + if (check_slot_fork_int(slot) < 0) + return -1; + if (spriv->forkid != kpriv->forkid) { + pkcs11_reload_key(key); + kpriv->forkid = spriv->forkid; + } + return 0; +} + +/* + * Locking interface to check_fork_int() + */ +int check_fork(PKCS11_CTX *ctx) +{ + PKCS11_CTX_private *cpriv; + int rv; + + if (ctx == NULL) + return -1; + cpriv = PRIVCTX(ctx); + CRYPTO_THREAD_write_lock(cpriv->rwlock); + rv = check_fork_int(ctx); + CRYPTO_THREAD_unlock(cpriv->rwlock); + return rv; +} + +/* + * Locking interface to check_slot_fork_int() + */ +int check_slot_fork(PKCS11_SLOT *slot) +{ + PKCS11_CTX_private *cpriv; + int rv; + + if (slot == NULL) + return -1; + cpriv = PRIVCTX(SLOT2CTX(slot)); + CRYPTO_THREAD_write_lock(cpriv->rwlock); + rv = check_slot_fork_int(slot); + CRYPTO_THREAD_unlock(cpriv->rwlock); + return rv; +} + +/* + * Reinitialize token (just its slot) + */ +int check_token_fork(PKCS11_TOKEN *token) +{ + if (token == NULL) + return -1; + return check_slot_fork(TOKEN2SLOT(token)); +} + +/* + * Locking interface to check_key_fork_int() + */ +int check_key_fork(PKCS11_KEY *key) +{ + PKCS11_CTX_private *cpriv; + int rv; + + if (key == NULL) + return -1; + cpriv = PRIVCTX(KEY2CTX(key)); + CRYPTO_THREAD_write_lock(cpriv->rwlock); + rv = check_key_fork_int(key); + CRYPTO_THREAD_unlock(cpriv->rwlock); + return rv; +} + +/* + * Reinitialize cert (just its token) + */ +int check_cert_fork(PKCS11_CERT *cert) +{ + if (cert == NULL) + return -1; + return check_token_fork(CERT2TOKEN(cert)); +} + +/* vim: set noexpandtab: */ diff --git a/src/p11_front.c b/src/p11_front.c index 167a778..efdd4c0 100644 --- a/src/p11_front.c +++ b/src/p11_front.c @@ -25,144 +25,6 @@ * PKCS11_get_ec_key_method */ -/* - * PKCS#11 reinitialization after fork - * It wipes out the internal state of the PKCS#11 library - * Any libp11 references to this state are no longer valid - */ -static int check_fork_int(PKCS11_CTX *ctx) -{ - PKCS11_CTX_private *cpriv = PRIVCTX(ctx); - - if (_P11_detect_fork(cpriv->forkid)) { - if (pkcs11_CTX_reload(ctx) < 0) - return -1; - cpriv->forkid = _P11_get_forkid(); - } - return 0; -} - -/* - * PKCS#11 reinitialization after fork - * Also relogins and reopens the session if needed - */ -static int check_slot_fork_int(PKCS11_SLOT *slot) -{ - PKCS11_SLOT_private *spriv = PRIVSLOT(slot); - PKCS11_CTX *ctx = SLOT2CTX(slot); - PKCS11_CTX_private *cpriv = PRIVCTX(ctx); - - if (check_fork_int(SLOT2CTX(slot)) < 0) - return -1; - if (spriv->forkid != cpriv->forkid) { - if (spriv->loggedIn) { - int saved = spriv->haveSession; - spriv->haveSession = 0; - spriv->loggedIn = 0; - if (pkcs11_relogin(slot) < 0) - return -1; - spriv->haveSession = saved; - } - if (spriv->haveSession) { - spriv->haveSession = 0; - if (pkcs11_reopen_session(slot) < 0) - return -1; - } - spriv->forkid = cpriv->forkid; - } - return 0; -} - -/* - * PKCS#11 reinitialization after fork - * Also reloads the key - */ -static int check_key_fork_int(PKCS11_KEY *key) -{ - PKCS11_SLOT *slot = KEY2SLOT(key); - PKCS11_KEY_private *kpriv = PRIVKEY(key); - PKCS11_SLOT_private *spriv = PRIVSLOT(slot); - - if (check_slot_fork_int(slot) < 0) - return -1; - if (spriv->forkid != kpriv->forkid) { - pkcs11_reload_key(key); - kpriv->forkid = spriv->forkid; - } - return 0; -} - -/* - * Locking interface to check_fork_int() - */ -static int check_fork(PKCS11_CTX *ctx) -{ - PKCS11_CTX_private *cpriv; - int rv; - - if (ctx == NULL) - return -1; - cpriv = PRIVCTX(ctx); - CRYPTO_THREAD_write_lock(cpriv->rwlock); - rv = check_fork_int(ctx); - CRYPTO_THREAD_unlock(cpriv->rwlock); - return rv; -} - -/* - * Locking interface to check_slot_fork_int() - */ -static int check_slot_fork(PKCS11_SLOT *slot) -{ - PKCS11_CTX_private *cpriv; - int rv; - - if (slot == NULL) - return -1; - cpriv = PRIVCTX(SLOT2CTX(slot)); - CRYPTO_THREAD_write_lock(cpriv->rwlock); - rv = check_slot_fork_int(slot); - CRYPTO_THREAD_unlock(cpriv->rwlock); - return rv; -} - -/* - * Reinitialize token (just its slot) - */ -static int check_token_fork(PKCS11_TOKEN *token) -{ - if (token == NULL) - return -1; - return check_slot_fork(TOKEN2SLOT(token)); -} - -/* - * Locking interface to check_key_fork_int() - */ -static int check_key_fork(PKCS11_KEY *key) -{ - PKCS11_CTX_private *cpriv; - int rv; - - if (key == NULL) - return -1; - cpriv = PRIVCTX(KEY2CTX(key)); - CRYPTO_THREAD_write_lock(cpriv->rwlock); - rv = check_key_fork_int(key); - CRYPTO_THREAD_unlock(cpriv->rwlock); - return rv; -} - -/* - * Reinitialize cert (just its token) - */ -static int check_cert_fork(PKCS11_CERT *cert) -{ - if (cert == NULL) - return -1; - return check_token_fork(CERT2TOKEN(cert)); -} - /* External interface to the libp11 features */ PKCS11_CTX *PKCS11_CTX_new(void) -- 2.17.1