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 #include <sys/types.h> 28 #include <unistd.h> 29 #include <rpc/rpc.h> 30 #include <rpc/key_prot.h> 31 #include <rpcsvc/nis_dhext.h> 32 #include <syslog.h> 33 #include <note.h> 34 35 /* defined in usr/src/libnsl/rpc/key_call.c */ 36 extern bool_t (*__key_encryptsession_pk_LOCAL)(); 37 extern bool_t (*__key_decryptsession_pk_LOCAL)(); 38 extern bool_t (*__key_gendes_LOCAL)(); 39 40 #define CLASSIC_PK_DH(k, a) (((k) == 192) && ((a) == 0)) 41 42 /* 43 * authsys_create_uid(uid_t uid) 44 * 45 * Create SYS (UNIX) style authenticator for the given uid/gid 46 * We don't include suplementary groups, since these are of no 47 * interest for the keyserv operations that we do. 48 */ 49 AUTH * 50 authsys_create_uid(uid_t uid, gid_t gid) 51 { 52 char host[MAX_MACHINE_NAME + 1]; 53 AUTH *res; 54 55 if (gethostname(host, sizeof (host) - 1) == -1) { 56 syslog(LOG_ERR, 57 "pam_dhkeys: Can't determine hostname: %m"); 58 return (NULL); 59 } 60 host[MAX_MACHINE_NAME] = '\0'; 61 62 res = authsys_create(host, uid, gid, 0, (gid_t *)NULL); 63 64 return (res); 65 } 66 67 /* 68 * my_key_call(proc, xdr_arg, arg, xdr_rslt, rslt, uit, gid) 69 * 70 * my_key_call is a copy of key_call() from libnsl with the 71 * added AUTHSYS rpc credential to make the keyserver use our 72 * REAL UID instead of our EFFECTIVE UID when handling our keys. 73 */ 74 int 75 my_key_call(rpcproc_t proc, xdrproc_t xdr_arg, char *arg, 76 xdrproc_t xdr_rslt, char *rslt, uid_t uid, gid_t gid) 77 { 78 CLIENT *clnt; 79 struct timeval wait_time = {0, 0}; 80 enum clnt_stat status; 81 int vers; 82 83 if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) { 84 cryptkeyres res; 85 bool_t r; 86 r = (*__key_encryptsession_pk_LOCAL)(uid, arg, &res); 87 if (r == TRUE) { 88 /* LINTED pointer alignment */ 89 *(cryptkeyres*)rslt = res; 90 return (1); 91 } 92 return (0); 93 } 94 if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) { 95 cryptkeyres res; 96 bool_t r; 97 r = (*__key_decryptsession_pk_LOCAL)(uid, arg, &res); 98 if (r == TRUE) { 99 /* LINTED pointer alignment */ 100 *(cryptkeyres*)rslt = res; 101 return (1); 102 } 103 return (0); 104 } 105 if (proc == KEY_GEN && __key_gendes_LOCAL) { 106 des_block res; 107 bool_t r; 108 r = (*__key_gendes_LOCAL)(uid, 0, &res); 109 if (r == TRUE) { 110 /* LINTED pointer alignment */ 111 *(des_block*)rslt = res; 112 return (1); 113 } 114 return (0); 115 } 116 117 if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || 118 (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || 119 (proc == KEY_GET_CONV)) 120 vers = 2; /* talk to version 2 */ 121 else 122 vers = 1; /* talk to version 1 */ 123 124 clnt = clnt_door_create(KEY_PROG, vers, 0); 125 126 if (clnt == NULL) 127 return (0); 128 129 clnt->cl_auth = authsys_create_uid(uid, gid); 130 131 status = CLNT_CALL(clnt, proc, xdr_arg, arg, xdr_rslt, 132 rslt, wait_time); 133 134 auth_destroy(clnt->cl_auth); 135 clnt_destroy(clnt); 136 137 return (status == RPC_SUCCESS ? 1 : 0); 138 } 139 140 int 141 key_setnet_uid(struct key_netstarg *arg, uid_t uid, gid_t gid) 142 { 143 keystatus status; 144 145 if (!my_key_call((rpcproc_t)KEY_NET_PUT, xdr_key_netstarg, 146 (char *)arg, xdr_keystatus, (char *)&status, uid, gid)) { 147 return (-1); 148 } 149 if (status != KEY_SUCCESS) { 150 return (-1); 151 } 152 153 return (1); 154 } 155 156 int 157 key_setnet_g_uid(const char *netname, const char *skey, keylen_t skeylen, 158 const char *pkey, keylen_t pkeylen, algtype_t algtype, 159 uid_t uid, gid_t gid) 160 { 161 key_netstarg3 arg; 162 keystatus status; 163 164 arg.st_netname = (char *)netname; 165 arg.algtype = algtype; 166 167 if (skeylen == 0) 168 arg.st_priv_key.keybuf3_len = 0; 169 else 170 arg.st_priv_key.keybuf3_len = skeylen/4 + 1; 171 172 arg.st_priv_key.keybuf3_val = (char *)skey; 173 174 if (pkeylen == 0) 175 arg.st_pub_key.keybuf3_len = 0; 176 else 177 arg.st_pub_key.keybuf3_len = pkeylen/4 + 1; 178 179 arg.st_pub_key.keybuf3_val = (char *)pkey; 180 181 if (skeylen == 0) { 182 if (pkeylen == 0) { 183 /* debug("keylens are both 0"); */ 184 return (-1); 185 } 186 arg.keylen = pkeylen; 187 } else { 188 if ((pkeylen != 0) && (skeylen != pkeylen)) { 189 /* debug("keylens don't match"); */ 190 return (-1); 191 } 192 arg.keylen = skeylen; 193 } 194 195 if (CLASSIC_PK_DH(arg.keylen, arg.algtype)) { 196 key_netstarg tmp; 197 198 if (skeylen != 0) { 199 (void) memcpy(&tmp.st_priv_key, skey, 200 sizeof (tmp.st_priv_key)); 201 } else { 202 (void) memset(&tmp.st_priv_key, 0, 203 sizeof (tmp.st_priv_key)); 204 } 205 if (pkeylen != 0) { 206 (void) memcpy(&tmp.st_pub_key, skey, 207 sizeof (tmp.st_pub_key)); 208 } else { 209 (void) memset(&tmp.st_pub_key, 0, 210 sizeof (tmp.st_pub_key)); 211 } 212 tmp.st_netname = (char *)netname; 213 return (key_setnet_uid(&tmp, uid, gid)); 214 } 215 216 if (!my_key_call((rpcproc_t)KEY_NET_PUT_3, xdr_key_netstarg3, 217 (char *)&arg, xdr_keystatus, (char *)&status, uid, gid)) { 218 return (-1); 219 } 220 221 if (status != KEY_SUCCESS) { 222 /* debug("key_setnet3 status is nonzero"); */ 223 return (-1); 224 } 225 return (0); 226 } 227 228 229 /* 230 * key_secretkey_is_set_uid() returns 1 if the keyserver has a secret key 231 * stored for the caller's REAL uid; it returns 0 otherwise 232 */ 233 int 234 key_secretkey_is_set_uid(uid_t uid, gid_t gid) 235 { 236 struct key_netstres kres; 237 238 (void) memset((void*)&kres, 0, sizeof (kres)); 239 240 if (my_key_call((rpcproc_t)KEY_NET_GET, xdr_void, (char *)NULL, 241 xdr_key_netstres, (char *)&kres, uid, gid) && 242 (kres.status == KEY_SUCCESS) && 243 (kres.key_netstres_u.knet.st_priv_key[0] != 0)) { 244 /* avoid leaving secret key in memory */ 245 (void) memset(kres.key_netstres_u.knet.st_priv_key, 0, 246 HEXKEYBYTES); 247 xdr_free(xdr_key_netstres, (char *)&kres); 248 return (1); 249 } 250 return (0); 251 } 252 253 int 254 key_removesecret_g_uid(uid_t uid, gid_t gid) 255 { 256 keystatus status; 257 258 if (my_key_call((rpcproc_t)KEY_CLEAR_3, xdr_void, (char *)NULL, 259 xdr_keystatus, (char *)&status, uid, gid)) 260 return (-1); 261 262 if (status != KEY_SUCCESS) 263 return (-1); 264 265 return (0); 266 } 267