1 /* kdcreq.c --- Key distribution (AS/TGS) request functions.
2 * Copyright (C) 2002-2013 Simon Josefsson
3 *
4 * This file is part of Shishi.
5 *
6 * Shishi is free software; you can redistribute it and/or modify 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
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU 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 /* Get _shishi_print_armored_data, etc. */
26 #include "diskio.h"
27
28 #define SHISHI_KDCREQ_DEFAULT_PVNO "5"
29 #define SHISHI_KDCREQ_DEFAULT_PVNO_LEN 0
30 #define SHISHI_AS_REQ_DEFAULT_MSG_TYPE "10"
31 #define SHISHI_AS_REQ_DEFAULT_MSG_TYPE_LEN 0
32 #define SHISHI_TGS_REQ_DEFAULT_MSG_TYPE "12"
33 #define SHISHI_TGS_REQ_DEFAULT_MSG_TYPE_LEN 0
34 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS "\x00\x00\x00\x00"
35 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS_LEN 32
36 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE "1" /* SHISHI_NT_PRINCIPAL */
37 #define SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE_LEN 0
38
39 static Shishi_asn1
_shishi_kdcreq(Shishi * handle,int as)40 _shishi_kdcreq (Shishi * handle, int as)
41 {
42 int res;
43 Shishi_asn1 node;
44 const char *servicebuf[3];
45 uint32_t nonce;
46
47 if (as)
48 node = shishi_asn1_asreq (handle);
49 else
50 node = shishi_asn1_tgsreq (handle);
51 if (!node)
52 return NULL;
53
54 res = shishi_asn1_write (handle, node, "pvno",
55 SHISHI_KDCREQ_DEFAULT_PVNO,
56 SHISHI_KDCREQ_DEFAULT_PVNO_LEN);
57 if (res != SHISHI_OK)
58 goto error;
59
60 if (as)
61 res = shishi_asn1_write (handle, node, "msg-type",
62 SHISHI_AS_REQ_DEFAULT_MSG_TYPE,
63 SHISHI_AS_REQ_DEFAULT_MSG_TYPE_LEN);
64 else
65 res = shishi_asn1_write (handle, node, "msg-type",
66 SHISHI_TGS_REQ_DEFAULT_MSG_TYPE,
67 SHISHI_TGS_REQ_DEFAULT_MSG_TYPE_LEN);
68 if (res != SHISHI_OK)
69 goto error;
70
71 res = shishi_asn1_write (handle, node, "req-body.kdc-options",
72 SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS,
73 SHISHI_KDCREQ_DEFAULT_REQ_BODY_KDC_OPTIONS_LEN);
74 if (res != SHISHI_OK)
75 goto error;
76
77 if (as)
78 res = shishi_kdcreq_set_cname (handle, node, SHISHI_NT_PRINCIPAL,
79 shishi_principal_default (handle));
80 else
81 res = shishi_asn1_write (handle, node, "req-body.cname", NULL, 0);
82 if (res != SHISHI_OK)
83 goto error;
84
85 res = shishi_kdcreq_set_realm (handle, node, shishi_realm_default (handle));
86 if (res != SHISHI_OK)
87 goto error;
88
89 servicebuf[0] = "krbtgt";
90 servicebuf[1] = shishi_realm_default (handle);
91 servicebuf[2] = NULL;
92 res = shishi_kdcreq_set_sname (handle, node,
93 SHISHI_NT_PRINCIPAL, servicebuf);
94 if (res != SHISHI_OK)
95 goto error;
96
97 res = shishi_asn1_write (handle, node, "req-body.sname.name-type",
98 SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE,
99 SHISHI_KDCREQ_DEFAULT_REQ_BODY_SNAME_NAME_TYPE_LEN);
100 if (res != SHISHI_OK)
101 goto error;
102
103 res = shishi_asn1_write (handle, node, "req-body.till",
104 shishi_generalize_time (handle,
105 time (NULL) +
106 handle->ticketlife), 0);
107 if (res != SHISHI_OK)
108 goto error;
109
110 shishi_randomize (handle, 0, &nonce, sizeof (nonce));
111 nonce &= 0x7FFFFFFF; /* XXX fix _libtasn1_convert_integer. */
112 res = shishi_kdcreq_nonce_set (handle, node, nonce);
113 if (res != SHISHI_OK)
114 goto error;
115
116 res = shishi_kdcreq_set_etype (handle, node, handle->clientkdcetypes,
117 handle->nclientkdcetypes);
118 if (res != SHISHI_OK)
119 goto error;
120
121 res = shishi_asn1_write (handle, node, "req-body.addresses", NULL, 0);
122 if (res != SHISHI_OK)
123 goto error;
124
125 res = shishi_asn1_write (handle, node,
126 "req-body.enc-authorization-data", NULL, 0);
127 if (res != SHISHI_OK)
128 goto error;
129
130 res =
131 shishi_asn1_write (handle, node, "req-body.additional-tickets", NULL, 0);
132 if (res != SHISHI_OK)
133 goto error;
134
135 return node;
136
137 error:
138 shishi_asn1_done (handle, node);
139 return NULL;
140 }
141
142 /**
143 * shishi_asreq:
144 * @handle: shishi handle as allocated by shishi_init().
145 *
146 * This function creates a new AS-REQ, populated with some default
147 * values.
148 *
149 * Return value: Returns the AS-REQ or NULL on failure.
150 **/
151 Shishi_asn1
shishi_asreq(Shishi * handle)152 shishi_asreq (Shishi * handle)
153 {
154 return _shishi_kdcreq (handle, 1);
155 }
156
157 /**
158 * shishi_tgsreq:
159 * @handle: shishi handle as allocated by shishi_init().
160 *
161 * This function creates a new TGS-REQ, populated with some default
162 * values.
163 *
164 * Return value: Returns the TGS-REQ or NULL on failure.
165 **/
166 Shishi_asn1
shishi_tgsreq(Shishi * handle)167 shishi_tgsreq (Shishi * handle)
168 {
169 return _shishi_kdcreq (handle, 0);
170 }
171
172 /**
173 * shishi_kdcreq_print:
174 * @handle: shishi handle as allocated by shishi_init().
175 * @fh: file handle open for writing.
176 * @kdcreq: KDC-REQ to print.
177 *
178 * Print ASCII armored DER encoding of KDC-REQ to file.
179 *
180 * Return value: Returns SHISHI_OK iff successful.
181 **/
182 int
shishi_kdcreq_print(Shishi * handle,FILE * fh,Shishi_asn1 kdcreq)183 shishi_kdcreq_print (Shishi * handle, FILE * fh, Shishi_asn1 kdcreq)
184 {
185 return _shishi_print_armored_data (handle, fh, kdcreq, "KDC-REQ", NULL);
186 }
187
188 /**
189 * shishi_kdcreq_save:
190 * @handle: shishi handle as allocated by shishi_init().
191 * @fh: file handle open for writing.
192 * @kdcreq: KDC-REQ to save.
193 *
194 * Print DER encoding of KDC-REQ to file.
195 *
196 * Return value: Returns SHISHI_OK iff successful.
197 **/
198 int
shishi_kdcreq_save(Shishi * handle,FILE * fh,Shishi_asn1 kdcreq)199 shishi_kdcreq_save (Shishi * handle, FILE * fh, Shishi_asn1 kdcreq)
200 {
201 return _shishi_save_data (handle, fh, kdcreq, "KDC-REQ");
202 }
203
204 /**
205 * shishi_kdcreq_to_file:
206 * @handle: shishi handle as allocated by shishi_init().
207 * @kdcreq: KDC-REQ to save.
208 * @filetype: input variable specifying type of file to be written,
209 * see Shishi_filetype.
210 * @filename: input variable with filename to write to.
211 *
212 * Write KDC-REQ to file in specified TYPE. The file will be truncated
213 * if it exists.
214 *
215 * Return value: Returns SHISHI_OK iff successful.
216 **/
217 int
shishi_kdcreq_to_file(Shishi * handle,Shishi_asn1 kdcreq,int filetype,const char * filename)218 shishi_kdcreq_to_file (Shishi * handle, Shishi_asn1 kdcreq,
219 int filetype, const char *filename)
220 {
221 FILE *fh;
222 int res;
223
224 if (VERBOSE (handle))
225 printf (_("Writing KDC-REQ to %s...\n"), filename);
226
227 fh = fopen (filename, "w");
228 if (fh == NULL)
229 return SHISHI_FOPEN_ERROR;
230
231 if (VERBOSE (handle))
232 printf (_("Writing KDC-REQ in %s format...\n"),
233 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
234
235 if (filetype == SHISHI_FILETYPE_TEXT)
236 res = shishi_kdcreq_print (handle, fh, kdcreq);
237 else
238 res = shishi_kdcreq_save (handle, fh, kdcreq);
239 if (res != SHISHI_OK)
240 return res;
241
242 res = fclose (fh);
243 if (res != 0)
244 return SHISHI_IO_ERROR;
245
246 if (VERBOSE (handle))
247 printf (_("Writing KDC-REQ to %s...done\n"), filename);
248
249 return SHISHI_OK;
250 }
251
252 /**
253 * shishi_kdcreq_parse:
254 * @handle: shishi handle as allocated by shishi_init().
255 * @fh: file handle open for reading.
256 * @kdcreq: output variable with newly allocated KDC-REQ.
257 *
258 * Read ASCII armored DER encoded KDC-REQ from file and populate given
259 * variable.
260 *
261 * Return value: Returns SHISHI_OK iff successful.
262 **/
263 int
shishi_kdcreq_parse(Shishi * handle,FILE * fh,Shishi_asn1 * kdcreq)264 shishi_kdcreq_parse (Shishi * handle, FILE * fh, Shishi_asn1 * kdcreq)
265 {
266 return _shishi_kdcreq_input (handle, fh, kdcreq, 0);
267 }
268
269 /**
270 * shishi_kdcreq_read:
271 * @handle: shishi handle as allocated by shishi_init().
272 * @fh: file handle open for reading.
273 * @kdcreq: output variable with newly allocated KDC-REQ.
274 *
275 * Read DER encoded KDC-REQ from file and populate given variable.
276 *
277 * Return value: Returns SHISHI_OK iff successful.
278 **/
279 int
shishi_kdcreq_read(Shishi * handle,FILE * fh,Shishi_asn1 * kdcreq)280 shishi_kdcreq_read (Shishi * handle, FILE * fh, Shishi_asn1 * kdcreq)
281 {
282 return _shishi_kdcreq_input (handle, fh, kdcreq, 1);
283 }
284
285 /**
286 * shishi_kdcreq_from_file:
287 * @handle: shishi handle as allocated by shishi_init().
288 * @kdcreq: output variable with newly allocated KDC-REQ.
289 * @filetype: input variable specifying type of file to be read,
290 * see Shishi_filetype.
291 * @filename: input variable with filename to read from.
292 *
293 * Read KDC-REQ from file in specified TYPE.
294 *
295 * Return value: Returns SHISHI_OK iff successful.
296 **/
297 int
shishi_kdcreq_from_file(Shishi * handle,Shishi_asn1 * kdcreq,int filetype,const char * filename)298 shishi_kdcreq_from_file (Shishi * handle, Shishi_asn1 * kdcreq,
299 int filetype, const char *filename)
300 {
301 int res;
302 FILE *fh;
303
304 if (VERBOSE (handle))
305 printf (_("Reading KDC-REQ from %s...\n"), filename);
306
307 fh = fopen (filename, "r");
308 if (fh == NULL)
309 return SHISHI_FOPEN_ERROR;
310
311 if (VERBOSE (handle))
312 printf (_("Reading KDC-REQ in %s format...\n"),
313 filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
314
315 if (filetype == SHISHI_FILETYPE_TEXT)
316 res = shishi_kdcreq_parse (handle, fh, kdcreq);
317 else
318 res = shishi_kdcreq_read (handle, fh, kdcreq);
319 if (res != SHISHI_OK)
320 return res;
321
322 res = fclose (fh);
323 if (res != 0)
324 return SHISHI_IO_ERROR;
325
326 if (VERBOSE (handle))
327 printf (_("Reading KDC-REQ from %s...done\n"), filename);
328
329 return SHISHI_OK;
330 }
331
332 int
shishi_kdcreq_nonce(Shishi * handle,Shishi_asn1 kdcreq,uint32_t * nonce)333 shishi_kdcreq_nonce (Shishi * handle, Shishi_asn1 kdcreq, uint32_t * nonce)
334 {
335 int res;
336
337 res = shishi_asn1_read_uint32 (handle, kdcreq, "req-body.nonce", nonce);
338 if (res != SHISHI_OK)
339 return res;
340
341 return SHISHI_OK;
342 }
343
344 /**
345 * shishi_kdcreq_nonce_set:
346 * @handle: shishi handle as allocated by shishi_init().
347 * @kdcreq: KDC-REQ variable to set client name field in.
348 * @nonce: integer nonce to store in KDC-REQ.
349 *
350 * Store nonce number field in KDC-REQ.
351 *
352 * Return value: Returns %SHISHI_OK iff successful.
353 **/
354 int
shishi_kdcreq_nonce_set(Shishi * handle,Shishi_asn1 kdcreq,uint32_t nonce)355 shishi_kdcreq_nonce_set (Shishi * handle, Shishi_asn1 kdcreq, uint32_t nonce)
356 {
357 int res;
358
359 res = shishi_asn1_write_uint32 (handle, kdcreq, "req-body.nonce", nonce);
360 if (res != SHISHI_OK)
361 return res;
362
363 return SHISHI_OK;
364 }
365
366 /**
367 * shishi_kdcreq_set_cname:
368 * @handle: shishi handle as allocated by shishi_init().
369 * @kdcreq: KDC-REQ variable to set client name field in.
370 * @name_type: type of principial, see Shishi_name_type, usually
371 * SHISHI_NT_UNKNOWN.
372 * @principal: input array with principal name.
373 *
374 * Set the client name field in the KDC-REQ.
375 *
376 * Return value: Returns SHISHI_OK iff successful.
377 **/
378 int
shishi_kdcreq_set_cname(Shishi * handle,Shishi_asn1 kdcreq,Shishi_name_type name_type,const char * principal)379 shishi_kdcreq_set_cname (Shishi * handle,
380 Shishi_asn1 kdcreq,
381 Shishi_name_type name_type, const char *principal)
382 {
383 int res;
384
385 res = shishi_principal_set (handle, kdcreq, "req-body.cname", principal);
386 if (res != SHISHI_OK)
387 return res;
388
389 return SHISHI_OK;
390 }
391
392 /**
393 * shishi_kdcreq_client:
394 * @handle: Shishi library handle create by shishi_init().
395 * @kdcreq: KDC-REQ variable to get client name from.
396 * @client: pointer to newly allocated zero terminated string containing
397 * principal name. May be %NULL (to only populate @clientlen).
398 * @clientlen: pointer to length of @client on output, excluding terminating
399 * zero. May be %NULL (to only populate @client).
400 *
401 * Represent client principal name in KDC-REQ as zero-terminated
402 * string. The string is allocate by this function, and it is the
403 * responsibility of the caller to deallocate it. Note that the
404 * output length @clientlen does not include the terminating zero.
405 *
406 * Return value: Returns SHISHI_OK iff successful.
407 **/
408 int
shishi_kdcreq_client(Shishi * handle,Shishi_asn1 kdcreq,char ** client,size_t * clientlen)409 shishi_kdcreq_client (Shishi * handle, Shishi_asn1 kdcreq,
410 char **client, size_t * clientlen)
411 {
412 return shishi_principal_name (handle, kdcreq, "req-body.cname",
413 client, clientlen);
414 }
415
416 /**
417 * shishi_asreq_clientrealm:
418 * @handle: Shishi library handle create by shishi_init().
419 * @asreq: AS-REQ variable to get client name and realm from.
420 * @client: pointer to newly allocated zero terminated string containing
421 * principal name and realm. May be %NULL (to only populate @clientlen).
422 * @clientlen: pointer to length of @client on output, excluding terminating
423 * zero. May be %NULL (to only populate @client).
424 *
425 * Convert cname and realm fields from AS-REQ to printable principal
426 * name format. The string is allocate by this function, and it is
427 * the responsibility of the caller to deallocate it. Note that the
428 * output length @clientlen does not include the terminating zero.
429 *
430 * Return value: Returns SHISHI_OK iff successful.
431 **/
432 int
shishi_asreq_clientrealm(Shishi * handle,Shishi_asn1 asreq,char ** client,size_t * clientlen)433 shishi_asreq_clientrealm (Shishi * handle,
434 Shishi_asn1 asreq,
435 char **client, size_t * clientlen)
436 {
437 return shishi_principal_name_realm (handle,
438 asreq, "req-body.cname",
439 asreq, "req-body.realm",
440 client, clientlen);
441 }
442
443 /**
444 * shishi_kdcreq_realm:
445 * @handle: Shishi library handle create by shishi_init().
446 * @kdcreq: KDC-REQ variable to get client name from.
447 * @realm: pointer to newly allocated zero terminated string containing
448 * realm. May be %NULL (to only populate @realmlen).
449 * @realmlen: pointer to length of @realm on output, excluding terminating
450 * zero. May be %NULL (to only populate @realmlen).
451 *
452 * Get realm field in KDC-REQ as zero-terminated string. The string
453 * is allocate by this function, and it is the responsibility of the
454 * caller to deallocate it. Note that the output length @realmlen
455 * does not include the terminating zero.
456 *
457 * Return value: Returns SHISHI_OK iff successful.
458 **/
459 int
shishi_kdcreq_realm(Shishi * handle,Shishi_asn1 kdcreq,char ** realm,size_t * realmlen)460 shishi_kdcreq_realm (Shishi * handle, Shishi_asn1 kdcreq,
461 char **realm, size_t * realmlen)
462 {
463 return shishi_asn1_read_optional (handle, kdcreq, "req-body.realm",
464 realm, realmlen);
465 }
466
467 int
shishi_kdcreq_realm_get(Shishi * handle,Shishi_asn1 kdcreq,char ** realm,size_t * realmlen)468 shishi_kdcreq_realm_get (Shishi * handle, Shishi_asn1 kdcreq,
469 char **realm, size_t * realmlen)
470 {
471 return shishi_asn1_read_optional (handle, kdcreq, "req-body.realm",
472 realm, realmlen);
473 }
474
475 /**
476 * shishi_kdcreq_set_realm:
477 * @handle: shishi handle as allocated by shishi_init().
478 * @kdcreq: KDC-REQ variable to set realm field in.
479 * @realm: input array with name of realm.
480 *
481 * Set the realm field in the KDC-REQ.
482 *
483 * Return value: Returns SHISHI_OK iff successful.
484 **/
485 int
shishi_kdcreq_set_realm(Shishi * handle,Shishi_asn1 kdcreq,const char * realm)486 shishi_kdcreq_set_realm (Shishi * handle, Shishi_asn1 kdcreq,
487 const char *realm)
488 {
489 int res;
490
491 res = shishi_asn1_write (handle, kdcreq, "req-body.realm", realm, 0);
492 if (res != SHISHI_OK)
493 return res;
494
495 return SHISHI_OK;
496 }
497
498 /**
499 * shishi_kdcreq_server:
500 * @handle: Shishi library handle create by shishi_init().
501 * @kdcreq: KDC-REQ variable to get server name from.
502 * @server: pointer to newly allocated zero terminated string containing
503 * principal name. May be %NULL (to only populate @serverlen).
504 * @serverlen: pointer to length of @server on output, excluding terminating
505 * zero. May be %NULL (to only populate @server).
506 *
507 * Represent server principal name in KDC-REQ as zero-terminated
508 * string. The string is allocate by this function, and it is the
509 * responsibility of the caller to deallocate it. Note that the
510 * output length @serverlen does not include the terminating zero.
511 *
512 * Return value: Returns SHISHI_OK iff successful.
513 **/
514 int
shishi_kdcreq_server(Shishi * handle,Shishi_asn1 kdcreq,char ** server,size_t * serverlen)515 shishi_kdcreq_server (Shishi * handle, Shishi_asn1 kdcreq,
516 char **server, size_t * serverlen)
517 {
518 return shishi_principal_name (handle, kdcreq, "req-body.sname",
519 server, serverlen);
520 }
521
522 /**
523 * shishi_kdcreq_set_sname:
524 * @handle: shishi handle as allocated by shishi_init().
525 * @kdcreq: KDC-REQ variable to set server name field in.
526 * @name_type: type of principial, see Shishi_name_type, usually
527 * SHISHI_NT_UNKNOWN.
528 * @sname: input array with principal name.
529 *
530 * Set the server name field in the KDC-REQ.
531 *
532 * Return value: Returns SHISHI_OK iff successful.
533 **/
534 int
shishi_kdcreq_set_sname(Shishi * handle,Shishi_asn1 kdcreq,Shishi_name_type name_type,const char * sname[])535 shishi_kdcreq_set_sname (Shishi * handle,
536 Shishi_asn1 kdcreq,
537 Shishi_name_type name_type, const char *sname[])
538 {
539 int res;
540
541 res = shishi_principal_name_set (handle, kdcreq, "req-body.sname",
542 name_type, sname);
543 if (res != SHISHI_OK)
544 return res;
545
546 return SHISHI_OK;
547 }
548
549 int
shishi_kdcreq_set_server(Shishi * handle,Shishi_asn1 req,const char * server)550 shishi_kdcreq_set_server (Shishi * handle, Shishi_asn1 req,
551 const char *server)
552 {
553 int res;
554
555 res = shishi_principal_set (handle, req, "req-body.sname", server);
556 if (res != SHISHI_OK)
557 return res;
558
559 return SHISHI_OK;
560 }
561
562 int
shishi_kdcreq_set_realmserver(Shishi * handle,Shishi_asn1 req,char * realm,char * server)563 shishi_kdcreq_set_realmserver (Shishi * handle,
564 Shishi_asn1 req, char *realm, char *server)
565 {
566 int res;
567
568 res = shishi_kdcreq_set_realm (handle, req, realm);
569 if (res != SHISHI_OK)
570 return res;
571
572 res = shishi_kdcreq_set_server (handle, req, server);
573 if (res != SHISHI_OK)
574 return res;
575
576 return SHISHI_OK;
577 }
578
579 /**
580 * shishi_kdcreq_till:
581 * @handle: Shishi library handle create by shishi_init().
582 * @kdcreq: KDC-REQ variable to get client name from.
583 * @till: pointer to newly allocated zero terminated string containing
584 * "till" field with generalized time. May be %NULL (to only
585 * populate @realmlen).
586 * @tilllen: pointer to length of @till on output, excluding
587 * terminating zero. May be %NULL (to only populate @tilllen).
588 *
589 * Get "till" field (i.e. "endtime") in KDC-REQ, as zero-terminated
590 * string. The string is typically 15 characters long. The string is
591 * allocated by this function, and it is the responsibility of the
592 * caller to deallocate it. Note that the output length @realmlen
593 * does not include the terminating zero.
594 *
595 * Return value: Returns SHISHI_OK iff successful.
596 **/
597 int
shishi_kdcreq_till(Shishi * handle,Shishi_asn1 kdcreq,char ** till,size_t * tilllen)598 shishi_kdcreq_till (Shishi * handle, Shishi_asn1 kdcreq,
599 char **till, size_t * tilllen)
600 {
601 return shishi_asn1_read (handle, kdcreq, "req-body.till", till, tilllen);
602 }
603
604 /**
605 * shishi_kdcreq_tillc:
606 * @handle: Shishi library handle create by shishi_init().
607 * @kdcreq: KDC-REQ variable to get till field from.
608 *
609 * Extract C time corresponding to the "till" field.
610 *
611 * Return value: Returns C time interpretation of the "till" field in
612 * KDC-REQ.
613 **/
614 time_t
shishi_kdcreq_tillc(Shishi * handle,Shishi_asn1 kdcreq)615 shishi_kdcreq_tillc (Shishi * handle, Shishi_asn1 kdcreq)
616 {
617 char *till;
618 size_t tilllen;
619 time_t t = (time_t) - 1;
620 int res;
621
622 res = shishi_kdcreq_till (handle, kdcreq, &till, &tilllen);
623 if (res != SHISHI_OK)
624 return t;
625
626 if (tilllen == SHISHI_GENERALIZEDTIME_LENGTH + 1) /* XXX why +1 ? */
627 t = shishi_generalize_ctime (handle, till);
628
629 free (till);
630
631 return t;
632 }
633
634 /**
635 * shishi_kdcreq_etype:
636 * @handle: shishi handle as allocated by shishi_init().
637 * @kdcreq: KDC-REQ variable to get etype field from.
638 * @etype: output encryption type.
639 * @netype: element number to return.
640 *
641 * Return the netype:th encryption type from KDC-REQ. The first etype
642 * is number 1.
643 *
644 * Return value: Returns SHISHI_OK iff etype successful set.
645 **/
646 int
shishi_kdcreq_etype(Shishi * handle,Shishi_asn1 kdcreq,int32_t * etype,int netype)647 shishi_kdcreq_etype (Shishi * handle,
648 Shishi_asn1 kdcreq, int32_t * etype, int netype)
649 {
650 char *buf;
651 int res;
652
653 asprintf (&buf, "req-body.etype.?%d", netype);
654 res = shishi_asn1_read_int32 (handle, kdcreq, buf, etype);
655 if (res != SHISHI_OK)
656 return res;
657
658 return SHISHI_OK;
659 }
660
661 /**
662 * shishi_kdcreq_set_etype:
663 * @handle: shishi handle as allocated by shishi_init().
664 * @kdcreq: KDC-REQ variable to set etype field in.
665 * @etype: input array with encryption types.
666 * @netype: number of elements in input array with encryption types.
667 *
668 * Set the list of supported or wanted encryption types in the
669 * request. The list should be sorted in priority order.
670 *
671 * Return value: Returns SHISHI_OK iff successful.
672 **/
673 int
shishi_kdcreq_set_etype(Shishi * handle,Shishi_asn1 kdcreq,int32_t * etype,int netype)674 shishi_kdcreq_set_etype (Shishi * handle,
675 Shishi_asn1 kdcreq, int32_t * etype, int netype)
676 {
677 int res;
678 char *buf;
679 int i;
680
681 res = shishi_asn1_write (handle, kdcreq, "req-body.etype", NULL, 0);
682 if (res != SHISHI_OK)
683 return res;
684
685 for (i = 1; i <= netype; i++)
686 {
687 res = shishi_asn1_write (handle, kdcreq, "req-body.etype", "NEW", 1);
688 if (res != SHISHI_OK)
689 return res;
690
691 asprintf (&buf, "req-body.etype.?%d", i);
692 res = shishi_asn1_write_int32 (handle, kdcreq, buf, etype[i - 1]);
693 free (buf);
694 if (res != SHISHI_OK)
695 return res;
696 }
697
698 return SHISHI_OK;
699 }
700
701 /**
702 * shishi_kdcreq_options:
703 * @handle: shishi handle as allocated by shishi_init().
704 * @kdcreq: KDC-REQ variable to get kdc-options field from.
705 * @flags: pointer to output integer with flags.
706 *
707 * Extract KDC-Options from KDC-REQ.
708 *
709 * Return value: Returns SHISHI_OK iff successful.
710 **/
711 int
shishi_kdcreq_options(Shishi * handle,Shishi_asn1 kdcreq,uint32_t * flags)712 shishi_kdcreq_options (Shishi * handle, Shishi_asn1 kdcreq, uint32_t * flags)
713 {
714 return shishi_asn1_read_bitstring (handle, kdcreq,
715 "req-body.kdc-options", flags);
716 }
717
718 /**
719 * shishi_kdcreq_forwardable_p:
720 * @handle: shishi handle as allocated by shishi_init().
721 * @kdcreq: KDC-REQ variable to get kdc-options field from.
722 *
723 * Determine if KDC-Option forwardable flag is set.
724 *
725 * The FORWARDABLE option indicates that the ticket to be issued is to
726 * have its forwardable flag set. It may only be set on the initial
727 * request, or in a subsequent request if the ticket-granting ticket
728 * on which it is based is also forwardable.
729 *
730 * Return value: Returns non-0 iff forwardable flag is set in KDC-REQ.
731 **/
732 int
shishi_kdcreq_forwardable_p(Shishi * handle,Shishi_asn1 kdcreq)733 shishi_kdcreq_forwardable_p (Shishi * handle, Shishi_asn1 kdcreq)
734 {
735 uint32_t options = 0;
736
737 shishi_kdcreq_options (handle, kdcreq, &options);
738
739 return options & SHISHI_KDCOPTIONS_FORWARDABLE;
740 }
741
742 /**
743 * shishi_kdcreq_forwarded_p:
744 * @handle: shishi handle as allocated by shishi_init().
745 * @kdcreq: KDC-REQ variable to get kdc-options field from.
746 *
747 * Determine if KDC-Option forwarded flag is set.
748 *
749 * The FORWARDED option is only specified in a request to the
750 * ticket-granting server and will only be honored if the
751 * ticket-granting ticket in the request has its FORWARDABLE bit
752 * set. This option indicates that this is a request for
753 * forwarding. The address(es) of the host from which the resulting
754 * ticket is to be valid are included in the addresses field of the
755 * request.
756 *
757 * Return value: Returns non-0 iff forwarded flag is set in KDC-REQ.
758 **/
759 int
shishi_kdcreq_forwarded_p(Shishi * handle,Shishi_asn1 kdcreq)760 shishi_kdcreq_forwarded_p (Shishi * handle, Shishi_asn1 kdcreq)
761 {
762 uint32_t options = 0;
763
764 shishi_kdcreq_options (handle, kdcreq, &options);
765
766 return options & SHISHI_KDCOPTIONS_FORWARDED;
767 }
768
769 /**
770 * shishi_kdcreq_proxiable_p:
771 * @handle: shishi handle as allocated by shishi_init().
772 * @kdcreq: KDC-REQ variable to get kdc-options field from.
773 *
774 * Determine if KDC-Option proxiable flag is set.
775 *
776 * The PROXIABLE option indicates that the ticket to be issued is to
777 * have its proxiable flag set. It may only be set on the initial
778 * request, or in a subsequent request if the ticket-granting ticket
779 * on which it is based is also proxiable.
780 *
781 * Return value: Returns non-0 iff proxiable flag is set in KDC-REQ.
782 **/
783 int
shishi_kdcreq_proxiable_p(Shishi * handle,Shishi_asn1 kdcreq)784 shishi_kdcreq_proxiable_p (Shishi * handle, Shishi_asn1 kdcreq)
785 {
786 uint32_t options = 0;
787
788 shishi_kdcreq_options (handle, kdcreq, &options);
789
790 return options & SHISHI_KDCOPTIONS_PROXIABLE;
791 }
792
793 /**
794 * shishi_kdcreq_proxy_p:
795 * @handle: shishi handle as allocated by shishi_init().
796 * @kdcreq: KDC-REQ variable to get kdc-options field from.
797 *
798 * Determine if KDC-Option proxy flag is set.
799 *
800 * The PROXY option indicates that this is a request for a proxy. This
801 * option will only be honored if the ticket-granting ticket in the
802 * request has its PROXIABLE bit set. The address(es) of the host
803 * from which the resulting ticket is to be valid are included in the
804 * addresses field of the request.
805 *
806 * Return value: Returns non-0 iff proxy flag is set in KDC-REQ.
807 **/
808 int
shishi_kdcreq_proxy_p(Shishi * handle,Shishi_asn1 kdcreq)809 shishi_kdcreq_proxy_p (Shishi * handle, Shishi_asn1 kdcreq)
810 {
811 uint32_t options = 0;
812
813 shishi_kdcreq_options (handle, kdcreq, &options);
814
815 return options & SHISHI_KDCOPTIONS_PROXY;
816 }
817
818 /**
819 * shishi_kdcreq_allow_postdate_p:
820 * @handle: shishi handle as allocated by shishi_init().
821 * @kdcreq: KDC-REQ variable to get kdc-options field from.
822 *
823 * Determine if KDC-Option allow-postdate flag is set.
824 *
825 * The ALLOW-POSTDATE option indicates that the ticket to be issued is
826 * to have its MAY-POSTDATE flag set. It may only be set on the
827 * initial request, or in a subsequent request if the ticket-granting
828 * ticket on which it is based also has its MAY-POSTDATE flag set.
829 *
830 * Return value: Returns non-0 iff allow-postdate flag is set in KDC-REQ.
831 **/
832 int
shishi_kdcreq_allow_postdate_p(Shishi * handle,Shishi_asn1 kdcreq)833 shishi_kdcreq_allow_postdate_p (Shishi * handle, Shishi_asn1 kdcreq)
834 {
835 uint32_t options = 0;
836
837 shishi_kdcreq_options (handle, kdcreq, &options);
838
839 return options & SHISHI_KDCOPTIONS_ALLOW_POSTDATE;
840 }
841
842 /**
843 * shishi_kdcreq_postdated_p:
844 * @handle: shishi handle as allocated by shishi_init().
845 * @kdcreq: KDC-REQ variable to get kdc-options field from.
846 *
847 * Determine if KDC-Option postdated flag is set.
848 *
849 * The POSTDATED option indicates that this is a request for a
850 * postdated ticket. This option will only be honored if the
851 * ticket-granting ticket on which it is based has its MAY-POSTDATE
852 * flag set. The resulting ticket will also have its INVALID flag set,
853 * and that flag may be reset by a subsequent request to the KDC after
854 * the starttime in the ticket has been reached.
855 *
856 * Return value: Returns non-0 iff postdated flag is set in KDC-REQ.
857 **/
858 int
shishi_kdcreq_postdated_p(Shishi * handle,Shishi_asn1 kdcreq)859 shishi_kdcreq_postdated_p (Shishi * handle, Shishi_asn1 kdcreq)
860 {
861 uint32_t options = 0;
862
863 shishi_kdcreq_options (handle, kdcreq, &options);
864
865 return options & SHISHI_KDCOPTIONS_POSTDATED;
866 }
867
868 /**
869 * shishi_kdcreq_renewable_p:
870 * @handle: shishi handle as allocated by shishi_init().
871 * @kdcreq: KDC-REQ variable to get kdc-options field from.
872 *
873 * Determine if KDC-Option renewable flag is set.
874 *
875 * The RENEWABLE option indicates that the ticket to be issued is to
876 * have its RENEWABLE flag set. It may only be set on the initial
877 * request, or when the ticket-granting ticket on which the request is
878 * based is also renewable. If this option is requested, then the
879 * rtime field in the request contains the desired absolute expiration
880 * time for the ticket.
881 *
882 * Return value: Returns non-0 iff renewable flag is set in KDC-REQ.
883 **/
884 int
shishi_kdcreq_renewable_p(Shishi * handle,Shishi_asn1 kdcreq)885 shishi_kdcreq_renewable_p (Shishi * handle, Shishi_asn1 kdcreq)
886 {
887 uint32_t options = 0;
888
889 shishi_kdcreq_options (handle, kdcreq, &options);
890
891 return options & SHISHI_KDCOPTIONS_RENEWABLE;
892 }
893
894 /**
895 * shishi_kdcreq_disable_transited_check_p:
896 * @handle: shishi handle as allocated by shishi_init().
897 * @kdcreq: KDC-REQ variable to get kdc-options field from.
898 *
899 * Determine if KDC-Option disable-transited-check flag is set.
900 *
901 * By default the KDC will check the transited field of a
902 * ticket-granting-ticket against the policy of the local realm before
903 * it will issue derivative tickets based on the ticket-granting
904 * ticket. If this flag is set in the request, checking of the
905 * transited field is disabled. Tickets issued without the performance
906 * of this check will be noted by the reset (0) value of the
907 * TRANSITED-POLICY-CHECKED flag, indicating to the application server
908 * that the tranisted field must be checked locally. KDCs are
909 * encouraged but not required to honor the DISABLE-TRANSITED-CHECK
910 * option.
911 *
912 * This flag is new since RFC 1510
913 *
914 * Return value: Returns non-0 iff disable-transited-check flag is set
915 * in KDC-REQ.
916 **/
917 int
shishi_kdcreq_disable_transited_check_p(Shishi * handle,Shishi_asn1 kdcreq)918 shishi_kdcreq_disable_transited_check_p (Shishi * handle, Shishi_asn1 kdcreq)
919 {
920 uint32_t options = 0;
921
922 shishi_kdcreq_options (handle, kdcreq, &options);
923
924 return options & SHISHI_KDCOPTIONS_DISABLE_TRANSITED_CHECK;
925 }
926
927 /**
928 * shishi_kdcreq_renewable_ok_p:
929 * @handle: shishi handle as allocated by shishi_init().
930 * @kdcreq: KDC-REQ variable to get kdc-options field from.
931 *
932 * Determine if KDC-Option renewable-ok flag is set.
933 *
934 * The RENEWABLE-OK option indicates that a renewable ticket will be
935 * acceptable if a ticket with the requested life cannot otherwise be
936 * provided. If a ticket with the requested life cannot be provided,
937 * then a renewable ticket may be issued with a renew-till equal to
938 * the requested endtime. The value of the renew-till field may still
939 * be limited by local limits, or limits selected by the individual
940 * principal or server.
941 *
942 * Return value: Returns non-0 iff renewable-ok flag is set in KDC-REQ.
943 **/
944 int
shishi_kdcreq_renewable_ok_p(Shishi * handle,Shishi_asn1 kdcreq)945 shishi_kdcreq_renewable_ok_p (Shishi * handle, Shishi_asn1 kdcreq)
946 {
947 uint32_t options = 0;
948
949 shishi_kdcreq_options (handle, kdcreq, &options);
950
951 return options & SHISHI_KDCOPTIONS_RENEWABLE_OK;
952 }
953
954 /**
955 * shishi_kdcreq_enc_tkt_in_skey_p:
956 * @handle: shishi handle as allocated by shishi_init().
957 * @kdcreq: KDC-REQ variable to get kdc-options field from.
958 *
959 * Determine if KDC-Option enc-tkt-in-skey flag is set.
960 *
961 * This option is used only by the ticket-granting service. The
962 * ENC-TKT-IN-SKEY option indicates that the ticket for the end server
963 * is to be encrypted in the session key from the additional
964 * ticket-granting ticket provided.
965 *
966 * Return value: Returns non-0 iff enc-tkt-in-skey flag is set in KDC-REQ.
967 **/
968 int
shishi_kdcreq_enc_tkt_in_skey_p(Shishi * handle,Shishi_asn1 kdcreq)969 shishi_kdcreq_enc_tkt_in_skey_p (Shishi * handle, Shishi_asn1 kdcreq)
970 {
971 uint32_t options = 0;
972
973 shishi_kdcreq_options (handle, kdcreq, &options);
974
975 return options & SHISHI_KDCOPTIONS_ENC_TKT_IN_SKEY;
976 }
977
978 /**
979 * shishi_kdcreq_renew_p:
980 * @handle: shishi handle as allocated by shishi_init().
981 * @kdcreq: KDC-REQ variable to get kdc-options field from.
982 *
983 * Determine if KDC-Option renew flag is set.
984 *
985 * This option is used only by the ticket-granting service. The RENEW
986 * option indicates that the present request is for a renewal. The
987 * ticket provided is encrypted in the secret key for the server on
988 * which it is valid. This option will only be honored if the ticket
989 * to be renewed has its RENEWABLE flag set and if the time in its
990 * renew-till field has not passed. The ticket to be renewed is passed
991 * in the padata field as part of the authentication header.
992 *
993 * Return value: Returns non-0 iff renew flag is set in KDC-REQ.
994 **/
995 int
shishi_kdcreq_renew_p(Shishi * handle,Shishi_asn1 kdcreq)996 shishi_kdcreq_renew_p (Shishi * handle, Shishi_asn1 kdcreq)
997 {
998 uint32_t options = 0;
999
1000 shishi_kdcreq_options (handle, kdcreq, &options);
1001
1002 return options & SHISHI_KDCOPTIONS_RENEW;
1003 }
1004
1005 /**
1006 * shishi_kdcreq_validate_p:
1007 * @handle: shishi handle as allocated by shishi_init().
1008 * @kdcreq: KDC-REQ variable to get kdc-options field from.
1009 *
1010 * Determine if KDC-Option validate flag is set.
1011 *
1012 * This option is used only by the ticket-granting service. The
1013 * VALIDATE option indicates that the request is to validate a
1014 * postdated ticket. It will only be honored if the ticket presented
1015 * is postdated, presently has its INVALID flag set, and would be
1016 * otherwise usable at this time. A ticket cannot be validated before
1017 * its starttime. The ticket presented for validation is encrypted in
1018 * the key of the server for which it is valid and is passed in the
1019 * padata field as part of the authentication header.
1020 *
1021 * Return value: Returns non-0 iff validate flag is set in KDC-REQ.
1022 **/
1023 int
shishi_kdcreq_validate_p(Shishi * handle,Shishi_asn1 kdcreq)1024 shishi_kdcreq_validate_p (Shishi * handle, Shishi_asn1 kdcreq)
1025 {
1026 uint32_t options = 0;
1027
1028 shishi_kdcreq_options (handle, kdcreq, &options);
1029
1030 return options & SHISHI_KDCOPTIONS_VALIDATE;
1031 }
1032
1033 /**
1034 * shishi_kdcreq_options_set:
1035 * @handle: shishi handle as allocated by shishi_init().
1036 * @kdcreq: KDC-REQ variable to set etype field in.
1037 * @options: integer with flags to store in KDC-REQ.
1038 *
1039 * Set options in KDC-REQ. Note that this reset any already existing
1040 * flags.
1041 *
1042 * Return value: Returns SHISHI_OK iff successful.
1043 **/
1044 int
shishi_kdcreq_options_set(Shishi * handle,Shishi_asn1 kdcreq,uint32_t options)1045 shishi_kdcreq_options_set (Shishi * handle,
1046 Shishi_asn1 kdcreq, uint32_t options)
1047 {
1048 int res;
1049
1050 res = shishi_asn1_write_bitstring (handle, kdcreq,
1051 "req-body.kdc-options", options);
1052 if (res != SHISHI_OK)
1053 return res;
1054
1055 return SHISHI_OK;
1056 }
1057
1058 /**
1059 * shishi_kdcreq_options_add:
1060 * @handle: shishi handle as allocated by shishi_init().
1061 * @kdcreq: KDC-REQ variable to set etype field in.
1062 * @option: integer with options to add in KDC-REQ.
1063 *
1064 * Add KDC-Option to KDC-REQ. This preserves all existing options.
1065 *
1066 * Return value: Returns SHISHI_OK iff successful.
1067 **/
1068 int
shishi_kdcreq_options_add(Shishi * handle,Shishi_asn1 kdcreq,uint32_t option)1069 shishi_kdcreq_options_add (Shishi * handle,
1070 Shishi_asn1 kdcreq, uint32_t option)
1071 {
1072 uint32_t options;
1073 int res;
1074
1075 res = shishi_kdcreq_options (handle, kdcreq, &options);
1076 if (res != SHISHI_OK)
1077 return res;
1078
1079 options |= option;
1080
1081 res = shishi_kdcreq_options_set (handle, kdcreq, options);
1082 if (res != SHISHI_OK)
1083 return res;
1084
1085 return SHISHI_OK;
1086 }
1087
1088 /**
1089 * shishi_kdcreq_clear_padata:
1090 * @handle: shishi handle as allocated by shishi_init().
1091 * @kdcreq: KDC-REQ to remove PA-DATA from.
1092 *
1093 * Remove the padata field from KDC-REQ.
1094 *
1095 * Return value: Returns SHISHI_OK iff successful.
1096 **/
1097 int
shishi_kdcreq_clear_padata(Shishi * handle,Shishi_asn1 kdcreq)1098 shishi_kdcreq_clear_padata (Shishi * handle, Shishi_asn1 kdcreq)
1099 {
1100 int res;
1101
1102 res = shishi_asn1_write (handle, kdcreq, "padata", NULL, 0);
1103 if (res != SHISHI_OK)
1104 return res;
1105
1106 return SHISHI_OK;
1107 }
1108
1109 /**
1110 * shishi_kdcreq_get_padata:
1111 * @handle: shishi handle as allocated by shishi_init().
1112 * @kdcreq: KDC-REQ to get PA-DATA from.
1113 * @padatatype: type of PA-DATA, see Shishi_padata_type.
1114 * @out: output array with newly allocated PA-DATA value.
1115 * @outlen: size of output array with PA-DATA value.
1116 *
1117 * Get pre authentication data (PA-DATA) from KDC-REQ. Pre
1118 * authentication data is used to pass various information to KDC,
1119 * such as in case of a SHISHI_PA_TGS_REQ padatatype the AP-REQ that
1120 * authenticates the user to get the ticket.
1121 *
1122 * Return value: Returns SHISHI_OK iff successful.
1123 **/
1124 int
shishi_kdcreq_get_padata(Shishi * handle,Shishi_asn1 kdcreq,Shishi_padata_type padatatype,char ** out,size_t * outlen)1125 shishi_kdcreq_get_padata (Shishi * handle,
1126 Shishi_asn1 kdcreq,
1127 Shishi_padata_type padatatype,
1128 char **out, size_t * outlen)
1129 {
1130 char *format;
1131 int res;
1132 size_t i, n;
1133
1134 res = shishi_asn1_number_of_elements (handle, kdcreq, "padata", &n);
1135 if (res != SHISHI_OK)
1136 return res;
1137
1138 *out = NULL;
1139 *outlen = 0;
1140
1141 for (i = 1; i <= n; i++)
1142 {
1143 int32_t patype;
1144
1145 asprintf (&format, "padata.?%d.padata-type", i);
1146 res = shishi_asn1_read_int32 (handle, kdcreq, format, &patype);
1147 free (format);
1148 if (res != SHISHI_OK)
1149 return res;
1150
1151 if (patype == (int32_t) padatatype)
1152 {
1153 asprintf (&format, "padata.?%d.padata-value", i);
1154 res = shishi_asn1_read (handle, kdcreq, format, out, outlen);
1155 free (format);
1156 if (res != SHISHI_OK)
1157 return res;
1158 break;
1159 }
1160 }
1161
1162 return SHISHI_OK;
1163 }
1164
1165 /**
1166 * shishi_kdcreq_get_padata_tgs:
1167 * @handle: shishi handle as allocated by shishi_init().
1168 * @kdcreq: KDC-REQ to get PA-TGS-REQ from.
1169 * @apreq: Output variable with newly allocated AP-REQ.
1170 *
1171 * Extract TGS pre-authentication data from KDC-REQ. The data is an
1172 * AP-REQ that authenticates the request. This function call
1173 * shishi_kdcreq_get_padata() with a SHISHI_PA_TGS_REQ padatatype and
1174 * DER decode the result (if any).
1175 *
1176 * Return value: Returns SHISHI_OK iff successful.
1177 **/
1178 int
shishi_kdcreq_get_padata_tgs(Shishi * handle,Shishi_asn1 kdcreq,Shishi_asn1 * apreq)1179 shishi_kdcreq_get_padata_tgs (Shishi * handle,
1180 Shishi_asn1 kdcreq, Shishi_asn1 * apreq)
1181 {
1182 char *der;
1183 size_t derlen;
1184 int rc;
1185
1186 if (VERBOSE (handle))
1187 printf ("Extracting AP-REQ from KDC-REQ...\n");
1188
1189 rc = shishi_kdcreq_get_padata (handle, kdcreq, SHISHI_PA_TGS_REQ,
1190 &der, &derlen);
1191 if (rc != SHISHI_OK)
1192 return rc;
1193
1194 *apreq = shishi_der2asn1_apreq (handle, der, derlen);
1195 if (!*apreq)
1196 return SHISHI_ASN1_ERROR;
1197
1198 if (VERBOSEASN1 (handle))
1199 shishi_apreq_print (handle, stdout, *apreq);
1200
1201 return SHISHI_OK;
1202 }
1203
1204 /**
1205 * shishi_kdcreq_add_padata:
1206 * @handle: shishi handle as allocated by shishi_init().
1207 * @kdcreq: KDC-REQ to add PA-DATA to.
1208 * @padatatype: type of PA-DATA, see Shishi_padata_type.
1209 * @data: input array with PA-DATA value.
1210 * @datalen: size of input array with PA-DATA value.
1211 *
1212 * Add new pre authentication data (PA-DATA) to KDC-REQ. This is used
1213 * to pass various information to KDC, such as in case of a
1214 * SHISHI_PA_TGS_REQ padatatype the AP-REQ that authenticates the user
1215 * to get the ticket. (But also see shishi_kdcreq_add_padata_tgs()
1216 * which takes an AP-REQ directly.)
1217 *
1218 * Return value: Returns SHISHI_OK iff successful.
1219 **/
1220 int
shishi_kdcreq_add_padata(Shishi * handle,Shishi_asn1 kdcreq,int padatatype,const char * data,size_t datalen)1221 shishi_kdcreq_add_padata (Shishi * handle,
1222 Shishi_asn1 kdcreq,
1223 int padatatype, const char *data, size_t datalen)
1224 {
1225 char *format;
1226 int res;
1227 size_t i;
1228
1229 res = shishi_asn1_write (handle, kdcreq, "padata", "NEW", 1);
1230 if (res != SHISHI_OK)
1231 return res;
1232
1233 res = shishi_asn1_number_of_elements (handle, kdcreq, "padata", &i);
1234 if (res != SHISHI_OK)
1235 return res;
1236
1237 asprintf (&format, "padata.?%d.padata-value", i);
1238 res = shishi_asn1_write (handle, kdcreq, format, data, datalen);
1239 free (format);
1240 if (res != SHISHI_OK)
1241 return res;
1242
1243 asprintf (&format, "padata.?%d.padata-type", i);
1244 res = shishi_asn1_write_uint32 (handle, kdcreq, format, padatatype);
1245 free (format);
1246 if (res != SHISHI_OK)
1247 return res;
1248
1249 return SHISHI_OK;
1250 }
1251
1252 /**
1253 * shishi_kdcreq_add_padata_tgs:
1254 * @handle: shishi handle as allocated by shishi_init().
1255 * @kdcreq: KDC-REQ to add PA-DATA to.
1256 * @apreq: AP-REQ to add as PA-DATA.
1257 *
1258 * Add TGS pre-authentication data to KDC-REQ. The data is an AP-REQ
1259 * that authenticates the request. This functions simply DER encodes
1260 * the AP-REQ and calls shishi_kdcreq_add_padata() with a
1261 * SHISHI_PA_TGS_REQ padatatype.
1262 *
1263 * Return value: Returns SHISHI_OK iff successful.
1264 **/
1265 int
shishi_kdcreq_add_padata_tgs(Shishi * handle,Shishi_asn1 kdcreq,Shishi_asn1 apreq)1266 shishi_kdcreq_add_padata_tgs (Shishi * handle,
1267 Shishi_asn1 kdcreq, Shishi_asn1 apreq)
1268 {
1269 int res;
1270 char *data;
1271 size_t datalen;
1272
1273 res = shishi_asn1_to_der (handle, apreq, &data, &datalen);
1274 if (res != SHISHI_OK)
1275 {
1276 shishi_error_printf (handle, "Could not DER encode AP-REQ: %s\n",
1277 shishi_strerror (res));
1278 return res;
1279 }
1280
1281 res = shishi_kdcreq_add_padata (handle, kdcreq,
1282 SHISHI_PA_TGS_REQ, data, datalen);
1283 free (data);
1284 if (res != SHISHI_OK)
1285 return res;
1286
1287 return res;
1288 }
1289
1290 /**
1291 * shishi_kdcreq_add_padata_preauth:
1292 * @handle: shishi handle as allocated by shishi_init().
1293 * @kdcreq: KDC-REQ to add pre-authentication data to.
1294 * @key: Key used to encrypt pre-auth data.
1295 *
1296 * Add pre-authentication data to KDC-REQ.
1297 *
1298 * Return value: Returns SHISHI_OK iff successful.
1299 **/
1300 int
shishi_kdcreq_add_padata_preauth(Shishi * handle,Shishi_asn1 kdcreq,Shishi_key * key)1301 shishi_kdcreq_add_padata_preauth (Shishi * handle,
1302 Shishi_asn1 kdcreq, Shishi_key * key)
1303 {
1304 char *der, *data;
1305 size_t derlen, datalen;
1306 Shishi_asn1 pa;
1307 struct timeval tv;
1308 int rc;
1309 Shishi_asn1 ed;
1310
1311 pa = shishi_asn1_pa_enc_ts_enc (handle);
1312 if (!pa)
1313 return SHISHI_ASN1_ERROR;
1314
1315 rc = gettimeofday (&tv, NULL);
1316 if (rc != 0)
1317 return SHISHI_GETTIMEOFDAY_ERROR;
1318
1319 rc = shishi_asn1_write (handle, pa, "patimestamp",
1320 shishi_generalize_time (handle, tv.tv_sec),
1321 SHISHI_GENERALIZEDTIME_LENGTH);
1322 if (rc != SHISHI_OK)
1323 return rc;
1324
1325 rc = shishi_asn1_write_integer (handle, pa, "pausec", tv.tv_usec);
1326 if (rc != SHISHI_OK)
1327 return rc;
1328
1329 rc = shishi_asn1_to_der (handle, pa, &der, &derlen);
1330 if (rc != SHISHI_OK)
1331 return rc;
1332
1333 rc = shishi_encrypt (handle, key, SHISHI_KEYUSAGE_ASREQ_PA_ENC_TIMESTAMP,
1334 der, derlen, &data, &datalen);
1335 free (der);
1336 if (rc != SHISHI_OK)
1337 return rc;
1338
1339 ed = shishi_asn1_encrypteddata (handle);
1340 if (!ed)
1341 return SHISHI_ASN1_ERROR;
1342
1343 rc = shishi_asn1_write_integer (handle, ed, "etype", shishi_key_type (key));
1344 if (rc != SHISHI_OK)
1345 return rc;
1346
1347 rc = shishi_asn1_write (handle, ed, "cipher", data, datalen);
1348 if (rc != SHISHI_OK)
1349 return rc;
1350
1351 rc = shishi_asn1_write (handle, ed, "kvno", NULL, 0);
1352 if (rc != SHISHI_OK)
1353 return rc;
1354
1355 rc = shishi_asn1_to_der (handle, ed, &der, &derlen);
1356 free (data);
1357 if (rc != SHISHI_OK)
1358 return rc;
1359
1360 rc = shishi_kdcreq_add_padata (handle, kdcreq, SHISHI_PA_ENC_TIMESTAMP,
1361 der, derlen);
1362 free (der);
1363 if (rc != SHISHI_OK)
1364 return rc;
1365
1366 return rc;
1367 }
1368
1369 int
shishi_kdcreq_build(Shishi * handle,Shishi_asn1 kdcreq)1370 shishi_kdcreq_build (Shishi * handle, Shishi_asn1 kdcreq)
1371 {
1372 int res;
1373 size_t n;
1374 int msgtype;
1375
1376 shishi_verbose (handle, "Building KDC-REQ...");
1377
1378 if (shishi_asn1_empty_p (handle, kdcreq, "req-body.rtime"))
1379 {
1380 res = shishi_asn1_write (handle, kdcreq, "req-body.rtime", NULL, 0);
1381 if (res != SHISHI_OK)
1382 {
1383 shishi_error_printf (handle, "Could not write rtime\n");
1384 return res;
1385 }
1386 }
1387
1388 if (shishi_asn1_empty_p (handle, kdcreq, "req-body.from"))
1389 {
1390 res = shishi_asn1_write (handle, kdcreq, "req-body.from", NULL, 0);
1391 if (res != SHISHI_OK)
1392 {
1393 shishi_error_printf (handle, "Could not write from\n");
1394 return res;
1395 }
1396 }
1397
1398 res = shishi_asn1_read_integer (handle, kdcreq, "msg-type", &msgtype);
1399 if (res != SHISHI_OK)
1400 return res;
1401 if (msgtype == SHISHI_MSGTYPE_AS_REQ)
1402 {
1403 res = shishi_asn1_number_of_elements (handle, kdcreq, "padata", &n);
1404 if (res == SHISHI_OK && n == 0)
1405 {
1406 res = shishi_kdcreq_clear_padata (handle, kdcreq);
1407 if (res != SHISHI_OK)
1408 {
1409 shishi_error_printf (handle, "Could not write padata\n");
1410 return res;
1411 }
1412 }
1413 }
1414
1415 return SHISHI_OK;
1416 }
1417