xref: /freebsd/crypto/heimdal/lib/krb5/auth_context.c (revision a8089ea5aee578e08acab2438e82fc9a9ae50ed8)
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 
36 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
37 krb5_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 
67 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
68 krb5_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 
89 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
90 krb5_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 
99 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
100 krb5_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 
108 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
109 krb5_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 
120 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
121 krb5_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 
132 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
133 krb5_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 
157 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
158 krb5_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 
219 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
220 krb5_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 
233 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
234 krb5_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] */
266 static krb5_error_code
267 copy_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 
277 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
278 krb5_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 
285 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
286 krb5_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] */
294 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
295 krb5_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 
302 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
303 krb5_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 
312 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
313 krb5_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 
322 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
323 krb5_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 
342 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
343 krb5_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 
352 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
353 krb5_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 
361 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
362 krb5_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 
370 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
371 krb5_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 
379 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
380 krb5_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
389 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
390 krb5_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 
403 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
404 krb5_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 
412 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
413 krb5_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 
421 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
422 krb5_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 
430 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
431 krb5_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 
439 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
440 krb5_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 
449 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
450 krb5_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 
466 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
467 krb5_free_authenticator(krb5_context context,
468 			krb5_authenticator *authenticator)
469 {
470     free_Authenticator (*authenticator);
471     free (*authenticator);
472     *authenticator = NULL;
473 }
474 
475 
476 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
477 krb5_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 
486 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
487 krb5_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 
495 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
496 krb5_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 
506 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
507 krb5_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 
514 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
515 krb5_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