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