Imported Upstream version 1.20.1
[platform/upstream/krb5.git] / src / lib / krb5 / krb / auth_con.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/auth_con.c */
3 /*
4  * Copyright 2010 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26
27 #include "k5-int.h"
28 #include "int-proto.h"
29 #include "auth_con.h"
30
31 krb5_error_code KRB5_CALLCONV
32 krb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context)
33 {
34     *auth_context =
35         (krb5_auth_context)calloc(1, sizeof(struct _krb5_auth_context));
36     if (!*auth_context)
37         return ENOMEM;
38
39     /* Default flags, do time not seq */
40     (*auth_context)->auth_context_flags =
41         KRB5_AUTH_CONTEXT_DO_TIME |  KRB5_AUTH_CONN_INITIALIZED;
42
43     (*auth_context)->checksum_func = NULL;
44     (*auth_context)->checksum_func_data = NULL;
45     (*auth_context)->negotiated_etype = ENCTYPE_NULL;
46     (*auth_context)->magic = KV5M_AUTH_CONTEXT;
47     return 0;
48 }
49
50 krb5_error_code KRB5_CALLCONV
51 krb5_auth_con_free(krb5_context context, krb5_auth_context auth_context)
52 {
53     if (auth_context == NULL)
54         return 0;
55     if (auth_context->local_addr)
56         krb5_free_address(context, auth_context->local_addr);
57     if (auth_context->remote_addr)
58         krb5_free_address(context, auth_context->remote_addr);
59     if (auth_context->local_port)
60         krb5_free_address(context, auth_context->local_port);
61     if (auth_context->remote_port)
62         krb5_free_address(context, auth_context->remote_port);
63     if (auth_context->authentp)
64         krb5_free_authenticator(context, auth_context->authentp);
65     if (auth_context->key)
66         krb5_k_free_key(context, auth_context->key);
67     if (auth_context->send_subkey)
68         krb5_k_free_key(context, auth_context->send_subkey);
69     if (auth_context->recv_subkey)
70         krb5_k_free_key(context, auth_context->recv_subkey);
71     zapfree(auth_context->cstate.data, auth_context->cstate.length);
72     if (auth_context->rcache)
73         k5_rc_close(context, auth_context->rcache);
74     if (auth_context->permitted_etypes)
75         free(auth_context->permitted_etypes);
76     if (auth_context->ad_context)
77         krb5_authdata_context_free(context, auth_context->ad_context);
78     k5_memrcache_free(context, auth_context->memrcache);
79     free(auth_context);
80     return 0;
81 }
82
83 krb5_error_code
84 krb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address *local_addr, krb5_address *remote_addr)
85 {
86     krb5_error_code     retval;
87
88     /* Free old addresses */
89     if (auth_context->local_addr)
90         (void) krb5_free_address(context, auth_context->local_addr);
91     if (auth_context->remote_addr)
92         (void) krb5_free_address(context, auth_context->remote_addr);
93
94     retval = 0;
95     if (local_addr)
96         retval = krb5_copy_addr(context,
97                                 local_addr,
98                                 &auth_context->local_addr);
99     else
100         auth_context->local_addr = NULL;
101
102     if (!retval && remote_addr)
103         retval = krb5_copy_addr(context,
104                                 remote_addr,
105                                 &auth_context->remote_addr);
106     else
107         auth_context->remote_addr = NULL;
108
109     return retval;
110 }
111
112 krb5_error_code KRB5_CALLCONV
113 krb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address **local_addr, krb5_address **remote_addr)
114 {
115     krb5_error_code     retval;
116
117     retval = 0;
118     if (local_addr && auth_context->local_addr) {
119         retval = krb5_copy_addr(context,
120                                 auth_context->local_addr,
121                                 local_addr);
122     }
123     if (!retval && (remote_addr) && auth_context->remote_addr) {
124         retval = krb5_copy_addr(context,
125                                 auth_context->remote_addr,
126                                 remote_addr);
127     }
128     return retval;
129 }
130
131 krb5_error_code KRB5_CALLCONV
132 krb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, krb5_address *local_port, krb5_address *remote_port)
133 {
134     krb5_error_code     retval;
135
136     /* Free old addresses */
137     if (auth_context->local_port)
138         (void) krb5_free_address(context, auth_context->local_port);
139     if (auth_context->remote_port)
140         (void) krb5_free_address(context, auth_context->remote_port);
141
142     retval = 0;
143     if (local_port)
144         retval = krb5_copy_addr(context,
145                                 local_port,
146                                 &auth_context->local_port);
147     else
148         auth_context->local_port = NULL;
149
150     if (!retval && remote_port)
151         retval = krb5_copy_addr(context,
152                                 remote_port,
153                                 &auth_context->remote_port);
154     else
155         auth_context->remote_port = NULL;
156
157     return retval;
158 }
159
160
161 /*
162  * This function overloads the keyblock field. It is only useful prior to
163  * a krb5_rd_req_decode() call for user to user authentication where the
164  * server has the key and needs to use it to decrypt the incoming request.
165  * Once decrypted this key is no longer necessary and is then overwritten
166  * with the session key sent by the client.
167  */
168 krb5_error_code KRB5_CALLCONV
169 krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock)
170 {
171     if (auth_context->key)
172         krb5_k_free_key(context, auth_context->key);
173     return(krb5_k_create_key(context, keyblock, &(auth_context->key)));
174 }
175
176 krb5_error_code KRB5_CALLCONV
177 krb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
178 {
179     if (auth_context->key)
180         return krb5_k_key_keyblock(context, auth_context->key, keyblock);
181     *keyblock = NULL;
182     return 0;
183 }
184
185 krb5_error_code KRB5_CALLCONV
186 krb5_auth_con_getkey_k(krb5_context context, krb5_auth_context auth_context,
187                        krb5_key *key)
188 {
189     krb5_k_reference_key(context, auth_context->key);
190     *key = auth_context->key;
191     return 0;
192 }
193
194 krb5_error_code KRB5_CALLCONV
195 krb5_auth_con_getlocalsubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
196 {
197     return krb5_auth_con_getsendsubkey(context, auth_context, keyblock);
198 }
199
200 krb5_error_code KRB5_CALLCONV
201 krb5_auth_con_getremotesubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
202 {
203     return krb5_auth_con_getrecvsubkey(context, auth_context, keyblock);
204 }
205
206 krb5_error_code KRB5_CALLCONV
207 krb5_auth_con_setsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
208 {
209     if (ac->send_subkey != NULL)
210         krb5_k_free_key(ctx, ac->send_subkey);
211     ac->send_subkey = NULL;
212     if (keyblock !=NULL)
213         return krb5_k_create_key(ctx, keyblock, &ac->send_subkey);
214     else
215         return 0;
216 }
217
218 krb5_error_code KRB5_CALLCONV
219 krb5_auth_con_setsendsubkey_k(krb5_context ctx, krb5_auth_context ac,
220                               krb5_key key)
221 {
222     krb5_k_free_key(ctx, ac->send_subkey);
223     ac->send_subkey = key;
224     krb5_k_reference_key(ctx, key);
225     return 0;
226 }
227
228 krb5_error_code KRB5_CALLCONV
229 krb5_auth_con_setrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
230 {
231     if (ac->recv_subkey != NULL)
232         krb5_k_free_key(ctx, ac->recv_subkey);
233     ac->recv_subkey = NULL;
234     if (keyblock != NULL)
235         return krb5_k_create_key(ctx, keyblock, &ac->recv_subkey);
236     else
237         return 0;
238 }
239
240 krb5_error_code KRB5_CALLCONV
241 krb5_auth_con_setrecvsubkey_k(krb5_context ctx, krb5_auth_context ac,
242                               krb5_key key)
243 {
244     krb5_k_free_key(ctx, ac->recv_subkey);
245     ac->recv_subkey = key;
246     krb5_k_reference_key(ctx, key);
247     return 0;
248 }
249
250 krb5_error_code KRB5_CALLCONV
251 krb5_auth_con_getsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
252 {
253     if (ac->send_subkey != NULL)
254         return krb5_k_key_keyblock(ctx, ac->send_subkey, keyblock);
255     *keyblock = NULL;
256     return 0;
257 }
258
259 krb5_error_code KRB5_CALLCONV
260 krb5_auth_con_getsendsubkey_k(krb5_context ctx, krb5_auth_context ac,
261                               krb5_key *key)
262 {
263     krb5_k_reference_key(ctx, ac->send_subkey);
264     *key = ac->send_subkey;
265     return 0;
266 }
267
268 krb5_error_code KRB5_CALLCONV
269 krb5_auth_con_getrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
270 {
271     if (ac->recv_subkey != NULL)
272         return krb5_k_key_keyblock(ctx, ac->recv_subkey, keyblock);
273     *keyblock = NULL;
274     return 0;
275 }
276
277 krb5_error_code KRB5_CALLCONV
278 krb5_auth_con_getrecvsubkey_k(krb5_context ctx, krb5_auth_context ac,
279                               krb5_key *key)
280 {
281     krb5_k_reference_key(ctx, ac->recv_subkey);
282     *key = ac->recv_subkey;
283     return 0;
284 }
285
286 krb5_error_code KRB5_CALLCONV
287 krb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
288 {
289     auth_context->req_cksumtype = cksumtype;
290     return 0;
291 }
292
293 krb5_error_code
294 krb5_auth_con_set_safe_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
295 {
296     auth_context->safe_cksumtype = cksumtype;
297     return 0;
298 }
299
300 krb5_error_code KRB5_CALLCONV
301 krb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
302 {
303     *seqnumber = auth_context->local_seq_number;
304     return 0;
305 }
306
307 krb5_error_code KRB5_CALLCONV
308 krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
309 {
310     *seqnumber = auth_context->remote_seq_number;
311     return 0;
312 }
313
314 krb5_error_code KRB5_CALLCONV
315 krb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context)
316 {
317     if (auth_context->key == NULL)
318         return EINVAL;
319     return krb5_c_init_state(context, &auth_context->key->keyblock,
320                              KRB5_KEYUSAGE_KRB_PRIV_ENCPART,
321                              &auth_context->cstate);
322 }
323
324 krb5_error_code
325 krb5_auth_con_setivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer ivector)
326 {
327     /*
328      * This function was part of the pre-1.2.2 API.  Because it aliased the
329      * caller's memory into auth_context, and doesn't provide the size of the
330      * cipher state, it's inconvenient to support now, so return an error.
331      */
332     return EINVAL;
333 }
334
335 krb5_error_code
336 krb5_auth_con_getivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer *ivector)
337 {
338     *ivector = auth_context->cstate.data;
339     return 0;
340 }
341
342 krb5_error_code KRB5_CALLCONV
343 krb5_auth_con_setflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 flags)
344 {
345     auth_context->auth_context_flags = flags;
346     return 0;
347 }
348
349 krb5_error_code KRB5_CALLCONV
350 krb5_auth_con_getflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 *flags)
351 {
352     *flags = auth_context->auth_context_flags;
353     return 0;
354 }
355
356 krb5_error_code KRB5_CALLCONV
357 krb5_auth_con_setrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache rcache)
358 {
359     auth_context->rcache = rcache;
360     return 0;
361 }
362
363 krb5_error_code
364 krb5_auth_con_getrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache *rcache)
365 {
366     *rcache = auth_context->rcache;
367     return 0;
368 }
369
370 krb5_error_code
371 krb5_auth_con_setpermetypes(krb5_context context,
372                             krb5_auth_context auth_context,
373                             const krb5_enctype *permetypes)
374 {
375     krb5_enctype *newpe;
376     krb5_error_code ret;
377
378     ret = k5_copy_etypes(permetypes, &newpe);
379     if (ret != 0)
380         return ret;
381
382     free(auth_context->permitted_etypes);
383     auth_context->permitted_etypes = newpe;
384     return 0;
385 }
386
387 krb5_error_code
388 krb5_auth_con_getpermetypes(krb5_context context,
389                             krb5_auth_context auth_context,
390                             krb5_enctype **permetypes)
391 {
392     *permetypes = NULL;
393     if (auth_context->permitted_etypes == NULL)
394         return 0;
395     return k5_copy_etypes(auth_context->permitted_etypes, permetypes);
396 }
397
398 krb5_error_code KRB5_CALLCONV
399 krb5_auth_con_set_checksum_func( krb5_context context,
400                                  krb5_auth_context  auth_context,
401                                  krb5_mk_req_checksum_func func,
402                                  void *data)
403 {
404     auth_context->checksum_func = func;
405     auth_context->checksum_func_data = data;
406     return 0;
407 }
408
409 krb5_error_code KRB5_CALLCONV
410 krb5_auth_con_get_checksum_func( krb5_context context,
411                                  krb5_auth_context auth_context,
412                                  krb5_mk_req_checksum_func *func,
413                                  void **data)
414 {
415     *func = auth_context->checksum_func;
416     *data = auth_context->checksum_func_data;
417     return 0;
418 }
419
420 krb5_error_code
421 krb5_auth_con_get_subkey_enctype(krb5_context context,
422                                  krb5_auth_context auth_context,
423                                  krb5_enctype *etype)
424 {
425     *etype = auth_context->negotiated_etype;
426     return 0;
427 }
428
429 krb5_error_code
430 krb5_auth_con_get_authdata_context(krb5_context context,
431                                    krb5_auth_context auth_context,
432                                    krb5_authdata_context *ad_context)
433 {
434     *ad_context = auth_context->ad_context;
435     return 0;
436 }
437
438 krb5_error_code
439 krb5_auth_con_set_authdata_context(krb5_context context,
440                                    krb5_auth_context auth_context,
441                                    krb5_authdata_context ad_context)
442 {
443     auth_context->ad_context = ad_context;
444     return 0;
445 }