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        = 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 krb5_error_code KRB5_LIB_CALL
133krb5_auth_con_setaddrs(krb5_context context,
134		       krb5_auth_context auth_context,
135		       krb5_address *local_addr,
136		       krb5_address *remote_addr)
137{
138    if (local_addr) {
139	if (auth_context->local_address)
140	    krb5_free_address (context, auth_context->local_address);
141	else
142	    if ((auth_context->local_address = malloc(sizeof(krb5_address))) == NULL)
143		return ENOMEM;
144	krb5_copy_address(context, local_addr, auth_context->local_address);
145    }
146    if (remote_addr) {
147	if (auth_context->remote_address)
148	    krb5_free_address (context, auth_context->remote_address);
149	else
150	    if ((auth_context->remote_address = malloc(sizeof(krb5_address))) == NULL)
151		return ENOMEM;
152	krb5_copy_address(context, remote_addr, auth_context->remote_address);
153    }
154    return 0;
155}
156
157KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
158krb5_auth_con_genaddrs(krb5_context context,
159		       krb5_auth_context auth_context,
160		       krb5_socket_t fd, int flags)
161{
162    krb5_error_code ret;
163    krb5_address local_k_address, remote_k_address;
164    krb5_address *lptr = NULL, *rptr = NULL;
165    struct sockaddr_storage ss_local, ss_remote;
166    struct sockaddr *local  = (struct sockaddr *)&ss_local;
167    struct sockaddr *remote = (struct sockaddr *)&ss_remote;
168    socklen_t len;
169
170    if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR) {
171	if (auth_context->local_address == NULL) {
172	    len = sizeof(ss_local);
173	    if(rk_IS_SOCKET_ERROR(getsockname(fd, local, &len))) {
174		char buf[128];
175		ret = rk_SOCK_ERRNO;
176		rk_strerror_r(ret, buf, sizeof(buf));
177		krb5_set_error_message(context, ret, "getsockname: %s", buf);
178		goto out;
179	    }
180	    ret = krb5_sockaddr2address (context, local, &local_k_address);
181	    if(ret) goto out;
182	    if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) {
183		krb5_sockaddr2port (context, local, &auth_context->local_port);
184	    } else
185		auth_context->local_port = 0;
186	    lptr = &local_k_address;
187	}
188    }
189    if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) {
190	len = sizeof(ss_remote);
191	if(rk_IS_SOCKET_ERROR(getpeername(fd, remote, &len))) {
192	    char buf[128];
193	    ret = rk_SOCK_ERRNO;
194	    rk_strerror_r(ret, buf, sizeof(buf));
195	    krb5_set_error_message(context, ret, "getpeername: %s", buf);
196	    goto out;
197	}
198	ret = krb5_sockaddr2address (context, remote, &remote_k_address);
199	if(ret) goto out;
200	if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) {
201	    krb5_sockaddr2port (context, remote, &auth_context->remote_port);
202	} else
203	    auth_context->remote_port = 0;
204	rptr = &remote_k_address;
205    }
206    ret = krb5_auth_con_setaddrs (context,
207				  auth_context,
208				  lptr,
209				  rptr);
210  out:
211    if (lptr)
212	krb5_free_address (context, lptr);
213    if (rptr)
214	krb5_free_address (context, rptr);
215    return ret;
216
217}
218
219KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
220krb5_auth_con_setaddrs_from_fd (krb5_context context,
221				krb5_auth_context auth_context,
222				void *p_fd)
223{
224    krb5_socket_t fd = *(krb5_socket_t *)p_fd;
225    int flags = 0;
226    if(auth_context->local_address == NULL)
227	flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR;
228    if(auth_context->remote_address == NULL)
229	flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR;
230    return krb5_auth_con_genaddrs(context, auth_context, fd, flags);
231}
232
233KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
234krb5_auth_con_getaddrs(krb5_context context,
235		       krb5_auth_context auth_context,
236		       krb5_address **local_addr,
237		       krb5_address **remote_addr)
238{
239    if(*local_addr)
240	krb5_free_address (context, *local_addr);
241    *local_addr = malloc (sizeof(**local_addr));
242    if (*local_addr == NULL) {
243	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
244	return ENOMEM;
245    }
246    krb5_copy_address(context,
247		      auth_context->local_address,
248		      *local_addr);
249
250    if(*remote_addr)
251	krb5_free_address (context, *remote_addr);
252    *remote_addr = malloc (sizeof(**remote_addr));
253    if (*remote_addr == NULL) {
254	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
255	krb5_free_address (context, *local_addr);
256	*local_addr = NULL;
257	return ENOMEM;
258    }
259    krb5_copy_address(context,
260		      auth_context->remote_address,
261		      *remote_addr);
262    return 0;
263}
264
265/* coverity[+alloc : arg-*2] */
266static krb5_error_code
267copy_key(krb5_context context,
268	 krb5_keyblock *in,
269	 krb5_keyblock **out)
270{
271    if(in)
272	return krb5_copy_keyblock(context, in, out);
273    *out = NULL; /* is this right? */
274    return 0;
275}
276
277KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
278krb5_auth_con_getkey(krb5_context context,
279		     krb5_auth_context auth_context,
280		     krb5_keyblock **keyblock)
281{
282    return copy_key(context, auth_context->keyblock, keyblock);
283}
284
285KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
286krb5_auth_con_getlocalsubkey(krb5_context context,
287			     krb5_auth_context auth_context,
288			     krb5_keyblock **keyblock)
289{
290    return copy_key(context, auth_context->local_subkey, keyblock);
291}
292
293/* coverity[+alloc : arg-*2] */
294KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
295krb5_auth_con_getremotesubkey(krb5_context context,
296			      krb5_auth_context auth_context,
297			      krb5_keyblock **keyblock)
298{
299    return copy_key(context, auth_context->remote_subkey, keyblock);
300}
301
302KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
303krb5_auth_con_setkey(krb5_context context,
304		     krb5_auth_context auth_context,
305		     krb5_keyblock *keyblock)
306{
307    if(auth_context->keyblock)
308	krb5_free_keyblock(context, auth_context->keyblock);
309    return copy_key(context, keyblock, &auth_context->keyblock);
310}
311
312KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
313krb5_auth_con_setlocalsubkey(krb5_context context,
314			     krb5_auth_context auth_context,
315			     krb5_keyblock *keyblock)
316{
317    if(auth_context->local_subkey)
318	krb5_free_keyblock(context, auth_context->local_subkey);
319    return copy_key(context, keyblock, &auth_context->local_subkey);
320}
321
322KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
323krb5_auth_con_generatelocalsubkey(krb5_context context,
324				  krb5_auth_context auth_context,
325				  krb5_keyblock *key)
326{
327    krb5_error_code ret;
328    krb5_keyblock *subkey;
329
330    ret = krb5_generate_subkey_extended (context, key,
331					 auth_context->keytype,
332					 &subkey);
333    if(ret)
334	return ret;
335    if(auth_context->local_subkey)
336	krb5_free_keyblock(context, auth_context->local_subkey);
337    auth_context->local_subkey = subkey;
338    return 0;
339}
340
341
342KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
343krb5_auth_con_setremotesubkey(krb5_context context,
344			      krb5_auth_context auth_context,
345			      krb5_keyblock *keyblock)
346{
347    if(auth_context->remote_subkey)
348	krb5_free_keyblock(context, auth_context->remote_subkey);
349    return copy_key(context, keyblock, &auth_context->remote_subkey);
350}
351
352KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
353krb5_auth_con_setcksumtype(krb5_context context,
354			   krb5_auth_context auth_context,
355			   krb5_cksumtype cksumtype)
356{
357    auth_context->cksumtype = cksumtype;
358    return 0;
359}
360
361KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
362krb5_auth_con_getcksumtype(krb5_context context,
363			   krb5_auth_context auth_context,
364			   krb5_cksumtype *cksumtype)
365{
366    *cksumtype = auth_context->cksumtype;
367    return 0;
368}
369
370KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
371krb5_auth_con_setkeytype (krb5_context context,
372			  krb5_auth_context auth_context,
373			  krb5_keytype keytype)
374{
375    auth_context->keytype = keytype;
376    return 0;
377}
378
379KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
380krb5_auth_con_getkeytype (krb5_context context,
381			  krb5_auth_context auth_context,
382			  krb5_keytype *keytype)
383{
384    *keytype = auth_context->keytype;
385    return 0;
386}
387
388#if 0
389KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
390krb5_auth_con_setenctype(krb5_context context,
391			 krb5_auth_context auth_context,
392			 krb5_enctype etype)
393{
394    if(auth_context->keyblock)
395	krb5_free_keyblock(context, auth_context->keyblock);
396    ALLOC(auth_context->keyblock, 1);
397    if(auth_context->keyblock == NULL)
398	return ENOMEM;
399    auth_context->keyblock->keytype = etype;
400    return 0;
401}
402
403KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
404krb5_auth_con_getenctype(krb5_context context,
405			 krb5_auth_context auth_context,
406			 krb5_enctype *etype)
407{
408    krb5_abortx(context, "unimplemented krb5_auth_getenctype called");
409}
410#endif
411
412KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
413krb5_auth_con_getlocalseqnumber(krb5_context context,
414			    krb5_auth_context auth_context,
415			    int32_t *seqnumber)
416{
417  *seqnumber = auth_context->local_seqnumber;
418  return 0;
419}
420
421KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
422krb5_auth_con_setlocalseqnumber (krb5_context context,
423			     krb5_auth_context auth_context,
424			     int32_t seqnumber)
425{
426  auth_context->local_seqnumber = seqnumber;
427  return 0;
428}
429
430KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
431krb5_auth_con_getremoteseqnumber(krb5_context context,
432				 krb5_auth_context auth_context,
433				 int32_t *seqnumber)
434{
435  *seqnumber = auth_context->remote_seqnumber;
436  return 0;
437}
438
439KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
440krb5_auth_con_setremoteseqnumber (krb5_context context,
441			      krb5_auth_context auth_context,
442			      int32_t seqnumber)
443{
444  auth_context->remote_seqnumber = seqnumber;
445  return 0;
446}
447
448
449KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
450krb5_auth_con_getauthenticator(krb5_context context,
451			   krb5_auth_context auth_context,
452			   krb5_authenticator *authenticator)
453{
454    *authenticator = malloc(sizeof(**authenticator));
455    if (*authenticator == NULL) {
456	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
457	return ENOMEM;
458    }
459
460    copy_Authenticator(auth_context->authenticator,
461		       *authenticator);
462    return 0;
463}
464
465
466KRB5_LIB_FUNCTION void KRB5_LIB_CALL
467krb5_free_authenticator(krb5_context context,
468			krb5_authenticator *authenticator)
469{
470    free_Authenticator (*authenticator);
471    free (*authenticator);
472    *authenticator = NULL;
473}
474
475
476KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
477krb5_auth_con_setuserkey(krb5_context context,
478			 krb5_auth_context auth_context,
479			 krb5_keyblock *keyblock)
480{
481    if(auth_context->keyblock)
482	krb5_free_keyblock(context, auth_context->keyblock);
483    return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock);
484}
485
486KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
487krb5_auth_con_getrcache(krb5_context context,
488			krb5_auth_context auth_context,
489			krb5_rcache *rcache)
490{
491    *rcache = auth_context->rcache;
492    return 0;
493}
494
495KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
496krb5_auth_con_setrcache(krb5_context context,
497			krb5_auth_context auth_context,
498			krb5_rcache rcache)
499{
500    auth_context->rcache = rcache;
501    return 0;
502}
503
504#if 0 /* not implemented */
505
506KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
507krb5_auth_con_initivector(krb5_context context,
508			  krb5_auth_context auth_context)
509{
510    krb5_abortx(context, "unimplemented krb5_auth_con_initivector called");
511}
512
513
514KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
515krb5_auth_con_setivector(krb5_context context,
516			 krb5_auth_context auth_context,
517			 krb5_pointer ivector)
518{
519    krb5_abortx(context, "unimplemented krb5_auth_con_setivector called");
520}
521
522#endif /* not implemented */
523