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