Home | History | Annotate | Line # | Download | only in krb5
      1 /*	$NetBSD: auth_context.c,v 1.5 2023/06/19 21:41:44 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997 - 2002 Kungliga Tekniska Hgskolan
      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