Branch data Line data Source code
1 : : /* as.c --- High level client AS functions
2 : : * Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008, 2010 Simon Josefsson
3 : : *
4 : : * This file is part of Shishi.
5 : : *
6 : : * Shishi is free software; you can redistribute it and/or modify it it
7 : : * under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation; either version 3 of the License, or
9 : : * (at your option) any later version.
10 : : *
11 : : * Shishi is distributed in the hope that it will be useful, but but
12 : : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with Shishi; if not, see http://www.gnu.org/licenses or write
18 : : * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19 : : * Floor, Boston, MA 02110-1301, USA
20 : : *
21 : : */
22 : :
23 : : #include "internal.h"
24 : :
25 : : struct Shishi_as
26 : : {
27 : : Shishi *handle;
28 : : Shishi_asn1 asreq;
29 : : Shishi_asn1 asrep;
30 : : Shishi_asn1 krberror;
31 : : Shishi_tkt *tkt;
32 : : };
33 : :
34 : : /**
35 : : * shishi_as:
36 : : * @handle: shishi handle as allocated by shishi_init().
37 : : * @as: holds pointer to newly allocate Shishi_as structure.
38 : : *
39 : : * Allocate a new AS exchange variable.
40 : : *
41 : : * Return value: Returns SHISHI_OK iff successful.
42 : : **/
43 : : int
44 : 0 : shishi_as (Shishi * handle, Shishi_as ** as)
45 : : {
46 : : Shishi_as *las;
47 : : int res;
48 : :
49 : 0 : *as = xmalloc (sizeof (**as));
50 : 0 : las = *as;
51 : 0 : memset (las, 0, sizeof (*las));
52 : :
53 : 0 : las->handle = handle;
54 : :
55 : 0 : las->asreq = shishi_asreq (handle);
56 [ # # ]: 0 : if (las->asreq == NULL)
57 : : {
58 : 0 : shishi_error_printf (handle, "Could not create AS-REQ: %s\n",
59 : : shishi_error (handle));
60 : 0 : return SHISHI_ASN1_ERROR;
61 : : }
62 : :
63 : 0 : las->asrep = shishi_asrep (handle);
64 [ # # ]: 0 : if (las->asrep == NULL)
65 : : {
66 : 0 : shishi_error_printf (handle, "Could not create AS-REP: %s\n",
67 : : shishi_error (handle));
68 : 0 : return SHISHI_ASN1_ERROR;
69 : : }
70 : :
71 : 0 : las->krberror = shishi_krberror (handle);
72 [ # # ]: 0 : if (las->krberror == NULL)
73 : : {
74 : 0 : shishi_error_printf (handle, "Could not create KRB-ERROR: %s\n",
75 : : shishi_error (handle));
76 : 0 : return SHISHI_ASN1_ERROR;
77 : : }
78 : :
79 : 0 : res = shishi_tkt (handle, &las->tkt);
80 [ # # ]: 0 : if (res != SHISHI_OK)
81 : 0 : return res;
82 : :
83 : 0 : res = shishi_tkt_flags_set (las->tkt, SHISHI_TICKETFLAGS_INITIAL);
84 [ # # ]: 0 : if (res != SHISHI_OK)
85 : 0 : return res;
86 : :
87 : 0 : return SHISHI_OK;
88 : : }
89 : :
90 : : /**
91 : : * shishi_as_done:
92 : : * @as: structure that holds information about AS exchange
93 : : *
94 : : * Deallocate resources associated with AS exchange. This should be
95 : : * called by the application when it no longer need to utilize the AS
96 : : * exchange handle.
97 : : **/
98 : : void
99 : 0 : shishi_as_done (Shishi_as * as)
100 : : {
101 : 0 : shishi_asn1_done (as->handle, as->asreq);
102 : 0 : shishi_asn1_done (as->handle, as->asrep);
103 : 0 : shishi_asn1_done (as->handle, as->krberror);
104 : 0 : shishi_tkt_done (as->tkt);
105 : 0 : free (as);
106 : 0 : }
107 : :
108 : : /* TODO: add shishi_as_clientserver(h,p,a,client,server) and make the
109 : : shishi_as_cnamerealmsname function take real cname/sname pointer
110 : : arrays. */
111 : :
112 : : /**
113 : : * shishi_as_req:
114 : : * @as: structure that holds information about AS exchange
115 : : *
116 : : * Get ASN.1 AS-REQ structure from AS exchange.
117 : : *
118 : : * Return value: Returns the generated AS-REQ packet from the AS
119 : : * exchange, or NULL if not yet set or an error occured.
120 : : **/
121 : : Shishi_asn1
122 : 0 : shishi_as_req (Shishi_as * as)
123 : : {
124 : 0 : return as->asreq;
125 : : }
126 : :
127 : : /**
128 : : * shishi_as_req_build:
129 : : * @as: structure that holds information about AS exchange
130 : : *
131 : : * Possibly remove unset fields (e.g., rtime).
132 : : *
133 : : * Return value: Returns SHISHI_OK iff successful.
134 : : **/
135 : : int
136 : 0 : shishi_as_req_build (Shishi_as * as)
137 : : {
138 : : int res;
139 : :
140 : 0 : res = shishi_kdcreq_build (as->handle, as->asreq);
141 [ # # ]: 0 : if (res != SHISHI_OK)
142 : 0 : return res;
143 : :
144 : 0 : return SHISHI_OK;
145 : : }
146 : :
147 : : /**
148 : : * shishi_as_req_set:
149 : : * @as: structure that holds information about AS exchange
150 : : * @asreq: asreq to store in AS.
151 : : *
152 : : * Set the AS-REQ in the AS exchange.
153 : : **/
154 : : void
155 : 0 : shishi_as_req_set (Shishi_as * as, Shishi_asn1 asreq)
156 : : {
157 [ # # ]: 0 : if (as->asreq)
158 : 0 : shishi_asn1_done (as->handle, as->asreq);
159 : 0 : as->asreq = asreq;
160 : 0 : }
161 : :
162 : : /**
163 : : * shishi_as_req_der:
164 : : * @as: structure that holds information about AS exchange
165 : : * @out: output array with newly allocated DER encoding of AS-REQ.
166 : : * @outlen: length of output array with DER encoding of AS-REQ.
167 : : *
168 : : * DER encode AS-REQ. @out is allocated by this function, and it is
169 : : * the responsibility of caller to deallocate it.
170 : : *
171 : : * Return value: Returns SHISHI_OK iff successful.
172 : : **/
173 : : int
174 : 0 : shishi_as_req_der (Shishi_as * as, char **out, size_t * outlen)
175 : : {
176 : : int rc;
177 : :
178 : 0 : rc = shishi_asn1_to_der (as->handle, as->asreq, out, outlen);
179 [ # # ]: 0 : if (rc != SHISHI_OK)
180 : 0 : return rc;
181 : :
182 : 0 : return SHISHI_OK;
183 : : }
184 : :
185 : : /**
186 : : * shishi_as_req_der_set:
187 : : * @as: structure that holds information about AS exchange
188 : : * @der: input array with DER encoded AP-REQ.
189 : : * @derlen: length of input array with DER encoded AP-REQ.
190 : : *
191 : : * DER decode AS-REQ and set it AS exchange. If decoding fails, the
192 : : * AS-REQ in the AS exchange remains.
193 : : *
194 : : * Return value: Returns SHISHI_OK.
195 : : **/
196 : : int
197 : 0 : shishi_as_req_der_set (Shishi_as * as, char *der, size_t derlen)
198 : : {
199 : : Shishi_asn1 asreq;
200 : :
201 : 0 : asreq = shishi_der2asn1_asreq (as->handle, der, derlen);
202 : :
203 [ # # ]: 0 : if (asreq == NULL)
204 : 0 : return SHISHI_ASN1_ERROR;
205 : :
206 : 0 : as->asreq = asreq;
207 : :
208 : 0 : return SHISHI_OK;
209 : : }
210 : :
211 : : /**
212 : : * shishi_as_rep:
213 : : * @as: structure that holds information about AS exchange
214 : : *
215 : : * Get ASN.1 AS-REP structure from AS exchange.
216 : : *
217 : : * Return value: Returns the received AS-REP packet from the AS
218 : : * exchange, or NULL if not yet set or an error occured.
219 : : **/
220 : : Shishi_asn1
221 : 0 : shishi_as_rep (Shishi_as * as)
222 : : {
223 : 0 : return as->asrep;
224 : : }
225 : :
226 : : /**
227 : : * shishi_as_rep_process:
228 : : * @as: structure that holds information about AS exchange
229 : : * @key: user's key, used to encrypt the encrypted part of the AS-REP.
230 : : * @password: user's password, used if key is NULL.
231 : : *
232 : : * Process new AS-REP and set ticket. The key is used to decrypt the
233 : : * AP-REP. If both key and password is NULL, the user is queried for
234 : : * it.
235 : : *
236 : : * Return value: Returns SHISHI_OK iff successful.
237 : : **/
238 : : int
239 : 0 : shishi_as_rep_process (Shishi_as * as, Shishi_key * key, const char *password)
240 : : {
241 : : Shishi_asn1 ticket, kdcreppart;
242 : : int res;
243 : :
244 [ # # ]: 0 : if (VERBOSE (as->handle))
245 : 0 : printf ("Processing AS-REQ and AS-REP...\n");
246 : :
247 [ # # ]: 0 : if (VERBOSEASN1 (as->handle))
248 : 0 : shishi_kdcreq_print (as->handle, stdout, as->asreq);
249 : :
250 [ # # ]: 0 : if (VERBOSEASN1 (as->handle))
251 : 0 : shishi_kdcrep_print (as->handle, stdout, as->asrep);
252 : :
253 [ # # ][ # # ]: 0 : if (key == NULL && password == NULL)
254 : : {
255 : : char *passwd;
256 : : char *user;
257 : : size_t userlen;
258 : :
259 : 0 : res = shishi_asreq_clientrealm (as->handle, as->asreq, &user, &userlen);
260 [ # # ]: 0 : if (res != SHISHI_OK)
261 : : {
262 : 0 : shishi_error_printf (as->handle, "Could not extract cname and "
263 : : "realm from AS-REQ: %s\n",
264 : : shishi_strerror (res));
265 : 0 : return res;
266 : : }
267 : :
268 : 0 : res = shishi_prompt_password (as->handle, &passwd,
269 : : "Enter password for `%s': ", user);
270 : 0 : free (user);
271 [ # # ]: 0 : if (res != SHISHI_OK)
272 : : {
273 : 0 : shishi_error_printf (as->handle, "Reading password failed: %s\n",
274 : : shishi_strerror (res));
275 : 0 : return res;
276 : : }
277 : :
278 : 0 : res = shishi_as_process (as->handle, as->asreq, as->asrep,
279 : : passwd, &kdcreppart);
280 : 0 : free (passwd);
281 : : }
282 [ # # ]: 0 : else if (key == NULL)
283 : 0 : res = shishi_as_process (as->handle, as->asreq, as->asrep,
284 : : password, &kdcreppart);
285 : : else
286 : 0 : res = shishi_kdc_process (as->handle, as->asreq, as->asrep, key,
287 : : SHISHI_KEYUSAGE_ENCASREPPART, &kdcreppart);
288 [ # # ]: 0 : if (res != SHISHI_OK)
289 : 0 : return res;
290 : :
291 [ # # ]: 0 : if (VERBOSE (as->handle))
292 : 0 : printf ("Got EncKDCRepPart...\n");
293 : :
294 [ # # ]: 0 : if (VERBOSEASN1 (as->handle))
295 : 0 : shishi_enckdcreppart_print (as->handle, stdout, kdcreppart);
296 : :
297 : 0 : res = shishi_kdcrep_get_ticket (as->handle, as->asrep, &ticket);
298 [ # # ]: 0 : if (res != SHISHI_OK)
299 : : {
300 : 0 : shishi_error_printf (as->handle,
301 : : "Could not extract ticket from AS-REP: %s",
302 : : shishi_error (as->handle));
303 : 0 : return res;
304 : : }
305 : :
306 [ # # ]: 0 : if (VERBOSE (as->handle))
307 : 0 : printf ("Got Ticket...\n");
308 : :
309 [ # # ]: 0 : if (VERBOSEASN1 (as->handle))
310 : 0 : shishi_ticket_print (as->handle, stdout, ticket);
311 : :
312 : : /* XXX */
313 : 0 : as->tkt = shishi_tkt2 (as->handle, ticket, kdcreppart, as->asrep);
314 : :
315 : 0 : return SHISHI_OK;
316 : : }
317 : :
318 : : /**
319 : : * shishi_as_rep_build:
320 : : * @as: structure that holds information about AS exchange
321 : : * @key: user's key, used to encrypt the encrypted part of the AS-REP.
322 : : *
323 : : * Build AS-REP.
324 : : *
325 : : * Return value: Returns SHISHI_OK iff successful.
326 : : **/
327 : : int
328 : 0 : shishi_as_rep_build (Shishi_as * as, Shishi_key * key)
329 : : {
330 : : int rc;
331 : :
332 : : /* XXX there are reasons for having padata in AS-REP */
333 : 0 : rc = shishi_kdcrep_clear_padata (as->handle, as->asrep);
334 [ # # ]: 0 : if (rc != SHISHI_OK)
335 : 0 : return rc;
336 : :
337 : 0 : rc = shishi_enckdcreppart_populate_encticketpart
338 : : (as->handle, shishi_tkt_enckdcreppart (as->tkt),
339 : : shishi_tkt_encticketpart (as->tkt));
340 [ # # ]: 0 : if (rc != SHISHI_OK)
341 : 0 : return rc;
342 : :
343 : 0 : rc = shishi_kdc_copy_nonce (as->handle, as->asreq,
344 : : shishi_tkt_enckdcreppart (as->tkt));
345 [ # # ]: 0 : if (rc != SHISHI_OK)
346 : 0 : return rc;
347 : :
348 : 0 : rc = shishi_kdcrep_add_enc_part (as->handle,
349 : : as->asrep,
350 : : key,
351 : : SHISHI_KEYUSAGE_ENCASREPPART,
352 : : shishi_tkt_enckdcreppart (as->tkt));
353 [ # # ]: 0 : if (rc != SHISHI_OK)
354 : 0 : return rc;
355 : :
356 : 0 : rc = shishi_kdcrep_set_ticket (as->handle, as->asrep,
357 : : shishi_tkt_ticket (as->tkt));
358 [ # # ]: 0 : if (rc != SHISHI_OK)
359 : 0 : return rc;
360 : :
361 : 0 : rc = shishi_kdc_copy_crealm (as->handle, as->asrep,
362 : : shishi_tkt_encticketpart (as->tkt));
363 [ # # ]: 0 : if (rc != SHISHI_OK)
364 : 0 : return rc;
365 : :
366 : 0 : rc = shishi_kdc_copy_cname (as->handle, as->asrep,
367 : : shishi_tkt_encticketpart (as->tkt));
368 [ # # ]: 0 : if (rc != SHISHI_OK)
369 : 0 : return rc;
370 : :
371 : 0 : return SHISHI_OK;
372 : : }
373 : :
374 : : /**
375 : : * shishi_as_rep_der:
376 : : * @as: structure that holds information about AS exchange
377 : : * @out: output array with newly allocated DER encoding of AS-REP.
378 : : * @outlen: length of output array with DER encoding of AS-REP.
379 : : *
380 : : * DER encode AS-REP. @out is allocated by this function, and it is
381 : : * the responsibility of caller to deallocate it.
382 : : *
383 : : * Return value: Returns SHISHI_OK iff successful.
384 : : **/
385 : : int
386 : 0 : shishi_as_rep_der (Shishi_as * as, char **out, size_t * outlen)
387 : : {
388 : : int rc;
389 : :
390 : 0 : rc = shishi_asn1_to_der (as->handle, as->asrep, out, outlen);
391 [ # # ]: 0 : if (rc != SHISHI_OK)
392 : 0 : return rc;
393 : :
394 : 0 : return SHISHI_OK;
395 : : }
396 : :
397 : : /**
398 : : * shishi_as_rep_set:
399 : : * @as: structure that holds information about AS exchange
400 : : * @asrep: asrep to store in AS.
401 : : *
402 : : * Set the AS-REP in the AS exchange.
403 : : **/
404 : : void
405 : 0 : shishi_as_rep_set (Shishi_as * as, Shishi_asn1 asrep)
406 : : {
407 [ # # ]: 0 : if (as->asrep)
408 : 0 : shishi_asn1_done (as->handle, as->asrep);
409 : 0 : as->asrep = asrep;
410 : 0 : }
411 : :
412 : : /**
413 : : * shishi_as_rep_der_set:
414 : : * @as: structure that holds information about AS exchange
415 : : * @der: input array with DER encoded AP-REP.
416 : : * @derlen: length of input array with DER encoded AP-REP.
417 : : *
418 : : * DER decode AS-REP and set it AS exchange. If decoding fails, the
419 : : * AS-REP in the AS exchange remains.
420 : : *
421 : : * Return value: Returns SHISHI_OK.
422 : : **/
423 : : int
424 : 0 : shishi_as_rep_der_set (Shishi_as * as, char *der, size_t derlen)
425 : : {
426 : : Shishi_asn1 asrep;
427 : :
428 : 0 : asrep = shishi_der2asn1_asrep (as->handle, der, derlen);
429 : :
430 [ # # ]: 0 : if (asrep == NULL)
431 : 0 : return SHISHI_ASN1_ERROR;
432 : :
433 : 0 : as->asrep = asrep;
434 : :
435 : 0 : return SHISHI_OK;
436 : : }
437 : :
438 : : /**
439 : : * shishi_as_krberror:
440 : : * @as: structure that holds information about AS exchange
441 : : *
442 : : * Get ASN.1 KRB-ERROR structure from AS exchange.
443 : : *
444 : : * Return value: Returns the received KRB-ERROR packet from the AS
445 : : * exchange, or NULL if not yet set or an error occured.
446 : : **/
447 : : Shishi_asn1
448 : 0 : shishi_as_krberror (Shishi_as * as)
449 : : {
450 : 0 : return as->krberror;
451 : : }
452 : :
453 : : /**
454 : : * shishi_as_krberror_der:
455 : : * @as: structure that holds information about AS exchange
456 : : * @out: output array with newly allocated DER encoding of KRB-ERROR.
457 : : * @outlen: length of output array with DER encoding of KRB-ERROR.
458 : : *
459 : : * DER encode KRB-ERROR. @out is allocated by this function, and it is
460 : : * the responsibility of caller to deallocate it.
461 : : *
462 : : * Return value: Returns SHISHI_OK iff successful.
463 : : **/
464 : : int
465 : 0 : shishi_as_krberror_der (Shishi_as * as, char **out, size_t * outlen)
466 : : {
467 : : int rc;
468 : :
469 : 0 : rc = shishi_krberror_der (as->handle, as->krberror, out, outlen);
470 [ # # ]: 0 : if (rc != SHISHI_OK)
471 : 0 : return rc;
472 : :
473 : 0 : return SHISHI_OK;
474 : : }
475 : :
476 : : /**
477 : : * shishi_as_krberror_set:
478 : : * @as: structure that holds information about AS exchange
479 : : * @krberror: krberror to store in AS.
480 : : *
481 : : * Set the KRB-ERROR in the AS exchange.
482 : : **/
483 : : void
484 : 0 : shishi_as_krberror_set (Shishi_as * as, Shishi_asn1 krberror)
485 : : {
486 [ # # ]: 0 : if (as->krberror)
487 : 0 : shishi_asn1_done (as->handle, as->krberror);
488 : 0 : as->krberror = krberror;
489 : 0 : }
490 : :
491 : : /**
492 : : * shishi_as_tkt:
493 : : * @as: structure that holds information about AS exchange
494 : : *
495 : : * Get Ticket in AS exchange.
496 : : *
497 : : * Return value: Returns the newly acquired tkt from the AS
498 : : * exchange, or NULL if not yet set or an error occured.
499 : : **/
500 : : Shishi_tkt *
501 : 0 : shishi_as_tkt (Shishi_as * as)
502 : : {
503 : 0 : return as->tkt;
504 : : }
505 : :
506 : : /**
507 : : * shishi_as_tkt_set:
508 : : * @as: structure that holds information about AS exchange
509 : : * @tkt: tkt to store in AS.
510 : : *
511 : : * Set the Tkt in the AS exchange.
512 : : **/
513 : : void
514 : 0 : shishi_as_tkt_set (Shishi_as * as, Shishi_tkt * tkt)
515 : : {
516 : 0 : as->tkt = tkt;
517 : 0 : }
518 : :
519 : : /**
520 : : * shishi_as_sendrecv_hint:
521 : : * @as: structure that holds information about AS exchange
522 : : * @hint: additional parameters that modify connection behaviour, or %NULL.
523 : : *
524 : : * Send AS-REQ and receive AS-REP or KRB-ERROR. This is the initial
525 : : * authentication, usually used to acquire a Ticket Granting Ticket.
526 : : * The @hint structure can be used to set, e.g., parameters for TLS
527 : : * authentication.
528 : : *
529 : : * Return value: Returns SHISHI_OK iff successful.
530 : : **/
531 : : int
532 : 0 : shishi_as_sendrecv_hint (Shishi_as * as, Shishi_tkts_hint * hint)
533 : : {
534 : : int res;
535 : :
536 [ # # ]: 0 : if (VERBOSE (as->handle))
537 : 0 : printf ("Sending AS-REQ...\n");
538 : :
539 [ # # ]: 0 : if (VERBOSEASN1 (as->handle))
540 : 0 : shishi_kdcreq_print (as->handle, stdout, as->asreq);
541 : :
542 : 0 : res = shishi_kdcreq_sendrecv_hint (as->handle, as->asreq, &as->asrep, hint);
543 [ # # ]: 0 : if (res == SHISHI_GOT_KRBERROR)
544 : : {
545 : 0 : as->krberror = as->asrep;
546 : 0 : as->asrep = NULL;
547 : :
548 [ # # ]: 0 : if (VERBOSE (as->handle))
549 : 0 : printf ("Received KRB-ERROR...\n");
550 [ # # ]: 0 : if (VERBOSEASN1 (as->handle))
551 : 0 : shishi_krberror_print (as->handle, stdout, as->krberror);
552 [ # # ]: 0 : if (VERBOSEASN1 (as->handle))
553 : 0 : shishi_krberror_pretty_print (as->handle, stdout, as->krberror);
554 : : }
555 [ # # ]: 0 : if (res != SHISHI_OK)
556 : 0 : return res;
557 : :
558 [ # # ]: 0 : if (VERBOSE (as->handle))
559 : 0 : printf ("Received AS-REP...\n");
560 : :
561 [ # # ]: 0 : if (VERBOSEASN1 (as->handle))
562 : 0 : shishi_kdcrep_print (as->handle, stdout, as->asrep);
563 : :
564 : 0 : return SHISHI_OK;
565 : : }
566 : :
567 : : /**
568 : : * shishi_as_sendrecv:
569 : : * @as: structure that holds information about AS exchange
570 : : *
571 : : * Send AS-REQ and receive AS-REP or KRB-ERROR. This is the initial
572 : : * authentication, usually used to acquire a Ticket Granting Ticket.
573 : : *
574 : : * Return value: Returns SHISHI_OK iff successful.
575 : : **/
576 : : int
577 : 0 : shishi_as_sendrecv (Shishi_as * as)
578 : : {
579 : 0 : return shishi_as_sendrecv_hint (as, NULL);
580 : : }
|