delete.c revision 7711facfe58561dd91d6ece0f5f41150c3956c83
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file implements the token object delete operation for this tool.
* It loads the PKCS#11 modules, finds the object to delete, deletes it,
* and cleans up. User must be R/W logged into the token.
*/
#include <stdio.h>
#include <string.h>
#include <cryptoutil.h>
#include <security/cryptoki.h>
#include "common.h"
/*
* Delete token objects.
*/
int
pk_delete(int argc, char *argv[])
{
int opt;
extern int optind;
extern char *optarg;
char *token_name = NULL;
char *manuf_id = NULL;
char *serial_no = NULL;
char full_name[FULL_NAME_LEN];
boolean_t public_objs = B_FALSE;
boolean_t private_objs = B_FALSE;
CK_BYTE *object_label = NULL;
int obj_type = 0x00;
CK_SLOT_ID slot_id;
CK_FLAGS pin_state;
CK_UTF8CHAR_PTR pin = NULL;
CK_ULONG pinlen = 0;
CK_SESSION_HANDLE sess;
CK_OBJECT_HANDLE *objs;
CK_ULONG num_objs;
CK_ATTRIBUTE label = { CKA_LABEL, NULL, 0 };
CK_RV rv = CKR_OK;
int i;
cryptodebug("inside pk_delete");
/* Parse command line options. Do NOT i18n/l10n. */
while ((opt = getopt(argc, argv, "p(private)P(public)l:(label)")) !=
EOF) {
switch (opt) {
case 'p': /* private objects */
private_objs = B_TRUE;
obj_type |= PK_PRIVATE_OBJ;
break;
case 'P': /* public objects */
public_objs = B_TRUE;
obj_type |= PK_PUBLIC_OBJ;
break;
case 'l': /* objects with specific label */
if (object_label)
return (PK_ERR_USAGE);
object_label = (CK_BYTE *)optarg;
break;
default:
return (PK_ERR_USAGE);
break;
}
}
/* At least one of public, private, or object label is required. */
if (!private_objs && !public_objs && object_label == NULL)
return (PK_ERR_USAGE);
/*
* If object label is given but neither public/private is specified,
* delete all objects with that label.
*/
if (!private_objs && !public_objs && object_label != NULL)
obj_type = PK_ALL_OBJ;
/* No additional args allowed. */
argc -= optind;
argv += optind;
if (argc)
return (PK_ERR_USAGE);
/* Done parsing command line options. */
/* Delete operation only supported on softtoken. */
if (token_name == NULL)
token_name = SOFT_TOKEN_LABEL;
if (manuf_id == NULL)
manuf_id = SOFT_MANUFACTURER_ID;
if (serial_no == NULL)
serial_no = SOFT_TOKEN_SERIAL;
full_token_name(token_name, manuf_id, serial_no, full_name);
/* Find the slot with token. */
if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
&pin_state)) != CKR_OK) {
cryptoerror(LOG_STDERR, gettext(
"Unable to find token %s (%s)."), full_name,
pkcs11_strerror(rv));
return (PK_ERR_PK11);
}
/* Always get the user's PIN for delete operations. */
if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
&pinlen)) != CKR_OK) {
cryptoerror(LOG_STDERR, gettext(
"Unable to get token passphrase (%s)."),
pkcs11_strerror(rv));
quick_finish(NULL);
return (PK_ERR_PK11);
}
/* Log the user R/W into the token. */
if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
CKR_OK) {
cryptoerror(LOG_STDERR, gettext(
"Unable to log into token (%s)."), pkcs11_strerror(rv));
quick_finish(sess);
return (PK_ERR_PK11);
}
/* Find the object(s) with the given label and/or type. */
if ((rv = find_objs(sess, obj_type, object_label, &objs, &num_objs)) !=
CKR_OK) {
cryptoerror(LOG_STDERR, gettext(
"Unable to find token objects (%s)."), pkcs11_strerror(rv));
quick_finish(sess);
return (PK_ERR_PK11);
}
if (num_objs == 0) {
(void) fprintf(stdout, gettext("No matching objects found.\n"));
quick_finish(sess);
return (0);
}
if (num_objs != 1) {
(void) fprintf(stdout, gettext(
"Warning: %d matching objects found, deleting all.\n"),
num_objs);
if (yesno(gettext("Continue with delete? "),
gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
quick_finish(sess);
return (0);
}
}
/* Destroy the objects if found. */
for (i = 0; i < num_objs; i++) {
/*
* To give nice feedback to the user, get the object's
* label before deleting it.
*/
cryptodebug("calling C_GetAttributeValue for label");
label.pValue = NULL;
label.ulValueLen = 0;
if (C_GetAttributeValue(sess, objs[i], &label, 1) == CKR_OK) {
if (label.ulValueLen != (CK_ULONG)-1 &&
label.ulValueLen != 0 &&
(label.pValue = malloc(label.ulValueLen)) != NULL) {
if (C_GetAttributeValue(sess, objs[i], &label,
1) != CKR_OK) {
free(label.pValue);
label.pValue = NULL;
label.ulValueLen = 0;
}
} else {
label.ulValueLen = 0;
}
}
cryptodebug("calling C_DestroyObject");
if ((rv = C_DestroyObject(sess, objs[i])) != CKR_OK) {
if (label.pValue != NULL)
cryptoerror(LOG_STDERR, gettext(
"Unable to delete object #%d \"%.*s\" "
"(%s)."), i+1, label.ulValueLen,
label.pValue, pkcs11_strerror(rv));
else
cryptoerror(LOG_STDERR, gettext(
"Unable to delete object #%d (%s)."),
i+1, pkcs11_strerror(rv));
} else {
if (label.pValue != NULL)
(void) fprintf(stdout, gettext("Object #%d "
"\"%.*s\" successfully deleted.\n"),
i+1, label.ulValueLen, label.pValue);
else
(void) fprintf(stdout, gettext(
"Object #%d successfully deleted.\n"), i+1);
}
if (label.pValue != NULL)
free(label.pValue);
}
/* Clean up. */
quick_finish(sess);
return (0);
}