xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/delete.c (revision 864:75df3e9f93de)
117Sdinak /*
217Sdinak  * CDDL HEADER START
317Sdinak  *
417Sdinak  * The contents of this file are subject to the terms of the
517Sdinak  * Common Development and Distribution License, Version 1.0 only
617Sdinak  * (the "License").  You may not use this file except in compliance
717Sdinak  * with the License.
817Sdinak  *
917Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1017Sdinak  * or http://www.opensolaris.org/os/licensing.
1117Sdinak  * See the License for the specific language governing permissions
1217Sdinak  * and limitations under the License.
1317Sdinak  *
1417Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
1517Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1617Sdinak  * If applicable, add the following below this CDDL HEADER, with the
1717Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
1817Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
1917Sdinak  *
2017Sdinak  * CDDL HEADER END
2117Sdinak  */
2217Sdinak /*
2317Sdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
2417Sdinak  * Use is subject to license terms.
2517Sdinak  */
2617Sdinak 
2717Sdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
2817Sdinak 
2917Sdinak /*
3017Sdinak  * This file implements the token object delete operation for this tool.
3117Sdinak  * It loads the PKCS#11 modules, finds the object to delete, deletes it,
3217Sdinak  * and cleans up.  User must be R/W logged into the token.
3317Sdinak  */
3417Sdinak 
3517Sdinak #include <stdio.h>
3617Sdinak #include <string.h>
3717Sdinak #include <cryptoutil.h>
3817Sdinak #include <security/cryptoki.h>
3917Sdinak #include "common.h"
4017Sdinak 
4117Sdinak /*
4217Sdinak  * Delete token objects.
4317Sdinak  */
4417Sdinak int
4517Sdinak pk_delete(int argc, char *argv[])
4617Sdinak {
4717Sdinak 	int		opt;
48*864Sdinak 	extern int	optind_av;
49*864Sdinak 	extern char	*optarg_av;
50*864Sdinak 	char		*token_spec = NULL;
5117Sdinak 	char		*token_name = NULL;
5217Sdinak 	char		*manuf_id = NULL;
5317Sdinak 	char		*serial_no = NULL;
54*864Sdinak 	char		*type_spec = NULL;
5517Sdinak 	char		full_name[FULL_NAME_LEN];
5617Sdinak 	boolean_t	public_objs = B_FALSE;
5717Sdinak 	boolean_t	private_objs = B_FALSE;
5817Sdinak 	CK_BYTE		*object_label = NULL;
5917Sdinak 	int		obj_type = 0x00;
6017Sdinak 	CK_SLOT_ID	slot_id;
6117Sdinak 	CK_FLAGS	pin_state;
6217Sdinak 	CK_UTF8CHAR_PTR	pin = NULL;
6317Sdinak 	CK_ULONG	pinlen = 0;
6417Sdinak 	CK_SESSION_HANDLE	sess;
6517Sdinak 	CK_OBJECT_HANDLE	*objs;
6617Sdinak 	CK_ULONG	num_objs;
6717Sdinak 	CK_ATTRIBUTE	label = { CKA_LABEL, NULL, 0 };
6817Sdinak 	CK_RV		rv = CKR_OK;
6917Sdinak 	int		i;
7017Sdinak 
7117Sdinak 	cryptodebug("inside pk_delete");
7217Sdinak 
7317Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
74*864Sdinak 	while ((opt = getopt_av(argc, argv,
75*864Sdinak 	    "T:(token)y:(objtype)l:(label)")) != EOF) {
7617Sdinak 		switch (opt) {
77*864Sdinak 		case 'T':	/* token specifier */
78*864Sdinak 			if (token_spec)
79*864Sdinak 				return (PK_ERR_USAGE);
80*864Sdinak 			token_spec = optarg_av;
8117Sdinak 			break;
82*864Sdinak 		case 'y':	/* object type:  public, private, both */
83*864Sdinak 			if (type_spec)
84*864Sdinak 				return (PK_ERR_USAGE);
85*864Sdinak 			type_spec = optarg_av;
8617Sdinak 			break;
8717Sdinak 		case 'l':	/* objects with specific label */
8817Sdinak 			if (object_label)
8917Sdinak 				return (PK_ERR_USAGE);
90*864Sdinak 			object_label = (CK_BYTE *)optarg_av;
9117Sdinak 			break;
9217Sdinak 		default:
9317Sdinak 			return (PK_ERR_USAGE);
9417Sdinak 			break;
9517Sdinak 		}
9617Sdinak 	}
9717Sdinak 
98*864Sdinak 	/* If no token is specified, default is to use softtoken. */
99*864Sdinak 	if (token_spec == NULL) {
100*864Sdinak 		token_name = SOFT_TOKEN_LABEL;
101*864Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
102*864Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
103*864Sdinak 	} else {
104*864Sdinak 		/*
105*864Sdinak 		 * Parse token specifier into token_name, manuf_id, serial_no.
106*864Sdinak 		 * Token_name is required; manuf_id and serial_no are optional.
107*864Sdinak 		 */
108*864Sdinak 		if (parse_token_spec(token_spec, &token_name, &manuf_id,
109*864Sdinak 		    &serial_no) < 0)
110*864Sdinak 			return (PK_ERR_USAGE);
111*864Sdinak 	}
112*864Sdinak 
113*864Sdinak 	/* If no object type specified, default is public objects. */
114*864Sdinak 	if (!type_spec) {
115*864Sdinak 		public_objs = B_TRUE;
116*864Sdinak 	} else {
117*864Sdinak 		/*
118*864Sdinak 		 * Otherwise, the object type must be "public", "private",
119*864Sdinak 		 * or "both".
120*864Sdinak 		 */
121*864Sdinak 		if (strcmp(type_spec, "private") == 0) {
122*864Sdinak 			private_objs = B_TRUE;
123*864Sdinak 		} else if (strcmp(type_spec, "public") == 0) {
124*864Sdinak 			public_objs = B_TRUE;
125*864Sdinak 		} else if (strcmp(type_spec, "both") == 0) {
126*864Sdinak 			private_objs = B_TRUE;
127*864Sdinak 			public_objs = B_TRUE;
128*864Sdinak 		} else
129*864Sdinak 			return (PK_ERR_USAGE);
130*864Sdinak 	}
131*864Sdinak 
132*864Sdinak 	if (private_objs)
133*864Sdinak 		obj_type |= PK_PRIVATE_OBJ;
134*864Sdinak 	if (public_objs)
135*864Sdinak 		obj_type |= PK_PUBLIC_OBJ;
136*864Sdinak 
13717Sdinak 	/* At least one of public, private, or object label is required. */
13817Sdinak 	if (!private_objs && !public_objs && object_label == NULL)
13917Sdinak 		return (PK_ERR_USAGE);
14017Sdinak 
14117Sdinak 	/*
14217Sdinak 	 * If object label is given but neither public/private is specified,
14317Sdinak 	 * delete all objects with that label.
14417Sdinak 	 */
14517Sdinak 	if (!private_objs && !public_objs && object_label != NULL)
14617Sdinak 		obj_type = PK_ALL_OBJ;
14717Sdinak 
14817Sdinak 	/* No additional args allowed. */
149*864Sdinak 	argc -= optind_av;
150*864Sdinak 	argv += optind_av;
15117Sdinak 	if (argc)
15217Sdinak 		return (PK_ERR_USAGE);
15317Sdinak 	/* Done parsing command line options. */
15417Sdinak 
15517Sdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
15617Sdinak 
15717Sdinak 	/* Find the slot with token. */
15817Sdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
15917Sdinak 	    &pin_state)) != CKR_OK) {
16017Sdinak 		cryptoerror(LOG_STDERR, gettext(
16117Sdinak 		    "Unable to find token %s (%s)."), full_name,
16217Sdinak 		    pkcs11_strerror(rv));
16317Sdinak 		return (PK_ERR_PK11);
16417Sdinak 	}
16517Sdinak 
16617Sdinak 	/* Always get the user's PIN for delete operations. */
16717Sdinak 	if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
16817Sdinak 	    &pinlen)) != CKR_OK) {
16917Sdinak 		cryptoerror(LOG_STDERR, gettext(
17017Sdinak 		    "Unable to get token passphrase (%s)."),
17117Sdinak 		    pkcs11_strerror(rv));
17217Sdinak 		quick_finish(NULL);
17317Sdinak 		return (PK_ERR_PK11);
17417Sdinak 	}
17517Sdinak 
17617Sdinak 	/* Log the user R/W into the token. */
17717Sdinak 	if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
17817Sdinak 	    CKR_OK) {
17917Sdinak 		cryptoerror(LOG_STDERR, gettext(
18017Sdinak 		    "Unable to log into token (%s)."), pkcs11_strerror(rv));
18117Sdinak 		quick_finish(sess);
18217Sdinak 		return (PK_ERR_PK11);
18317Sdinak 	}
18417Sdinak 
18517Sdinak 	/* Find the object(s) with the given label and/or type. */
18617Sdinak 	if ((rv = find_objs(sess, obj_type, object_label, &objs, &num_objs)) !=
18717Sdinak 	    CKR_OK) {
18817Sdinak 		cryptoerror(LOG_STDERR, gettext(
18917Sdinak 		    "Unable to find token objects (%s)."), pkcs11_strerror(rv));
19017Sdinak 		quick_finish(sess);
19117Sdinak 		return (PK_ERR_PK11);
19217Sdinak 	}
19317Sdinak 
19417Sdinak 	if (num_objs == 0) {
19517Sdinak 		(void) fprintf(stdout, gettext("No matching objects found.\n"));
19617Sdinak 		quick_finish(sess);
19717Sdinak 		return (0);
19817Sdinak 	}
19917Sdinak 
20017Sdinak 	if (num_objs != 1) {
20117Sdinak 		(void) fprintf(stdout, gettext(
20217Sdinak 		    "Warning: %d matching objects found, deleting all.\n"),
20317Sdinak 		    num_objs);
20417Sdinak 		if (yesno(gettext("Continue with delete? "),
20517Sdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
20617Sdinak 			quick_finish(sess);
20717Sdinak 			return (0);
20817Sdinak 		}
20917Sdinak 	}
21017Sdinak 
21117Sdinak 	/* Destroy the objects if found. */
21217Sdinak 	for (i = 0; i < num_objs; i++) {
21317Sdinak 		/*
21417Sdinak 		 * To give nice feedback to the user, get the object's
21517Sdinak 		 * label before deleting it.
21617Sdinak 		 */
21717Sdinak 		cryptodebug("calling C_GetAttributeValue for label");
21817Sdinak 		label.pValue = NULL;
21917Sdinak 		label.ulValueLen = 0;
22017Sdinak 		if (C_GetAttributeValue(sess, objs[i], &label, 1) == CKR_OK) {
22117Sdinak 			if (label.ulValueLen != (CK_ULONG)-1 &&
22217Sdinak 			    label.ulValueLen != 0 &&
22317Sdinak 			    (label.pValue = malloc(label.ulValueLen)) != NULL) {
22417Sdinak 				if (C_GetAttributeValue(sess, objs[i], &label,
22517Sdinak 				    1) != CKR_OK) {
22617Sdinak 					free(label.pValue);
22717Sdinak 					label.pValue = NULL;
22817Sdinak 					label.ulValueLen = 0;
22917Sdinak 				}
23017Sdinak 			} else {
23117Sdinak 				label.ulValueLen = 0;
23217Sdinak 			}
23317Sdinak 		}
23417Sdinak 
23517Sdinak 		cryptodebug("calling C_DestroyObject");
23617Sdinak 		if ((rv = C_DestroyObject(sess, objs[i])) != CKR_OK) {
23717Sdinak 			if (label.pValue != NULL)
23817Sdinak 				cryptoerror(LOG_STDERR, gettext(
23917Sdinak 				    "Unable to delete object #%d \"%.*s\" "
24017Sdinak 				    "(%s)."), i+1, label.ulValueLen,
24117Sdinak 				    label.pValue, pkcs11_strerror(rv));
24217Sdinak 			else
24317Sdinak 				cryptoerror(LOG_STDERR, gettext(
24417Sdinak 				    "Unable to delete object #%d (%s)."),
24517Sdinak 				    i+1, pkcs11_strerror(rv));
24617Sdinak 		} else {
24717Sdinak 			if (label.pValue != NULL)
24817Sdinak 				(void) fprintf(stdout, gettext("Object #%d "
24917Sdinak 				    "\"%.*s\" successfully deleted.\n"),
25017Sdinak 				    i+1, label.ulValueLen, label.pValue);
25117Sdinak 			else
25217Sdinak 				(void) fprintf(stdout, gettext(
25317Sdinak 				    "Object #%d successfully deleted.\n"), i+1);
25417Sdinak 		}
25517Sdinak 
25617Sdinak 		if (label.pValue != NULL)
25717Sdinak 			free(label.pValue);
25817Sdinak 	}
25917Sdinak 
26017Sdinak 	/* Clean up. */
26117Sdinak 	quick_finish(sess);
26217Sdinak 	return (0);
26317Sdinak }
264