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
36RCSID("$Id: auth_context.c 21745 2007-07-31 16:11:25Z lha $");
37
38krb5_error_code KRB5_LIB_FUNCTION
39krb5_auth_con_init(krb5_context context,
40		   krb5_auth_context *auth_context)
41{
42    krb5_auth_context p;
43
44    ALLOC(p, 1);
45    if(!p) {
46	krb5_set_error_string(context, "malloc: out of memory");
47	return ENOMEM;
48    }
49    memset(p, 0, sizeof(*p));
50    ALLOC(p->authenticator, 1);
51    if (!p->authenticator) {
52	krb5_set_error_string(context, "malloc: out of memory");
53	free(p);
54	return ENOMEM;
55    }
56    memset (p->authenticator, 0, sizeof(*p->authenticator));
57    p->flags = KRB5_AUTH_CONTEXT_DO_TIME;
58
59    p->local_address  = NULL;
60    p->remote_address = NULL;
61    p->local_port     = 0;
62    p->remote_port    = 0;
63    p->keytype        = KEYTYPE_NULL;
64    p->cksumtype      = CKSUMTYPE_NONE;
65    *auth_context     = p;
66    return 0;
67}
68
69krb5_error_code KRB5_LIB_FUNCTION
70krb5_auth_con_free(krb5_context context,
71		   krb5_auth_context auth_context)
72{
73    if (auth_context != NULL) {
74	krb5_free_authenticator(context, &auth_context->authenticator);
75	if(auth_context->local_address){
76	    free_HostAddress(auth_context->local_address);
77	    free(auth_context->local_address);
78	}
79	if(auth_context->remote_address){
80	    free_HostAddress(auth_context->remote_address);
81	    free(auth_context->remote_address);
82	}
83	krb5_free_keyblock(context, auth_context->keyblock);
84	krb5_free_keyblock(context, auth_context->remote_subkey);
85	krb5_free_keyblock(context, auth_context->local_subkey);
86	free (auth_context);
87    }
88    return 0;
89}
90
91krb5_error_code KRB5_LIB_FUNCTION
92krb5_auth_con_setflags(krb5_context context,
93		       krb5_auth_context auth_context,
94		       int32_t flags)
95{
96    auth_context->flags = flags;
97    return 0;
98}
99
100
101krb5_error_code KRB5_LIB_FUNCTION
102krb5_auth_con_getflags(krb5_context context,
103		       krb5_auth_context auth_context,
104		       int32_t *flags)
105{
106    *flags = auth_context->flags;
107    return 0;
108}
109
110krb5_error_code KRB5_LIB_FUNCTION
111krb5_auth_con_addflags(krb5_context context,
112		       krb5_auth_context auth_context,
113		       int32_t addflags,
114		       int32_t *flags)
115{
116    if (flags)
117	*flags = auth_context->flags;
118    auth_context->flags |= addflags;
119    return 0;
120}
121
122krb5_error_code KRB5_LIB_FUNCTION
123krb5_auth_con_removeflags(krb5_context context,
124			  krb5_auth_context auth_context,
125			  int32_t removeflags,
126			  int32_t *flags)
127{
128    if (flags)
129	*flags = auth_context->flags;
130    auth_context->flags &= ~removeflags;
131    return 0;
132}
133
134krb5_error_code KRB5_LIB_FUNCTION
135krb5_auth_con_setaddrs(krb5_context context,
136		       krb5_auth_context auth_context,
137		       krb5_address *local_addr,
138		       krb5_address *remote_addr)
139{
140    if (local_addr) {
141	if (auth_context->local_address)
142	    krb5_free_address (context, auth_context->local_address);
143	else
144	    if ((auth_context->local_address = malloc(sizeof(krb5_address))) == NULL)
145		return ENOMEM;
146	krb5_copy_address(context, local_addr, auth_context->local_address);
147    }
148    if (remote_addr) {
149	if (auth_context->remote_address)
150	    krb5_free_address (context, auth_context->remote_address);
151	else
152	    if ((auth_context->remote_address = malloc(sizeof(krb5_address))) == NULL)
153		return ENOMEM;
154	krb5_copy_address(context, remote_addr, auth_context->remote_address);
155    }
156    return 0;
157}
158
159krb5_error_code KRB5_LIB_FUNCTION
160krb5_auth_con_genaddrs(krb5_context context,
161		       krb5_auth_context auth_context,
162		       int fd, int flags)
163{
164    krb5_error_code ret;
165    krb5_address local_k_address, remote_k_address;
166    krb5_address *lptr = NULL, *rptr = NULL;
167    struct sockaddr_storage ss_local, ss_remote;
168    struct sockaddr *local  = (struct sockaddr *)&ss_local;
169    struct sockaddr *remote = (struct sockaddr *)&ss_remote;
170    socklen_t len;
171
172    if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR) {
173	if (auth_context->local_address == NULL) {
174	    len = sizeof(ss_local);
175	    if(getsockname(fd, local, &len) < 0) {
176		ret = errno;
177		krb5_set_error_string (context, "getsockname: %s",
178				       strerror(ret));
179		goto out;
180	    }
181	    ret = krb5_sockaddr2address (context, local, &local_k_address);
182	    if(ret) goto out;
183	    if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) {
184		krb5_sockaddr2port (context, local, &auth_context->local_port);
185	    } else
186		auth_context->local_port = 0;
187	    lptr = &local_k_address;
188	}
189    }
190    if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) {
191	len = sizeof(ss_remote);
192	if(getpeername(fd, remote, &len) < 0) {
193	    ret = errno;
194	    krb5_set_error_string (context, "getpeername: %s", strerror(ret));
195	    goto out;
196	}
197	ret = krb5_sockaddr2address (context, remote, &remote_k_address);
198	if(ret) goto out;
199	if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) {
200	    krb5_sockaddr2port (context, remote, &auth_context->remote_port);
201	} else
202	    auth_context->remote_port = 0;
203	rptr = &remote_k_address;
204    }
205    ret = krb5_auth_con_setaddrs (context,
206				  auth_context,
207				  lptr,
208				  rptr);
209  out:
210    if (lptr)
211	krb5_free_address (context, lptr);
212    if (rptr)
213	krb5_free_address (context, rptr);
214    return ret;
215
216}
217
218krb5_error_code KRB5_LIB_FUNCTION
219krb5_auth_con_setaddrs_from_fd (krb5_context context,
220				krb5_auth_context auth_context,
221				void *p_fd)
222{
223    int fd = *(int*)p_fd;
224    int flags = 0;
225    if(auth_context->local_address == NULL)
226	flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR;
227    if(auth_context->remote_address == NULL)
228	flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR;
229    return krb5_auth_con_genaddrs(context, auth_context, fd, flags);
230}
231
232krb5_error_code KRB5_LIB_FUNCTION
233krb5_auth_con_getaddrs(krb5_context context,
234		       krb5_auth_context auth_context,
235		       krb5_address **local_addr,
236		       krb5_address **remote_addr)
237{
238    if(*local_addr)
239	krb5_free_address (context, *local_addr);
240    *local_addr = malloc (sizeof(**local_addr));
241    if (*local_addr == NULL) {
242	krb5_set_error_string(context, "malloc: out of memory");
243	return ENOMEM;
244    }
245    krb5_copy_address(context,
246		      auth_context->local_address,
247		      *local_addr);
248
249    if(*remote_addr)
250	krb5_free_address (context, *remote_addr);
251    *remote_addr = malloc (sizeof(**remote_addr));
252    if (*remote_addr == NULL) {
253	krb5_set_error_string(context, "malloc: out of memory");
254	krb5_free_address (context, *local_addr);
255	*local_addr = NULL;
256	return ENOMEM;
257    }
258    krb5_copy_address(context,
259		      auth_context->remote_address,
260		      *remote_addr);
261    return 0;
262}
263
264static krb5_error_code
265copy_key(krb5_context context,
266	 krb5_keyblock *in,
267	 krb5_keyblock **out)
268{
269    if(in)
270	return krb5_copy_keyblock(context, in, out);
271    *out = NULL; /* is this right? */
272    return 0;
273}
274
275krb5_error_code KRB5_LIB_FUNCTION
276krb5_auth_con_getkey(krb5_context context,
277		     krb5_auth_context auth_context,
278		     krb5_keyblock **keyblock)
279{
280    return copy_key(context, auth_context->keyblock, keyblock);
281}
282
283krb5_error_code KRB5_LIB_FUNCTION
284krb5_auth_con_getlocalsubkey(krb5_context context,
285			     krb5_auth_context auth_context,
286			     krb5_keyblock **keyblock)
287{
288    return copy_key(context, auth_context->local_subkey, keyblock);
289}
290
291krb5_error_code KRB5_LIB_FUNCTION
292krb5_auth_con_getremotesubkey(krb5_context context,
293			      krb5_auth_context auth_context,
294			      krb5_keyblock **keyblock)
295{
296    return copy_key(context, auth_context->remote_subkey, keyblock);
297}
298
299krb5_error_code KRB5_LIB_FUNCTION
300krb5_auth_con_setkey(krb5_context context,
301		     krb5_auth_context auth_context,
302		     krb5_keyblock *keyblock)
303{
304    if(auth_context->keyblock)
305	krb5_free_keyblock(context, auth_context->keyblock);
306    return copy_key(context, keyblock, &auth_context->keyblock);
307}
308
309krb5_error_code KRB5_LIB_FUNCTION
310krb5_auth_con_setlocalsubkey(krb5_context context,
311			     krb5_auth_context auth_context,
312			     krb5_keyblock *keyblock)
313{
314    if(auth_context->local_subkey)
315	krb5_free_keyblock(context, auth_context->local_subkey);
316    return copy_key(context, keyblock, &auth_context->local_subkey);
317}
318
319krb5_error_code KRB5_LIB_FUNCTION
320krb5_auth_con_generatelocalsubkey(krb5_context context,
321				  krb5_auth_context auth_context,
322				  krb5_keyblock *key)
323{
324    krb5_error_code ret;
325    krb5_keyblock *subkey;
326
327    ret = krb5_generate_subkey_extended (context, key,
328					 auth_context->keytype,
329					 &subkey);
330    if(ret)
331	return ret;
332    if(auth_context->local_subkey)
333	krb5_free_keyblock(context, auth_context->local_subkey);
334    auth_context->local_subkey = subkey;
335    return 0;
336}
337
338
339krb5_error_code KRB5_LIB_FUNCTION
340krb5_auth_con_setremotesubkey(krb5_context context,
341			      krb5_auth_context auth_context,
342			      krb5_keyblock *keyblock)
343{
344    if(auth_context->remote_subkey)
345	krb5_free_keyblock(context, auth_context->remote_subkey);
346    return copy_key(context, keyblock, &auth_context->remote_subkey);
347}
348
349krb5_error_code KRB5_LIB_FUNCTION
350krb5_auth_con_setcksumtype(krb5_context context,
351			   krb5_auth_context auth_context,
352			   krb5_cksumtype cksumtype)
353{
354    auth_context->cksumtype = cksumtype;
355    return 0;
356}
357
358krb5_error_code KRB5_LIB_FUNCTION
359krb5_auth_con_getcksumtype(krb5_context context,
360			   krb5_auth_context auth_context,
361			   krb5_cksumtype *cksumtype)
362{
363    *cksumtype = auth_context->cksumtype;
364    return 0;
365}
366
367krb5_error_code KRB5_LIB_FUNCTION
368krb5_auth_con_setkeytype (krb5_context context,
369			  krb5_auth_context auth_context,
370			  krb5_keytype keytype)
371{
372    auth_context->keytype = keytype;
373    return 0;
374}
375
376krb5_error_code KRB5_LIB_FUNCTION
377krb5_auth_con_getkeytype (krb5_context context,
378			  krb5_auth_context auth_context,
379			  krb5_keytype *keytype)
380{
381    *keytype = auth_context->keytype;
382    return 0;
383}
384
385#if 0
386krb5_error_code KRB5_LIB_FUNCTION
387krb5_auth_con_setenctype(krb5_context context,
388			 krb5_auth_context auth_context,
389			 krb5_enctype etype)
390{
391    if(auth_context->keyblock)
392	krb5_free_keyblock(context, auth_context->keyblock);
393    ALLOC(auth_context->keyblock, 1);
394    if(auth_context->keyblock == NULL)
395	return ENOMEM;
396    auth_context->keyblock->keytype = etype;
397    return 0;
398}
399
400krb5_error_code KRB5_LIB_FUNCTION
401krb5_auth_con_getenctype(krb5_context context,
402			 krb5_auth_context auth_context,
403			 krb5_enctype *etype)
404{
405    krb5_abortx(context, "unimplemented krb5_auth_getenctype called");
406}
407#endif
408
409krb5_error_code KRB5_LIB_FUNCTION
410krb5_auth_con_getlocalseqnumber(krb5_context context,
411			    krb5_auth_context auth_context,
412			    int32_t *seqnumber)
413{
414  *seqnumber = auth_context->local_seqnumber;
415  return 0;
416}
417
418krb5_error_code KRB5_LIB_FUNCTION
419krb5_auth_con_setlocalseqnumber (krb5_context context,
420			     krb5_auth_context auth_context,
421			     int32_t seqnumber)
422{
423  auth_context->local_seqnumber = seqnumber;
424  return 0;
425}
426
427krb5_error_code KRB5_LIB_FUNCTION
428krb5_auth_getremoteseqnumber(krb5_context context,
429			     krb5_auth_context auth_context,
430			     int32_t *seqnumber)
431{
432  *seqnumber = auth_context->remote_seqnumber;
433  return 0;
434}
435
436krb5_error_code KRB5_LIB_FUNCTION
437krb5_auth_con_setremoteseqnumber (krb5_context context,
438			      krb5_auth_context auth_context,
439			      int32_t seqnumber)
440{
441  auth_context->remote_seqnumber = seqnumber;
442  return 0;
443}
444
445
446krb5_error_code KRB5_LIB_FUNCTION
447krb5_auth_con_getauthenticator(krb5_context context,
448			   krb5_auth_context auth_context,
449			   krb5_authenticator *authenticator)
450{
451    *authenticator = malloc(sizeof(**authenticator));
452    if (*authenticator == NULL) {
453	krb5_set_error_string(context, "malloc: out of memory");
454	return ENOMEM;
455    }
456
457    copy_Authenticator(auth_context->authenticator,
458		       *authenticator);
459    return 0;
460}
461
462
463void KRB5_LIB_FUNCTION
464krb5_free_authenticator(krb5_context context,
465			krb5_authenticator *authenticator)
466{
467    free_Authenticator (*authenticator);
468    free (*authenticator);
469    *authenticator = NULL;
470}
471
472
473krb5_error_code KRB5_LIB_FUNCTION
474krb5_auth_con_setuserkey(krb5_context context,
475			 krb5_auth_context auth_context,
476			 krb5_keyblock *keyblock)
477{
478    if(auth_context->keyblock)
479	krb5_free_keyblock(context, auth_context->keyblock);
480    return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock);
481}
482
483krb5_error_code KRB5_LIB_FUNCTION
484krb5_auth_con_getrcache(krb5_context context,
485			krb5_auth_context auth_context,
486			krb5_rcache *rcache)
487{
488    *rcache = auth_context->rcache;
489    return 0;
490}
491
492krb5_error_code KRB5_LIB_FUNCTION
493krb5_auth_con_setrcache(krb5_context context,
494			krb5_auth_context auth_context,
495			krb5_rcache rcache)
496{
497    auth_context->rcache = rcache;
498    return 0;
499}
500
501#if 0 /* not implemented */
502
503krb5_error_code KRB5_LIB_FUNCTION
504krb5_auth_con_initivector(krb5_context context,
505			  krb5_auth_context auth_context)
506{
507    krb5_abortx(context, "unimplemented krb5_auth_con_initivector called");
508}
509
510
511krb5_error_code KRB5_LIB_FUNCTION
512krb5_auth_con_setivector(krb5_context context,
513			 krb5_auth_context auth_context,
514			 krb5_pointer ivector)
515{
516    krb5_abortx(context, "unimplemented krb5_auth_con_setivector called");
517}
518
519#endif /* not implemented */
520