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
krb5_auth_con_init(krb5_context context,krb5_auth_context * auth_context)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
krb5_auth_con_free(krb5_context context,krb5_auth_context auth_context)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
krb5_auth_con_setaddrs(krb5_context context,krb5_auth_context auth_context,krb5_address * local_addr,krb5_address * remote_addr)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
krb5_auth_con_getaddrs(krb5_context context,krb5_auth_context auth_context,krb5_address ** local_addr,krb5_address ** remote_addr)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
krb5_auth_con_setports(krb5_context context,krb5_auth_context auth_context,krb5_address * local_port,krb5_address * remote_port)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
krb5_auth_con_setuseruserkey(krb5_context context,krb5_auth_context auth_context,krb5_keyblock * keyblock)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
krb5_auth_con_getkey(krb5_context context,krb5_auth_context auth_context,krb5_keyblock ** keyblock)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
krb5_auth_con_getkey_k(krb5_context context,krb5_auth_context auth_context,krb5_key * key)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
krb5_auth_con_getlocalsubkey(krb5_context context,krb5_auth_context auth_context,krb5_keyblock ** keyblock)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
krb5_auth_con_getremotesubkey(krb5_context context,krb5_auth_context auth_context,krb5_keyblock ** keyblock)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
krb5_auth_con_setsendsubkey(krb5_context ctx,krb5_auth_context ac,krb5_keyblock * keyblock)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
krb5_auth_con_setsendsubkey_k(krb5_context ctx,krb5_auth_context ac,krb5_key key)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
krb5_auth_con_setrecvsubkey(krb5_context ctx,krb5_auth_context ac,krb5_keyblock * keyblock)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
krb5_auth_con_setrecvsubkey_k(krb5_context ctx,krb5_auth_context ac,krb5_key key)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
krb5_auth_con_getsendsubkey(krb5_context ctx,krb5_auth_context ac,krb5_keyblock ** keyblock)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
krb5_auth_con_getsendsubkey_k(krb5_context ctx,krb5_auth_context ac,krb5_key * key)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
krb5_auth_con_getrecvsubkey(krb5_context ctx,krb5_auth_context ac,krb5_keyblock ** keyblock)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
krb5_auth_con_getrecvsubkey_k(krb5_context ctx,krb5_auth_context ac,krb5_key * key)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
krb5_auth_con_set_req_cksumtype(krb5_context context,krb5_auth_context auth_context,krb5_cksumtype cksumtype)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
krb5_auth_con_set_safe_cksumtype(krb5_context context,krb5_auth_context auth_context,krb5_cksumtype cksumtype)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
krb5_auth_con_getlocalseqnumber(krb5_context context,krb5_auth_context auth_context,krb5_int32 * seqnumber)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
krb5_auth_con_getremoteseqnumber(krb5_context context,krb5_auth_context auth_context,krb5_int32 * seqnumber)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
krb5_auth_con_initivector(krb5_context context,krb5_auth_context auth_context)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
krb5_auth_con_setivector(krb5_context context,krb5_auth_context auth_context,krb5_pointer ivector)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
krb5_auth_con_getivector(krb5_context context,krb5_auth_context auth_context,krb5_pointer * ivector)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
krb5_auth_con_setflags(krb5_context context,krb5_auth_context auth_context,krb5_int32 flags)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
krb5_auth_con_getflags(krb5_context context,krb5_auth_context auth_context,krb5_int32 * flags)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
krb5_auth_con_setrcache(krb5_context context,krb5_auth_context auth_context,krb5_rcache rcache)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
krb5_auth_con_getrcache(krb5_context context,krb5_auth_context auth_context,krb5_rcache * rcache)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
krb5_auth_con_setpermetypes(krb5_context context,krb5_auth_context auth_context,const krb5_enctype * permetypes)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
krb5_auth_con_getpermetypes(krb5_context context,krb5_auth_context auth_context,krb5_enctype ** permetypes)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
krb5_auth_con_set_checksum_func(krb5_context context,krb5_auth_context auth_context,krb5_mk_req_checksum_func func,void * data)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
krb5_auth_con_get_checksum_func(krb5_context context,krb5_auth_context auth_context,krb5_mk_req_checksum_func * func,void ** data)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
krb5_auth_con_get_subkey_enctype(krb5_context context,krb5_auth_context auth_context,krb5_enctype * etype)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
krb5_auth_con_get_authdata_context(krb5_context context,krb5_auth_context auth_context,krb5_authdata_context * ad_context)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
krb5_auth_con_set_authdata_context(krb5_context context,krb5_auth_context auth_context,krb5_authdata_context ad_context)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 }
446