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