1 /* $NetBSD: auth_context.c,v 1.4 2017/01/28 21:31:49 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "krb5_locl.h" 37 38 /** 39 * Allocate and initialize an autentication context. 40 * 41 * @param context A kerberos context. 42 * @param auth_context The authentication context to be initialized. 43 * 44 * Use krb5_auth_con_free() to release the memory when done using the context. 45 * 46 * @return An krb5 error code, see krb5_get_error_message(). 47 */ 48 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 49 krb5_auth_con_init(krb5_context context, 50 krb5_auth_context *auth_context) 51 { 52 krb5_auth_context p; 53 54 ALLOC(p, 1); 55 if (!p) 56 return krb5_enomem(context); 57 memset(p, 0, sizeof(*p)); 58 ALLOC(p->authenticator, 1); 59 if (!p->authenticator) { 60 free(p); 61 return krb5_enomem(context); 62 } 63 memset (p->authenticator, 0, sizeof(*p->authenticator)); 64 p->flags = KRB5_AUTH_CONTEXT_DO_TIME; 65 66 p->local_address = NULL; 67 p->remote_address = NULL; 68 p->local_port = 0; 69 p->remote_port = 0; 70 p->keytype = KRB5_ENCTYPE_NULL; 71 p->cksumtype = CKSUMTYPE_NONE; 72 p->auth_data = NULL; 73 *auth_context = p; 74 return 0; 75 } 76 77 /** 78 * Deallocate an authentication context previously initialized with 79 * krb5_auth_con_init(). 80 * 81 * @param context A kerberos context. 82 * @param auth_context The authentication context to be deallocated. 83 * 84 * @return An krb5 error code, see krb5_get_error_message(). 85 */ 86 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 87 krb5_auth_con_free(krb5_context context, 88 krb5_auth_context auth_context) 89 { 90 if (auth_context != NULL) { 91 krb5_free_authenticator(context, &auth_context->authenticator); 92 if(auth_context->local_address){ 93 free_HostAddress(auth_context->local_address); 94 free(auth_context->local_address); 95 } 96 if(auth_context->remote_address){ 97 free_HostAddress(auth_context->remote_address); 98 free(auth_context->remote_address); 99 } 100 krb5_free_keyblock(context, auth_context->keyblock); 101 krb5_free_keyblock(context, auth_context->remote_subkey); 102 krb5_free_keyblock(context, auth_context->local_subkey); 103 if (auth_context->auth_data) { 104 free_AuthorizationData(auth_context->auth_data); 105 free(auth_context->auth_data); 106 } 107 free (auth_context); 108 } 109 return 0; 110 } 111 112 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 113 krb5_auth_con_setflags(krb5_context context, 114 krb5_auth_context auth_context, 115 int32_t flags) 116 { 117 auth_context->flags = flags; 118 return 0; 119 } 120 121 122 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 123 krb5_auth_con_getflags(krb5_context context, 124 krb5_auth_context auth_context, 125 int32_t *flags) 126 { 127 *flags = auth_context->flags; 128 return 0; 129 } 130 131 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 132 krb5_auth_con_addflags(krb5_context context, 133 krb5_auth_context auth_context, 134 int32_t addflags, 135 int32_t *flags) 136 { 137 if (flags) 138 *flags = auth_context->flags; 139 auth_context->flags |= addflags; 140 return 0; 141 } 142 143 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 144 krb5_auth_con_removeflags(krb5_context context, 145 krb5_auth_context auth_context, 146 int32_t removeflags, 147 int32_t *flags) 148 { 149 if (flags) 150 *flags = auth_context->flags; 151 auth_context->flags &= ~removeflags; 152 return 0; 153 } 154 155 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 156 krb5_auth_con_setaddrs(krb5_context context, 157 krb5_auth_context auth_context, 158 krb5_address *local_addr, 159 krb5_address *remote_addr) 160 { 161 if (local_addr) { 162 if (auth_context->local_address) 163 krb5_free_address (context, auth_context->local_address); 164 else 165 if ((auth_context->local_address = malloc(sizeof(krb5_address))) == NULL) 166 return krb5_enomem(context); 167 krb5_copy_address(context, local_addr, auth_context->local_address); 168 } 169 if (remote_addr) { 170 if (auth_context->remote_address) 171 krb5_free_address (context, auth_context->remote_address); 172 else 173 if ((auth_context->remote_address = malloc(sizeof(krb5_address))) == NULL) 174 return krb5_enomem(context); 175 krb5_copy_address(context, remote_addr, auth_context->remote_address); 176 } 177 return 0; 178 } 179 180 /** 181 * Update the authentication context \a auth_context with the local 182 * and remote addresses from socket \a fd, according to \a flags. 183 * 184 * @return An krb5 error code, see krb5_get_error_message(). 185 */ 186 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 187 krb5_auth_con_genaddrs(krb5_context context, 188 krb5_auth_context auth_context, 189 krb5_socket_t fd, int flags) 190 { 191 krb5_error_code ret; 192 krb5_address local_k_address, remote_k_address; 193 krb5_address *lptr = NULL, *rptr = NULL; 194 struct sockaddr_storage ss_local, ss_remote; 195 struct sockaddr *local = (struct sockaddr *)&ss_local; 196 struct sockaddr *remote = (struct sockaddr *)&ss_remote; 197 socklen_t len; 198 199 if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR) { 200 if (auth_context->local_address == NULL) { 201 len = sizeof(ss_local); 202 if(rk_IS_SOCKET_ERROR(getsockname(fd, local, &len))) { 203 char buf[128]; 204 ret = rk_SOCK_ERRNO; 205 rk_strerror_r(ret, buf, sizeof(buf)); 206 krb5_set_error_message(context, ret, "getsockname: %s", buf); 207 goto out; 208 } 209 ret = krb5_sockaddr2address (context, local, &local_k_address); 210 if(ret) goto out; 211 if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) { 212 krb5_sockaddr2port (context, local, &auth_context->local_port); 213 } else 214 auth_context->local_port = 0; 215 lptr = &local_k_address; 216 } 217 } 218 if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) { 219 len = sizeof(ss_remote); 220 if(rk_IS_SOCKET_ERROR(getpeername(fd, remote, &len))) { 221 char buf[128]; 222 ret = rk_SOCK_ERRNO; 223 rk_strerror_r(ret, buf, sizeof(buf)); 224 krb5_set_error_message(context, ret, "getpeername: %s", buf); 225 goto out; 226 } 227 ret = krb5_sockaddr2address (context, remote, &remote_k_address); 228 if(ret) goto out; 229 if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) { 230 krb5_sockaddr2port (context, remote, &auth_context->remote_port); 231 } else 232 auth_context->remote_port = 0; 233 rptr = &remote_k_address; 234 } 235 ret = krb5_auth_con_setaddrs (context, 236 auth_context, 237 lptr, 238 rptr); 239 out: 240 if (lptr) 241 krb5_free_address (context, lptr); 242 if (rptr) 243 krb5_free_address (context, rptr); 244 return ret; 245 246 } 247 248 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 249 krb5_auth_con_setaddrs_from_fd (krb5_context context, 250 krb5_auth_context auth_context, 251 void *p_fd) 252 { 253 krb5_socket_t fd = *(krb5_socket_t *)p_fd; 254 int flags = 0; 255 if(auth_context->local_address == NULL) 256 flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR; 257 if(auth_context->remote_address == NULL) 258 flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR; 259 return krb5_auth_con_genaddrs(context, auth_context, fd, flags); 260 } 261 262 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 263 krb5_auth_con_getaddrs(krb5_context context, 264 krb5_auth_context auth_context, 265 krb5_address **local_addr, 266 krb5_address **remote_addr) 267 { 268 if(*local_addr) 269 krb5_free_address (context, *local_addr); 270 *local_addr = malloc (sizeof(**local_addr)); 271 if (*local_addr == NULL) 272 return krb5_enomem(context); 273 krb5_copy_address(context, 274 auth_context->local_address, 275 *local_addr); 276 277 if(*remote_addr) 278 krb5_free_address (context, *remote_addr); 279 *remote_addr = malloc (sizeof(**remote_addr)); 280 if (*remote_addr == NULL) { 281 krb5_free_address (context, *local_addr); 282 *local_addr = NULL; 283 return krb5_enomem(context); 284 } 285 krb5_copy_address(context, 286 auth_context->remote_address, 287 *remote_addr); 288 return 0; 289 } 290 291 /* coverity[+alloc : arg-*2] */ 292 static krb5_error_code 293 copy_key(krb5_context context, 294 krb5_keyblock *in, 295 krb5_keyblock **out) 296 { 297 *out = NULL; 298 if (in) 299 return krb5_copy_keyblock(context, in, out); 300 return 0; 301 } 302 303 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 304 krb5_auth_con_getkey(krb5_context context, 305 krb5_auth_context auth_context, 306 krb5_keyblock **keyblock) 307 { 308 return copy_key(context, auth_context->keyblock, keyblock); 309 } 310 311 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 312 krb5_auth_con_getlocalsubkey(krb5_context context, 313 krb5_auth_context auth_context, 314 krb5_keyblock **keyblock) 315 { 316 return copy_key(context, auth_context->local_subkey, keyblock); 317 } 318 319 /* coverity[+alloc : arg-*2] */ 320 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 321 krb5_auth_con_getremotesubkey(krb5_context context, 322 krb5_auth_context auth_context, 323 krb5_keyblock **keyblock) 324 { 325 return copy_key(context, auth_context->remote_subkey, keyblock); 326 } 327 328 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 329 krb5_auth_con_setkey(krb5_context context, 330 krb5_auth_context auth_context, 331 krb5_keyblock *keyblock) 332 { 333 if(auth_context->keyblock) 334 krb5_free_keyblock(context, auth_context->keyblock); 335 return copy_key(context, keyblock, &auth_context->keyblock); 336 } 337 338 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 339 krb5_auth_con_setlocalsubkey(krb5_context context, 340 krb5_auth_context auth_context, 341 krb5_keyblock *keyblock) 342 { 343 if(auth_context->local_subkey) 344 krb5_free_keyblock(context, auth_context->local_subkey); 345 return copy_key(context, keyblock, &auth_context->local_subkey); 346 } 347 348 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 349 krb5_auth_con_generatelocalsubkey(krb5_context context, 350 krb5_auth_context auth_context, 351 krb5_keyblock *key) 352 { 353 krb5_error_code ret; 354 krb5_keyblock *subkey; 355 356 ret = krb5_generate_subkey_extended (context, key, 357 auth_context->keytype, 358 &subkey); 359 if(ret) 360 return ret; 361 if(auth_context->local_subkey) 362 krb5_free_keyblock(context, auth_context->local_subkey); 363 auth_context->local_subkey = subkey; 364 return 0; 365 } 366 367 368 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 369 krb5_auth_con_setremotesubkey(krb5_context context, 370 krb5_auth_context auth_context, 371 krb5_keyblock *keyblock) 372 { 373 if(auth_context->remote_subkey) 374 krb5_free_keyblock(context, auth_context->remote_subkey); 375 return copy_key(context, keyblock, &auth_context->remote_subkey); 376 } 377 378 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 379 krb5_auth_con_setcksumtype(krb5_context context, 380 krb5_auth_context auth_context, 381 krb5_cksumtype cksumtype) 382 { 383 auth_context->cksumtype = cksumtype; 384 return 0; 385 } 386 387 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 388 krb5_auth_con_getcksumtype(krb5_context context, 389 krb5_auth_context auth_context, 390 krb5_cksumtype *cksumtype) 391 { 392 *cksumtype = auth_context->cksumtype; 393 return 0; 394 } 395 396 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 397 krb5_auth_con_setkeytype (krb5_context context, 398 krb5_auth_context auth_context, 399 krb5_keytype keytype) 400 { 401 auth_context->keytype = keytype; 402 return 0; 403 } 404 405 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 406 krb5_auth_con_getkeytype (krb5_context context, 407 krb5_auth_context auth_context, 408 krb5_keytype *keytype) 409 { 410 *keytype = auth_context->keytype; 411 return 0; 412 } 413 414 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 415 krb5_auth_con_add_AuthorizationData(krb5_context context, 416 krb5_auth_context auth_context, 417 int type, 418 krb5_data *data) 419 { 420 AuthorizationDataElement el; 421 422 if (auth_context->auth_data == NULL) { 423 auth_context->auth_data = calloc(1, sizeof(*auth_context->auth_data)); 424 if (auth_context->auth_data == NULL) 425 return krb5_enomem(context); 426 } 427 el.ad_type = type; 428 el.ad_data.data = data->data; 429 el.ad_data.length = data->length; 430 431 return add_AuthorizationData(auth_context->auth_data, &el); 432 } 433 434 435 436 #if 0 437 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 438 krb5_auth_con_setenctype(krb5_context context, 439 krb5_auth_context auth_context, 440 krb5_enctype etype) 441 { 442 if(auth_context->keyblock) 443 krb5_free_keyblock(context, auth_context->keyblock); 444 ALLOC(auth_context->keyblock, 1); 445 if(auth_context->keyblock == NULL) 446 return krb5_enomem(context); 447 auth_context->keyblock->keytype = etype; 448 return 0; 449 } 450 451 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 452 krb5_auth_con_getenctype(krb5_context context, 453 krb5_auth_context auth_context, 454 krb5_enctype *etype) 455 { 456 krb5_abortx(context, "unimplemented krb5_auth_getenctype called"); 457 } 458 #endif 459 460 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 461 krb5_auth_con_getlocalseqnumber(krb5_context context, 462 krb5_auth_context auth_context, 463 int32_t *seqnumber) 464 { 465 *seqnumber = auth_context->local_seqnumber; 466 return 0; 467 } 468 469 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 470 krb5_auth_con_setlocalseqnumber (krb5_context context, 471 krb5_auth_context auth_context, 472 int32_t seqnumber) 473 { 474 auth_context->local_seqnumber = seqnumber; 475 return 0; 476 } 477 478 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 479 krb5_auth_con_getremoteseqnumber(krb5_context context, 480 krb5_auth_context auth_context, 481 int32_t *seqnumber) 482 { 483 *seqnumber = auth_context->remote_seqnumber; 484 return 0; 485 } 486 487 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 488 krb5_auth_con_setremoteseqnumber (krb5_context context, 489 krb5_auth_context auth_context, 490 int32_t seqnumber) 491 { 492 auth_context->remote_seqnumber = seqnumber; 493 return 0; 494 } 495 496 497 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 498 krb5_auth_con_getauthenticator(krb5_context context, 499 krb5_auth_context auth_context, 500 krb5_authenticator *authenticator) 501 { 502 *authenticator = malloc(sizeof(**authenticator)); 503 if (*authenticator == NULL) 504 return krb5_enomem(context); 505 506 copy_Authenticator(auth_context->authenticator, 507 *authenticator); 508 return 0; 509 } 510 511 512 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 513 krb5_free_authenticator(krb5_context context, 514 krb5_authenticator *authenticator) 515 { 516 free_Authenticator (*authenticator); 517 free (*authenticator); 518 *authenticator = NULL; 519 } 520 521 522 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 523 krb5_auth_con_setuserkey(krb5_context context, 524 krb5_auth_context auth_context, 525 krb5_keyblock *keyblock) 526 { 527 if(auth_context->keyblock) 528 krb5_free_keyblock(context, auth_context->keyblock); 529 return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock); 530 } 531 532 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 533 krb5_auth_con_getrcache(krb5_context context, 534 krb5_auth_context auth_context, 535 krb5_rcache *rcache) 536 { 537 *rcache = auth_context->rcache; 538 return 0; 539 } 540 541 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 542 krb5_auth_con_setrcache(krb5_context context, 543 krb5_auth_context auth_context, 544 krb5_rcache rcache) 545 { 546 auth_context->rcache = rcache; 547 return 0; 548 } 549 550 #if 0 /* not implemented */ 551 552 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 553 krb5_auth_con_initivector(krb5_context context, 554 krb5_auth_context auth_context) 555 { 556 krb5_abortx(context, "unimplemented krb5_auth_con_initivector called"); 557 } 558 559 560 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 561 krb5_auth_con_setivector(krb5_context context, 562 krb5_auth_context auth_context, 563 krb5_pointer ivector) 564 { 565 krb5_abortx(context, "unimplemented krb5_auth_con_setivector called"); 566 } 567 568 #endif /* not implemented */ 569