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 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 */
48KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
49krb5_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 */
86KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
87krb5_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
112KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
113krb5_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
122KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
123krb5_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
131KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
132krb5_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
143KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
144krb5_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
155KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
156krb5_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 */
186KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
187krb5_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
248KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
249krb5_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
262KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
263krb5_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] */
292static krb5_error_code
293copy_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
303KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
304krb5_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
311KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
312krb5_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] */
320KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
321krb5_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
328KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
329krb5_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
338KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
339krb5_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
348KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
349krb5_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
368KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
369krb5_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
378KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
379krb5_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
387KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
388krb5_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
396KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
397krb5_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
405KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
406krb5_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
414KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
415krb5_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
437KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
438krb5_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
451KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
452krb5_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
460KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
461krb5_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
469KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
470krb5_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
478KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
479krb5_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
487KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
488krb5_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
497KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
498krb5_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
512KRB5_LIB_FUNCTION void KRB5_LIB_CALL
513krb5_free_authenticator(krb5_context context,
514			krb5_authenticator *authenticator)
515{
516    free_Authenticator (*authenticator);
517    free (*authenticator);
518    *authenticator = NULL;
519}
520
521
522KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
523krb5_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
532KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
533krb5_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
541KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
542krb5_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
552KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
553krb5_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
560KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
561krb5_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