e4fb50e5b820fcb4b176460a05fa85c686b00b2b
[metze/samba/wip.git] / source / heimdal / lib / krb5 / auth_context.c
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 RCSID("$Id: auth_context.c 23273 2008-06-23 03:25:00Z lha $");
37
38 krb5_error_code KRB5_LIB_FUNCTION
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, "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, "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
69 krb5_error_code KRB5_LIB_FUNCTION
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_error_code KRB5_LIB_FUNCTION
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_error_code KRB5_LIB_FUNCTION
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_error_code KRB5_LIB_FUNCTION
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_error_code KRB5_LIB_FUNCTION
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_error_code KRB5_LIB_FUNCTION
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_error_code KRB5_LIB_FUNCTION
160 krb5_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_message(context, ret,
178                                        "getsockname: %s",
179                                        strerror(ret));
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(getpeername(fd, remote, &len) < 0) {
194             ret = errno;
195             krb5_set_error_message(context, ret, 
196                                    "getpeername: %s", strerror(ret));
197             goto out;
198         }
199         ret = krb5_sockaddr2address (context, remote, &remote_k_address);
200         if(ret) goto out;
201         if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) {
202             krb5_sockaddr2port (context, remote, &auth_context->remote_port);
203         } else
204             auth_context->remote_port = 0;
205         rptr = &remote_k_address;
206     }
207     ret = krb5_auth_con_setaddrs (context,
208                                   auth_context,
209                                   lptr,
210                                   rptr);
211   out:
212     if (lptr)
213         krb5_free_address (context, lptr);
214     if (rptr)
215         krb5_free_address (context, rptr);
216     return ret;
217
218 }
219
220 krb5_error_code KRB5_LIB_FUNCTION
221 krb5_auth_con_setaddrs_from_fd (krb5_context context,
222                                 krb5_auth_context auth_context,
223                                 void *p_fd)
224 {
225     int fd = *(int*)p_fd;
226     int flags = 0;
227     if(auth_context->local_address == NULL)
228         flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR;
229     if(auth_context->remote_address == NULL)
230         flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR;
231     return krb5_auth_con_genaddrs(context, auth_context, fd, flags);
232 }
233
234 krb5_error_code KRB5_LIB_FUNCTION
235 krb5_auth_con_getaddrs(krb5_context context,
236                        krb5_auth_context auth_context,
237                        krb5_address **local_addr,
238                        krb5_address **remote_addr)
239 {
240     if(*local_addr)
241         krb5_free_address (context, *local_addr);
242     *local_addr = malloc (sizeof(**local_addr));
243     if (*local_addr == NULL) {
244         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
245         return ENOMEM;
246     }
247     krb5_copy_address(context,
248                       auth_context->local_address,
249                       *local_addr);
250
251     if(*remote_addr)
252         krb5_free_address (context, *remote_addr);
253     *remote_addr = malloc (sizeof(**remote_addr));
254     if (*remote_addr == NULL) {
255         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
256         krb5_free_address (context, *local_addr);
257         *local_addr = NULL;
258         return ENOMEM;
259     }
260     krb5_copy_address(context,
261                       auth_context->remote_address,
262                       *remote_addr);
263     return 0;
264 }
265
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_error_code KRB5_LIB_FUNCTION
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_error_code KRB5_LIB_FUNCTION
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 krb5_error_code KRB5_LIB_FUNCTION
294 krb5_auth_con_getremotesubkey(krb5_context context,
295                               krb5_auth_context auth_context,
296                               krb5_keyblock **keyblock)
297 {
298     return copy_key(context, auth_context->remote_subkey, keyblock);
299 }
300
301 krb5_error_code KRB5_LIB_FUNCTION
302 krb5_auth_con_setkey(krb5_context context,
303                      krb5_auth_context auth_context,
304                      krb5_keyblock *keyblock)
305 {
306     if(auth_context->keyblock)
307         krb5_free_keyblock(context, auth_context->keyblock);
308     return copy_key(context, keyblock, &auth_context->keyblock);
309 }
310
311 krb5_error_code KRB5_LIB_FUNCTION
312 krb5_auth_con_setlocalsubkey(krb5_context context,
313                              krb5_auth_context auth_context,
314                              krb5_keyblock *keyblock)
315 {
316     if(auth_context->local_subkey)
317         krb5_free_keyblock(context, auth_context->local_subkey);
318     return copy_key(context, keyblock, &auth_context->local_subkey);
319 }
320
321 krb5_error_code KRB5_LIB_FUNCTION
322 krb5_auth_con_generatelocalsubkey(krb5_context context,
323                                   krb5_auth_context auth_context,
324                                   krb5_keyblock *key)
325 {
326     krb5_error_code ret;
327     krb5_keyblock *subkey;
328
329     ret = krb5_generate_subkey_extended (context, key,
330                                          auth_context->keytype,
331                                          &subkey);
332     if(ret)
333         return ret;
334     if(auth_context->local_subkey)
335         krb5_free_keyblock(context, auth_context->local_subkey);
336     auth_context->local_subkey = subkey;
337     return 0;
338 }
339
340
341 krb5_error_code KRB5_LIB_FUNCTION
342 krb5_auth_con_setremotesubkey(krb5_context context,
343                               krb5_auth_context auth_context,
344                               krb5_keyblock *keyblock)
345 {
346     if(auth_context->remote_subkey)
347         krb5_free_keyblock(context, auth_context->remote_subkey);
348     return copy_key(context, keyblock, &auth_context->remote_subkey);
349 }
350
351 krb5_error_code KRB5_LIB_FUNCTION
352 krb5_auth_con_setcksumtype(krb5_context context,
353                            krb5_auth_context auth_context,
354                            krb5_cksumtype cksumtype)
355 {
356     auth_context->cksumtype = cksumtype;
357     return 0;
358 }
359
360 krb5_error_code KRB5_LIB_FUNCTION
361 krb5_auth_con_getcksumtype(krb5_context context,
362                            krb5_auth_context auth_context,
363                            krb5_cksumtype *cksumtype)
364 {
365     *cksumtype = auth_context->cksumtype;
366     return 0;
367 }
368
369 krb5_error_code KRB5_LIB_FUNCTION
370 krb5_auth_con_setkeytype (krb5_context context,
371                           krb5_auth_context auth_context,
372                           krb5_keytype keytype)
373 {
374     auth_context->keytype = keytype;
375     return 0;
376 }
377
378 krb5_error_code KRB5_LIB_FUNCTION
379 krb5_auth_con_getkeytype (krb5_context context,
380                           krb5_auth_context auth_context,
381                           krb5_keytype *keytype)
382 {
383     *keytype = auth_context->keytype;
384     return 0;
385 }
386
387 #if 0
388 krb5_error_code KRB5_LIB_FUNCTION
389 krb5_auth_con_setenctype(krb5_context context,
390                          krb5_auth_context auth_context,
391                          krb5_enctype etype)
392 {
393     if(auth_context->keyblock)
394         krb5_free_keyblock(context, auth_context->keyblock);
395     ALLOC(auth_context->keyblock, 1);
396     if(auth_context->keyblock == NULL)
397         return ENOMEM;
398     auth_context->keyblock->keytype = etype;
399     return 0;
400 }
401
402 krb5_error_code KRB5_LIB_FUNCTION
403 krb5_auth_con_getenctype(krb5_context context,
404                          krb5_auth_context auth_context,
405                          krb5_enctype *etype)
406 {
407     krb5_abortx(context, "unimplemented krb5_auth_getenctype called");
408 }
409 #endif
410
411 krb5_error_code KRB5_LIB_FUNCTION
412 krb5_auth_con_getlocalseqnumber(krb5_context context,
413                             krb5_auth_context auth_context,
414                             int32_t *seqnumber)
415 {
416   *seqnumber = auth_context->local_seqnumber;
417   return 0;
418 }
419
420 krb5_error_code KRB5_LIB_FUNCTION
421 krb5_auth_con_setlocalseqnumber (krb5_context context,
422                              krb5_auth_context auth_context,
423                              int32_t seqnumber)
424 {
425   auth_context->local_seqnumber = seqnumber;
426   return 0;
427 }
428
429 krb5_error_code KRB5_LIB_FUNCTION
430 krb5_auth_getremoteseqnumber(krb5_context context,
431                              krb5_auth_context auth_context,
432                              int32_t *seqnumber)
433 {
434   *seqnumber = auth_context->remote_seqnumber;
435   return 0;
436 }
437
438 krb5_error_code KRB5_LIB_FUNCTION
439 krb5_auth_con_setremoteseqnumber (krb5_context context,
440                               krb5_auth_context auth_context,
441                               int32_t seqnumber)
442 {
443   auth_context->remote_seqnumber = seqnumber;
444   return 0;
445 }
446
447
448 krb5_error_code KRB5_LIB_FUNCTION
449 krb5_auth_con_getauthenticator(krb5_context context,
450                            krb5_auth_context auth_context,
451                            krb5_authenticator *authenticator)
452 {
453     *authenticator = malloc(sizeof(**authenticator));
454     if (*authenticator == NULL) {
455         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
456         return ENOMEM;
457     }
458
459     copy_Authenticator(auth_context->authenticator,
460                        *authenticator);
461     return 0;
462 }
463
464
465 void KRB5_LIB_FUNCTION
466 krb5_free_authenticator(krb5_context context,
467                         krb5_authenticator *authenticator)
468 {
469     free_Authenticator (*authenticator);
470     free (*authenticator);
471     *authenticator = NULL;
472 }
473
474
475 krb5_error_code KRB5_LIB_FUNCTION
476 krb5_auth_con_setuserkey(krb5_context context,
477                          krb5_auth_context auth_context,
478                          krb5_keyblock *keyblock)
479 {
480     if(auth_context->keyblock)
481         krb5_free_keyblock(context, auth_context->keyblock);
482     return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock);
483 }
484
485 krb5_error_code KRB5_LIB_FUNCTION
486 krb5_auth_con_getrcache(krb5_context context,
487                         krb5_auth_context auth_context,
488                         krb5_rcache *rcache)
489 {
490     *rcache = auth_context->rcache;
491     return 0;
492 }
493
494 krb5_error_code KRB5_LIB_FUNCTION
495 krb5_auth_con_setrcache(krb5_context context,
496                         krb5_auth_context auth_context,
497                         krb5_rcache rcache)
498 {
499     auth_context->rcache = rcache;
500     return 0;
501 }
502
503 #if 0 /* not implemented */
504
505 krb5_error_code KRB5_LIB_FUNCTION
506 krb5_auth_con_initivector(krb5_context context,
507                           krb5_auth_context auth_context)
508 {
509     krb5_abortx(context, "unimplemented krb5_auth_con_initivector called");
510 }
511
512
513 krb5_error_code KRB5_LIB_FUNCTION
514 krb5_auth_con_setivector(krb5_context context,
515                          krb5_auth_context auth_context,
516                          krb5_pointer ivector)
517 {
518     krb5_abortx(context, "unimplemented krb5_auth_con_setivector called");
519 }
520
521 #endif /* not implemented */