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