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