1*17Sdinak /*
2*17Sdinak  * CDDL HEADER START
3*17Sdinak  *
4*17Sdinak  * The contents of this file are subject to the terms of the
5*17Sdinak  * Common Development and Distribution License, Version 1.0 only
6*17Sdinak  * (the "License").  You may not use this file except in compliance
7*17Sdinak  * with the License.
8*17Sdinak  *
9*17Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*17Sdinak  * or http://www.opensolaris.org/os/licensing.
11*17Sdinak  * See the License for the specific language governing permissions
12*17Sdinak  * and limitations under the License.
13*17Sdinak  *
14*17Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
15*17Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*17Sdinak  * If applicable, add the following below this CDDL HEADER, with the
17*17Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
18*17Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
19*17Sdinak  *
20*17Sdinak  * CDDL HEADER END
21*17Sdinak  */
22*17Sdinak /*
23*17Sdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*17Sdinak  * Use is subject to license terms.
25*17Sdinak  */
26*17Sdinak 
27*17Sdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*17Sdinak 
29*17Sdinak /*
30*17Sdinak  * This file implements the token object delete operation for this tool.
31*17Sdinak  * It loads the PKCS#11 modules, finds the object to delete, deletes it,
32*17Sdinak  * and cleans up.  User must be R/W logged into the token.
33*17Sdinak  */
34*17Sdinak 
35*17Sdinak #include <stdio.h>
36*17Sdinak #include <string.h>
37*17Sdinak #include <cryptoutil.h>
38*17Sdinak #include <security/cryptoki.h>
39*17Sdinak #include "common.h"
40*17Sdinak 
41*17Sdinak /*
42*17Sdinak  * Delete token objects.
43*17Sdinak  */
44*17Sdinak int
45*17Sdinak pk_delete(int argc, char *argv[])
46*17Sdinak {
47*17Sdinak 	int		opt;
48*17Sdinak 	extern int	optind;
49*17Sdinak 	extern char	*optarg;
50*17Sdinak 	char		*token_name = NULL;
51*17Sdinak 	char		*manuf_id = NULL;
52*17Sdinak 	char		*serial_no = NULL;
53*17Sdinak 	char		full_name[FULL_NAME_LEN];
54*17Sdinak 	boolean_t	public_objs = B_FALSE;
55*17Sdinak 	boolean_t	private_objs = B_FALSE;
56*17Sdinak 	CK_BYTE		*object_label = NULL;
57*17Sdinak 	int		obj_type = 0x00;
58*17Sdinak 	CK_SLOT_ID	slot_id;
59*17Sdinak 	CK_FLAGS	pin_state;
60*17Sdinak 	CK_UTF8CHAR_PTR	pin = NULL;
61*17Sdinak 	CK_ULONG	pinlen = 0;
62*17Sdinak 	CK_SESSION_HANDLE	sess;
63*17Sdinak 	CK_OBJECT_HANDLE	*objs;
64*17Sdinak 	CK_ULONG	num_objs;
65*17Sdinak 	CK_ATTRIBUTE	label = { CKA_LABEL, NULL, 0 };
66*17Sdinak 	CK_RV		rv = CKR_OK;
67*17Sdinak 	int		i;
68*17Sdinak 
69*17Sdinak 	cryptodebug("inside pk_delete");
70*17Sdinak 
71*17Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
72*17Sdinak 	while ((opt = getopt(argc, argv, "p(private)P(public)l:(label)")) !=
73*17Sdinak 	    EOF) {
74*17Sdinak 		switch (opt) {
75*17Sdinak 		case 'p':	/* private objects */
76*17Sdinak 			private_objs = B_TRUE;
77*17Sdinak 			obj_type |= PK_PRIVATE_OBJ;
78*17Sdinak 			break;
79*17Sdinak 		case 'P':	/* public objects */
80*17Sdinak 			public_objs = B_TRUE;
81*17Sdinak 			obj_type |= PK_PUBLIC_OBJ;
82*17Sdinak 			break;
83*17Sdinak 		case 'l':	/* objects with specific label */
84*17Sdinak 			if (object_label)
85*17Sdinak 				return (PK_ERR_USAGE);
86*17Sdinak 			object_label = (CK_BYTE *)optarg;
87*17Sdinak 			break;
88*17Sdinak 		default:
89*17Sdinak 			return (PK_ERR_USAGE);
90*17Sdinak 			break;
91*17Sdinak 		}
92*17Sdinak 	}
93*17Sdinak 
94*17Sdinak 	/* At least one of public, private, or object label is required. */
95*17Sdinak 	if (!private_objs && !public_objs && object_label == NULL)
96*17Sdinak 		return (PK_ERR_USAGE);
97*17Sdinak 
98*17Sdinak 	/*
99*17Sdinak 	 * If object label is given but neither public/private is specified,
100*17Sdinak 	 * delete all objects with that label.
101*17Sdinak 	 */
102*17Sdinak 	if (!private_objs && !public_objs && object_label != NULL)
103*17Sdinak 		obj_type = PK_ALL_OBJ;
104*17Sdinak 
105*17Sdinak 	/* No additional args allowed. */
106*17Sdinak 	argc -= optind;
107*17Sdinak 	argv += optind;
108*17Sdinak 	if (argc)
109*17Sdinak 		return (PK_ERR_USAGE);
110*17Sdinak 	/* Done parsing command line options. */
111*17Sdinak 
112*17Sdinak 	/* Delete operation only supported on softtoken. */
113*17Sdinak 	if (token_name == NULL)
114*17Sdinak 		token_name = SOFT_TOKEN_LABEL;
115*17Sdinak 	if (manuf_id == NULL)
116*17Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
117*17Sdinak 	if (serial_no == NULL)
118*17Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
119*17Sdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
120*17Sdinak 
121*17Sdinak 	/* Find the slot with token. */
122*17Sdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
123*17Sdinak 	    &pin_state)) != CKR_OK) {
124*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
125*17Sdinak 		    "Unable to find token %s (%s)."), full_name,
126*17Sdinak 		    pkcs11_strerror(rv));
127*17Sdinak 		return (PK_ERR_PK11);
128*17Sdinak 	}
129*17Sdinak 
130*17Sdinak 	/* Always get the user's PIN for delete operations. */
131*17Sdinak 	if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
132*17Sdinak 	    &pinlen)) != CKR_OK) {
133*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
134*17Sdinak 		    "Unable to get token passphrase (%s)."),
135*17Sdinak 		    pkcs11_strerror(rv));
136*17Sdinak 		quick_finish(NULL);
137*17Sdinak 		return (PK_ERR_PK11);
138*17Sdinak 	}
139*17Sdinak 
140*17Sdinak 	/* Log the user R/W into the token. */
141*17Sdinak 	if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
142*17Sdinak 	    CKR_OK) {
143*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
144*17Sdinak 		    "Unable to log into token (%s)."), pkcs11_strerror(rv));
145*17Sdinak 		quick_finish(sess);
146*17Sdinak 		return (PK_ERR_PK11);
147*17Sdinak 	}
148*17Sdinak 
149*17Sdinak 	/* Find the object(s) with the given label and/or type. */
150*17Sdinak 	if ((rv = find_objs(sess, obj_type, object_label, &objs, &num_objs)) !=
151*17Sdinak 	    CKR_OK) {
152*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
153*17Sdinak 		    "Unable to find token objects (%s)."), pkcs11_strerror(rv));
154*17Sdinak 		quick_finish(sess);
155*17Sdinak 		return (PK_ERR_PK11);
156*17Sdinak 	}
157*17Sdinak 
158*17Sdinak 	if (num_objs == 0) {
159*17Sdinak 		(void) fprintf(stdout, gettext("No matching objects found.\n"));
160*17Sdinak 		quick_finish(sess);
161*17Sdinak 		return (0);
162*17Sdinak 	}
163*17Sdinak 
164*17Sdinak 	if (num_objs != 1) {
165*17Sdinak 		(void) fprintf(stdout, gettext(
166*17Sdinak 		    "Warning: %d matching objects found, deleting all.\n"),
167*17Sdinak 		    num_objs);
168*17Sdinak 		if (yesno(gettext("Continue with delete? "),
169*17Sdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
170*17Sdinak 			quick_finish(sess);
171*17Sdinak 			return (0);
172*17Sdinak 		}
173*17Sdinak 	}
174*17Sdinak 
175*17Sdinak 	/* Destroy the objects if found. */
176*17Sdinak 	for (i = 0; i < num_objs; i++) {
177*17Sdinak 		/*
178*17Sdinak 		 * To give nice feedback to the user, get the object's
179*17Sdinak 		 * label before deleting it.
180*17Sdinak 		 */
181*17Sdinak 		cryptodebug("calling C_GetAttributeValue for label");
182*17Sdinak 		label.pValue = NULL;
183*17Sdinak 		label.ulValueLen = 0;
184*17Sdinak 		if (C_GetAttributeValue(sess, objs[i], &label, 1) == CKR_OK) {
185*17Sdinak 			if (label.ulValueLen != (CK_ULONG)-1 &&
186*17Sdinak 			    label.ulValueLen != 0 &&
187*17Sdinak 			    (label.pValue = malloc(label.ulValueLen)) != NULL) {
188*17Sdinak 				if (C_GetAttributeValue(sess, objs[i], &label,
189*17Sdinak 				    1) != CKR_OK) {
190*17Sdinak 					free(label.pValue);
191*17Sdinak 					label.pValue = NULL;
192*17Sdinak 					label.ulValueLen = 0;
193*17Sdinak 				}
194*17Sdinak 			} else {
195*17Sdinak 				label.ulValueLen = 0;
196*17Sdinak 			}
197*17Sdinak 		}
198*17Sdinak 
199*17Sdinak 		cryptodebug("calling C_DestroyObject");
200*17Sdinak 		if ((rv = C_DestroyObject(sess, objs[i])) != CKR_OK) {
201*17Sdinak 			if (label.pValue != NULL)
202*17Sdinak 				cryptoerror(LOG_STDERR, gettext(
203*17Sdinak 				    "Unable to delete object #%d \"%.*s\" "
204*17Sdinak 				    "(%s)."), i+1, label.ulValueLen,
205*17Sdinak 				    label.pValue, pkcs11_strerror(rv));
206*17Sdinak 			else
207*17Sdinak 				cryptoerror(LOG_STDERR, gettext(
208*17Sdinak 				    "Unable to delete object #%d (%s)."),
209*17Sdinak 				    i+1, pkcs11_strerror(rv));
210*17Sdinak 		} else {
211*17Sdinak 			if (label.pValue != NULL)
212*17Sdinak 				(void) fprintf(stdout, gettext("Object #%d "
213*17Sdinak 				    "\"%.*s\" successfully deleted.\n"),
214*17Sdinak 				    i+1, label.ulValueLen, label.pValue);
215*17Sdinak 			else
216*17Sdinak 				(void) fprintf(stdout, gettext(
217*17Sdinak 				    "Object #%d successfully deleted.\n"), i+1);
218*17Sdinak 		}
219*17Sdinak 
220*17Sdinak 		if (label.pValue != NULL)
221*17Sdinak 			free(label.pValue);
222*17Sdinak 	}
223*17Sdinak 
224*17Sdinak 	/* Clean up. */
225*17Sdinak 	quick_finish(sess);
226*17Sdinak 	return (0);
227*17Sdinak }
228