From 45d6529dbe1b69f3a838d01a83f0688e91696377 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Trojnara?= <Michal.Trojnara@stunnel.org>
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 <http://www.gnu.org/licenses/>
- *
- */
-
-#include "libp11-int.h"
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <winsock2.h>
-#else
-#include <sys/socket.h>
-#endif
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <atfork.h>
-
-#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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "libp11-int.h"
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#endif
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <atfork.h>
+
+#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