Converted krb5/des425 and krb5/asn.1 to the PC
[krb5.git] / src / lib / krb5 / asn.1 / asn1_k_decode.c
1 /*
2  * src/lib/krb5/asn.1/asn1_k_decode.c
3  * 
4  * Copyright 1994 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.  M.I.T. makes no representations about the suitability of
20  * this software for any purpose.  It is provided "as is" without express
21  * or implied warranty.
22  */
23
24 #include "asn1_k_decode.h"
25 #include "asn1_decode.h"
26 #include "asn1_get.h"
27 #include "asn1_misc.h"
28
29 #define setup()\
30 asn1_error_code retval;\
31 asn1_class class;\
32 asn1_construction construction;\
33 asn1_tagnum tagnum;\
34 int length
35
36 #define next_tag()\
37 retval = asn1_get_tag(&subbuf,&class,&construction,&tagnum,NULL);\
38 if(retval) return retval;\
39 if(class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)\
40   return ASN1_BAD_ID
41
42 #define alloc_field(var,type)\
43 var = (type*)calloc(1,sizeof(type));\
44 if((var) == NULL) return ENOMEM
45
46
47 #define apptag(tagexpect)\
48 retval = asn1_get_tag(buf,&class,&construction,&tagnum,NULL);\
49 if(retval) return retval;\
50 if(class != APPLICATION || construction != CONSTRUCTED ||\
51    tagnum != (tagexpect)) return ASN1_BAD_ID
52
53 /**** normal fields ****/
54 #define get_field_body(var,decoder)\
55 retval = decoder(&subbuf,&(var));\
56 if(retval) return retval;\
57 next_tag()
58
59 #define get_field(var,tagexpect,decoder)\
60 if(tagnum > (tagexpect)) return ASN1_MISSING_FIELD;\
61 if(tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;\
62 get_field_body(var,decoder)
63
64 #define opt_field(var,tagexpect,decoder,optvalue)\
65 if(tagnum == (tagexpect)){\
66   get_field_body(var,decoder); }\
67 else var = optvalue
68
69 /**** fields w/ length ****/
70 #define get_lenfield_body(len,var,decoder)\
71 retval = decoder(&subbuf,&(len),&(var));\
72 if(retval) return retval;\
73 next_tag()
74
75 #define get_lenfield(len,var,tagexpect,decoder)\
76 if(tagnum > (tagexpect)) return ASN1_MISSING_FIELD;\
77 if(tagnum < (tagexpect)) return ASN1_MISPLACED_FIELD;\
78 get_lenfield_body(len,var,decoder)
79
80
81
82 #define begin_structure()\
83 asn1buf subbuf;\
84 retval = asn1_get_tag(buf,&class,&construction,&tagnum,&length);\
85 if(retval) return retval;\
86 if(class != UNIVERSAL || construction != CONSTRUCTED ||\
87    tagnum != ASN1_SEQUENCE) return ASN1_BAD_ID;\
88 retval = asn1buf_imbed(&subbuf,buf,length);\
89 if(retval) return retval;\
90 next_tag()
91
92 #define end_structure()\
93 asn1buf_sync(buf,&subbuf)
94
95 #define sequence_of(buf)\
96 int size=0;\
97 asn1buf seqbuf;\
98 int length;\
99 retval = asn1_get_sequence(buf,&length);\
100 if(retval) return retval;\
101 retval = asn1buf_imbed(&seqbuf,buf,length);\
102 if(retval) return retval
103
104 #define end_sequence_of(buf)\
105 asn1buf_sync(buf,&seqbuf)
106
107 #define cleanup()\
108 return 0
109
110
111
112 /* scalars */
113 asn1_error_code INTERFACE asn1_decode_kerberos_time(buf, val)
114      asn1buf * buf;
115      krb5_timestamp * val;
116 {
117     time_t      t;
118     asn1_error_code retval;
119     
120     retval =  asn1_decode_generaltime(buf,&t);
121     if (retval)
122         return retval;
123
124     *val = t;
125     return 0;
126 }
127
128 #define integer_convert(fname,ktype)\
129 asn1_error_code INTERFACE fname(buf, val)\
130      asn1buf * buf;\
131      ktype * val;\
132 {\
133   asn1_error_code retval;\
134   long n;\
135   retval = asn1_decode_integer(buf,&n);\
136   if(retval) return retval;\
137   *val = (ktype)n;\
138   return 0;\
139 }
140 #define unsigned_integer_convert(fname,ktype)\
141 asn1_error_code INTERFACE fname(buf, val)\
142      asn1buf * buf;\
143      ktype * val;\
144 {\
145   asn1_error_code retval;\
146   unsigned long n;\
147   retval = asn1_decode_unsigned_integer(buf,&n);\
148   if(retval) return retval;\
149   *val = (ktype)n;\
150   return 0;\
151 }
152 integer_convert(asn1_decode_int,int)
153 integer_convert(asn1_decode_int32,krb5_int32)
154 integer_convert(asn1_decode_kvno,krb5_kvno)
155 integer_convert(asn1_decode_keytype,krb5_keytype)
156 integer_convert(asn1_decode_cksumtype,krb5_cksumtype)
157 integer_convert(asn1_decode_enctype,krb5_enctype)
158 integer_convert(asn1_decode_octet,krb5_octet)
159 integer_convert(asn1_decode_addrtype,krb5_addrtype)
160 integer_convert(asn1_decode_authdatatype,krb5_authdatatype)
161 unsigned_integer_convert(asn1_decode_ui_2,krb5_ui_2)
162 unsigned_integer_convert(asn1_decode_ui_4,krb5_ui_4)
163
164 asn1_error_code INTERFACE asn1_decode_msgtype(buf, val)
165      asn1buf * buf;
166      krb5_msgtype * val;
167 {
168   asn1_error_code retval;
169   unsigned long n;
170   
171   retval = asn1_decode_unsigned_integer(buf,&n);
172   if(retval) return retval;
173   
174   *val = (krb5_msgtype) n;
175   return 0;
176 }
177
178
179 /* structures */
180 asn1_error_code INTERFACE asn1_decode_realm(buf, val)
181      asn1buf * buf;
182      krb5_principal * val;
183 {
184   return asn1_decode_generalstring(buf,
185                                    &((*val)->realm.length),
186                                    &((*val)->realm.data));
187 }
188
189 asn1_error_code INTERFACE asn1_decode_principal_name(buf, val)
190      asn1buf * buf;
191      krb5_principal * val;
192 {
193   setup();
194   { begin_structure();
195     get_field((*val)->type,0,asn1_decode_int32);
196   
197     { sequence_of(&subbuf);
198       while(asn1buf_remains(&seqbuf)){
199         size++;
200         if ((*val)->data == NULL)
201           (*val)->data = (krb5_data*)malloc(size*sizeof(krb5_data));
202         else
203           (*val)->data = (krb5_data*)realloc((*val)->data,
204                                              size*sizeof(krb5_data));
205         if((*val)->data == NULL) return ENOMEM;
206         retval = asn1_decode_generalstring(&seqbuf,
207                                            &((*val)->data[size-1].length),
208                                            &((*val)->data[size-1].data));
209         if(retval) return retval;
210       }
211       (*val)->length = size;
212       end_sequence_of(&subbuf);
213     }
214     end_structure();
215     (*val)->magic = KV5M_PRINCIPAL;
216   }
217   cleanup();
218 }
219
220 asn1_error_code INTERFACE asn1_decode_checksum(buf, val)
221      asn1buf * buf;
222      krb5_checksum * val;
223 {
224   setup();
225   { begin_structure();
226     get_field(val->checksum_type,0,asn1_decode_cksumtype);
227     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
228     end_structure();
229     val->magic = KV5M_CHECKSUM;
230   }
231   cleanup();
232 }
233
234 asn1_error_code INTERFACE asn1_decode_encryption_key(buf, val)
235      asn1buf * buf;
236      krb5_keyblock * val;
237 {
238   setup();
239   { begin_structure();
240     get_field(val->keytype,0,asn1_decode_keytype);
241     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
242     end_structure();
243     val->magic = KV5M_KEYBLOCK;
244     val->etype = ETYPE_UNKNOWN;
245   }
246   cleanup();
247 }
248
249 asn1_error_code INTERFACE asn1_decode_encrypted_data(buf, val)
250      asn1buf * buf;
251      krb5_enc_data * val;
252 {
253   setup();
254   { begin_structure();
255     get_field(val->etype,0,asn1_decode_enctype);
256     opt_field(val->kvno,1,asn1_decode_kvno,0);
257     get_lenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_decode_charstring);
258     end_structure();
259     val->magic = KV5M_ENC_DATA;
260   }
261   cleanup();
262 }
263
264 asn1_error_code INTERFACE asn1_decode_krb5_flags(buf, val)
265      asn1buf * buf;
266      krb5_flags * val;
267 {
268   setup();
269   asn1_octet o;
270   int i;
271   krb5_flags f=0;
272
273   retval = asn1_get_tag(buf,&class,&construction,&tagnum,&length);
274   if(retval) return retval;
275   if(class != UNIVERSAL || construction != PRIMITIVE ||
276      tagnum != ASN1_BITSTRING) return ASN1_BAD_ID;
277   if(length != 5) return ASN1_BAD_LENGTH;
278
279   retval = asn1buf_remove_octet(buf,&o); /* # of padding bits */
280   if(retval) return retval;     /*  should be 0 */
281   if(o != 0) return ASN1_BAD_FORMAT;
282
283   for(i=0; i<4; i++){
284     retval = asn1buf_remove_octet(buf,&o);
285     if(retval) return retval;
286     f = (f<<8) | ((krb5_flags)o&0xFF);
287   }
288   *val = f;
289   return 0;
290 }
291
292 asn1_error_code INTERFACE asn1_decode_ticket_flags(buf, val)
293      asn1buf * buf;
294      krb5_flags * val;
295 { return asn1_decode_krb5_flags(buf,val); }
296
297 asn1_error_code INTERFACE asn1_decode_ap_options(buf, val)
298      asn1buf * buf;
299      krb5_flags * val;
300 { return asn1_decode_krb5_flags(buf,val); }
301
302 asn1_error_code INTERFACE asn1_decode_kdc_options(buf, val)
303      asn1buf * buf;
304      krb5_flags * val;
305 { return asn1_decode_krb5_flags(buf,val); }
306
307 asn1_error_code INTERFACE asn1_decode_transited_encoding(buf, val)
308      asn1buf * buf;
309      krb5_transited * val;
310 {
311   setup();
312   { begin_structure();
313     get_field(val->tr_type,0,asn1_decode_octet);
314     get_lenfield(val->tr_contents.length,val->tr_contents.data,1,asn1_decode_charstring);
315     end_structure();
316     val->magic = KV5M_TRANSITED;
317   }
318   cleanup();
319 }
320
321 asn1_error_code INTERFACE asn1_decode_enc_kdc_rep_part(buf, val)
322      asn1buf * buf;
323      krb5_enc_kdc_rep_part * val;
324 {
325   setup();
326   { begin_structure();
327     alloc_field(val->session,krb5_keyblock);
328     get_field(*(val->session),0,asn1_decode_encryption_key);
329     get_field(val->last_req,1,asn1_decode_last_req);
330     get_field(val->nonce,2,asn1_decode_int32);
331     opt_field(val->key_exp,3,asn1_decode_kerberos_time,0);
332     get_field(val->flags,4,asn1_decode_ticket_flags);
333     get_field(val->times.authtime,5,asn1_decode_kerberos_time);
334     opt_field(val->times.starttime,6,asn1_decode_kerberos_time,0);
335     get_field(val->times.endtime,7,asn1_decode_kerberos_time);
336     opt_field(val->times.renew_till,8,asn1_decode_kerberos_time,0);
337     alloc_field(val->server,krb5_principal_data);
338     get_field(val->server,9,asn1_decode_realm);
339     get_field(val->server,10,asn1_decode_principal_name);
340     opt_field(val->caddrs,11,asn1_decode_host_addresses,NULL);
341     end_structure();
342     val->magic = KV5M_ENC_KDC_REP_PART;
343   }
344   cleanup();
345 }
346
347 asn1_error_code INTERFACE asn1_decode_ticket(buf, val)
348      asn1buf * buf;
349      krb5_ticket * val;
350 {
351   setup();
352   apptag(1);
353   { begin_structure();
354     { krb5_kvno vno;
355       get_field(vno,0,asn1_decode_kvno);
356       if(vno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
357     alloc_field(val->server,krb5_principal_data);
358     get_field(val->server,1,asn1_decode_realm);
359     get_field(val->server,2,asn1_decode_principal_name);
360     get_field(val->enc_part,3,asn1_decode_encrypted_data);
361     end_structure();
362     val->magic = KV5M_TICKET;
363   }
364   cleanup();
365 }
366
367 asn1_error_code INTERFACE asn1_decode_kdc_req(buf, val)
368      asn1buf * buf;
369      krb5_kdc_req * val;
370 {
371   setup();
372   { begin_structure();
373     { krb5_kvno kvno;
374       get_field(kvno,1,asn1_decode_kvno);
375       if(kvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
376     get_field(val->msg_type,2,asn1_decode_msgtype);
377     opt_field(val->padata,3,asn1_decode_sequence_of_pa_data,NULL);
378     get_field(*val,4,asn1_decode_kdc_req_body);
379     end_structure();
380     val->magic = KV5M_KDC_REQ;
381   }
382   cleanup();
383 }
384
385 asn1_error_code INTERFACE asn1_decode_kdc_req_body(buf, val)
386      asn1buf * buf;
387      krb5_kdc_req * val;
388 {
389   setup();
390   { begin_structure();
391     get_field(val->kdc_options,0,asn1_decode_kdc_options);
392     if(tagnum == 1){ alloc_field(val->client,krb5_principal_data); }
393     opt_field(val->client,1,asn1_decode_principal_name,NULL);
394     alloc_field(val->server,krb5_principal_data);
395     get_field(val->server,2,asn1_decode_realm);
396     if(val->client != NULL){
397       retval = asn1_krb5_realm_copy(val->client,val->server);
398       if(retval) return retval; }
399     opt_field(val->server,3,asn1_decode_principal_name,NULL);
400     opt_field(val->from,4,asn1_decode_kerberos_time,0);
401     get_field(val->till,5,asn1_decode_kerberos_time);
402     opt_field(val->rtime,6,asn1_decode_kerberos_time,0);
403     get_field(val->nonce,7,asn1_decode_int32);
404     get_lenfield(val->netypes,val->etype,8,asn1_decode_sequence_of_enctype);
405     opt_field(val->addresses,9,asn1_decode_host_addresses,0);
406     if(tagnum == 10){
407       get_field(val->authorization_data,10,asn1_decode_encrypted_data); }
408     else{
409       val->authorization_data.magic = 0;
410       val->authorization_data.etype = 0;
411       val->authorization_data.kvno = 0;
412       val->authorization_data.ciphertext.data = NULL;
413       val->authorization_data.ciphertext.length = 0;
414     }
415     opt_field(val->second_ticket,11,asn1_decode_sequence_of_ticket,NULL);
416     end_structure();
417     val->magic = KV5M_KDC_REQ;
418   }
419   cleanup();
420 }
421
422 asn1_error_code INTERFACE asn1_decode_krb_safe_body(buf, val)
423      asn1buf * buf;
424      krb5_safe * val;
425 {
426   setup();
427   { begin_structure();
428     get_lenfield(val->user_data.length,val->user_data.data,0,asn1_decode_charstring);
429     opt_field(val->timestamp,1,asn1_decode_kerberos_time,0);
430     opt_field(val->usec,2,asn1_decode_int32,0);
431     opt_field(val->seq_number,3,asn1_decode_int32,0);
432     alloc_field(val->s_address,krb5_address);
433     get_field(*(val->s_address),4,asn1_decode_host_address);
434     if(tagnum == 5){
435       alloc_field(val->r_address,krb5_address);
436       get_field(*(val->r_address),5,asn1_decode_host_address);
437     } else val->r_address = NULL;
438     end_structure();
439     val->magic = KV5M_SAFE;
440   }
441   cleanup();
442 }
443
444 asn1_error_code INTERFACE asn1_decode_host_address(buf, val)
445      asn1buf * buf;
446      krb5_address * val;
447 {
448   setup();
449   { begin_structure();
450     get_field(val->addrtype,0,asn1_decode_addrtype);
451     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
452     end_structure();
453     val->magic = KV5M_ADDRESS;
454   }
455   cleanup();
456 }
457
458 asn1_error_code INTERFACE asn1_decode_kdc_rep(buf, val)
459      asn1buf * buf;
460      krb5_kdc_rep * val;
461 {
462   setup();
463   { begin_structure();
464     { krb5_kvno pvno;
465       get_field(pvno,0,asn1_decode_kvno);
466       if(pvno != KVNO) return KRB5KDC_ERR_BAD_PVNO; }
467     get_field(val->msg_type,1,asn1_decode_msgtype);
468     opt_field(val->padata,2,asn1_decode_sequence_of_pa_data,NULL);
469     alloc_field(val->client,krb5_principal_data);
470     get_field(val->client,3,asn1_decode_realm);
471     get_field(val->client,4,asn1_decode_principal_name);
472     alloc_field(val->ticket,krb5_ticket);
473     get_field(*(val->ticket),5,asn1_decode_ticket);
474     get_field(val->enc_part,6,asn1_decode_encrypted_data);
475     end_structure();
476     val->magic = KV5M_KDC_REP;
477   }
478   cleanup();
479 }
480
481
482 /* arrays */
483 #define get_element(element,decoder)\
484 retval = decoder(&seqbuf,element);\
485 if(retval) return retval
486      
487 #define array_append(array,size,element,type)\
488 size++;\
489 if (*(array) == NULL)\
490      *(array) = (type**)malloc((size+1)*sizeof(type*));\
491 else\
492   *(array) = (type**)realloc(*(array),\
493                              (size+1)*sizeof(type*));\
494 if(*(array) == NULL) return ENOMEM;\
495 (*(array))[(size)-1] = elt
496      
497 #define decode_array_body(type,decoder)\
498   asn1_error_code retval;\
499   type *elt;\
500 \
501   { sequence_of(buf);\
502     while(asn1buf_remains(&seqbuf) > 0){\
503       alloc_field(elt,type);\
504       get_element(elt,decoder);\
505       array_append(val,size,elt,type);\
506     }\
507     (*val)[size] = NULL;\
508     end_sequence_of(buf);\
509   }\
510   cleanup()
511
512
513 asn1_error_code INTERFACE asn1_decode_authorization_data(buf, val)
514      asn1buf * buf;
515      krb5_authdata *** val;
516 {
517   decode_array_body(krb5_authdata,asn1_decode_authdata_elt);
518 }
519
520 asn1_error_code INTERFACE asn1_decode_authdata_elt(buf, val)
521      asn1buf * buf;
522      krb5_authdata * val;
523 {
524   setup();
525   { begin_structure();
526     get_field(val->ad_type,0,asn1_decode_authdatatype);
527     get_lenfield(val->length,val->contents,1,asn1_decode_octetstring);
528     end_structure();
529     val->magic = KV5M_AUTHDATA;
530   }
531   cleanup();
532 }
533
534 asn1_error_code INTERFACE asn1_decode_host_addresses(buf, val)
535      asn1buf * buf;
536      krb5_address *** val;
537 {
538   decode_array_body(krb5_address,asn1_decode_host_address);
539 }
540
541 asn1_error_code INTERFACE asn1_decode_sequence_of_ticket(buf, val)
542      asn1buf * buf;
543      krb5_ticket *** val;
544 {
545   decode_array_body(krb5_ticket,asn1_decode_ticket);
546 }
547
548 asn1_error_code INTERFACE asn1_decode_sequence_of_krb_cred_info(buf, val)
549      asn1buf * buf;
550      krb5_cred_info *** val;
551 {
552   decode_array_body(krb5_cred_info,asn1_decode_krb_cred_info);
553 }
554
555 asn1_error_code INTERFACE asn1_decode_krb_cred_info(buf, val)
556      asn1buf * buf;
557      krb5_cred_info * val;
558 {
559   setup();
560   { begin_structure();
561     alloc_field(val->session,krb5_keyblock);
562     get_field(*(val->session),0,asn1_decode_encryption_key);
563     if(tagnum == 1){
564       alloc_field(val->client,krb5_principal_data);
565       opt_field(val->client,1,asn1_decode_realm,NULL);
566       opt_field(val->client,2,asn1_decode_principal_name,NULL); }
567     opt_field(val->flags,3,asn1_decode_ticket_flags,0);
568     opt_field(val->times.authtime,4,asn1_decode_kerberos_time,0);
569     opt_field(val->times.starttime,5,asn1_decode_kerberos_time,0);
570     opt_field(val->times.endtime,6,asn1_decode_kerberos_time,0);
571     opt_field(val->times.renew_till,7,asn1_decode_kerberos_time,0);
572     if(tagnum == 8){
573       alloc_field(val->server,krb5_principal_data);
574       opt_field(val->server,8,asn1_decode_realm,NULL);
575       opt_field(val->server,9,asn1_decode_principal_name,NULL); }
576     opt_field(val->caddrs,10,asn1_decode_host_addresses,NULL);
577     end_structure();
578     val->magic = KV5M_CRED_INFO;
579   }
580   cleanup();
581 }
582
583 asn1_error_code INTERFACE asn1_decode_sequence_of_pa_data(buf, val)
584      asn1buf * buf;
585      krb5_pa_data *** val;
586 {
587   decode_array_body(krb5_pa_data,asn1_decode_pa_data);
588 }
589
590 asn1_error_code INTERFACE asn1_decode_pa_data(buf, val)
591      asn1buf * buf;
592      krb5_pa_data * val;
593 {
594   setup();
595   { begin_structure();
596     get_field(val->pa_type,1,asn1_decode_ui_2);
597     get_lenfield(val->length,val->contents,2,asn1_decode_octetstring);
598     end_structure();
599     val->magic = KV5M_PA_DATA;
600   }
601   cleanup();
602 }
603
604 asn1_error_code INTERFACE asn1_decode_last_req(buf, val)
605      asn1buf * buf;
606      krb5_last_req_entry *** val;
607 {
608   decode_array_body(krb5_last_req_entry,asn1_decode_last_req_entry);
609 }
610
611 asn1_error_code INTERFACE asn1_decode_last_req_entry(buf, val)
612      asn1buf * buf;
613      krb5_last_req_entry * val;
614 {
615   setup();
616   { begin_structure();
617     get_field(val->lr_type,0,asn1_decode_octet);
618     get_field(val->value,1,asn1_decode_kerberos_time);
619     end_structure();
620     val->magic = KV5M_LAST_REQ_ENTRY;
621   }
622   cleanup();
623 }
624
625 asn1_error_code INTERFACE asn1_decode_sequence_of_enctype(buf, num, val)
626      asn1buf * buf;
627      int * num;
628      krb5_enctype ** val;
629 {
630   asn1_error_code retval;
631   { sequence_of(buf);
632     while(asn1buf_remains(&seqbuf) > 0){
633       size++;
634       if (*val == NULL)
635         *val = (krb5_enctype*)malloc(size*sizeof(krb5_enctype));
636       else
637         *val = (krb5_enctype*)realloc(*val,size*sizeof(krb5_enctype));
638       if(*val == NULL) return ENOMEM;
639       retval = asn1_decode_enctype(&seqbuf,&((*val)[size-1]));
640       if(retval) return retval;
641     }
642     *num = size;
643     end_sequence_of(buf);
644   }
645   cleanup();
646 }
647
648 asn1_error_code INTERFACE asn1_decode_passwdsequence(buf, val)
649      asn1buf * buf;
650      passwd_phrase_element * val;
651 {
652   setup();
653   { begin_structure();
654     alloc_field(val->passwd,krb5_data);
655     get_lenfield(val->passwd->length,val->passwd->data,
656                  0,asn1_decode_charstring);
657     alloc_field(val->phrase,krb5_data);
658     get_lenfield(val->phrase->length,val->phrase->data,
659                  1,asn1_decode_charstring);
660     end_structure();
661   }
662   cleanup();
663 }
664
665 asn1_error_code INTERFACE asn1_decode_sequence_of_passwdsequence(buf, val)
666      asn1buf * buf;
667      passwd_phrase_element *** val;
668 {
669   decode_array_body(passwd_phrase_element,asn1_decode_passwdsequence);
670 }