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 * cred.c 24 * 25 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 * 28 */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <unistd.h> 33 #include <sys/note.h> 34 #include "dh_gssapi.h" 35 36 /* 37 * This module supports the GSS credential family of routines for 38 * Diffie-Hellman mechanism. 39 */ 40 41 /* 42 * __dh_gss_acquire_cred: Get the credential associated with principal 43 * with the requested expire time and usage. Return the credential with 44 * the optional set of supported mechs and actual time left on the credential. 45 * 46 * Note in Diffie-Hellman the supplied principal name must be that of 47 * the caller. There is no way to delegate credentials. 48 * 49 * Libgss alwas sets desired_mechs to GSS_C_NO_OID_SET and set the return 50 * set of mechs to NULL. 51 */ 52 53 OM_uint32 54 __dh_gss_acquire_cred(void *ctx, /* Per mechanism context */ 55 OM_uint32 *minor, /* Mechanism status */ 56 gss_name_t principal, /* Requested principal */ 57 OM_uint32 expire_req, /* Requested Expire time */ 58 gss_OID_set desired_mechs, /* Set of desired mechs */ 59 gss_cred_usage_t usage, /* Usage: init, accept, both */ 60 gss_cred_id_t *cred, /* The return credential */ 61 gss_OID_set *mechs, /* The return set of mechs */ 62 OM_uint32 *expire_rec /* The expire time received*/) 63 { 64 /* Diffie-Hellman mechanism context is ctx */ 65 dh_context_t cntx = (dh_context_t)ctx; 66 dh_principal netname; 67 dh_cred_id_t dh_cred; 68 69 /* Need to write to these */ 70 if (minor == 0 || cred == 0) 71 return (GSS_S_CALL_INACCESSIBLE_WRITE); 72 73 /* Set sane outputs */ 74 *minor = 0; 75 if (mechs) 76 *mechs = GSS_C_NO_OID_SET; 77 if (expire_rec) 78 *expire_rec = 0; 79 *cred = GSS_C_NO_CREDENTIAL; 80 81 /* 82 * If not GSS_C_NO_OID_SET then the set must contain the 83 * Diffie-Hellman mechanism 84 */ 85 if (desired_mechs != GSS_C_NO_OID_SET && 86 !__OID_is_member(desired_mechs, cntx->mech)) 87 return (GSS_S_BAD_MECH); 88 89 /* See if the callers secretkey is available */ 90 if (!cntx->keyopts->key_secretkey_is_set()) 91 return (GSS_S_NO_CRED); 92 93 /* Get the principal name of the caller */ 94 if ((netname = cntx->keyopts->get_principal()) == NULL) 95 return (GSS_S_NO_CRED); 96 97 /* 98 * Diffie-Hellman requires the principal to be the principal 99 * of the caller 100 */ 101 102 if (principal && 103 strncmp(netname, (char *)principal, MAXNETNAMELEN) != 0) { 104 Free(netname); 105 return (GSS_S_NO_CRED); 106 } 107 108 /* Allocate the credential */ 109 dh_cred = New(dh_cred_id_desc, 1); 110 if (dh_cred == NULL) { 111 Free(netname); 112 *minor = DH_NOMEM_FAILURE; 113 return (GSS_S_FAILURE); 114 } 115 116 /* Set credential state */ 117 dh_cred->uid = geteuid(); 118 dh_cred->usage = usage; 119 dh_cred->principal = netname; 120 dh_cred->expire = expire_req ? time(0) + expire_req : GSS_C_INDEFINITE; 121 122 /* 123 * If mechs set it to the set that contains the appropriate 124 * Diffie-Hellman mechanism 125 */ 126 if (mechs && (*minor = __OID_to_OID_set(mechs, cntx->mech))) { 127 Free(dh_cred); 128 Free(netname); 129 return (GSS_S_FAILURE); 130 } 131 132 /* Register the credential */ 133 if ((*minor = __dh_install_cred(dh_cred)) != DH_SUCCESS) { 134 Free(dh_cred); 135 Free(netname); 136 return (GSS_S_FAILURE); 137 } 138 139 if (expire_rec) 140 *expire_rec = expire_req ? expire_req : GSS_C_INDEFINITE; 141 142 /* Return the Diffie-Hellman credential through cred */ 143 *cred = (gss_cred_id_t)dh_cred; 144 145 return (GSS_S_COMPLETE); 146 } 147 148 149 /* 150 * __dh_gss_add_cred is currently a no-op. All the work is done at the 151 * libgss layer. That layer will invoke the mechanism specific gss_acquire_cred 152 * routine. This entry point should never be called. The entry point for 153 * this routine is set to NULL in dhmech.c. 154 */ 155 156 /* 157 * OM_uint32 158 * __dh_gss_add_cred(void * ctx, OM_uint32 *minor, gss_cred_id_t cred_in, 159 * gss_name_t name, gss_OID mech, gss_cred_usage_t usage, 160 * OM_uint32 init_time_req, OM_uint32 accep_time_req, 161 * gss_cred_id_t *cred_out, gss_OID_set *mechs, 162 * OM_uint32 *init_time_rec, OM_uint32 *accep_time_rec) 163 * { 164 * return (GSS_S_UNAVAILABLE); 165 * } 166 */ 167 168 /* 169 * __dh_gss_inquire_cred: Return tracked state of the supplied credential. 170 */ 171 OM_uint32 172 __dh_gss_inquire_cred(void *ctx, /* Per mechanism context */ 173 OM_uint32 *minor, /* Mechanism status */ 174 gss_cred_id_t cred, /* cred of interest */ 175 gss_name_t *name, /* name of principal */ 176 OM_uint32 *lifetime, /* return the time remainning */ 177 gss_cred_usage_t *usage, /* usage: init, accept, both */ 178 gss_OID_set *mechs /* Set containing mech_dh */) 179 { 180 /* cred is a Diffie-Hellman credential */ 181 dh_cred_id_t crid = (dh_cred_id_t)cred; 182 /* ctx is a Diffie-Hellman context */ 183 dh_context_t cntx = (dh_context_t)ctx; 184 OM_uint32 t = GSS_C_INDEFINITE; 185 186 if (minor == 0) 187 return (GSS_S_CALL_INACCESSIBLE_WRITE); 188 if (cntx == 0) 189 return (GSS_S_CALL_INACCESSIBLE_READ); 190 191 *minor = DH_SUCCESS; 192 193 /* Default case */ 194 if (cred == GSS_C_NO_CREDENTIAL) { 195 if (!(*cntx->keyopts->key_secretkey_is_set)()) 196 return (GSS_S_NO_CRED); 197 if (name) 198 *name = (gss_name_t)(*cntx->keyopts->get_principal)(); 199 if (lifetime) 200 *lifetime = GSS_C_INDEFINITE; 201 if (usage) 202 *usage = GSS_C_BOTH; 203 } else { 204 /* Validate creditial */ 205 if ((*minor = __dh_validate_cred(crid)) != DH_SUCCESS) 206 return (GSS_S_DEFECTIVE_CREDENTIAL); 207 if (name) 208 *name = (gss_name_t)strdup(crid->principal); 209 if (lifetime) { 210 if (crid->expire == GSS_C_INDEFINITE) 211 *lifetime = GSS_C_INDEFINITE; 212 else { 213 time_t now = time(0); 214 t = crid->expire > now ? crid->expire-now : 0; 215 *lifetime = t; 216 } 217 } 218 if (usage) 219 *usage = crid->usage; 220 } 221 222 if (name && *name == 0) 223 return (GSS_S_FAILURE); 224 225 226 if (mechs && 227 (*minor = __OID_to_OID_set(mechs, cntx->mech)) != DH_SUCCESS) { 228 free(name); 229 return (GSS_S_FAILURE); 230 } 231 232 /* Check if the credential is still valid */ 233 return (t ? GSS_S_COMPLETE : GSS_S_CREDENTIALS_EXPIRED); 234 } 235 236 237 /* 238 * __dh_gss_inquire_cred_by_mech: Return the information associated with 239 * cred and mech. Since we're a backend, mech must be our mech. 240 * 241 * We verify that passed in mech is correct and use the above routine 242 * to do the work. 243 */ 244 OM_uint32 245 __dh_gss_inquire_cred_by_mech(void *ctx, /* Per mechananism context */ 246 OM_uint32 *minor, /* Mechanism status */ 247 gss_cred_id_t cred, /* Cred to iquire about */ 248 gss_OID mech, /* Along with the mechanism */ 249 gss_name_t *name, /* where to return principal */ 250 OM_uint32 *init_time, /* Init time left */ 251 OM_uint32 *accept_time, /* Accept time left */ 252 gss_cred_usage_t *usage /* cred usage */) 253 { 254 /* ctx is them Diffie-Hellman mechanism context */ 255 dh_context_t context = (dh_context_t)ctx; 256 OM_uint32 lifetime; 257 OM_uint32 major; 258 gss_cred_usage_t use; 259 260 /* This should never happen. It would indicate a libgss failure */ 261 if (!__OID_equal(mech, context->mech)) { 262 *minor = DH_BAD_CONTEXT; 263 return (GSS_S_FAILURE); 264 } 265 266 /* Fetch cred info */ 267 major = __dh_gss_inquire_cred(ctx, minor, cred, name, 268 &lifetime, &use, NULL); 269 270 /* Return option values */ 271 if (major == GSS_S_COMPLETE) { 272 /* set init_time if we can */ 273 if (init_time) 274 *init_time = (use == GSS_C_BOTH || 275 use == GSS_C_INITIATE) ? lifetime : 0; 276 /* Ditto for accept time */ 277 if (accept_time) 278 *accept_time = (use == GSS_C_BOTH || 279 use == GSS_C_ACCEPT) ? lifetime : 0; 280 if (usage) 281 *usage = use; 282 } 283 284 return (major); 285 } 286 287 /* 288 * __dh_gss_release_cred: Release the resources associated with cred. 289 */ 290 OM_uint32 291 __dh_gss_release_cred(void *ctx, /* Per mechananism context (not used) */ 292 OM_uint32 *minor, /* Mechanism status */ 293 gss_cred_id_t *cred /* The cred to free */) 294 { 295 _NOTE(ARGUNUSED(ctx)) 296 dh_cred_id_t dh_cred = (dh_cred_id_t)*cred; 297 298 /* Check that we can read and write required parameters */ 299 if (minor == 0 || cred == 0) 300 return (GSS_S_CALL_INACCESSIBLE_WRITE); 301 302 /* Nothing to do */ 303 if (*cred == GSS_C_NO_CREDENTIAL) 304 return (GSS_S_COMPLETE); 305 306 /* Check if the credential is valid */ 307 if ((*minor = __dh_validate_cred(dh_cred)) != DH_SUCCESS) 308 return (GSS_S_NO_CRED); 309 310 /* Unregister the credential */ 311 *minor = __dh_remove_cred(dh_cred); 312 313 /* Free the principal and the cred itself */ 314 Free(dh_cred->principal); 315 Free(dh_cred); 316 317 /* Set cred to no credential */ 318 *cred = GSS_C_NO_CREDENTIAL; 319 320 return (GSS_S_COMPLETE); 321 } 322