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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <stdio.h> 29 #include <stdarg.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <sys/types.h> 33 #include <unistd.h> 34 #include <signal.h> 35 #include <locale.h> 36 #include <sys/param.h> 37 #include <openssl/bio.h> 38 39 #include <libinst.h> 40 #include <pkglib.h> 41 #include <pkgerr.h> 42 #include <keystore.h> 43 #include "pkgadm.h" 44 #include "pkgadm_msgs.h" 45 46 /* 47 * Name: removecert 48 * Desc: Removes a user certificate and associated private key, 49 * or a trusted certificate, from the keystore. 50 * Syntax: addcert [-a app] [-k keystore] -n name [-P passarg] [-R altroot] 51 */ 52 int 53 removecert(int argc, char **argv) 54 { 55 int i; 56 char keystore_file[MAXPATHLEN] = ""; 57 char *keystore_base = NULL; 58 char *homedir; 59 char *passarg = NULL; 60 char *altroot = NULL; 61 char *prog = NULL; 62 char *alias = NULL; 63 int ret = 1; 64 PKG_ERR *err = NULL; 65 keystore_handle_t keystore = NULL; 66 67 while ((i = getopt(argc, argv, ":a:k:n:P:R:")) != EOF) { 68 switch (i) { 69 case 'a': 70 prog = optarg; 71 break; 72 case 'k': 73 keystore_base = optarg; 74 break; 75 case 'n': 76 alias = optarg; 77 break; 78 case 'P': 79 passarg = optarg; 80 break; 81 case 'R': 82 altroot = optarg; 83 break; 84 case ':': 85 log_msg(LOG_MSG_ERR, MSG_MISSING_OPERAND, optopt); 86 /* fallthrough intentional */ 87 case '?': 88 default: 89 log_msg(LOG_MSG_ERR, MSG_USAGE); 90 goto cleanup; 91 } 92 } 93 94 /* we require a name */ 95 if (alias == NULL) { 96 log_msg(LOG_MSG_ERR, MSG_USAGE); 97 goto cleanup; 98 } 99 100 /* should be no arguments left */ 101 if ((argc-optind) > 0) { 102 log_msg(LOG_MSG_ERR, MSG_USAGE); 103 goto cleanup; 104 } 105 106 /* set up proper keystore */ 107 if (keystore_base == NULL) { 108 if (geteuid() == 0 || altroot != NULL) { 109 /* 110 * If we have an alternate 111 * root, then we have no choice but to use 112 * root's keystore on that alternate root, 113 * since there is no way to resolve a 114 * user's home dir given an alternate root 115 */ 116 if (strlcat(keystore_file, PKGSEC, 117 MAXPATHLEN) >= MAXPATHLEN) { 118 log_msg(LOG_MSG_ERR, MSG_TOO_LONG, 119 keystore_file); 120 goto cleanup; 121 } 122 } else { 123 if ((homedir = getenv("HOME")) == NULL) { 124 /* 125 * not superuser, but no home dir, so 126 * use superuser's keystore 127 */ 128 if (strlcat(keystore_file, PKGSEC, 129 MAXPATHLEN) >= MAXPATHLEN) { 130 log_msg(LOG_MSG_ERR, MSG_TOO_LONG, 131 keystore_file); 132 goto cleanup; 133 } 134 } else { 135 if (strlcat(keystore_file, homedir, 136 MAXPATHLEN) >= MAXPATHLEN) { 137 log_msg(LOG_MSG_ERR, MSG_TOO_LONG, 138 homedir); 139 goto cleanup; 140 } 141 if (strlcat(keystore_file, "/.pkg/security", 142 MAXPATHLEN) >= MAXPATHLEN) { 143 log_msg(LOG_MSG_ERR, MSG_TOO_LONG, 144 keystore_file); 145 goto cleanup; 146 } 147 } 148 } 149 } else { 150 if (strlcat(keystore_file, keystore_base, 151 MAXPATHLEN) >= MAXPATHLEN) { 152 log_msg(LOG_MSG_ERR, MSG_TOO_LONG, 153 keystore_base); 154 goto cleanup; 155 } 156 } 157 158 err = pkgerr_new(); 159 160 /* now load the key store */ 161 log_msg(LOG_MSG_DEBUG, "Loading keystore <%s>", keystore_file); 162 163 set_passphrase_prompt(MSG_KEYSTORE_PASSPROMPT); 164 set_passphrase_passarg(passarg); 165 166 if (open_keystore(err, keystore_file, prog, pkg_passphrase_cb, 167 KEYSTORE_ACCESS_READWRITE | KEYSTORE_PATH_HARD, &keystore) != 0) { 168 log_pkgerr(LOG_MSG_ERR, err); 169 goto cleanup; 170 } 171 172 /* now remove the selected certs */ 173 log_msg(LOG_MSG_DEBUG, "Removing certificate(s) with name <%s>", 174 alias); 175 if (delete_cert_and_keys(err, keystore, alias) != 0) { 176 log_pkgerr(LOG_MSG_ERR, err); 177 log_msg(LOG_MSG_ERR, MSG_NO_REMOVECERT, alias); 178 goto cleanup; 179 } 180 181 /* now write it back out */ 182 log_msg(LOG_MSG_DEBUG, "Closing keystore"); 183 set_passphrase_prompt(MSG_KEYSTORE_PASSOUTPROMPT); 184 set_passphrase_passarg(passarg); 185 if (close_keystore(err, keystore, pkg_passphrase_cb) != 0) { 186 log_pkgerr(LOG_MSG_ERR, err); 187 log_msg(LOG_MSG_ERR, MSG_NO_REMOVECERT, alias); 188 goto cleanup; 189 } 190 191 log_msg(LOG_MSG_INFO, MSG_REMOVED, alias); 192 193 ret = 0; 194 /* fallthrough intentional */ 195 cleanup: 196 197 if (err != NULL) 198 pkgerr_free(err); 199 200 return (ret); 201 } 202