1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 3376 mp153739 * Common Development and Distribution License (the "License"). 6 3376 mp153739 * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 9698 Peter * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel /* 27 0 stevel * glue routine for gss_acquire_cred 28 0 stevel */ 29 0 stevel #include <mechglueP.h> 30 0 stevel #include <stdio.h> 31 0 stevel #ifdef HAVE_STDLIB_H 32 0 stevel #include <stdlib.h> 33 0 stevel #endif 34 0 stevel #include <string.h> 35 0 stevel #include <errno.h> 36 0 stevel #include <time.h> 37 5053 gtb 38 0 stevel /* local functions */ 39 0 stevel static gss_OID_set create_actual_mechs(const gss_OID, int); 40 0 stevel 41 0 stevel static gss_OID_set 42 0 stevel create_actual_mechs(mechs_array, count) 43 0 stevel const gss_OID mechs_array; 44 0 stevel int count; 45 0 stevel { 46 0 stevel gss_OID_set actual_mechs; 47 0 stevel int i; 48 0 stevel OM_uint32 minor; 49 0 stevel 50 0 stevel actual_mechs = (gss_OID_set) malloc(sizeof (gss_OID_set_desc)); 51 0 stevel if (!actual_mechs) 52 0 stevel return (NULL); 53 0 stevel 54 0 stevel actual_mechs->elements = (gss_OID) 55 0 stevel malloc(sizeof (gss_OID_desc) * count); 56 0 stevel if (!actual_mechs->elements) { 57 0 stevel free(actual_mechs); 58 0 stevel return (NULL); 59 0 stevel } 60 0 stevel 61 0 stevel actual_mechs->count = 0; 62 0 stevel 63 0 stevel for (i = 0; i < count; i++) { 64 0 stevel actual_mechs->elements[i].elements = (void *) 65 0 stevel malloc(mechs_array[i].length); 66 0 stevel if (actual_mechs->elements[i].elements == NULL) { 67 0 stevel (void) gss_release_oid_set(&minor, &actual_mechs); 68 0 stevel return (NULL); 69 0 stevel } 70 0 stevel g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]); 71 0 stevel actual_mechs->count++; 72 0 stevel } 73 0 stevel 74 0 stevel return (actual_mechs); 75 0 stevel } 76 0 stevel 77 9698 Peter static OM_uint32 78 9698 Peter val_acq_cred_args( 79 9698 Peter OM_uint32 *minor_status, 80 9698 Peter gss_cred_id_t *output_cred_handle, 81 9698 Peter gss_OID_set *actual_mechs, 82 9698 Peter OM_uint32 *time_rec) 83 9698 Peter { 84 9698 Peter 85 9698 Peter /* Initialize outputs. */ 86 9698 Peter 87 9698 Peter if (minor_status != NULL) 88 9698 Peter *minor_status = 0; 89 9698 Peter 90 9698 Peter if (output_cred_handle != NULL) 91 9698 Peter *output_cred_handle = GSS_C_NO_CREDENTIAL; 92 9698 Peter 93 9698 Peter if (actual_mechs != NULL) 94 9698 Peter *actual_mechs = GSS_C_NULL_OID_SET; 95 9698 Peter 96 9698 Peter if (time_rec != NULL) 97 9698 Peter *time_rec = 0; 98 9698 Peter 99 9698 Peter /* Validate arguments. */ 100 9698 Peter 101 9698 Peter if (minor_status == NULL) 102 9698 Peter return (GSS_S_CALL_INACCESSIBLE_WRITE); 103 9698 Peter 104 9698 Peter if (output_cred_handle == NULL) 105 9698 Peter return (GSS_S_CALL_INACCESSIBLE_WRITE); 106 9698 Peter 107 9698 Peter return (GSS_S_COMPLETE); 108 9698 Peter } 109 0 stevel 110 0 stevel OM_uint32 111 0 stevel gss_acquire_cred(minor_status, 112 0 stevel desired_name, 113 0 stevel time_req, 114 0 stevel desired_mechs, 115 0 stevel cred_usage, 116 0 stevel output_cred_handle, 117 0 stevel actual_mechs, 118 0 stevel time_rec) 119 0 stevel 120 0 stevel OM_uint32 * minor_status; 121 0 stevel const gss_name_t desired_name; 122 0 stevel OM_uint32 time_req; 123 0 stevel const gss_OID_set desired_mechs; 124 0 stevel int cred_usage; 125 0 stevel gss_cred_id_t *output_cred_handle; 126 0 stevel gss_OID_set * actual_mechs; 127 0 stevel OM_uint32 * time_rec; 128 0 stevel 129 0 stevel { 130 0 stevel OM_uint32 major = GSS_S_FAILURE; 131 0 stevel OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE; 132 0 stevel gss_OID_set_desc default_OID_set; 133 0 stevel gss_OID_set mechs; 134 0 stevel gss_OID_desc default_OID; 135 0 stevel gss_mechanism mech; 136 0 stevel int i; 137 0 stevel gss_union_cred_t creds; 138 0 stevel 139 9698 Peter major = val_acq_cred_args(minor_status, 140 9698 Peter output_cred_handle, 141 9698 Peter actual_mechs, 142 9698 Peter time_rec); 143 9698 Peter if (major != GSS_S_COMPLETE) 144 9698 Peter return (major); 145 0 stevel 146 9698 Peter /* Initial value needed below. */ 147 9698 Peter major = GSS_S_FAILURE; 148 0 stevel 149 0 stevel /* 150 0 stevel * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an 151 0 stevel * appropriate default. We use the first mechanism in the 152 0 stevel * mechansim list as the default. This set is created with 153 0 stevel * statics thus needs not be freed 154 0 stevel */ 155 0 stevel if (desired_mechs == GSS_C_NULL_OID_SET) { 156 0 stevel mech = __gss_get_mechanism(NULL); 157 0 stevel if (mech == NULL) 158 0 stevel return (GSS_S_BAD_MECH); 159 0 stevel 160 0 stevel mechs = &default_OID_set; 161 0 stevel default_OID_set.count = 1; 162 0 stevel default_OID_set.elements = &default_OID; 163 0 stevel default_OID.length = mech->mech_type.length; 164 0 stevel default_OID.elements = mech->mech_type.elements; 165 0 stevel } else 166 0 stevel mechs = desired_mechs; 167 0 stevel 168 0 stevel if (mechs->count == NULL) 169 0 stevel return (GSS_S_BAD_MECH); 170 0 stevel 171 0 stevel /* allocate the output credential structure */ 172 0 stevel creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc)); 173 0 stevel if (creds == NULL) 174 0 stevel return (GSS_S_FAILURE); 175 0 stevel 176 0 stevel /* initialize to 0s */ 177 0 stevel (void) memset(creds, 0, sizeof (gss_union_cred_desc)); 178 0 stevel 179 0 stevel /* for each requested mech attempt to obtain a credential */ 180 0 stevel for (i = 0; i < mechs->count; i++) { 181 0 stevel major = gss_add_cred(minor_status, (gss_cred_id_t)creds, 182 0 stevel desired_name, 183 0 stevel &mechs->elements[i], 184 0 stevel cred_usage, time_req, time_req, NULL, 185 0 stevel NULL, &initTimeOut, &acceptTimeOut); 186 0 stevel if (major == GSS_S_COMPLETE) { 187 0 stevel /* update the credential's time */ 188 0 stevel if (cred_usage == GSS_C_ACCEPT) { 189 0 stevel if (outTime > acceptTimeOut) 190 0 stevel outTime = acceptTimeOut; 191 0 stevel } else if (cred_usage == GSS_C_INITIATE) { 192 0 stevel if (outTime > initTimeOut) 193 0 stevel outTime = initTimeOut; 194 0 stevel } else { 195 0 stevel /* 196 0 stevel * time_rec is the lesser of the 197 0 stevel * init/accept times 198 0 stevel */ 199 0 stevel if (initTimeOut > acceptTimeOut) 200 0 stevel outTime = (outTime > acceptTimeOut) ? 201 0 stevel acceptTimeOut : outTime; 202 0 stevel else 203 0 stevel outTime = (outTime > initTimeOut) ? 204 0 stevel initTimeOut : outTime; 205 0 stevel } 206 0 stevel } 207 0 stevel } /* for */ 208 0 stevel 209 0 stevel /* ensure that we have at least one credential element */ 210 0 stevel if (creds->count < 1) { 211 0 stevel free(creds); 212 0 stevel return (major); 213 0 stevel } 214 0 stevel 215 0 stevel /* 216 0 stevel * fill in output parameters 217 0 stevel * setup the actual mechs output parameter 218 0 stevel */ 219 0 stevel if (actual_mechs != NULL) { 220 0 stevel if ((*actual_mechs = create_actual_mechs(creds->mechs_array, 221 0 stevel creds->count)) == NULL) { 222 0 stevel (void) gss_release_cred(minor_status, 223 0 stevel (gss_cred_id_t *)&creds); 224 0 stevel *minor_status = 0; 225 0 stevel return (GSS_S_FAILURE); 226 0 stevel } 227 0 stevel } 228 0 stevel 229 0 stevel if (time_rec) 230 0 stevel *time_rec = outTime; 231 0 stevel 232 0 stevel 233 0 stevel *output_cred_handle = (gss_cred_id_t)creds; 234 0 stevel return (GSS_S_COMPLETE); 235 0 stevel } 236 0 stevel 237 9698 Peter static OM_uint32 238 9698 Peter val_add_cred_args( 239 9698 Peter OM_uint32 *minor_status, 240 9698 Peter gss_cred_id_t input_cred_handle, 241 9698 Peter gss_cred_id_t *output_cred_handle, 242 9698 Peter gss_OID_set *actual_mechs, 243 9698 Peter OM_uint32 *initiator_time_rec, 244 9698 Peter OM_uint32 *acceptor_time_rec) 245 9698 Peter { 246 9698 Peter 247 9698 Peter /* Initialize outputs. */ 248 9698 Peter 249 9698 Peter if (minor_status != NULL) 250 9698 Peter *minor_status = 0; 251 9698 Peter 252 9698 Peter if (output_cred_handle != NULL) 253 9698 Peter *output_cred_handle = GSS_C_NO_CREDENTIAL; 254 9698 Peter 255 9698 Peter if (actual_mechs != NULL) 256 9698 Peter *actual_mechs = GSS_C_NO_OID_SET; 257 9698 Peter 258 9698 Peter if (acceptor_time_rec != NULL) 259 9698 Peter *acceptor_time_rec = 0; 260 9698 Peter 261 9698 Peter if (initiator_time_rec != NULL) 262 9698 Peter *initiator_time_rec = 0; 263 9698 Peter 264 9698 Peter /* Validate arguments. */ 265 9698 Peter 266 9698 Peter if (minor_status == NULL) 267 9698 Peter return (GSS_S_CALL_INACCESSIBLE_WRITE); 268 9698 Peter 269 9698 Peter if (input_cred_handle == GSS_C_NO_CREDENTIAL && 270 9698 Peter output_cred_handle == NULL) 271 9698 Peter 272 9698 Peter return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); 273 9698 Peter 274 9698 Peter return (GSS_S_COMPLETE); 275 9698 Peter } 276 9698 Peter 277 0 stevel /* V2 INTERFACE */ 278 0 stevel OM_uint32 279 0 stevel gss_add_cred(minor_status, input_cred_handle, 280 0 stevel desired_name, desired_mech, cred_usage, 281 0 stevel initiator_time_req, acceptor_time_req, 282 0 stevel output_cred_handle, actual_mechs, 283 0 stevel initiator_time_rec, acceptor_time_rec) 284 0 stevel OM_uint32 *minor_status; 285 0 stevel const gss_cred_id_t input_cred_handle; 286 0 stevel const gss_name_t desired_name; 287 0 stevel const gss_OID desired_mech; 288 0 stevel gss_cred_usage_t cred_usage; 289 0 stevel OM_uint32 initiator_time_req; 290 0 stevel OM_uint32 acceptor_time_req; 291 0 stevel gss_cred_id_t *output_cred_handle; 292 0 stevel gss_OID_set *actual_mechs; 293 0 stevel OM_uint32 *initiator_time_rec; 294 0 stevel OM_uint32 *acceptor_time_rec; 295 0 stevel { 296 0 stevel OM_uint32 status, time_req, time_rec, temp_minor_status; 297 0 stevel gss_mechanism mech; 298 0 stevel gss_union_name_t union_name = NULL; 299 0 stevel gss_union_cred_t union_cred, new_union_cred; 300 0 stevel gss_name_t internal_name = GSS_C_NO_NAME; 301 0 stevel gss_name_t allocated_name = GSS_C_NO_NAME; 302 0 stevel gss_cred_id_t cred = NULL; 303 0 stevel gss_OID new_mechs_array = NULL; 304 0 stevel gss_cred_id_t *new_cred_array = NULL; 305 0 stevel 306 9698 Peter status = val_add_cred_args(minor_status, 307 9698 Peter input_cred_handle, 308 9698 Peter output_cred_handle, 309 9698 Peter actual_mechs, 310 9698 Peter initiator_time_rec, 311 9698 Peter acceptor_time_rec); 312 9698 Peter if (status != GSS_S_COMPLETE) 313 9698 Peter return (status); 314 0 stevel 315 0 stevel mech = __gss_get_mechanism(desired_mech); 316 0 stevel if (!mech) 317 0 stevel return (GSS_S_BAD_MECH); 318 0 stevel else if (!mech->gss_acquire_cred) 319 0 stevel return (GSS_S_UNAVAILABLE); 320 0 stevel 321 0 stevel if (input_cred_handle == GSS_C_NO_CREDENTIAL) { 322 0 stevel union_cred = malloc(sizeof (gss_union_cred_desc)); 323 0 stevel if (union_cred == NULL) 324 0 stevel return (GSS_S_FAILURE); 325 0 stevel 326 0 stevel (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); 327 160 wyllys } else { 328 160 wyllys /* Input Cred is non-NULL */ 329 160 wyllys union_cred = (gss_union_cred_t)input_cred_handle; 330 0 stevel 331 0 stevel if (__gss_get_mechanism_cred(union_cred, desired_mech) != 332 160 wyllys GSS_C_NO_CREDENTIAL) { 333 160 wyllys status = GSS_S_DUPLICATE_ELEMENT; 334 160 wyllys goto errout; 335 160 wyllys } 336 0 stevel 337 160 wyllys /* 338 160 wyllys * If no name was given, determine the name from the 339 160 wyllys * existing credential. 340 160 wyllys */ 341 160 wyllys if (desired_name == GSS_C_NO_NAME) { 342 160 wyllys if (gss_import_name(minor_status, 343 160 wyllys &union_cred->auxinfo.name, 344 160 wyllys union_cred->auxinfo.name_type, 345 160 wyllys &allocated_name) == GSS_S_COMPLETE && 346 160 wyllys (gss_canonicalize_name(minor_status, 347 160 wyllys allocated_name, 348 160 wyllys &mech->mech_type, 349 160 wyllys NULL) == GSS_S_COMPLETE)) { 350 0 stevel internal_name = allocated_name; 351 0 stevel } 352 160 wyllys } /* else, get the name from the desired_name below */ 353 160 wyllys } 354 160 wyllys if (desired_name != GSS_C_NO_NAME) { 355 160 wyllys /* may need to create a mechanism specific name */ 356 160 wyllys union_name = (gss_union_name_t)desired_name; 357 160 wyllys 358 160 wyllys if (union_name->mech_type && 359 160 wyllys g_OID_equal(union_name->mech_type, 360 160 wyllys &mech->mech_type)) 361 160 wyllys internal_name = union_name->mech_name; 362 160 wyllys else { 363 160 wyllys if (__gss_import_internal_name(minor_status, 364 160 wyllys &mech->mech_type, union_name, 365 160 wyllys &allocated_name) != GSS_S_COMPLETE) { 366 160 wyllys status = GSS_S_BAD_NAME; 367 160 wyllys goto errout; 368 160 wyllys } 369 160 wyllys internal_name = allocated_name; 370 0 stevel } 371 0 stevel } 372 0 stevel 373 0 stevel if (cred_usage == GSS_C_ACCEPT) 374 0 stevel time_req = acceptor_time_req; 375 0 stevel else if (cred_usage == GSS_C_INITIATE) 376 0 stevel time_req = initiator_time_req; 377 0 stevel else if (cred_usage == GSS_C_BOTH) 378 0 stevel time_req = (acceptor_time_req > initiator_time_req) ? 379 0 stevel acceptor_time_req : initiator_time_req; 380 0 stevel 381 0 stevel status = mech->gss_acquire_cred(mech->context, minor_status, 382 0 stevel internal_name, time_req, 383 0 stevel GSS_C_NULL_OID_SET, cred_usage, 384 0 stevel &cred, NULL, &time_rec); 385 0 stevel 386 0 stevel if (status != GSS_S_COMPLETE) 387 0 stevel goto errout; 388 0 stevel 389 160 wyllys /* may need to set credential auxinfo structure */ 390 0 stevel if (union_cred->auxinfo.creation_time == 0) { 391 0 stevel union_cred->auxinfo.creation_time = time(NULL); 392 0 stevel union_cred->auxinfo.time_rec = time_rec; 393 0 stevel union_cred->auxinfo.cred_usage = cred_usage; 394 0 stevel 395 3376 mp153739 /* 396 3376 mp153739 * If internal_name is GSS_C_NO_NAME a cred with no associated 397 3376 mp153739 * name was requested: don't set auxinfo.name or auxinfo.name_type. 398 3376 mp153739 */ 399 3376 mp153739 if (internal_name != GSS_C_NO_NAME) { 400 3376 mp153739 if ((status = mech->gss_display_name(mech->context, 401 3376 mp153739 &temp_minor_status, internal_name, 402 3376 mp153739 &union_cred->auxinfo.name, 403 3376 mp153739 &union_cred->auxinfo.name_type)) != 404 3376 mp153739 GSS_S_COMPLETE) 405 0 stevel goto errout; 406 0 stevel } 407 0 stevel } 408 0 stevel 409 0 stevel /* now add the new credential elements */ 410 0 stevel new_mechs_array = (gss_OID) 411 0 stevel malloc(sizeof (gss_OID_desc) * (union_cred->count+1)); 412 0 stevel 413 0 stevel new_cred_array = (gss_cred_id_t *) 414 0 stevel malloc(sizeof (gss_cred_id_t) * (union_cred->count+1)); 415 0 stevel 416 0 stevel if (!new_mechs_array || !new_cred_array) { 417 0 stevel status = GSS_S_FAILURE; 418 0 stevel goto errout; 419 0 stevel } 420 0 stevel 421 0 stevel if (acceptor_time_rec) 422 0 stevel if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) 423 0 stevel *acceptor_time_rec = time_rec; 424 0 stevel if (initiator_time_rec) 425 0 stevel if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) 426 0 stevel *initiator_time_rec = time_rec; 427 0 stevel 428 0 stevel /* 429 0 stevel * OK, expand the mechanism array and the credential array 430 0 stevel */ 431 0 stevel (void) memcpy(new_mechs_array, union_cred->mechs_array, 432 0 stevel sizeof (gss_OID_desc) * union_cred->count); 433 0 stevel (void) memcpy(new_cred_array, union_cred->cred_array, 434 0 stevel sizeof (gss_cred_id_t) * union_cred->count); 435 0 stevel 436 0 stevel new_cred_array[union_cred->count] = cred; 437 0 stevel if ((new_mechs_array[union_cred->count].elements = 438 0 stevel malloc(mech->mech_type.length)) == NULL) 439 0 stevel goto errout; 440 0 stevel 441 0 stevel g_OID_copy(&new_mechs_array[union_cred->count], 442 0 stevel &mech->mech_type); 443 0 stevel 444 0 stevel if (actual_mechs) { 445 0 stevel *actual_mechs = create_actual_mechs(new_mechs_array, 446 0 stevel union_cred->count + 1); 447 0 stevel if (*actual_mechs == NULL) { 448 0 stevel free(new_mechs_array[union_cred->count].elements); 449 0 stevel goto errout; 450 0 stevel } 451 0 stevel } 452 0 stevel 453 0 stevel if (output_cred_handle == NULL) { 454 0 stevel free(union_cred->mechs_array); 455 0 stevel free(union_cred->cred_array); 456 0 stevel new_union_cred = union_cred; 457 0 stevel } else { 458 0 stevel new_union_cred = malloc(sizeof (gss_union_cred_desc)); 459 0 stevel if (new_union_cred == NULL) { 460 0 stevel free(new_mechs_array[union_cred->count].elements); 461 0 stevel goto errout; 462 0 stevel } 463 0 stevel *new_union_cred = *union_cred; 464 0 stevel *output_cred_handle = (gss_cred_id_t)new_union_cred; 465 0 stevel } 466 0 stevel 467 0 stevel new_union_cred->mechs_array = new_mechs_array; 468 0 stevel new_union_cred->cred_array = new_cred_array; 469 0 stevel new_union_cred->count++; 470 0 stevel 471 0 stevel /* We're done with the internal name. Free it if we allocated it. */ 472 0 stevel 473 0 stevel if (allocated_name) 474 0 stevel (void) __gss_release_internal_name(&temp_minor_status, 475 0 stevel &mech->mech_type, 476 0 stevel &allocated_name); 477 0 stevel 478 0 stevel return (GSS_S_COMPLETE); 479 0 stevel 480 0 stevel errout: 481 0 stevel if (new_mechs_array) 482 0 stevel free(new_mechs_array); 483 0 stevel if (new_cred_array) 484 0 stevel free(new_cred_array); 485 0 stevel 486 0 stevel if (cred != NULL && mech->gss_release_cred) 487 0 stevel mech->gss_release_cred(mech->context, 488 0 stevel &temp_minor_status, &cred); 489 0 stevel 490 0 stevel if (allocated_name) 491 0 stevel (void) __gss_release_internal_name(&temp_minor_status, 492 0 stevel &mech->mech_type, 493 0 stevel &allocated_name); 494 0 stevel 495 0 stevel if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) { 496 0 stevel if (union_cred->auxinfo.name.value) 497 0 stevel free(union_cred->auxinfo.name.value); 498 0 stevel free(union_cred); 499 0 stevel } 500 0 stevel 501 0 stevel return (status); 502 0 stevel } 503