p11_child_nss.c revision cc2d77d5218c188119fa954c856e858cbde76947
/*
SSSD
Helper child to commmunicate with SmartCard via NSS
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2015 Red Hat
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <popt.h>
#include <nss.h>
#include <base64.h>
#include <cryptohi.h>
#include <secmod.h>
#include <cert.h>
#include <keyhi.h>
#include <pk11pub.h>
#include <prerror.h>
#include <ocsp.h>
#include "util/child_common.h"
#include "util/crypto/sss_crypto.h"
enum op_mode {
};
enum pin_mode {
};
{
/* give up if 1) no password was supplied, or 2) the password has already
* been rejected once by this token. */
return NULL;
}
}
struct cert_verify_opts *cert_verify_opts,
char **cert, char **token_name_out)
{
int ret;
const char *slot_name;
const char *token_name;
NSSInitParameters parameters = { 0 };
unsigned char random_value[128];
SECItem signed_random_value = {0};
PR_GetError());
return EIO;
}
}
}
}
if (slot_name_in != NULL) {
slot_name_in, PR_GetError());
return EIO;
}
} else {
NULL);
return EIO;
}
"Description [%s] Manufacturer [%s] flags [%lu].\n",
break;
}
}
return EIO;
}
}
if (PK11_IsFriendly(slot)) {
} else {
"Token is NOT friendly.\n");
if (mode == OP_PREAUTH) {
if (rv != SECSuccess) {
"PK11_UpdateSlotAttribute failed, continue.\n");
}
}
}
/* TODO: check PK11_ProtectedAuthenticationPath() and return the result */
if (rv != SECSuccess) {
PR_GetError());
return EIO;
}
} else {
"Login required but no pin available, continue.\n");
}
} else {
}
PR_GetError());
return EIO;
}
if (cert_list_node->cert) {
} else {
}
}
if (rv != SECSuccess) {
PR_GetError());
return EIO;
}
if (rv != SECSuccess) {
PR_GetError());
return EIO;
}
PR_GetError());
return EIO;
}
if (cert_verify_opts->do_ocsp) {
if (rv != SECSuccess) {
PR_GetError());
return EIO;
}
if (rv != SECSuccess) {
"CERT_SetOCSPDefaultResponder failed: [%d].\n",
PR_GetError());
return EIO;
}
if (rv != SECSuccess) {
"CERT_EnableOCSPDefaultResponder failed: [%d].\n",
PR_GetError());
return EIO;
}
}
}
found_cert = NULL;
if (cert_list_node->cert) {
if (cert_verify_opts->do_verification) {
if (rv != SECSuccess) {
"Certificate [%s][%s] not valid [%d], skipping.\n",
continue;
}
}
if (found_cert == NULL) {
} else {
"using just the first one.\n");
}
} else {
}
}
/* Disable OCSP default responder so that NSS can shutdown properly */
if (cert_verify_opts->do_ocsp
if (rv != SECSuccess) {
"CERT_DisableOCSPDefaultResponder failed: [%d].\n",
PR_GetError());
}
}
if (found_cert == NULL) {
*token_name_out = NULL;
goto done;
}
if (rv != SECSuccess) {
"PK11_GenerateRandom failed [%d].\n", PR_GetError());
return EIO;
}
"PK11_FindPrivateKeyFromCert failed [%d]." \
"Maybe pin is missing.\n", PR_GetError());
goto done;
}
if (algtag == SEC_OID_UNKNOWN) {
"SEC_GetSignatureAlgorithmOidTag failed [%d].\n",
PR_GetError());
goto done;
}
random_value, sizeof(random_value),
if (rv != SECSuccess) {
PR_GetError());
goto done;
}
"CERT_ExtractPublicKey failed [%d].\n", PR_GetError());
goto done;
}
NULL);
if (rv != SECSuccess) {
PR_GetError());
goto done;
}
"Certificate verified and validated.\n");
}
goto done;
}
if (*token_name_out == NULL) {
goto done;
}
done:
}
}
if (rv != SECSuccess) {
PR_GetError());
}
return ret;
}
{
char *str;
errno = 0;
if (len == -1) {
return ret;
}
return EINVAL;
}
return ENOMEM;
}
"Input contains additional data, only PIN expected.\n");
return EINVAL;
}
return EOK;
}
{
int opt;
int debug_fd = -1;
char *cert;
char *slot_name_in = NULL;
char *token_name_out = NULL;
struct cert_verify_opts *cert_verify_opts;
char *verify_opts = NULL;
struct poptOption long_options[] = {
_("Debug level"), NULL},
_("Add debug timestamps"), NULL},
_("Show timestamps with microseconds"), NULL},
_("An open file descriptor for the debug logs"), NULL},
&debug_to_stderr, 0,
_("Send the debug output to stderr directly."), NULL },
NULL},
NULL},
NULL},
};
/* Set debug level to invalid value so we can decide if -d 0 was used. */
/*
* This child can run as root or as sssd user relying on policy kit to
* grant access to pcscd. This means that no setuid or setgid bit must be
* set on the binary. We still should make sure to run with a restrictive
* umask but do not have to make additional precautions like clearing the
* environment. This would allow to use e.g. pkcs11-spy.so for further
* debugging.
*/
switch(opt) {
case 'a':
"\n--auth and --pre are mutually exclusive and " \
"should be only used once.\n\n");
_exit(-1);
}
break;
case 'p':
"\n--auth and --pre are mutually exclusive and " \
"should be only used once.\n\n");
_exit(-1);
}
mode = OP_PREAUTH;
break;
case 'i':
"and should be only used once.\n\n");
_exit(-1);
}
break;
case 'k':
"and should be only used once.\n\n");
_exit(-1);
}
break;
default:
_exit(-1);
}
}
_exit(-1);
}
"either --auth or --pre must be specified.\n\n");
_exit(-1);
"either --pin or --keypad must be specified.\n");
_exit(-1);
}
if (debug_prg_name == NULL) {
goto fail;
}
if (debug_fd != -1) {
}
}
goto fail;
}
goto fail;
}
goto fail;
}
}
&cert, &token_name_out);
goto fail;
}
}
return EXIT_SUCCESS;
fail:
return EXIT_FAILURE;
}