10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53089Swyllys * Common Development and Distribution License (the "License"). 63089Swyllys * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*6051Swyllys * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * This file contains the functions that are shared among 300Sstevel@tonic-gate * the various services this tool will ultimately provide. 3117Sdinak * The functions in this file return PKCS#11 CK_RV errors. 3217Sdinak * Only one session and one login per token is supported 3317Sdinak * at this time. 340Sstevel@tonic-gate */ 350Sstevel@tonic-gate 360Sstevel@tonic-gate #include <stdio.h> 370Sstevel@tonic-gate #include <stdlib.h> 380Sstevel@tonic-gate #include <string.h> 390Sstevel@tonic-gate #include <ctype.h> 403089Swyllys #include <sys/types.h> 413089Swyllys #include <sys/stat.h> 423089Swyllys #include <fcntl.h> 433089Swyllys #include <tzfile.h> 440Sstevel@tonic-gate #include <cryptoutil.h> 450Sstevel@tonic-gate #include <security/cryptoki.h> 463089Swyllys #include <kmfapi.h> 470Sstevel@tonic-gate 483089Swyllys #include "common.h" 4917Sdinak 5017Sdinak /* Local status variables. */ 5117Sdinak static boolean_t initialized = B_FALSE; 5217Sdinak static boolean_t session_opened = B_FALSE; 5317Sdinak static boolean_t logged_in = B_FALSE; 5417Sdinak 55864Sdinak /* Supporting structures and global variables for getopt_av(). */ 56864Sdinak typedef struct av_opts_s { 57864Sdinak int shortnm; /* short name character */ 58864Sdinak char *longnm; /* long name string, NOT terminated */ 59864Sdinak int longnm_len; /* length of long name string */ 60864Sdinak boolean_t has_arg; /* takes optional argument */ 61864Sdinak } av_opts; 62864Sdinak static av_opts *opts_av = NULL; 63864Sdinak static const char *_save_optstr = NULL; 64864Sdinak static int _save_numopts = 0; 65864Sdinak 66864Sdinak int optind_av = 1; 67864Sdinak char *optarg_av = NULL; 68864Sdinak 693089Swyllys static void close_sess(CK_SESSION_HANDLE); 703089Swyllys static void logout_token(CK_SESSION_HANDLE); 713089Swyllys 7217Sdinak /* 7317Sdinak * Perform PKCS#11 setup here. Currently only C_Initialize is required, 7417Sdinak * along with setting/resetting state variables. 7517Sdinak */ 7617Sdinak CK_RV 7717Sdinak init_pk11(void) 7817Sdinak { 7917Sdinak CK_RV rv = CKR_OK; 8017Sdinak 8117Sdinak /* If C_Initialize() already called, nothing to do here. */ 8217Sdinak if (initialized == B_TRUE) 8317Sdinak return (CKR_OK); 8417Sdinak 8517Sdinak /* Reset state variables because C_Initialize() not yet done. */ 8617Sdinak session_opened = B_FALSE; 8717Sdinak logged_in = B_FALSE; 8817Sdinak 8917Sdinak /* Initialize PKCS#11 library. */ 9017Sdinak if ((rv = C_Initialize(NULL_PTR)) != CKR_OK && 9117Sdinak rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 9217Sdinak return (rv); 9317Sdinak } 9417Sdinak 9517Sdinak initialized = B_TRUE; 9617Sdinak return (CKR_OK); 9717Sdinak } 9817Sdinak 9917Sdinak /* 10017Sdinak * Finalize PKCS#11 library and reset state variables. Open sessions, 10117Sdinak * if any, are closed, and thereby any logins are logged out also. 10217Sdinak */ 10317Sdinak void 10417Sdinak final_pk11(CK_SESSION_HANDLE sess) 10517Sdinak { 10617Sdinak 10717Sdinak /* If the library wasn't initialized, nothing to do here. */ 10817Sdinak if (!initialized) 10917Sdinak return; 11017Sdinak 11117Sdinak /* Make sure the sesion is closed first. */ 11217Sdinak close_sess(sess); 11317Sdinak 11417Sdinak (void) C_Finalize(NULL); 11517Sdinak initialized = B_FALSE; 11617Sdinak } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /* 11917Sdinak * Close PKCS#11 session and reset state variables. Any logins are 12017Sdinak * logged out. 12117Sdinak */ 1223089Swyllys static void 12317Sdinak close_sess(CK_SESSION_HANDLE sess) 12417Sdinak { 12517Sdinak 12617Sdinak if (sess == NULL) { 12717Sdinak return; 12817Sdinak } 12917Sdinak 13017Sdinak /* If session is already closed, nothing to do here. */ 13117Sdinak if (!session_opened) 13217Sdinak return; 1330Sstevel@tonic-gate 13417Sdinak /* Make sure user is logged out of token. */ 13517Sdinak logout_token(sess); 13617Sdinak 13717Sdinak (void) C_CloseSession(sess); 13817Sdinak session_opened = B_FALSE; 13917Sdinak } 14017Sdinak 14117Sdinak /* 14217Sdinak * Log user out of token and reset status variable. 14317Sdinak */ 1443089Swyllys static void 14517Sdinak logout_token(CK_SESSION_HANDLE sess) 14617Sdinak { 14717Sdinak 14817Sdinak if (sess == NULL) { 14917Sdinak return; 15017Sdinak } 15117Sdinak 15217Sdinak /* If already logged out, nothing to do here. */ 15317Sdinak if (!logged_in) 15417Sdinak return; 15517Sdinak 15617Sdinak (void) C_Logout(sess); 15717Sdinak logged_in = B_FALSE; 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate /* 16117Sdinak * Gets PIN from user. Caller needs to free the returned PIN when done. 16217Sdinak * If two prompts are given, the PIN is confirmed with second prompt. 16317Sdinak * Note that getphassphrase() may return data in static memory area. 16417Sdinak */ 16517Sdinak CK_RV 16617Sdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen) 16717Sdinak { 168*6051Swyllys char *save_phrase, *phrase1, *phrase2; 1690Sstevel@tonic-gate 17017Sdinak /* Prompt user for a PIN. */ 17117Sdinak if (prompt1 == NULL) { 17217Sdinak return (CKR_ARGUMENTS_BAD); 17317Sdinak } 17417Sdinak if ((phrase1 = getpassphrase(prompt1)) == NULL) { 17517Sdinak return (CKR_FUNCTION_FAILED); 17617Sdinak } 17717Sdinak 17817Sdinak /* Duplicate 1st PIN in separate chunk of memory. */ 17917Sdinak if ((save_phrase = strdup(phrase1)) == NULL) 18017Sdinak return (CKR_HOST_MEMORY); 18117Sdinak 18217Sdinak /* If second prompt given, PIN confirmation is requested. */ 18317Sdinak if (prompt2 != NULL) { 18417Sdinak if ((phrase2 = getpassphrase(prompt2)) == NULL) { 18517Sdinak free(save_phrase); 18617Sdinak return (CKR_FUNCTION_FAILED); 18717Sdinak } 18817Sdinak if (strcmp(save_phrase, phrase2) != 0) { 18917Sdinak free(save_phrase); 19017Sdinak return (CKR_PIN_INCORRECT); 19117Sdinak } 1920Sstevel@tonic-gate } 1930Sstevel@tonic-gate 19417Sdinak *pin = (CK_UTF8CHAR_PTR)save_phrase; 19517Sdinak *pinlen = strlen(save_phrase); 19617Sdinak return (CKR_OK); 19717Sdinak } 19817Sdinak 199*6051Swyllys int 200*6051Swyllys yn_to_int(char *ynstr) 201*6051Swyllys { 202*6051Swyllys char *y = gettext("yes"); 203*6051Swyllys char *n = gettext("no"); 204*6051Swyllys if (ynstr == NULL) 205*6051Swyllys return (-1); 206*6051Swyllys 207*6051Swyllys if (strncasecmp(ynstr, y, 1) == 0) 208*6051Swyllys return (1); 209*6051Swyllys else if (strncasecmp(ynstr, n, 1) == 0) 210*6051Swyllys return (0); 211*6051Swyllys else 212*6051Swyllys return (-1); 213*6051Swyllys } 214*6051Swyllys 21517Sdinak /* 21617Sdinak * Gets yes/no response from user. If either no prompt is supplied, a 21717Sdinak * default prompt is used. If not message for invalid input is supplied, 21817Sdinak * a default will not be provided. If the user provides no response, 21917Sdinak * the input default B_TRUE == yes, B_FALSE == no is returned. 22017Sdinak * Otherwise, B_TRUE is returned for yes, and B_FALSE for no. 22117Sdinak */ 22217Sdinak boolean_t 22317Sdinak yesno(char *prompt, char *invalid, boolean_t dflt) 22417Sdinak { 225*6051Swyllys char *response, buf[1024]; 226*6051Swyllys int ans; 22717Sdinak 22817Sdinak if (prompt == NULL) 22917Sdinak prompt = gettext("Enter (y)es or (n)o? "); 23017Sdinak 23117Sdinak for (;;) { 23217Sdinak /* Prompt user. */ 23317Sdinak (void) printf("%s", prompt); 23417Sdinak (void) fflush(stdout); 23517Sdinak 23617Sdinak /* Get the response. */ 23717Sdinak if ((response = fgets(buf, sizeof (buf), stdin)) == NULL) 23817Sdinak break; /* go to default response */ 23917Sdinak 24017Sdinak /* Skip any leading white space. */ 24117Sdinak while (isspace(*response)) 24217Sdinak response++; 24317Sdinak if (*response == '\0') 24417Sdinak break; /* go to default response */ 24517Sdinak 246*6051Swyllys ans = yn_to_int(response); 247*6051Swyllys if (ans == 1) 24817Sdinak return (B_TRUE); 249*6051Swyllys else if (ans == 0) 25017Sdinak return (B_FALSE); 25117Sdinak 25217Sdinak /* Indicate invalid input, and try again. */ 25317Sdinak if (invalid != NULL) 2545051Swyllys (void) printf("%s", invalid); 25517Sdinak } 25617Sdinak return (dflt); 25717Sdinak } 25817Sdinak 25917Sdinak /* 26017Sdinak * Gets the list of slots which have tokens in them. Keeps adjusting 26117Sdinak * the size of the slot list buffer until the call is successful or an 26217Sdinak * irrecoverable error occurs. 26317Sdinak */ 26417Sdinak CK_RV 26517Sdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count) 26617Sdinak { 26717Sdinak CK_ULONG tmp_count = 0; 26817Sdinak CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 26917Sdinak int rv = CKR_OK; 27017Sdinak 27117Sdinak if (!initialized) 27217Sdinak if ((rv = init_pk11()) != CKR_OK) 27317Sdinak return (rv); 27417Sdinak 27517Sdinak /* 27617Sdinak * Get the slot count first because we don't know how many 27717Sdinak * slots there are and how many of those slots even have tokens. 27817Sdinak * Don't specify an arbitrary buffer size for the slot list; 27917Sdinak * it may be too small (see section 11.5 of PKCS#11 spec). 28017Sdinak * Also select only those slots that have tokens in them, 28117Sdinak * because this tool has no need to know about empty slots. 28217Sdinak */ 28317Sdinak if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK) 28417Sdinak return (rv); 28517Sdinak 28617Sdinak if (tmp_count == 0) { 28717Sdinak *slot_list = NULL_PTR; 28817Sdinak *slot_count = 0; 28917Sdinak return (CKR_OK); 29017Sdinak } 29117Sdinak 29217Sdinak /* Allocate initial space for the slot list. */ 29317Sdinak if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 29417Sdinak sizeof (CK_SLOT_ID))) == NULL) 29517Sdinak return (CKR_HOST_MEMORY); 29617Sdinak 29717Sdinak /* Then get the slot list itself. */ 29817Sdinak for (;;) { 29917Sdinak if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) { 30017Sdinak *slot_list = tmp_list; 30117Sdinak *slot_count = tmp_count; 30217Sdinak break; 30317Sdinak } 30417Sdinak 30517Sdinak if (rv != CKR_BUFFER_TOO_SMALL) { 30617Sdinak free(tmp_list); 30717Sdinak break; 30817Sdinak } 30917Sdinak 31017Sdinak /* If the number of slots grew, try again. */ 31117Sdinak if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 31217Sdinak tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 31317Sdinak free(tmp_list); 31417Sdinak rv = CKR_HOST_MEMORY; 31517Sdinak break; 31617Sdinak } 31717Sdinak tmp_list = tmp2_list; 31817Sdinak } 31917Sdinak 32017Sdinak return (rv); 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate /* 324864Sdinak * Breaks out the getopt-style option string into a structure that can be 325864Sdinak * traversed later for calls to getopt_av(). Option string is NOT altered, 326864Sdinak * but the struct fields point to locations within option string. 327864Sdinak */ 328864Sdinak static int 329864Sdinak populate_opts(char *optstring) 330864Sdinak { 331864Sdinak int i; 332864Sdinak av_opts *temp; 333864Sdinak char *marker; 334864Sdinak 335864Sdinak if (optstring == NULL || *optstring == '\0') 336864Sdinak return (0); 337864Sdinak 338864Sdinak /* 339864Sdinak * This tries to imitate getopt(3c) Each option must conform to: 340864Sdinak * <short name char> [ ':' ] [ '(' <long name string> ')' ] 341864Sdinak * If long name is missing, the short name is used for long name. 342864Sdinak */ 343864Sdinak for (i = 0; *optstring != '\0'; i++) { 344864Sdinak if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) : 345864Sdinak realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) { 3463089Swyllys if (opts_av != NULL) 3473089Swyllys free(opts_av); 348864Sdinak opts_av = NULL; 349864Sdinak return (0); 3503089Swyllys } else { 351864Sdinak opts_av = (av_opts *)temp; 3523089Swyllys } 353864Sdinak 3543089Swyllys (void) memset(&opts_av[i], 0, sizeof (av_opts)); 355864Sdinak marker = optstring; /* may need optstring later */ 356864Sdinak 357864Sdinak opts_av[i].shortnm = *marker++; /* set short name */ 358864Sdinak 359864Sdinak if (*marker == ':') { /* check for opt arg */ 360864Sdinak marker++; 361864Sdinak opts_av[i].has_arg = B_TRUE; 362864Sdinak } 363864Sdinak 364864Sdinak if (*marker == '(') { /* check and set long name */ 365864Sdinak marker++; 366864Sdinak opts_av[i].longnm = marker; 367864Sdinak opts_av[i].longnm_len = strcspn(marker, ")"); 368864Sdinak optstring = marker + opts_av[i].longnm_len + 1; 369864Sdinak } else { 370864Sdinak /* use short name option character */ 371864Sdinak opts_av[i].longnm = optstring; 372864Sdinak opts_av[i].longnm_len = 1; 373864Sdinak optstring = marker; 374864Sdinak } 375864Sdinak } 376864Sdinak 377864Sdinak return (i); 378864Sdinak } 379864Sdinak 380864Sdinak /* 381864Sdinak * getopt_av() is very similar to getopt(3c) in that the takes an option 382864Sdinak * string, compares command line arguments for matches, and returns a single 383864Sdinak * letter option when a match is found. However, getopt_av() differs from 384864Sdinak * getopt(3c) by requiring that only longname options and values be found 385864Sdinak * on the command line and all leading dashes are omitted. In other words, 386864Sdinak * it tries to enforce only longname "option=value" arguments on the command 387864Sdinak * line. Boolean options are not allowed either. 388864Sdinak */ 389864Sdinak int 390864Sdinak getopt_av(int argc, char * const *argv, const char *optstring) 391864Sdinak { 392864Sdinak int i; 393864Sdinak int len; 3943089Swyllys char *cur_option; 395864Sdinak 396864Sdinak if (optind_av >= argc) 397864Sdinak return (EOF); 398864Sdinak 399864Sdinak /* First time or when optstring changes from previous one */ 400864Sdinak if (_save_optstr != optstring) { 401864Sdinak if (opts_av != NULL) 4025051Swyllys free(opts_av); 403864Sdinak opts_av = NULL; 404864Sdinak _save_optstr = optstring; 405864Sdinak _save_numopts = populate_opts((char *)optstring); 406864Sdinak } 407864Sdinak 408864Sdinak for (i = 0; i < _save_numopts; i++) { 4093089Swyllys cur_option = argv[optind_av]; 4103089Swyllys 4113089Swyllys if (strcmp(cur_option, "--") == 0) { 412864Sdinak optind_av++; 413864Sdinak break; 414864Sdinak } 415864Sdinak 4163089Swyllys if (cur_option[0] == '-' && strlen(cur_option) == 2) { 4173089Swyllys len = 1; 4183089Swyllys cur_option++; /* remove "-" */ 4193089Swyllys } else { 4203089Swyllys len = strcspn(cur_option, "="); 4213089Swyllys } 422864Sdinak 4233089Swyllys if (len == opts_av[i].longnm_len && strncmp(cur_option, 424864Sdinak opts_av[i].longnm, opts_av[i].longnm_len) == 0) { 425864Sdinak /* matched */ 426864Sdinak if (!opts_av[i].has_arg) { 427864Sdinak optind_av++; 428864Sdinak return (opts_av[i].shortnm); 429864Sdinak } 430864Sdinak 431864Sdinak /* needs optarg */ 4323089Swyllys if (cur_option[len] == '=') { 4333089Swyllys optarg_av = &(cur_option[len+1]); 434864Sdinak optind_av++; 435864Sdinak return (opts_av[i].shortnm); 436864Sdinak } 437864Sdinak 438864Sdinak optarg_av = NULL; 439864Sdinak optind_av++; 440864Sdinak return ((int)'?'); 441864Sdinak } 442864Sdinak } 443864Sdinak 444864Sdinak return (EOF); 445864Sdinak } 4463089Swyllys 4473089Swyllys KMF_KEYSTORE_TYPE 4483089Swyllys KS2Int(char *keystore_str) 4493089Swyllys { 4503089Swyllys if (keystore_str == NULL) 4513089Swyllys return (0); 452*6051Swyllys if (strcasecmp(keystore_str, "pkcs11") == 0) 4533089Swyllys return (KMF_KEYSTORE_PK11TOKEN); 454*6051Swyllys else if (strcasecmp(keystore_str, "nss") == 0) 4553089Swyllys return (KMF_KEYSTORE_NSS); 456*6051Swyllys else if (strcasecmp(keystore_str, "file") == 0) 4573089Swyllys return (KMF_KEYSTORE_OPENSSL); 4583089Swyllys else 4593089Swyllys return (0); 4603089Swyllys } 4613089Swyllys 4623089Swyllys 4633089Swyllys int 4643089Swyllys Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg) 4653089Swyllys { 4663089Swyllys if (algm == NULL) { 4673089Swyllys *sigAlg = KMF_ALGID_MD5WithRSA; 4683089Swyllys *ktype = KMF_RSA; 4693089Swyllys } else if (strcasecmp(algm, "DSA") == 0) { 4703089Swyllys *sigAlg = KMF_ALGID_SHA1WithDSA; 4713089Swyllys *ktype = KMF_DSA; 4723089Swyllys } else if (strcasecmp(algm, "RSA") == 0) { 4733089Swyllys *sigAlg = KMF_ALGID_MD5WithRSA; 4743089Swyllys *ktype = KMF_RSA; 4753089Swyllys } else { 4763089Swyllys return (-1); 4773089Swyllys } 4783089Swyllys return (0); 4793089Swyllys } 4803089Swyllys 4813089Swyllys int 4823089Swyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype) 4833089Swyllys { 4843089Swyllys if (algm == NULL) 4853089Swyllys *ktype = KMF_AES; 4863089Swyllys else if (strcasecmp(algm, "aes") == 0) 4873089Swyllys *ktype = KMF_AES; 4883089Swyllys else if (strcasecmp(algm, "arcfour") == 0) 4893089Swyllys *ktype = KMF_RC4; 4903089Swyllys else if (strcasecmp(algm, "des") == 0) 4913089Swyllys *ktype = KMF_DES; 4923089Swyllys else if (strcasecmp(algm, "3des") == 0) 4933089Swyllys *ktype = KMF_DES3; 4943812Shylee else if (strcasecmp(algm, "generic") == 0) 4953812Shylee *ktype = KMF_GENERIC_SECRET; 4963089Swyllys else 4973089Swyllys return (-1); 4983089Swyllys 4993089Swyllys return (0); 5003089Swyllys } 5013089Swyllys 5023089Swyllys int 5033089Swyllys Str2Lifetime(char *ltimestr, uint32_t *ltime) 5043089Swyllys { 5053089Swyllys int num; 5063089Swyllys char timetok[6]; 5073089Swyllys 508*6051Swyllys if (ltimestr == NULL || strlen(ltimestr) == 0) { 5093089Swyllys /* default to 1 year lifetime */ 5103089Swyllys *ltime = SECSPERDAY * DAYSPERNYEAR; 5113089Swyllys return (0); 5123089Swyllys } 5133089Swyllys 5143089Swyllys (void) memset(timetok, 0, sizeof (timetok)); 5153089Swyllys if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2) 5163089Swyllys return (-1); 5173089Swyllys 518*6051Swyllys if (strcasecmp(timetok, "day") == 0|| 519*6051Swyllys strcasecmp(timetok, "days") == 0) { 5203089Swyllys *ltime = num * SECSPERDAY; 521*6051Swyllys } else if (strcasecmp(timetok, "hour") == 0|| 522*6051Swyllys strcasecmp(timetok, "hours") == 0) { 5233089Swyllys *ltime = num * SECSPERHOUR; 524*6051Swyllys } else if (strcasecmp(timetok, "year") == 0 || 525*6051Swyllys strcasecmp(timetok, "years") == 0) { 5263089Swyllys *ltime = num * SECSPERDAY * DAYSPERNYEAR; 5273089Swyllys } else { 5283089Swyllys *ltime = 0; 5293089Swyllys return (-1); 5303089Swyllys } 5313089Swyllys 5323089Swyllys return (0); 5333089Swyllys } 5343089Swyllys 5353089Swyllys int 5363089Swyllys OT2Int(char *objclass) 5373089Swyllys { 5383089Swyllys char *c = NULL; 5393089Swyllys int retval = 0; 5403089Swyllys 5413089Swyllys if (objclass == NULL) 5423089Swyllys return (-1); 5433089Swyllys 5443089Swyllys c = strchr(objclass, ':'); 5453089Swyllys if (c != NULL) { 546*6051Swyllys if (strcasecmp(c, ":private") == 0) 5473089Swyllys retval = PK_PRIVATE_OBJ; 548*6051Swyllys else if (strcasecmp(c, ":public") == 0) 5493089Swyllys retval = PK_PUBLIC_OBJ; 550*6051Swyllys else if (strcasecmp(c, ":both") == 0) 5513089Swyllys retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ; 5523089Swyllys else /* unrecognized option */ 5533089Swyllys return (-1); 5543089Swyllys 5553089Swyllys *c = '\0'; 5563089Swyllys } 5573089Swyllys 558*6051Swyllys if (strcasecmp(objclass, "public") == 0) { 5593089Swyllys if (retval) 5603089Swyllys return (-1); 5615051Swyllys return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ); 562*6051Swyllys } else if (strcasecmp(objclass, "private") == 0) { 5633089Swyllys if (retval) 5643089Swyllys return (-1); 5653089Swyllys return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ); 566*6051Swyllys } else if (strcasecmp(objclass, "both") == 0) { 5673089Swyllys if (retval) 5683089Swyllys return (-1); 5693089Swyllys return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ); 570*6051Swyllys } else if (strcasecmp(objclass, "cert") == 0) { 5713089Swyllys return (retval | PK_CERT_OBJ); 572*6051Swyllys } else if (strcasecmp(objclass, "key") == 0) { 5733089Swyllys if (retval == 0) /* return all keys */ 5743089Swyllys return (retval | PK_KEY_OBJ); 5753089Swyllys else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ)) 5763089Swyllys /* return all keys */ 5773089Swyllys return (retval | PK_KEY_OBJ); 5783089Swyllys else if (retval & PK_PUBLIC_OBJ) 5793089Swyllys /* Only return public keys */ 5803089Swyllys return (retval | PK_PUBKEY_OBJ); 5813089Swyllys else if (retval & PK_PRIVATE_OBJ) 5823089Swyllys /* Only return private keys */ 5833089Swyllys return (retval | PK_PRIKEY_OBJ); 584*6051Swyllys } else if (strcasecmp(objclass, "crl") == 0) { 5853089Swyllys if (retval) 5863089Swyllys return (-1); 5873089Swyllys return (retval | PK_CRL_OBJ); 5883089Swyllys } 5893089Swyllys 5903089Swyllys if (retval == 0) /* No matches found */ 5913089Swyllys retval = -1; 5923089Swyllys return (retval); 5933089Swyllys } 5943089Swyllys 5953089Swyllys KMF_ENCODE_FORMAT 5963089Swyllys Str2Format(char *formstr) 5973089Swyllys { 598*6051Swyllys if (formstr == NULL || strcasecmp(formstr, "der") == 0) 5993089Swyllys return (KMF_FORMAT_ASN1); 600*6051Swyllys if (strcasecmp(formstr, "pem") == 0) 6013089Swyllys return (KMF_FORMAT_PEM); 602*6051Swyllys if (strcasecmp(formstr, "pkcs12") == 0) 6033089Swyllys return (KMF_FORMAT_PKCS12); 604*6051Swyllys if (strcasecmp(formstr, "raw") == 0) 6055051Swyllys return (KMF_FORMAT_RAWKEY); 6063089Swyllys 6073089Swyllys return (KMF_FORMAT_UNDEF); 6083089Swyllys } 6093089Swyllys 6103089Swyllys KMF_RETURN 611*6051Swyllys select_token(void *kmfhandle, char *token, int readonly) 6123089Swyllys { 6135051Swyllys KMF_ATTRIBUTE attlist[10]; 6145051Swyllys int i = 0; 6155051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 6163089Swyllys KMF_RETURN rv = KMF_OK; 6173089Swyllys 6183089Swyllys if (token == NULL) 6193089Swyllys return (KMF_ERR_BAD_PARAMETER); 6203089Swyllys 6215051Swyllys kmf_set_attr_at_index(attlist, i, 6225051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 6235051Swyllys sizeof (kstype)); 6245051Swyllys i++; 6253089Swyllys 6265051Swyllys if (token) { 6275051Swyllys kmf_set_attr_at_index(attlist, i, 6285051Swyllys KMF_TOKEN_LABEL_ATTR, token, 6295051Swyllys strlen(token)); 6305051Swyllys i++; 6315051Swyllys } 6325051Swyllys 6335051Swyllys kmf_set_attr_at_index(attlist, i, 6345051Swyllys KMF_READONLY_ATTR, &readonly, 6355051Swyllys sizeof (readonly)); 6365051Swyllys i++; 6375051Swyllys 6385051Swyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 6393089Swyllys if (rv == KMF_ERR_TOKEN_SELECTED) 6403089Swyllys rv = KMF_OK; 6413089Swyllys return (rv); 6423089Swyllys } 6433089Swyllys 6443089Swyllys KMF_RETURN 6453089Swyllys configure_nss(void *kmfhandle, char *dir, char *prefix) 6463089Swyllys { 6475051Swyllys KMF_ATTRIBUTE attlist[10]; 6485051Swyllys int i = 0; 6495051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 6503089Swyllys KMF_RETURN rv = KMF_OK; 6515051Swyllys 6525051Swyllys kmf_set_attr_at_index(attlist, i, 6535051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 6545051Swyllys sizeof (kstype)); 6555051Swyllys i++; 6563089Swyllys 6575051Swyllys if (dir) { 6585051Swyllys kmf_set_attr_at_index(attlist, i, 6595051Swyllys KMF_DIRPATH_ATTR, dir, 6605051Swyllys strlen(dir)); 6615051Swyllys i++; 6625051Swyllys } 6633089Swyllys 6645051Swyllys if (prefix) { 6655051Swyllys kmf_set_attr_at_index(attlist, i, 6665051Swyllys KMF_CERTPREFIX_ATTR, prefix, 6675051Swyllys strlen(prefix)); 6685051Swyllys i++; 6695051Swyllys 6705051Swyllys kmf_set_attr_at_index(attlist, i, 6715051Swyllys KMF_KEYPREFIX_ATTR, prefix, 6725051Swyllys strlen(prefix)); 6735051Swyllys i++; 6745051Swyllys } 6755051Swyllys 6765051Swyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 6773089Swyllys if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED) 6783089Swyllys rv = KMF_OK; 6793089Swyllys 6803089Swyllys return (rv); 6813089Swyllys } 6823089Swyllys 6833089Swyllys KMF_RETURN 6843089Swyllys get_pk12_password(KMF_CREDENTIAL *cred) 6853089Swyllys { 6863089Swyllys KMF_RETURN rv = KMF_OK; 6873089Swyllys char prompt[1024]; 6883089Swyllys 6893089Swyllys /* 6903089Swyllys * Get the password to use for the PK12 encryption. 6913089Swyllys */ 6923089Swyllys (void) strlcpy(prompt, 6935051Swyllys gettext("Enter password to use for " 6945051Swyllys "accessing the PKCS12 file: "), sizeof (prompt)); 6953089Swyllys 6963089Swyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 6975051Swyllys (ulong_t *)&cred->credlen) != CKR_OK) { 6983089Swyllys cred->cred = NULL; 6993089Swyllys cred->credlen = 0; 7003089Swyllys } 7013089Swyllys 7023089Swyllys return (rv); 7033089Swyllys } 7043089Swyllys 7055221Swyllys #define FILENAME_PROMPT gettext("Filename:") 7065221Swyllys #define FILENAME_MINLEN 1 7075221Swyllys #define FILENAME_MAXLEN MAXPATHLEN 7083089Swyllys 7095221Swyllys #define COUNTRY_PROMPT gettext("Country Name (2 letter code) [US]:") 7105221Swyllys #define STATE_PROMPT gettext("State or Province Name (full name) " \ 7115221Swyllys "[Some-State]:") 7125221Swyllys #define LOCALITY_PROMPT gettext("Locality Name (eg, city) []:") 7135221Swyllys #define ORG_PROMPT gettext("Organization Name (eg, company) []:") 7145221Swyllys #define UNIT_PROMPT gettext("Organizational Unit Name (eg, section) []:") 7155221Swyllys #define NAME_PROMPT gettext("Common Name (eg, YOUR name) []:") 7165221Swyllys #define EMAIL_PROMPT gettext("Email Address []:") 7175221Swyllys 7185221Swyllys #define SERNO_PROMPT gettext("Serial Number (hex value, example: " \ 7195221Swyllys "0x01020304):") 7205221Swyllys #define SERNO_MINLEN 3 7215221Swyllys #define SERNO_MAXLEN 42 7225221Swyllys 7235221Swyllys #define LABEL_PROMPT gettext("Enter a label for the certificate:") 7245221Swyllys #define LABEL_MINLEN 1 7255221Swyllys #define LABEL_MAXLEN 1024 7263089Swyllys 7273089Swyllys #define COUNTRY_DEFAULT "US" 7285221Swyllys #define STATE_DEFAULT NULL 7295221Swyllys #define INVALID_INPUT gettext("Invalid input; please re-enter ...") 7303089Swyllys 7313089Swyllys #define SUBNAMESIZ 1024 7323089Swyllys #define RDN_MIN 1 7333089Swyllys #define RDN_MAX 64 7343089Swyllys #define COUNTRYNAME_MIN 2 7353089Swyllys #define COUNTRYNAME_MAX 2 7363089Swyllys 7373089Swyllys static char * 7383089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len) 7393089Swyllys { 7403089Swyllys char buf[1024]; 7413089Swyllys char *response = NULL; 7423089Swyllys char *ret = NULL; 7433089Swyllys int len; 7443089Swyllys 7453089Swyllys for (;;) { 7463089Swyllys (void) printf("\t%s", prompt); 7473089Swyllys (void) fflush(stdout); 7483089Swyllys 7493089Swyllys response = fgets(buf, sizeof (buf), stdin); 7503089Swyllys if (response == NULL) { 7513089Swyllys if (default_str != NULL) { 7523089Swyllys ret = strdup(default_str); 7533089Swyllys } 7543089Swyllys break; 7553089Swyllys } 7563089Swyllys 7573089Swyllys /* Skip any leading white space. */ 7583089Swyllys while (isspace(*response)) 7593089Swyllys response++; 7603089Swyllys if (*response == '\0') { 7613089Swyllys if (default_str != NULL) { 7623089Swyllys ret = strdup(default_str); 7633089Swyllys } 7643089Swyllys break; 7653089Swyllys } 7663089Swyllys 7673089Swyllys len = strlen(response); 7683089Swyllys response[len-1] = '\0'; /* get rid of "LF" */ 7693089Swyllys len--; 7703089Swyllys if (len >= min_len && len <= max_len) { 7713089Swyllys ret = strdup(response); 7723089Swyllys break; 7733089Swyllys } 7743089Swyllys 7753089Swyllys (void) printf("%s\n", INVALID_INPUT); 7763089Swyllys 7773089Swyllys } 7783089Swyllys 7793089Swyllys return (ret); 7803089Swyllys } 7813089Swyllys 7823089Swyllys int 7835221Swyllys get_filename(char *txt, char **result) 7845221Swyllys { 7855221Swyllys char prompt[1024]; 7865221Swyllys char *fname = NULL; 7875221Swyllys 7885221Swyllys (void) snprintf(prompt, sizeof (prompt), 7895221Swyllys gettext("Enter filename for the %s: "), 7905221Swyllys txt); 7915221Swyllys fname = get_input_string(prompt, NULL, 7925221Swyllys FILENAME_MINLEN, FILENAME_MAXLEN); 7935221Swyllys *result = fname; 7945221Swyllys return (0); 7955221Swyllys } 7965221Swyllys 7975221Swyllys int 7985221Swyllys get_certlabel(char **result) 7995221Swyllys { 8005221Swyllys char *label = NULL; 8015221Swyllys 8025221Swyllys label = get_input_string(LABEL_PROMPT, NULL, 8035221Swyllys LABEL_MINLEN, LABEL_MAXLEN); 8045221Swyllys *result = label; 8055221Swyllys return (0); 8065221Swyllys } 8075221Swyllys 8085221Swyllys int 8095221Swyllys get_serial(char **result) 8105221Swyllys { 8115221Swyllys char *serial = NULL; 8125221Swyllys 8135221Swyllys serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN, 8145221Swyllys SERNO_MAXLEN); 8155221Swyllys 8165221Swyllys *result = serial; 8175221Swyllys return (0); 8185221Swyllys } 8195221Swyllys 8205221Swyllys int 8213089Swyllys get_subname(char **result) 8223089Swyllys { 8233089Swyllys char *country = NULL; 8243089Swyllys char *state = NULL; 8253089Swyllys char *locality = NULL; 8263089Swyllys char *org = NULL; 8273089Swyllys char *unit = NULL; 8283089Swyllys char *name = NULL; 8293089Swyllys char *email = NULL; 8303089Swyllys char *subname = NULL; 8313089Swyllys 8323089Swyllys (void) printf("Entering following fields for subject (a DN) ...\n"); 8333089Swyllys country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT, 8343089Swyllys COUNTRYNAME_MIN, COUNTRYNAME_MAX); 8353089Swyllys if (country == NULL) 8363089Swyllys return (-1); 8373089Swyllys 8383089Swyllys state = get_input_string(STATE_PROMPT, STATE_DEFAULT, 8393089Swyllys RDN_MIN, RDN_MAX); 8403089Swyllys 8413089Swyllys locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX); 8423089Swyllys org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX); 8433089Swyllys unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX); 8443089Swyllys name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX); 8453089Swyllys email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX); 8463089Swyllys 8473089Swyllys /* Now create a subject name from the input strings */ 8483089Swyllys if ((subname = malloc(SUBNAMESIZ)) == NULL) 8493089Swyllys goto out; 8503089Swyllys 8513089Swyllys (void) memset(subname, 0, SUBNAMESIZ); 8523089Swyllys (void) strlcpy(subname, "C=", SUBNAMESIZ); 8533089Swyllys (void) strlcat(subname, country, SUBNAMESIZ); 8545221Swyllys if (state != NULL) { 8555221Swyllys (void) strlcat(subname, ", ST=", SUBNAMESIZ); 8565221Swyllys (void) strlcat(subname, state, SUBNAMESIZ); 8575221Swyllys } 8583089Swyllys 8595221Swyllys if (locality != NULL) { 8605221Swyllys (void) strlcat(subname, ", L=", SUBNAMESIZ); 8613089Swyllys (void) strlcat(subname, locality, SUBNAMESIZ); 8623089Swyllys } 8633089Swyllys 8645221Swyllys if (org != NULL) { 8655221Swyllys (void) strlcat(subname, ", O=", SUBNAMESIZ); 8663089Swyllys (void) strlcat(subname, org, SUBNAMESIZ); 8673089Swyllys } 8683089Swyllys 8695221Swyllys if (unit != NULL) { 8705221Swyllys (void) strlcat(subname, ", OU=", SUBNAMESIZ); 8713089Swyllys (void) strlcat(subname, unit, SUBNAMESIZ); 8723089Swyllys } 8733089Swyllys 8745221Swyllys if (name != NULL) { 8755221Swyllys (void) strlcat(subname, ", CN=", SUBNAMESIZ); 8763089Swyllys (void) strlcat(subname, name, SUBNAMESIZ); 8773089Swyllys } 8783089Swyllys 8795221Swyllys if (email != NULL) { 8805221Swyllys (void) strlcat(subname, ", E=", SUBNAMESIZ); 8813089Swyllys (void) strlcat(subname, email, SUBNAMESIZ); 8823089Swyllys } 8833089Swyllys 8843089Swyllys out: 8853089Swyllys if (country) 8863089Swyllys free(country); 8873089Swyllys if (state) 8883089Swyllys free(state); 8893089Swyllys if (locality) 8903089Swyllys free(locality); 8913089Swyllys if (org) 8923089Swyllys free(org); 8933089Swyllys if (unit) 8943089Swyllys free(unit); 8953089Swyllys if (name) 8963089Swyllys free(name); 8973089Swyllys if (email) 8983089Swyllys free(email); 8993089Swyllys 9003089Swyllys if (subname == NULL) 9013089Swyllys return (-1); 9023089Swyllys else { 9033089Swyllys *result = subname; 9043089Swyllys return (0); 9053089Swyllys } 9063089Swyllys } 9073089Swyllys 9083089Swyllys /* 9093089Swyllys * Parse a string of KeyUsage values and convert 9103089Swyllys * them to the correct KU Bits. 9113089Swyllys * The field may be marked "critical" by prepending 9123089Swyllys * "critical:" to the list. 9133089Swyllys * EX: critical:digitialSignature,keyEncipherment 9143089Swyllys */ 9153089Swyllys KMF_RETURN 9163089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical) 9173089Swyllys { 9183089Swyllys KMF_RETURN ret = KMF_OK; 9193089Swyllys uint16_t kuval; 9203089Swyllys char *k; 9213089Swyllys 9223089Swyllys *kubits = 0; 923*6051Swyllys if (kustr == NULL || strlen(kustr) == 0) 9243089Swyllys return (KMF_ERR_BAD_PARAMETER); 9253089Swyllys 9263089Swyllys /* Check to see if this is critical */ 927*6051Swyllys if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) { 9283089Swyllys *critical = TRUE; 9293089Swyllys kustr += strlen("critical:"); 9303089Swyllys } else { 9313089Swyllys *critical = FALSE; 9323089Swyllys } 9333089Swyllys 9343089Swyllys k = strtok(kustr, ","); 9353089Swyllys while (k != NULL) { 9365051Swyllys kuval = kmf_string_to_ku(k); 9373089Swyllys if (kuval == 0) { 9383089Swyllys *kubits = 0; 9393089Swyllys return (KMF_ERR_BAD_PARAMETER); 9403089Swyllys } 9413089Swyllys *kubits |= kuval; 9423089Swyllys k = strtok(NULL, ","); 9433089Swyllys } 9443089Swyllys 9453089Swyllys return (ret); 9463089Swyllys } 9473089Swyllys 9483089Swyllys /* 9493089Swyllys * Verify the alternate subject label is real or invalid. 9503089Swyllys * 9513089Swyllys * The field may be marked "critical" by prepending 9523089Swyllys * "critical:" to the list. 9533089Swyllys * EX: "critical:IP=1.2.3.4" 9543089Swyllys */ 9553089Swyllys KMF_RETURN 9563089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical) 9573089Swyllys { 9583089Swyllys char *p; 9593089Swyllys KMF_RETURN rv = KMF_OK; 9603089Swyllys 9613089Swyllys /* Check to see if this is critical */ 962*6051Swyllys if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) { 9633089Swyllys *critical = TRUE; 9643089Swyllys arg += strlen("critical:"); 9653089Swyllys } else { 9663089Swyllys *critical = FALSE; 9673089Swyllys } 9683089Swyllys 9693089Swyllys /* Make sure there is an "=" sign */ 9703089Swyllys p = strchr(arg, '='); 9713089Swyllys if (p == NULL) 9723089Swyllys return (KMF_ERR_BAD_PARAMETER); 9733089Swyllys 9743089Swyllys p[0] = '\0'; 9753089Swyllys 9763089Swyllys if (strcmp(arg, "IP") == 0) 9773089Swyllys *type = GENNAME_IPADDRESS; 9783089Swyllys else if (strcmp(arg, "DNS") == 0) 9793089Swyllys *type = GENNAME_DNSNAME; 9803089Swyllys else if (strcmp(arg, "EMAIL") == 0) 9813089Swyllys *type = GENNAME_RFC822NAME; 9823089Swyllys else if (strcmp(arg, "URI") == 0) 9833089Swyllys *type = GENNAME_URI; 9843089Swyllys else if (strcmp(arg, "DN") == 0) 9853089Swyllys *type = GENNAME_DIRECTORYNAME; 9863089Swyllys else if (strcmp(arg, "RID") == 0) 9873089Swyllys *type = GENNAME_REGISTEREDID; 988*6051Swyllys else if (strcmp(arg, "KRB") == 0) 989*6051Swyllys *type = GENNAME_KRB5PRINC; 990*6051Swyllys else if (strcmp(arg, "UPN") == 0) 991*6051Swyllys *type = GENNAME_SCLOGON_UPN; 9923089Swyllys else 9933089Swyllys rv = KMF_ERR_BAD_PARAMETER; 9943089Swyllys 9953089Swyllys p[0] = '='; 9963089Swyllys 9973089Swyllys return (rv); 9983089Swyllys } 9993089Swyllys 10003089Swyllys int 10013089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype, 10023089Swyllys char *token_spec, KMF_CREDENTIAL *cred) 10033089Swyllys { 10043089Swyllys char prompt[1024]; 10053089Swyllys char *p = NULL; 10063089Swyllys 10073089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN) { 10083089Swyllys p = strchr(token_spec, ':'); 10093089Swyllys if (p != NULL) 10103089Swyllys *p = 0; 10113089Swyllys } 10123089Swyllys /* 10133089Swyllys * Login to the token first. 10143089Swyllys */ 10153089Swyllys (void) snprintf(prompt, sizeof (prompt), 10165051Swyllys gettext(DEFAULT_TOKEN_PROMPT), token_spec); 10173089Swyllys 10183089Swyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 10195051Swyllys (ulong_t *)&cred->credlen) != CKR_OK) { 10203089Swyllys cred->cred = NULL; 10213089Swyllys cred->credlen = 0; 10223089Swyllys } 10233089Swyllys 10243089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL) 10253089Swyllys *p = ':'; 10263089Swyllys return (KMF_OK); 10273089Swyllys } 10283089Swyllys 10293089Swyllys KMF_RETURN 10303089Swyllys verify_file(char *filename) 10313089Swyllys { 10323089Swyllys KMF_RETURN ret = KMF_OK; 10333089Swyllys int fd; 10343089Swyllys 10353089Swyllys /* 10363089Swyllys * Attempt to open with the EXCL flag so that if 10373089Swyllys * it already exists, the open will fail. It will 10383089Swyllys * also fail if the file cannot be created due to 10393089Swyllys * permissions on the parent directory, or if the 10403089Swyllys * parent directory itself does not exist. 10413089Swyllys */ 10423089Swyllys fd = open(filename, O_CREAT | O_EXCL, 0600); 10433089Swyllys if (fd == -1) 10443089Swyllys return (KMF_ERR_OPEN_FILE); 10453089Swyllys 10463089Swyllys /* If we were able to create it, delete it. */ 10473089Swyllys (void) close(fd); 10483089Swyllys (void) unlink(filename); 10493089Swyllys 10503089Swyllys return (ret); 10513089Swyllys } 10523089Swyllys 10533089Swyllys void 10543089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix) 10553089Swyllys { 10563089Swyllys KMF_RETURN rv1, rv2; 10573089Swyllys char *plugin_errmsg = NULL; 10583089Swyllys char *kmf_errmsg = NULL; 10593089Swyllys 10605051Swyllys rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg); 10615051Swyllys rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg); 10623089Swyllys 10633089Swyllys cryptoerror(LOG_STDERR, "%s:", prefix); 10643089Swyllys if (rv1 == KMF_OK && plugin_errmsg) { 10655051Swyllys cryptoerror(LOG_STDERR, gettext("keystore error: %s"), 10665051Swyllys plugin_errmsg); 10675051Swyllys kmf_free_str(plugin_errmsg); 10683089Swyllys } 10693089Swyllys 10703089Swyllys if (rv2 == KMF_OK && kmf_errmsg) { 10715051Swyllys cryptoerror(LOG_STDERR, gettext("libkmf error: %s"), 10725051Swyllys kmf_errmsg); 10735051Swyllys kmf_free_str(kmf_errmsg); 10743089Swyllys } 10753089Swyllys 10763089Swyllys if (rv1 != KMF_OK && rv2 != KMF_OK) 10773089Swyllys cryptoerror(LOG_STDERR, gettext("<unknown error>\n")); 10783089Swyllys 10793089Swyllys } 1080*6051Swyllys 1081*6051Swyllys static KMF_RETURN 1082*6051Swyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid) 1083*6051Swyllys { 1084*6051Swyllys if (newoid != NULL && ekus != NULL) { 1085*6051Swyllys ekus->eku_count++; 1086*6051Swyllys 1087*6051Swyllys ekus->critlist = realloc(ekus->critlist, 1088*6051Swyllys ekus->eku_count * sizeof (int)); 1089*6051Swyllys if (ekus->critlist != NULL) 1090*6051Swyllys ekus->critlist[ekus->eku_count-1] = critical; 1091*6051Swyllys else 1092*6051Swyllys return (KMF_ERR_MEMORY); 1093*6051Swyllys 1094*6051Swyllys ekus->ekulist = realloc( 1095*6051Swyllys ekus->ekulist, ekus->eku_count * sizeof (KMF_OID)); 1096*6051Swyllys if (ekus->ekulist != NULL) 1097*6051Swyllys ekus->ekulist[ekus->eku_count-1] = *newoid; 1098*6051Swyllys else 1099*6051Swyllys return (KMF_ERR_MEMORY); 1100*6051Swyllys } 1101*6051Swyllys return (KMF_OK); 1102*6051Swyllys } 1103*6051Swyllys 1104*6051Swyllys void 1105*6051Swyllys free_eku_list(EKU_LIST *ekus) 1106*6051Swyllys { 1107*6051Swyllys if (ekus != NULL && ekus->eku_count > 0) { 1108*6051Swyllys int i; 1109*6051Swyllys for (i = 0; i < ekus->eku_count; i++) { 1110*6051Swyllys kmf_free_data(&ekus->ekulist[i]); 1111*6051Swyllys } 1112*6051Swyllys free(ekus->ekulist); 1113*6051Swyllys free(ekus->critlist); 1114*6051Swyllys } 1115*6051Swyllys } 1116*6051Swyllys 1117*6051Swyllys static KMF_RETURN 1118*6051Swyllys parse_ekus(char *ekustr, EKU_LIST *ekus) 1119*6051Swyllys { 1120*6051Swyllys KMF_RETURN rv = KMF_OK; 1121*6051Swyllys KMF_OID *newoid; 1122*6051Swyllys int critical; 1123*6051Swyllys 1124*6051Swyllys if (strncasecmp(ekustr, "critical:", 1125*6051Swyllys strlen("critical:")) == 0) { 1126*6051Swyllys critical = TRUE; 1127*6051Swyllys ekustr += strlen("critical:"); 1128*6051Swyllys } else { 1129*6051Swyllys critical = FALSE; 1130*6051Swyllys } 1131*6051Swyllys newoid = kmf_ekuname_to_oid(ekustr); 1132*6051Swyllys if (newoid != NULL) { 1133*6051Swyllys rv = addToEKUList(ekus, critical, newoid); 1134*6051Swyllys free(newoid); 1135*6051Swyllys } else { 1136*6051Swyllys rv = PK_ERR_USAGE; 1137*6051Swyllys } 1138*6051Swyllys 1139*6051Swyllys return (rv); 1140*6051Swyllys } 1141*6051Swyllys 1142*6051Swyllys KMF_RETURN 1143*6051Swyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist) 1144*6051Swyllys { 1145*6051Swyllys KMF_RETURN rv = KMF_OK; 1146*6051Swyllys char *p; 1147*6051Swyllys EKU_LIST *ekus = NULL; 1148*6051Swyllys 1149*6051Swyllys if (ekuliststr == NULL || strlen(ekuliststr) == 0) 1150*6051Swyllys return (0); 1151*6051Swyllys 1152*6051Swyllys /* 1153*6051Swyllys * The list should be comma separated list of EKU Names. 1154*6051Swyllys */ 1155*6051Swyllys p = strtok(ekuliststr, ","); 1156*6051Swyllys 1157*6051Swyllys /* If no tokens found, then maybe it's just a single EKU value */ 1158*6051Swyllys if (p == NULL) { 1159*6051Swyllys rv = parse_ekus(ekuliststr, ekus); 1160*6051Swyllys } 1161*6051Swyllys 1162*6051Swyllys while (p != NULL) { 1163*6051Swyllys rv = parse_ekus(p, ekus); 1164*6051Swyllys 1165*6051Swyllys if (rv != KMF_OK) 1166*6051Swyllys break; 1167*6051Swyllys p = strtok(NULL, ","); 1168*6051Swyllys } 1169*6051Swyllys 1170*6051Swyllys if (rv != KMF_OK) 1171*6051Swyllys free_eku_list(ekus); 1172*6051Swyllys else 1173*6051Swyllys *ekulist = ekus; 1174*6051Swyllys 1175*6051Swyllys return (rv); 1176*6051Swyllys } 1177