Blame src/p11_atfork.c

Packit 6b81fa
/* libp11, a simple layer on to of PKCS#11 API
Packit 6b81fa
 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
Packit 6b81fa
 * Copyright (C) 2014 Red Hat
Packit 6b81fa
 * Copyright (C) 2018 MichaƂ Trojnara <Michal.Trojnara@stunnel.org>
Packit 6b81fa
 *
Packit 6b81fa
 * Author: Nikos Mavrogiannopoulos
Packit 6b81fa
 *
Packit 6b81fa
 * This is free software; you can redistribute it and/or
Packit 6b81fa
 * modify it under the terms of the GNU Lesser General Public License
Packit 6b81fa
 * as published by the Free Software Foundation; either version 2.1 of
Packit 6b81fa
 * the License, or (at your option) any later version.
Packit 6b81fa
 *
Packit 6b81fa
 * This library is distributed in the hope that it will be useful, but
Packit 6b81fa
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6b81fa
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6b81fa
 * Lesser General Public License for more details.
Packit 6b81fa
 *
Packit 6b81fa
 * You should have received a copy of the GNU Lesser General Public License
Packit 6b81fa
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
Packit 6b81fa
 *
Packit 6b81fa
 */
Packit 6b81fa
Packit 6b81fa
#include "libp11-int.h"
Packit 6b81fa
Packit 6b81fa
#ifndef _WIN32
Packit 6b81fa
Packit 6b81fa
#ifndef __STDC_VERSION__
Packit 6b81fa
/* older than C90 */
Packit 6b81fa
#define inline
Packit 6b81fa
#endif /* __STDC_VERSION__ */
Packit 6b81fa
Packit 6b81fa
#ifdef HAVE___REGISTER_ATFORK
Packit 6b81fa
Packit 6b81fa
#ifdef __sun
Packit 6b81fa
#pragma fini(lib_deinit)
Packit 6b81fa
#pragma init(lib_init)
Packit 6b81fa
#define _CONSTRUCTOR
Packit 6b81fa
#define _DESTRUCTOR
Packit 6b81fa
#else /* __sun */
Packit 6b81fa
#define _CONSTRUCTOR __attribute__((constructor))
Packit 6b81fa
#define _DESTRUCTOR __attribute__((destructor))
Packit 6b81fa
#endif /* __sun */
Packit 6b81fa
Packit 6b81fa
static unsigned int P11_forkid = 0;
Packit 6b81fa
Packit 6b81fa
inline static unsigned int _P11_get_forkid(void)
Packit 6b81fa
{
Packit 6b81fa
	return P11_forkid;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
inline static int _P11_detect_fork(unsigned int forkid)
Packit 6b81fa
{
Packit 6b81fa
	if (forkid == P11_forkid)
Packit 6b81fa
		return 0;
Packit 6b81fa
	return 1;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
static void fork_handler(void)
Packit 6b81fa
{
Packit 6b81fa
	P11_forkid++;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
Packit 6b81fa
extern void *__dso_handle;
Packit 6b81fa
Packit 6b81fa
_CONSTRUCTOR
Packit 6b81fa
int _P11_register_fork_handler(void)
Packit 6b81fa
{
Packit 6b81fa
	if (__register_atfork(0, 0, fork_handler, __dso_handle) != 0)
Packit 6b81fa
		return -1;
Packit 6b81fa
	return 0;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
#else /* HAVE___REGISTER_ATFORK */
Packit 6b81fa
Packit 6b81fa
inline static unsigned int _P11_get_forkid(void)
Packit 6b81fa
{
Packit 6b81fa
	return getpid();
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
inline static int _P11_detect_fork(unsigned int forkid)
Packit 6b81fa
{
Packit 6b81fa
	if (getpid() == forkid)
Packit 6b81fa
		return 0;
Packit 6b81fa
	return 1;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
#endif /* HAVE___REGISTER_ATFORK */
Packit 6b81fa
Packit 6b81fa
#else /* !_WIN32 */
Packit 6b81fa
Packit 6b81fa
#define _P11_get_forkid() 0
Packit 6b81fa
#define _P11_detect_fork(x) 0
Packit 6b81fa
Packit 6b81fa
#endif /* !_WIN32 */
Packit 6b81fa
Packit 6b81fa
unsigned int get_forkid()
Packit 6b81fa
{
Packit 6b81fa
	return _P11_get_forkid();
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/*
Packit 6b81fa
 * PKCS#11 reinitialization after fork
Packit 6b81fa
 * It wipes out the internal state of the PKCS#11 library
Packit 6b81fa
 * Any libp11 references to this state are no longer valid
Packit 6b81fa
 */
Packit 6b81fa
static int check_fork_int(PKCS11_CTX *ctx)
Packit 6b81fa
{
Packit 6b81fa
	PKCS11_CTX_private *cpriv = PRIVCTX(ctx);
Packit 6b81fa
Packit 6b81fa
	if (_P11_detect_fork(cpriv->forkid)) {
Packit 6b81fa
		if (pkcs11_CTX_reload(ctx) < 0)
Packit 6b81fa
			return -1;
Packit 6b81fa
		cpriv->forkid = _P11_get_forkid();
Packit 6b81fa
	}
Packit 6b81fa
	return 0;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/*
Packit 6b81fa
 * PKCS#11 reinitialization after fork
Packit 6b81fa
 * Also relogins and reopens the session if needed
Packit 6b81fa
 */
Packit 6b81fa
static int check_slot_fork_int(PKCS11_SLOT *slot)
Packit 6b81fa
{
Packit 6b81fa
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
Packit 6b81fa
	PKCS11_CTX *ctx = SLOT2CTX(slot);
Packit 6b81fa
	PKCS11_CTX_private *cpriv = PRIVCTX(ctx);
Packit 6b81fa
Packit 6b81fa
	if (check_fork_int(SLOT2CTX(slot)) < 0)
Packit 6b81fa
		return -1;
Packit 6b81fa
	if (spriv->forkid != cpriv->forkid) {
Packit 6b81fa
		if (spriv->loggedIn) {
Packit 6b81fa
			int saved = spriv->haveSession;
Packit 6b81fa
			spriv->haveSession = 0;
Packit 6b81fa
			spriv->loggedIn = 0;
Packit 6b81fa
			if (pkcs11_relogin(slot) < 0)
Packit 6b81fa
				return -1;
Packit 6b81fa
			spriv->haveSession = saved;
Packit 6b81fa
		}
Packit 6b81fa
		if (spriv->haveSession) {
Packit 6b81fa
			spriv->haveSession = 0;
Packit 6b81fa
			if (pkcs11_reopen_session(slot) < 0)
Packit 6b81fa
				return -1;
Packit 6b81fa
		}
Packit 6b81fa
		spriv->forkid = cpriv->forkid;
Packit 6b81fa
	}
Packit 6b81fa
	return 0;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/*
Packit 6b81fa
 * PKCS#11 reinitialization after fork
Packit 6b81fa
 * Also reloads the key
Packit 6b81fa
 */
Packit 6b81fa
static int check_key_fork_int(PKCS11_KEY *key)
Packit 6b81fa
{
Packit 6b81fa
	PKCS11_SLOT *slot = KEY2SLOT(key);
Packit 6b81fa
	PKCS11_KEY_private *kpriv = PRIVKEY(key);
Packit 6b81fa
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
Packit 6b81fa
Packit 6b81fa
	if (check_slot_fork_int(slot) < 0)
Packit 6b81fa
		return -1;
Packit 6b81fa
	if (spriv->forkid != kpriv->forkid) {
Packit 6b81fa
		pkcs11_reload_key(key);
Packit 6b81fa
		kpriv->forkid = spriv->forkid;
Packit 6b81fa
	}
Packit 6b81fa
	return 0;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/*
Packit 6b81fa
 * Locking interface to check_fork_int()
Packit 6b81fa
 */
Packit 6b81fa
int check_fork(PKCS11_CTX *ctx)
Packit 6b81fa
{
Packit 6b81fa
	PKCS11_CTX_private *cpriv;
Packit 6b81fa
	int rv;
Packit 6b81fa
Packit 6b81fa
	if (ctx == NULL)
Packit 6b81fa
		return -1;
Packit 6b81fa
	cpriv = PRIVCTX(ctx);
Packit 6b81fa
	CRYPTO_THREAD_write_lock(cpriv->rwlock);
Packit 6b81fa
	rv = check_fork_int(ctx);
Packit 6b81fa
	CRYPTO_THREAD_unlock(cpriv->rwlock);
Packit 6b81fa
	return rv;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/*
Packit 6b81fa
 * Locking interface to check_slot_fork_int()
Packit 6b81fa
 */
Packit 6b81fa
int check_slot_fork(PKCS11_SLOT *slot)
Packit 6b81fa
{
Packit 6b81fa
	PKCS11_CTX_private *cpriv;
Packit 6b81fa
	int rv;
Packit 6b81fa
Packit 6b81fa
	if (slot == NULL)
Packit 6b81fa
		return -1;
Packit 6b81fa
	cpriv = PRIVCTX(SLOT2CTX(slot));
Packit 6b81fa
	CRYPTO_THREAD_write_lock(cpriv->rwlock);
Packit 6b81fa
	rv = check_slot_fork_int(slot);
Packit 6b81fa
	CRYPTO_THREAD_unlock(cpriv->rwlock);
Packit 6b81fa
	return rv;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/*
Packit 6b81fa
 * Reinitialize token (just its slot)
Packit 6b81fa
 */
Packit 6b81fa
int check_token_fork(PKCS11_TOKEN *token)
Packit 6b81fa
{
Packit 6b81fa
	if (token == NULL)
Packit 6b81fa
		return -1;
Packit 6b81fa
	return check_slot_fork(TOKEN2SLOT(token));
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/*
Packit 6b81fa
 * Locking interface to check_key_fork_int()
Packit 6b81fa
 */
Packit 6b81fa
int check_key_fork(PKCS11_KEY *key)
Packit 6b81fa
{
Packit 6b81fa
	PKCS11_CTX_private *cpriv;
Packit 6b81fa
	int rv;
Packit 6b81fa
Packit 6b81fa
	if (key == NULL)
Packit 6b81fa
		return -1;
Packit 6b81fa
	cpriv = PRIVCTX(KEY2CTX(key));
Packit 6b81fa
	CRYPTO_THREAD_write_lock(cpriv->rwlock);
Packit 6b81fa
	rv = check_key_fork_int(key);
Packit 6b81fa
	CRYPTO_THREAD_unlock(cpriv->rwlock);
Packit 6b81fa
	return rv;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/*
Packit 6b81fa
 * Reinitialize cert (just its token)
Packit 6b81fa
 */
Packit 6b81fa
int check_cert_fork(PKCS11_CERT *cert)
Packit 6b81fa
{
Packit 6b81fa
	if (cert == NULL)
Packit 6b81fa
		return -1;
Packit 6b81fa
	return check_token_fork(CERT2TOKEN(cert));
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/* vim: set noexpandtab: */