1 /* kdcrep.c --- Key distribution (AS/TGS) Reply 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_KDCREP_DEFAULT_PVNO      "5"
29 #define SHISHI_KDCREP_DEFAULT_PVNO_LEN  0
30 #define SHISHI_AS_REP_DEFAULT_MSG_TYPE      "11"
31 #define SHISHI_AS_REP_DEFAULT_MSG_TYPE_LEN  0
32 #define SHISHI_TGS_REP_DEFAULT_MSG_TYPE      "13"
33 #define SHISHI_TGS_REP_DEFAULT_MSG_TYPE_LEN  0
34 
35 static Shishi_asn1
_shishi_kdcrep(Shishi * handle,int as)36 _shishi_kdcrep (Shishi * handle, int as)
37 {
38   int res;
39   Shishi_asn1 node;
40 
41   if (as)
42     node = shishi_asn1_asrep (handle);
43   else
44     node = shishi_asn1_tgsrep (handle);
45   if (!node)
46     return NULL;
47 
48   res = shishi_asn1_write (handle, node, "pvno",
49 			   SHISHI_KDCREP_DEFAULT_PVNO,
50 			   SHISHI_KDCREP_DEFAULT_PVNO_LEN);
51   if (res != SHISHI_OK)
52     goto error;
53 
54   if (as)
55     res = shishi_asn1_write (handle, node, "msg-type",
56 			     SHISHI_AS_REP_DEFAULT_MSG_TYPE,
57 			     SHISHI_AS_REP_DEFAULT_MSG_TYPE_LEN);
58   else
59     res = shishi_asn1_write (handle, node, "msg-type",
60 			     SHISHI_TGS_REP_DEFAULT_MSG_TYPE,
61 			     SHISHI_TGS_REP_DEFAULT_MSG_TYPE_LEN);
62   if (res != SHISHI_OK)
63     goto error;
64 
65   return node;
66 
67 error:
68   shishi_asn1_done (handle, node);
69   return NULL;
70 }
71 
72 /**
73  * shishi_asrep:
74  * @handle: shishi handle as allocated by shishi_init().
75  *
76  * This function creates a new AS-REP, populated with some default
77  * values.
78  *
79  * Return value: Returns the AS-REP or NULL on failure.
80  **/
81 Shishi_asn1
shishi_asrep(Shishi * handle)82 shishi_asrep (Shishi * handle)
83 {
84   return _shishi_kdcrep (handle, 1);
85 }
86 
87 /**
88  * shishi_tgsrep:
89  * @handle: shishi handle as allocated by shishi_init().
90  *
91  * This function creates a new TGS-REP, populated with some default
92  * values.
93  *
94  * Return value: Returns the TGS-REP or NULL on failure.
95  **/
96 Shishi_asn1
shishi_tgsrep(Shishi * handle)97 shishi_tgsrep (Shishi * handle)
98 {
99   return _shishi_kdcrep (handle, 0);
100 }
101 
102 
103 /**
104  * shishi_kdcrep_print:
105  * @handle: shishi handle as allocated by shishi_init().
106  * @fh: file handle open for writing.
107  * @kdcrep: KDC-REP to print.
108  *
109  * Print ASCII armored DER encoding of KDC-REP to file.
110  *
111  * Return value: Returns SHISHI_OK iff successful.
112  **/
113 int
shishi_kdcrep_print(Shishi * handle,FILE * fh,Shishi_asn1 kdcrep)114 shishi_kdcrep_print (Shishi * handle, FILE * fh, Shishi_asn1 kdcrep)
115 {
116   return _shishi_print_armored_data (handle, fh, kdcrep, "KDC-REP", NULL);
117 }
118 
119 /**
120  * shishi_kdcrep_save:
121  * @handle: shishi handle as allocated by shishi_init().
122  * @fh: file handle open for writing.
123  * @kdcrep: KDC-REP to save.
124  *
125  * Print  DER encoding of KDC-REP to file.
126  *
127  * Return value: Returns SHISHI_OK iff successful.
128  **/
129 int
shishi_kdcrep_save(Shishi * handle,FILE * fh,Shishi_asn1 kdcrep)130 shishi_kdcrep_save (Shishi * handle, FILE * fh, Shishi_asn1 kdcrep)
131 {
132   return _shishi_save_data (handle, fh, kdcrep, "KDC-REP");
133 }
134 
135 /**
136  * shishi_kdcrep_to_file:
137  * @handle: shishi handle as allocated by shishi_init().
138  * @kdcrep: KDC-REP to save.
139  * @filetype: input variable specifying type of file to be written,
140  *            see Shishi_filetype.
141  * @filename: input variable with filename to write to.
142  *
143  * Write KDC-REP to file in specified TYPE.  The file will be truncated
144  * if it exists.
145  *
146  * Return value: Returns SHISHI_OK iff successful.
147  **/
148 int
shishi_kdcrep_to_file(Shishi * handle,Shishi_asn1 kdcrep,int filetype,const char * filename)149 shishi_kdcrep_to_file (Shishi * handle, Shishi_asn1 kdcrep,
150 		       int filetype, const char *filename)
151 {
152   FILE *fh;
153   int res;
154 
155   if (VERBOSE (handle))
156     printf (_("Writing KDC-REP to %s...\n"), filename);
157 
158   fh = fopen (filename, "w");
159   if (fh == NULL)
160     return SHISHI_FOPEN_ERROR;
161 
162   if (VERBOSE (handle))
163     printf (_("Writing KDC-REP in %s format...\n"),
164 	    filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
165 
166   if (filetype == SHISHI_FILETYPE_TEXT)
167     res = shishi_kdcrep_print (handle, fh, kdcrep);
168   else
169     res = shishi_kdcrep_save (handle, fh, kdcrep);
170   if (res != SHISHI_OK)
171     return res;
172 
173   res = fclose (fh);
174   if (res != 0)
175     return SHISHI_IO_ERROR;
176 
177   if (VERBOSE (handle))
178     printf (_("Writing KDC-REP to %s...done\n"), filename);
179 
180   return SHISHI_OK;
181 }
182 
183 /**
184  * shishi_kdcrep_parse:
185  * @handle: shishi handle as allocated by shishi_init().
186  * @fh: file handle open for reading.
187  * @kdcrep: output variable with newly allocated KDC-REP.
188  *
189  * Read ASCII armored DER encoded KDC-REP from file and populate given
190  * variable.
191  *
192  * Return value: Returns SHISHI_OK iff successful.
193  **/
194 int
shishi_kdcrep_parse(Shishi * handle,FILE * fh,Shishi_asn1 * kdcrep)195 shishi_kdcrep_parse (Shishi * handle, FILE * fh, Shishi_asn1 * kdcrep)
196 {
197   return _shishi_kdcrep_input (handle, fh, kdcrep, 0);
198 }
199 
200 /**
201  * shishi_kdcrep_read:
202  * @handle: shishi handle as allocated by shishi_init().
203  * @fh: file handle open for reading.
204  * @kdcrep: output variable with newly allocated KDC-REP.
205  *
206  * Read DER encoded KDC-REP from file and populate given variable.
207  *
208  * Return value: Returns SHISHI_OK iff successful.
209  **/
210 int
shishi_kdcrep_read(Shishi * handle,FILE * fh,Shishi_asn1 * kdcrep)211 shishi_kdcrep_read (Shishi * handle, FILE * fh, Shishi_asn1 * kdcrep)
212 {
213   return _shishi_kdcrep_input (handle, fh, kdcrep, 1);
214 }
215 
216 /**
217  * shishi_kdcrep_from_file:
218  * @handle: shishi handle as allocated by shishi_init().
219  * @kdcrep: output variable with newly allocated KDC-REP.
220  * @filetype: input variable specifying type of file to be read,
221  *            see Shishi_filetype.
222  * @filename: input variable with filename to read from.
223  *
224  * Read KDC-REP from file in specified TYPE.
225  *
226  * Return value: Returns SHISHI_OK iff successful.
227  **/
228 int
shishi_kdcrep_from_file(Shishi * handle,Shishi_asn1 * kdcrep,int filetype,const char * filename)229 shishi_kdcrep_from_file (Shishi * handle, Shishi_asn1 * kdcrep,
230 			 int filetype, const char *filename)
231 {
232   int res;
233   FILE *fh;
234 
235   if (VERBOSE (handle))
236     printf (_("Reading KDC-REP from %s...\n"), filename);
237 
238   fh = fopen (filename, "r");
239   if (fh == NULL)
240     return SHISHI_FOPEN_ERROR;
241 
242   if (VERBOSE (handle))
243     printf (_("Reading KDC-REP in %s format...\n"),
244 	    filetype == SHISHI_FILETYPE_TEXT ? "TEXT" : "DER");
245 
246   if (filetype == SHISHI_FILETYPE_TEXT)
247     res = shishi_kdcrep_parse (handle, fh, kdcrep);
248   else
249     res = shishi_kdcrep_read (handle, fh, kdcrep);
250   if (res != SHISHI_OK)
251     return res;
252 
253   res = fclose (fh);
254   if (res != 0)
255     return SHISHI_IO_ERROR;
256 
257   if (VERBOSE (handle))
258     printf (_("Reading KDC-REP from %s...done\n"), filename);
259 
260   return SHISHI_OK;
261 }
262 
263 /**
264  * shishi_kdcrep_crealm_set:
265  * @handle: shishi handle as allocated by shishi_init().
266  * @kdcrep: Kdcrep variable to set realm field in.
267  * @crealm: input array with name of realm.
268  *
269  * Set the client realm field in the KDC-REP.
270  *
271  * Return value: Returns SHISHI_OK iff successful.
272  **/
273 int
shishi_kdcrep_crealm_set(Shishi * handle,Shishi_asn1 kdcrep,const char * crealm)274 shishi_kdcrep_crealm_set (Shishi * handle,
275 			  Shishi_asn1 kdcrep, const char *crealm)
276 {
277   int res;
278 
279   res = shishi_asn1_write (handle, kdcrep, "crealm", crealm, 0);
280   if (res != SHISHI_OK)
281     return res;
282 
283   return SHISHI_OK;
284 }
285 
286 /**
287  * shishi_kdcrep_cname_set:
288  * @handle: shishi handle as allocated by shishi_init().
289  * @kdcrep: Kdcrep variable to set server name field in.
290  * @name_type: type of principial, see Shishi_name_type, usually
291  *             SHISHI_NT_UNKNOWN.
292  * @cname: input array with principal name.
293  *
294  * Set the client name field in the KDC-REP.
295  *
296  * Return value: Returns SHISHI_OK iff successful.
297  **/
298 int
shishi_kdcrep_cname_set(Shishi * handle,Shishi_asn1 kdcrep,Shishi_name_type name_type,const char * cname[])299 shishi_kdcrep_cname_set (Shishi * handle,
300 			 Shishi_asn1 kdcrep,
301 			 Shishi_name_type name_type, const char *cname[])
302 {
303   int res;
304 
305   res = shishi_principal_name_set (handle, kdcrep, "cname", name_type, cname);
306   if (res != SHISHI_OK)
307     return res;
308 
309   return SHISHI_OK;
310 }
311 
312 /**
313  * shishi_kdcrep_client_set:
314  * @handle: shishi handle as allocated by shishi_init().
315  * @kdcrep: Kdcrep variable to set server name field in.
316  * @client: zero-terminated string with principal name on RFC 1964 form.
317  *
318  * Set the client name field in the KDC-REP.
319  *
320  * Return value: Returns SHISHI_OK iff successful.
321  **/
322 int
shishi_kdcrep_client_set(Shishi * handle,Shishi_asn1 kdcrep,const char * client)323 shishi_kdcrep_client_set (Shishi * handle,
324 			  Shishi_asn1 kdcrep, const char *client)
325 {
326   int res;
327 
328   res = shishi_principal_set (handle, kdcrep, "cname", client);
329   if (res != SHISHI_OK)
330     return res;
331 
332   return SHISHI_OK;
333 }
334 
335 int
shishi_kdcrep_crealmserver_set(Shishi * handle,Shishi_asn1 kdcrep,const char * crealm,const char * client)336 shishi_kdcrep_crealmserver_set (Shishi * handle,
337 				Shishi_asn1 kdcrep,
338 				const char *crealm, const char *client)
339 {
340   int res;
341 
342   res = shishi_kdcrep_crealm_set (handle, kdcrep, crealm);
343   if (res != SHISHI_OK)
344     return res;
345 
346   res = shishi_kdcrep_client_set (handle, kdcrep, client);
347   if (res != SHISHI_OK)
348     return res;
349 
350   return SHISHI_OK;
351 }
352 
353 /**
354  * shishi_kdcrep_get_enc_part_etype:
355  * @handle: shishi handle as allocated by shishi_init().
356  * @kdcrep: KDC-REP variable to get value from.
357  * @etype: output variable that holds the value.
358  *
359  * Extract KDC-REP.enc-part.etype.
360  *
361  * Return value: Returns SHISHI_OK iff successful.
362  **/
363 int
shishi_kdcrep_get_enc_part_etype(Shishi * handle,Shishi_asn1 kdcrep,int32_t * etype)364 shishi_kdcrep_get_enc_part_etype (Shishi * handle,
365 				  Shishi_asn1 kdcrep, int32_t * etype)
366 {
367   return shishi_asn1_read_int32 (handle, kdcrep, "enc-part.etype", etype);
368 }
369 
370 /**
371  * shishi_kdcrep_get_ticket:
372  * @handle: shishi handle as allocated by shishi_init().
373  * @kdcrep: KDC-REP variable to get ticket from.
374  * @ticket: output variable to hold extracted ticket.
375  *
376  * Extract ticket from KDC-REP.
377  *
378  * Return value: Returns SHISHI_OK iff successful.
379  **/
380 int
shishi_kdcrep_get_ticket(Shishi * handle,Shishi_asn1 kdcrep,Shishi_asn1 * ticket)381 shishi_kdcrep_get_ticket (Shishi * handle,
382 			  Shishi_asn1 kdcrep, Shishi_asn1 * ticket)
383 {
384   char *buf;
385   char *format;
386   size_t buflen;
387   int res;
388   size_t i, n;
389 
390   /* there's GOT to be an easier way to do this */
391 
392   *ticket = shishi_ticket (handle);
393   if (!*ticket)
394     return SHISHI_ASN1_ERROR;
395 
396   res = shishi_asn1_read (handle, kdcrep, "ticket.tkt-vno", &buf, &buflen);
397   if (res != SHISHI_OK)
398     goto error;
399 
400   res = shishi_asn1_write (handle, *ticket, "tkt-vno", buf, buflen);
401   free (buf);
402   if (res != SHISHI_OK)
403     goto error;
404 
405   res = shishi_asn1_read (handle, kdcrep, "ticket.realm", &buf, &buflen);
406   if (res != SHISHI_OK)
407     goto error;
408 
409   res = shishi_asn1_write (handle, *ticket, "realm", buf, buflen);
410   free (buf);
411   if (res != SHISHI_OK)
412     goto error;
413 
414   res = shishi_asn1_read (handle, kdcrep, "ticket.sname.name-type",
415 			  &buf, &buflen);
416   if (res != SHISHI_OK)
417     goto error;
418 
419   res = shishi_asn1_write (handle, *ticket, "sname.name-type", buf, buflen);
420   free (buf);
421   if (res != SHISHI_OK)
422     goto error;
423 
424   res = shishi_asn1_number_of_elements (handle, kdcrep,
425 					"ticket.sname.name-string", &n);
426   if (res != SHISHI_OK)
427     goto error;
428 
429   for (i = 1; i <= n; i++)
430     {
431       res = shishi_asn1_write (handle, *ticket, "sname.name-string",
432 			       "NEW", 1);
433       if (res != SHISHI_OK)
434 	goto error;
435 
436       format = xasprintf ("ticket.sname.name-string.?%d", i);
437       res = shishi_asn1_read (handle, kdcrep, format, &buf, &buflen);
438       free (format);
439       if (res != SHISHI_OK)
440 	goto error;
441 
442       format = xasprintf ("sname.name-string.?%d", i);
443       res = shishi_asn1_write (handle, *ticket, format, buf, buflen);
444       free (format);
445       free (buf);
446       if (res != SHISHI_OK)
447 	goto error;
448     }
449 
450   res = shishi_asn1_read (handle, kdcrep, "ticket.enc-part.etype",
451 			  &buf, &buflen);
452   if (res != SHISHI_OK)
453     goto error;
454 
455   res = shishi_asn1_write (handle, *ticket, "enc-part.etype", buf, buflen);
456   free (buf);
457   if (res != SHISHI_OK)
458     goto error;
459 
460   res = shishi_asn1_read (handle, kdcrep, "ticket.enc-part.kvno",
461 			  &buf, &buflen);
462   if (res != SHISHI_OK && res != SHISHI_ASN1_NO_ELEMENT)
463     goto error;
464 
465   if (res == SHISHI_ASN1_NO_ELEMENT)
466     res = shishi_asn1_write (handle, *ticket, "enc-part.kvno", NULL, 0);
467   else
468     {
469       res = shishi_asn1_write (handle, *ticket, "enc-part.kvno", buf, buflen);
470       free (buf);
471     }
472   if (res != SHISHI_OK)
473     goto error;
474 
475   res = shishi_asn1_read (handle, kdcrep, "ticket.enc-part.cipher",
476 			  &buf, &buflen);
477   if (res != SHISHI_OK)
478     goto error;
479 
480   res = shishi_asn1_write (handle, *ticket, "enc-part.cipher", buf, buflen);
481   free (buf);
482   if (res != SHISHI_OK)
483     goto error;
484 
485   return SHISHI_OK;
486 
487 error:
488   shishi_asn1_done (handle, *ticket);
489   return res;
490 }
491 
492 /**
493  * shishi_kdcrep_set_ticket:
494  * @handle: shishi handle as allocated by shishi_init().
495  * @kdcrep: KDC-REP to add ticket field to.
496  * @ticket: input ticket to copy into KDC-REP ticket field.
497  *
498  * Copy ticket into KDC-REP.
499  *
500  * Return value: Returns SHISHI_OK iff successful.
501  **/
502 int
shishi_kdcrep_set_ticket(Shishi * handle,Shishi_asn1 kdcrep,Shishi_asn1 ticket)503 shishi_kdcrep_set_ticket (Shishi * handle, Shishi_asn1 kdcrep,
504 			  Shishi_asn1 ticket)
505 {
506   int res = SHISHI_OK;
507   char *format;
508   char *buf;
509   size_t buflen;
510   size_t i, n;
511 
512   res = shishi_asn1_read (handle, ticket, "tkt-vno", &buf, &buflen);
513   if (res != SHISHI_OK)
514     return res;
515 
516   res = shishi_asn1_write (handle, kdcrep, "ticket.tkt-vno", buf, buflen);
517   free (buf);
518   if (res != SHISHI_OK)
519     return res;
520 
521   res = shishi_asn1_read (handle, ticket, "realm", &buf, &buflen);
522   if (res != SHISHI_OK)
523     return res;
524 
525   res = shishi_asn1_write (handle, kdcrep, "ticket.realm", buf, buflen);
526   free (buf);
527   if (res != SHISHI_OK)
528     return res;
529 
530   res = shishi_asn1_read (handle, ticket, "sname.name-type", &buf, &buflen);
531   if (res != SHISHI_OK)
532     return res;
533 
534   res = shishi_asn1_write (handle, kdcrep, "ticket.sname.name-type",
535 			   buf, buflen);
536   free (buf);
537   if (res != SHISHI_OK)
538     return res;
539 
540   res = shishi_asn1_number_of_elements (handle, ticket,
541 					"sname.name-string", &n);
542   if (res != SHISHI_OK)
543     return res;
544 
545   for (i = 1; i <= n; i++)
546     {
547       res = shishi_asn1_write (handle, kdcrep,
548 			       "ticket.sname.name-string", "NEW", 1);
549       if (res != SHISHI_OK)
550 	return res;
551 
552       format = xasprintf ("sname.name-string.?%d", i);
553       res = shishi_asn1_read (handle, ticket, format, &buf, &buflen);
554       free (format);
555       if (res != SHISHI_OK)
556 	return res;
557 
558       format = xasprintf ("ticket.sname.name-string.?%d", i);
559       res = shishi_asn1_write (handle, kdcrep, format, buf, buflen);
560       free (format);
561       free (buf);
562       if (res != SHISHI_OK)
563 	return res;
564     }
565 
566   res = shishi_asn1_read (handle, ticket, "enc-part.etype", &buf, &buflen);
567   if (res != SHISHI_OK)
568     return res;
569 
570   res = shishi_asn1_write (handle, kdcrep, "ticket.enc-part.etype",
571 			   buf, buflen);
572   free (buf);
573   if (res != SHISHI_OK)
574     return res;
575 
576   res = shishi_asn1_read (handle, ticket, "enc-part.kvno", &buf, &buflen);
577   if (res != SHISHI_OK)
578     res = shishi_asn1_write (handle, kdcrep, "ticket.enc-part.kvno", NULL, 0);
579   else
580     {
581       res = shishi_asn1_write (handle, kdcrep, "ticket.enc-part.kvno",
582 			       buf, buflen);
583       free (buf);
584     }
585   if (res != SHISHI_OK)
586     return res;
587 
588   res = shishi_asn1_read (handle, ticket, "enc-part.cipher", &buf, &buflen);
589   if (res != SHISHI_OK)
590     return res;
591 
592   res = shishi_asn1_write (handle, kdcrep, "ticket.enc-part.cipher",
593 			   buf, buflen);
594   free (buf);
595   if (res != SHISHI_OK)
596     return res;
597 
598   return SHISHI_OK;
599 }
600 
601 /**
602  * shishi_kdcrep_set_enc_part:
603  * @handle: shishi handle as allocated by shishi_init().
604  * @kdcrep: KDC-REP to add enc-part field to.
605  * @etype: encryption type used to encrypt enc-part.
606  * @kvno: key version number.
607  * @buf: input array with encrypted enc-part.
608  * @buflen: size of input array with encrypted enc-part.
609  *
610  * Set the encrypted enc-part field in the KDC-REP.  The encrypted
611  * data is usually created by calling shishi_encrypt() on the DER
612  * encoded enc-part.  To save time, you may want to use
613  * shishi_kdcrep_add_enc_part() instead, which calculates the
614  * encrypted data and calls this function in one step.
615  *
616  * Return value: Returns SHISHI_OK iff successful.
617  **/
618 int
shishi_kdcrep_set_enc_part(Shishi * handle,Shishi_asn1 kdcrep,int32_t etype,uint32_t kvno,const char * buf,size_t buflen)619 shishi_kdcrep_set_enc_part (Shishi * handle,
620 			    Shishi_asn1 kdcrep,
621 			    int32_t etype, uint32_t kvno,
622 			    const char *buf, size_t buflen)
623 {
624   int res = SHISHI_OK;
625 
626   res = shishi_asn1_write (handle, kdcrep, "enc-part.cipher", buf, buflen);
627   if (res != SHISHI_OK)
628     return res;
629 
630   res = shishi_asn1_write_int32 (handle, kdcrep, "enc-part.etype", etype);
631   if (res != SHISHI_OK)
632     return res;
633 
634   if (kvno == UINT32_MAX)
635     res = shishi_asn1_write (handle, kdcrep, "enc-part.kvno", NULL, 0);
636   else
637     res = shishi_asn1_write_uint32 (handle, kdcrep, "enc-part.kvno", kvno);
638   if (res != SHISHI_OK)
639     return res;
640 
641   return SHISHI_OK;
642 }
643 
644 /**
645  * shishi_kdcrep_add_enc_part:
646  * @handle: shishi handle as allocated by shishi_init().
647  * @kdcrep: KDC-REP to add enc-part field to.
648  * @key: key used to encrypt enc-part.
649  * @keyusage: key usage to use, normally SHISHI_KEYUSAGE_ENCASREPPART,
650  *            SHISHI_KEYUSAGE_ENCTGSREPPART_SESSION_KEY or
651  *            SHISHI_KEYUSAGE_ENCTGSREPPART_AUTHENTICATOR_KEY.
652  * @enckdcreppart: EncKDCRepPart to add.
653  *
654  * Encrypts DER encoded EncKDCRepPart using key and stores it in the
655  * KDC-REP.
656  *
657  * Return value: Returns SHISHI_OK iff successful.
658  **/
659 int
shishi_kdcrep_add_enc_part(Shishi * handle,Shishi_asn1 kdcrep,Shishi_key * key,int keyusage,Shishi_asn1 enckdcreppart)660 shishi_kdcrep_add_enc_part (Shishi * handle,
661 			    Shishi_asn1 kdcrep,
662 			    Shishi_key * key,
663 			    int keyusage, Shishi_asn1 enckdcreppart)
664 {
665   int res = SHISHI_OK;
666   char *buf;
667   size_t buflen;
668   char *der;
669   size_t derlen;
670 
671   res = shishi_asn1_to_der (handle, enckdcreppart, &der, &derlen);
672   if (res != SHISHI_OK)
673     {
674       shishi_error_printf (handle, "Could not DER encode enckdcreppart: %s\n",
675 			   shishi_strerror (res));
676       return SHISHI_ASN1_ERROR;
677     }
678 
679   res = shishi_encrypt (handle, key, keyusage, der, derlen, &buf, &buflen);
680 
681   free (der);
682 
683   if (res != SHISHI_OK)
684     {
685       shishi_error_printf (handle, "Cannot encrypt EncKDCRepPart\n");
686       return res;
687     }
688 
689   res = shishi_kdcrep_set_enc_part (handle, kdcrep, shishi_key_type (key),
690 				    shishi_key_version (key), buf, buflen);
691 
692   free (buf);
693 
694   return res;
695 }
696 
697 int
shishi_kdcrep_decrypt(Shishi * handle,Shishi_asn1 kdcrep,Shishi_key * key,int keyusage,Shishi_asn1 * enckdcreppart)698 shishi_kdcrep_decrypt (Shishi * handle,
699 		       Shishi_asn1 kdcrep,
700 		       Shishi_key * key,
701 		       int keyusage, Shishi_asn1 * enckdcreppart)
702 {
703   int res;
704   int i;
705   char *buf;
706   size_t buflen;
707   char *cipher;
708   size_t cipherlen;
709   int etype;
710 
711   res = shishi_kdcrep_get_enc_part_etype (handle, kdcrep, &etype);
712   if (res != SHISHI_OK)
713     return res;
714 
715   if (etype != shishi_key_type (key))
716     return SHISHI_KDCREP_BAD_KEYTYPE;
717 
718   res = shishi_asn1_read (handle, kdcrep, "enc-part.cipher",
719 			  &cipher, &cipherlen);
720   if (res != SHISHI_OK)
721     return res;
722 
723   res = shishi_decrypt (handle, key, keyusage,
724 			cipher, cipherlen, &buf, &buflen);
725   free (cipher);
726   if (res != SHISHI_OK)
727     {
728       shishi_error_printf (handle,
729 			   "KDCRep decryption failed, wrong password?");
730       return res;
731     }
732 
733   /* The crypto is so 1980; no length indicator. Trim off pad bytes
734      until we can parse it. */
735   for (i = 0; i < 8; i++)
736     {
737       if (VERBOSEASN1 (handle))
738 	printf ("Trying with %d pad in enckdcrep...\n", i);
739 
740       *enckdcreppart = shishi_der2asn1_encasreppart (handle, &buf[0],
741 						     buflen - i);
742       if (*enckdcreppart != NULL)
743 	break;
744 
745       *enckdcreppart = shishi_der2asn1_enctgsreppart (handle, &buf[0],
746 						      buflen - i);
747       if (*enckdcreppart != NULL)
748 	break;
749 
750       *enckdcreppart = shishi_der2asn1_enckdcreppart (handle, &buf[0],
751 						      buflen - i);
752       if (*enckdcreppart != NULL)
753 	break;
754     }
755 
756   free (buf);
757 
758   if (*enckdcreppart == NULL)
759     {
760       shishi_error_printf (handle, "Could not DER decode EncKDCRepPart. "
761 			   "Password probably correct (decrypt ok) though\n");
762       return SHISHI_ASN1_ERROR;
763     }
764 
765   return SHISHI_OK;
766 }
767 
768 /**
769  * shishi_kdcrep_clear_padata:
770  * @handle: shishi handle as allocated by shishi_init().
771  * @kdcrep: KDC-REP to remove PA-DATA from.
772  *
773  * Remove the padata field from KDC-REP.
774  *
775  * Return value: Returns SHISHI_OK iff successful.
776  **/
777 int
shishi_kdcrep_clear_padata(Shishi * handle,Shishi_asn1 kdcrep)778 shishi_kdcrep_clear_padata (Shishi * handle, Shishi_asn1 kdcrep)
779 {
780   int res;
781 
782   res = shishi_asn1_write (handle, kdcrep, "padata", NULL, 0);
783   if (res != SHISHI_OK)
784     return res;
785 
786   return SHISHI_OK;
787 }
788