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