* asn1_k_decode.c (asn1_decode_etype_info_entry): If the optional
[krb5.git] / src / lib / krb5 / asn.1 / asn1_k_encode.c
1 /*
2  * src/lib/krb5/asn.1/asn1_k_encode.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_encode.h"
25 #include "asn1_make.h"
26 #include "asn1_encode.h"
27
28 /**** asn1 macros ****/
29 #if 0
30    How to write an asn1 encoder function using these macros:
31
32    asn1_error_code asn1_encode_krb5_substructure(asn1buf *buf,
33                                                  const krb5_type *val,
34                                                  int *retlen)
35    {
36      asn1_setup();
37
38      asn1_addfield(val->last_field, n, asn1_type);
39      asn1_addfield(rep->next_to_last_field, n-1, asn1_type);
40      ...
41
42      /* for OPTIONAL fields */
43      if(rep->field_i == should_not_be_omitted)
44        asn1_addfield(rep->field_i, i, asn1_type);
45
46      /* for string fields (these encoders take an additional argument,
47         the length of the string) */
48      addlenfield(rep->field_length, rep->field, i-1, asn1_type);
49
50      /* if you really have to do things yourself... */
51      retval = asn1_encode_asn1_type(buf,rep->field,&length);
52      if(retval) return retval;
53      sum += length;
54      retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, tag_number, length,
55                              &length);
56      if(retval) return retval;
57      sum += length;
58
59      ...
60      asn1_addfield(rep->second_field, 1, asn1_type);
61      asn1_addfield(rep->first_field, 0, asn1_type);
62      asn1_makeseq();
63
64      asn1_cleanup();
65    }
66 #endif
67
68 /* setup() -- create and initialize bookkeeping variables
69      retval: stores error codes returned from subroutines
70      length: length of the most-recently produced encoding
71      sum: cumulative length of the entire encoding */
72 #define asn1_setup()\
73   asn1_error_code retval;\
74   int length, sum=0
75   
76 /* asn1_addfield -- add a field, or component, to the encoding */
77 #define asn1_addfield(value,tag,encoder)\
78 { retval = encoder(buf,value,&length);\
79   if(retval){\
80     asn1buf_destroy(&buf);\
81     return retval; }\
82   sum += length;\
83   retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
84   if(retval){\
85     asn1buf_destroy(&buf);\
86     return retval; }\
87   sum += length; }
88
89 /* asn1_addlenfield -- add a field whose length must be separately specified */
90 #define asn1_addlenfield(len,value,tag,encoder)\
91 { retval = encoder(buf,len,value,&length);\
92   if(retval){\
93     asn1buf_destroy(&buf);\
94     return retval; }\
95   sum += length;\
96   retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
97   if(retval){\
98     asn1buf_destroy(&buf);\
99     return retval; }\
100   sum += length; }
101
102 /* form a sequence (by adding a sequence header to the current encoding) */
103 #define asn1_makeseq()\
104   retval = asn1_make_sequence(buf,sum,&length);\
105   if(retval){\
106     asn1buf_destroy(&buf);\
107     return retval; }\
108   sum += length
109
110 /* add an APPLICATION class tag to the current encoding */
111 #define asn1_apptag(num)\
112   retval = asn1_make_etag(buf,APPLICATION,num,sum,&length);\
113   if(retval){\
114     asn1buf_destroy(&buf);\
115     return retval; }\
116   sum += length
117
118 /* produce the final output and clean up the workspace */
119 #define asn1_cleanup()\
120   *retlen = sum;\
121   return 0
122
123 asn1_error_code asn1_encode_ui_4(buf, val, retlen)
124      asn1buf * buf;
125      const krb5_ui_4 val;
126      int *retlen;
127 {
128   return asn1_encode_unsigned_integer(buf,val,retlen);
129 }
130
131
132 asn1_error_code asn1_encode_realm(buf, val, retlen)
133      asn1buf * buf;
134      const krb5_principal val;
135      int * retlen;
136 {
137   if(val == NULL || val->realm.data == NULL) return ASN1_MISSING_FIELD;
138   return asn1_encode_generalstring(buf,val->realm.length,val->realm.data,
139                                    retlen);
140 }
141
142 asn1_error_code asn1_encode_principal_name(buf, val, retlen)
143      asn1buf * buf;
144      const krb5_principal val;
145      int * retlen;
146 {
147   asn1_setup();
148   int n;
149
150   if(val == NULL || val->data == NULL) return ASN1_MISSING_FIELD;
151
152   for(n = (int) ((val->length)-1); n >= 0; n--){
153     if(val->data[n].data == NULL) return ASN1_MISSING_FIELD;
154     retval = asn1_encode_generalstring(buf,
155                                        (val->data)[n].length,
156                                        (val->data)[n].data,
157                                        &length);
158     if(retval) return retval;
159     sum += length;
160   }
161   asn1_makeseq();
162   retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,1,sum,&length);
163   if(retval) return retval;
164   sum += length;
165
166   asn1_addfield(val->type,0,asn1_encode_integer);
167
168   asn1_makeseq();
169
170   asn1_cleanup();
171 }
172
173 asn1_error_code asn1_encode_kerberos_time(buf, val, retlen)
174      asn1buf * buf;
175      const krb5_timestamp val;
176      int * retlen;
177      
178 {
179   return asn1_encode_generaltime(buf,val,retlen);
180 }
181
182 asn1_error_code asn1_encode_host_address(buf, val, retlen)
183      asn1buf * buf;
184      const krb5_address * val;
185      int * retlen;
186 {
187   asn1_setup();
188
189   if(val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
190
191   asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
192   asn1_addfield(val->addrtype,0,asn1_encode_integer);
193   asn1_makeseq();
194
195   asn1_cleanup();
196 }
197
198 asn1_error_code asn1_encode_host_addresses(buf, val, retlen)
199      asn1buf * buf;
200      const krb5_address ** val;
201      int * retlen;
202 {
203   asn1_setup();
204   int i;
205
206   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
207
208   for(i=0; val[i] != NULL; i++); /* go to end of array */
209   for(i--; i>=0; i--){
210     retval = asn1_encode_host_address(buf,val[i],&length);
211     if(retval) return retval;
212     sum += length;
213   }
214   asn1_makeseq();
215
216   asn1_cleanup();
217 }
218
219 asn1_error_code asn1_encode_encrypted_data(buf, val, retlen)
220      asn1buf * buf;
221      const krb5_enc_data * val;
222      int * retlen;
223 {
224   asn1_setup();
225
226   if(val == NULL || val->ciphertext.data == NULL) return ASN1_MISSING_FIELD;
227
228   asn1_addlenfield(val->ciphertext.length,val->ciphertext.data,2,asn1_encode_charstring);
229   if(val->kvno)
230     asn1_addfield(val->kvno,1,asn1_encode_integer);
231   asn1_addfield(val->enctype,0,asn1_encode_integer);
232
233   asn1_makeseq();
234
235   asn1_cleanup();
236 }
237
238 asn1_error_code asn1_encode_krb5_flags(buf, val, retlen)
239      asn1buf * buf;
240      const krb5_flags val;
241      int * retlen;
242 {
243   asn1_setup();
244   krb5_flags valcopy = val;
245   int i;
246
247   for(i=0; i<4; i++){
248     retval = asn1buf_insert_octet(buf,(asn1_octet) (valcopy&0xFF));
249     if(retval) return retval;
250     valcopy >>= 8;
251   }
252   retval = asn1buf_insert_octet(buf,0); /* 0 padding bits */
253   if(retval) return retval;
254   sum = 5;
255
256   retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_BITSTRING,sum,
257                          &length);
258   if(retval) return retval;
259   sum += length;
260
261   *retlen = sum;
262   return 0;
263 }
264
265 asn1_error_code asn1_encode_ap_options(buf, val, retlen)
266      asn1buf * buf;
267      const krb5_flags val;
268      int * retlen;
269 {
270   return asn1_encode_krb5_flags(buf,val,retlen);
271 }
272
273 asn1_error_code asn1_encode_ticket_flags(buf, val, retlen)
274      asn1buf * buf;
275      const krb5_flags val;
276      int * retlen;
277 {
278   return asn1_encode_krb5_flags(buf,val,retlen);
279 }
280
281 asn1_error_code asn1_encode_kdc_options(buf, val, retlen)
282      asn1buf * buf;
283      const krb5_flags val;
284      int * retlen;
285 {
286   return asn1_encode_krb5_flags(buf,val,retlen);
287 }
288
289 asn1_error_code asn1_encode_authorization_data(buf, val, retlen)
290      asn1buf * buf;
291      const krb5_authdata ** val;
292      int * retlen;
293 {
294   asn1_setup();
295   int i;
296   
297   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
298   
299   for(i=0; val[i] != NULL; i++); /* get to the end of the array */
300   for(i--; i>=0; i--){
301     retval = asn1_encode_krb5_authdata_elt(buf,val[i],&length);
302     if(retval) return retval;
303     sum += length;
304   }
305   asn1_makeseq();
306
307   asn1_cleanup();
308 }
309
310 asn1_error_code asn1_encode_krb5_authdata_elt(buf, val, retlen)
311      asn1buf * buf;
312      const krb5_authdata * val;
313      int * retlen;
314 {
315   asn1_setup();
316
317   if(val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
318
319   /* ad-data[1]         OCTET STRING */
320   asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
321   /* ad-type[0]         INTEGER */
322   asn1_addfield(val->ad_type,0,asn1_encode_integer);
323   /* SEQUENCE */
324   asn1_makeseq();
325
326   asn1_cleanup();
327 }
328
329 asn1_error_code asn1_encode_kdc_rep(msg_type, buf, val, retlen)
330      int msg_type;
331      asn1buf * buf;
332      const krb5_kdc_rep * val;
333      int * retlen;
334 {
335   asn1_setup();
336
337   if(val == NULL) return ASN1_MISSING_FIELD;
338
339   asn1_addfield(&(val->enc_part),6,asn1_encode_encrypted_data);
340   asn1_addfield(val->ticket,5,asn1_encode_ticket);
341   asn1_addfield(val->client,4,asn1_encode_principal_name);
342   asn1_addfield(val->client,3,asn1_encode_realm);
343   if(val->padata != NULL && val->padata[0] != NULL)
344     asn1_addfield((const krb5_pa_data**)val->padata,2,asn1_encode_sequence_of_pa_data);
345   if (msg_type != KRB5_AS_REP && msg_type != KRB5_TGS_REP)
346           return KRB5_BADMSGTYPE;
347   asn1_addfield(msg_type,1,asn1_encode_integer);
348   asn1_addfield(KVNO,0,asn1_encode_integer);
349   asn1_makeseq();
350
351   asn1_cleanup();
352 }
353
354 asn1_error_code asn1_encode_enc_kdc_rep_part(buf, val, retlen)
355      asn1buf * buf;
356      const krb5_enc_kdc_rep_part * val;
357      int * retlen;
358 {
359   asn1_setup();
360
361   if(val == NULL) return ASN1_MISSING_FIELD;
362
363   /* caddr[11]          HostAddresses OPTIONAL */
364   if(val->caddrs != NULL && val->caddrs[0] != NULL)
365     asn1_addfield((const krb5_address**)(val->caddrs),11,asn1_encode_host_addresses);
366
367   /* sname[10]          PrincipalName */
368   asn1_addfield(val->server,10,asn1_encode_principal_name);
369
370   /* srealm[9]          Realm */
371   asn1_addfield(val->server,9,asn1_encode_realm);
372
373   /* renew-till[8]      KerberosTime OPTIONAL */
374   if(val->flags & TKT_FLG_RENEWABLE)
375     asn1_addfield(val->times.renew_till,8,asn1_encode_kerberos_time);
376
377   /* endtime[7]         KerberosTime */
378   asn1_addfield(val->times.endtime,7,asn1_encode_kerberos_time);
379
380   /* starttime[6]       KerberosTime OPTIONAL */
381   if(val->times.starttime)
382     asn1_addfield(val->times.starttime,6,asn1_encode_kerberos_time);
383
384   /* authtime[5]        KerberosTime */
385   asn1_addfield(val->times.authtime,5,asn1_encode_kerberos_time);
386
387   /* flags[4]           TicketFlags */
388   asn1_addfield(val->flags,4,asn1_encode_ticket_flags);
389
390   /* key-expiration[3]  KerberosTime OPTIONAL */
391   if(val->key_exp)
392     asn1_addfield(val->key_exp,3,asn1_encode_kerberos_time);
393
394   /* nonce[2]           INTEGER */
395   asn1_addfield(val->nonce,2,asn1_encode_integer);
396
397   /* last-req[1]        LastReq */
398   asn1_addfield((const krb5_last_req_entry**)val->last_req,1,asn1_encode_last_req);
399
400   /* key[0]             EncryptionKey */
401   asn1_addfield(val->session,0,asn1_encode_encryption_key);
402
403   /* EncKDCRepPart ::= SEQUENCE */
404   asn1_makeseq();
405
406   asn1_cleanup();
407 }
408
409 asn1_error_code asn1_encode_kdc_req_body(buf, rep, retlen)
410      asn1buf * buf;
411      const krb5_kdc_req * rep;
412      int * retlen;
413 {
414   asn1_setup();
415   
416   if(rep == NULL) return ASN1_MISSING_FIELD;
417
418   /* additional-tickets[11]     SEQUENCE OF Ticket OPTIONAL */
419   if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL)
420     asn1_addfield((const krb5_ticket**)rep->second_ticket,
421                   11,asn1_encode_sequence_of_ticket);
422
423   /* enc-authorization-data[10] EncryptedData OPTIONAL, */
424   /*                            -- Encrypted AuthorizationData encoding */
425   if(rep->authorization_data.ciphertext.data != NULL)
426     asn1_addfield(&(rep->authorization_data),10,asn1_encode_encrypted_data);
427
428   /* addresses[9]               HostAddresses OPTIONAL, */
429   if(rep->addresses != NULL && rep->addresses[0] != NULL)
430     asn1_addfield((const krb5_address**)rep->addresses,9,asn1_encode_host_addresses);
431
432   /* etype[8]                   SEQUENCE OF INTEGER, -- EncryptionType, */
433   /*                            -- in preference order */
434   asn1_addlenfield(rep->nktypes,rep->ktype,8,asn1_encode_sequence_of_enctype);
435
436   /* nonce[7]                   INTEGER, */
437   asn1_addfield(rep->nonce,7,asn1_encode_integer);
438
439   /* rtime[6]                   KerberosTime OPTIONAL, */
440   if(rep->rtime)
441     asn1_addfield(rep->rtime,6,asn1_encode_kerberos_time);
442
443   /* till[5]                    KerberosTime, */
444   asn1_addfield(rep->till,5,asn1_encode_kerberos_time);
445
446   /* from[4]                    KerberosTime OPTIONAL, */
447   if(rep->from)
448   asn1_addfield(rep->from,4,asn1_encode_kerberos_time);
449
450   /* sname[3]                   PrincipalName OPTIONAL, */
451   if(rep->server != NULL)
452     asn1_addfield(rep->server,3,asn1_encode_principal_name);
453
454   /* realm[2]                   Realm, -- Server's realm */
455   /*                            -- Also client's in AS-REQ */
456   if(rep->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY){
457     if(rep->second_ticket != NULL && rep->second_ticket[0] != NULL){
458       asn1_addfield(rep->second_ticket[0]->server,2,asn1_encode_realm)
459     } else return ASN1_MISSING_FIELD;
460   }else if(rep->server != NULL){
461     asn1_addfield(rep->server,2,asn1_encode_realm);
462   }else return ASN1_MISSING_FIELD;
463
464   /* cname[1]                   PrincipalName OPTIONAL, */
465   /*                            -- Used only in AS-REQ */
466   if(rep->client != NULL)
467     asn1_addfield(rep->client,1,asn1_encode_principal_name);
468
469   /* kdc-options[0]             KDCOptions, */
470   asn1_addfield(rep->kdc_options,0,asn1_encode_kdc_options);
471
472   /* KDC-REQ-BODY ::= SEQUENCE */
473   asn1_makeseq();
474
475   asn1_cleanup();
476 }
477
478 asn1_error_code asn1_encode_encryption_key(buf, val, retlen)
479      asn1buf * buf;
480      const krb5_keyblock * val;
481      int * retlen;
482 {
483   asn1_setup();
484
485   if(val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
486
487   asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
488   asn1_addfield(val->enctype,0,asn1_encode_integer);
489   asn1_makeseq();
490
491   asn1_cleanup();
492 }
493
494 asn1_error_code asn1_encode_checksum(buf, val, retlen)
495      asn1buf * buf;
496      const krb5_checksum * val;
497      int * retlen;
498 {
499   asn1_setup();
500
501   if(val == NULL || val->contents == NULL) return ASN1_MISSING_FIELD;
502
503   asn1_addlenfield(val->length,val->contents,1,asn1_encode_octetstring);
504   asn1_addfield(val->checksum_type,0,asn1_encode_integer);
505   asn1_makeseq();
506
507   asn1_cleanup();
508 }
509
510 asn1_error_code asn1_encode_transited_encoding(buf, val, retlen)
511      asn1buf * buf;
512      const krb5_transited * val;
513      int * retlen;
514 {
515   asn1_setup();
516
517   if(val == NULL ||
518      (val->tr_contents.length != 0 && val->tr_contents.data == NULL))
519     return ASN1_MISSING_FIELD;
520
521   asn1_addlenfield(val->tr_contents.length,val->tr_contents.data,
522                    1,asn1_encode_charstring);
523   asn1_addfield(val->tr_type,0,asn1_encode_integer);
524   asn1_makeseq();
525
526   asn1_cleanup();
527 }
528
529 asn1_error_code asn1_encode_last_req(buf, val, retlen)
530      asn1buf * buf;
531      const krb5_last_req_entry ** val;
532      int * retlen;
533 {
534   asn1_setup();
535   int i;
536
537   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
538
539   for(i=0; val[i] != NULL; i++); /* go to end of array */
540   for(i--; i>=0; i--){
541     retval = asn1_encode_last_req_entry(buf,val[i],&length);
542     if(retval) return retval;
543     sum += length;
544   }
545   asn1_makeseq();
546
547   asn1_cleanup();
548 }
549
550 asn1_error_code asn1_encode_last_req_entry(buf, val, retlen)
551      asn1buf * buf;
552      const krb5_last_req_entry * val;
553      int * retlen;
554 {
555   asn1_setup();
556
557   if(val == NULL) return ASN1_MISSING_FIELD;
558
559   asn1_addfield(val->value,1,asn1_encode_kerberos_time);
560   asn1_addfield(val->lr_type,0,asn1_encode_integer);
561   asn1_makeseq();
562
563   asn1_cleanup();
564 }
565
566 asn1_error_code asn1_encode_sequence_of_pa_data(buf, val, retlen)
567      asn1buf * buf;
568      const krb5_pa_data ** val;
569      int * retlen;
570 {
571   asn1_setup();
572   int i;
573
574   if (val == NULL) return ASN1_MISSING_FIELD;
575
576   for(i=0; val[i] != NULL; i++);
577   for(i--; i>=0; i--){
578     retval = asn1_encode_pa_data(buf,val[i],&length);
579     if(retval) return retval;
580     sum += length;
581   }
582   asn1_makeseq();
583
584   asn1_cleanup();
585 }
586
587 asn1_error_code asn1_encode_pa_data(buf, val, retlen)
588      asn1buf * buf;
589      const krb5_pa_data * val;
590      int * retlen;
591 {
592   asn1_setup();
593
594   if(val == NULL || (val->length != 0 && val->contents == NULL))
595      return ASN1_MISSING_FIELD;
596
597   asn1_addlenfield(val->length,val->contents,2,asn1_encode_octetstring);
598   asn1_addfield(val->pa_type,1,asn1_encode_integer);
599   asn1_makeseq();
600
601   asn1_cleanup();
602 }
603
604 asn1_error_code asn1_encode_sequence_of_ticket(buf, val, retlen)
605      asn1buf * buf;
606      const krb5_ticket ** val;
607      int * retlen;
608 {
609   asn1_setup();
610   int i;
611
612   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
613
614   for(i=0; val[i] != NULL; i++);
615   for(i--; i>=0; i--){
616     retval = asn1_encode_ticket(buf,val[i],&length);
617     if(retval) return retval;
618     sum += length;
619   }
620   asn1_makeseq();
621
622   asn1_cleanup();
623 }
624
625 asn1_error_code asn1_encode_ticket(buf, val, retlen)
626      asn1buf * buf;
627      const krb5_ticket * val;
628      int * retlen;
629 {
630   asn1_setup();
631
632   if(val == NULL) return ASN1_MISSING_FIELD;
633
634   asn1_addfield(&(val->enc_part),3,asn1_encode_encrypted_data);
635   asn1_addfield(val->server,2,asn1_encode_principal_name);
636   asn1_addfield(val->server,1,asn1_encode_realm);
637   asn1_addfield(KVNO,0,asn1_encode_integer);
638   asn1_makeseq();
639   asn1_apptag(1);
640
641   asn1_cleanup();
642 }
643
644 asn1_error_code asn1_encode_sequence_of_enctype(buf, len, val, retlen)
645      asn1buf * buf;
646      const int len;
647      const krb5_enctype * val;
648      int * retlen;
649 {
650   asn1_setup();
651   int i;
652
653   if(val == NULL) return ASN1_MISSING_FIELD;
654
655   for(i=len-1; i>=0; i--){
656     retval = asn1_encode_integer(buf,val[i],&length);
657     if(retval) return retval;
658     sum += length;
659   }
660   asn1_makeseq();
661
662   asn1_cleanup();
663 }
664
665 asn1_error_code asn1_encode_kdc_req(msg_type, buf, val, retlen)
666      int msg_type;
667      asn1buf * buf;
668      const krb5_kdc_req * val;
669      int * retlen;
670 {
671   asn1_setup();
672
673   if(val == NULL) return ASN1_MISSING_FIELD;
674
675   asn1_addfield(val,4,asn1_encode_kdc_req_body);
676   if(val->padata != NULL && val->padata[0] != NULL)
677     asn1_addfield((const krb5_pa_data**)val->padata,3,asn1_encode_sequence_of_pa_data);
678   if (msg_type != KRB5_AS_REQ && msg_type != KRB5_TGS_REQ)
679           return KRB5_BADMSGTYPE;
680   asn1_addfield(msg_type,2,asn1_encode_integer);
681   asn1_addfield(KVNO,1,asn1_encode_integer);
682   asn1_makeseq();
683
684   asn1_cleanup();
685 }
686
687 asn1_error_code asn1_encode_krb_safe_body(buf, val, retlen)
688      asn1buf * buf;
689      const krb5_safe * val;
690      int * retlen;
691 {
692   asn1_setup();
693
694   if(val == NULL) return ASN1_MISSING_FIELD;
695
696   if(val->r_address != NULL)
697     asn1_addfield(val->r_address,5,asn1_encode_host_address);
698   asn1_addfield(val->s_address,4,asn1_encode_host_address);
699   if(val->seq_number)
700     asn1_addfield(val->seq_number,3,asn1_encode_integer);
701   if(val->timestamp){
702     asn1_addfield(val->usec,2,asn1_encode_integer);
703     asn1_addfield(val->timestamp,1,asn1_encode_kerberos_time);
704   }
705   if(val->user_data.data == NULL) return ASN1_MISSING_FIELD;
706   asn1_addlenfield(val->user_data.length,val->user_data.data,0,asn1_encode_charstring)
707 ;
708
709   asn1_makeseq();
710   asn1_cleanup();
711 }
712
713 asn1_error_code asn1_encode_sequence_of_krb_cred_info(buf, val, retlen)
714      asn1buf * buf;
715      const krb5_cred_info ** val;
716      int * retlen;
717 {
718   asn1_setup();
719   int i;
720
721   if(val == NULL) return ASN1_MISSING_FIELD;
722
723   for(i=0; val[i] != NULL; i++);
724   for(i--; i>=0; i--){
725     retval = asn1_encode_krb_cred_info(buf,val[i],&length);
726     if(retval) return retval;
727     sum += length;
728   }
729   asn1_makeseq();
730
731   asn1_cleanup();
732 }
733
734 asn1_error_code asn1_encode_krb_cred_info(buf, val, retlen)
735      asn1buf * buf;
736      const krb5_cred_info * val;
737      int * retlen;
738 {
739   asn1_setup();
740
741   if(val == NULL) return ASN1_MISSING_FIELD;
742
743   if(val->caddrs != NULL && val->caddrs[0] != NULL)
744     asn1_addfield((const krb5_address**)val->caddrs,10,asn1_encode_host_addresses);
745   if(val->server != NULL){
746     asn1_addfield(val->server,9,asn1_encode_principal_name);
747     asn1_addfield(val->server,8,asn1_encode_realm);
748   }
749   if(val->times.renew_till)
750     asn1_addfield(val->times.renew_till,7,asn1_encode_kerberos_time);
751   if(val->times.endtime)
752     asn1_addfield(val->times.endtime,6,asn1_encode_kerberos_time);
753   if(val->times.starttime)
754     asn1_addfield(val->times.starttime,5,asn1_encode_kerberos_time);
755   if(val->times.authtime)
756     asn1_addfield(val->times.authtime,4,asn1_encode_kerberos_time);
757   if(val->flags)
758     asn1_addfield(val->flags,3,asn1_encode_ticket_flags);
759   if(val->client != NULL){
760     asn1_addfield(val->client,2,asn1_encode_principal_name);
761     asn1_addfield(val->client,1,asn1_encode_realm);
762   }
763   asn1_addfield(val->session,0,asn1_encode_encryption_key);
764
765   asn1_makeseq();
766
767   asn1_cleanup();
768 }
769
770 asn1_error_code asn1_encode_etype_info_entry(buf, val, retlen)
771      asn1buf * buf;
772      const krb5_etype_info_entry * val;
773      int * retlen;
774 {
775   asn1_setup();
776
777   if(val == NULL || (val->length >= 0 && val->salt == NULL))
778      return ASN1_MISSING_FIELD;
779
780   if (val->length >= 0)
781           asn1_addlenfield((int) val->length,val->salt,1,
782                            asn1_encode_octetstring);
783   asn1_addfield(val->etype,0,asn1_encode_integer);
784   asn1_makeseq();
785
786   asn1_cleanup();
787 }
788
789 asn1_error_code asn1_encode_etype_info(buf, val, retlen)
790      asn1buf * buf;
791      const krb5_etype_info_entry ** val;
792      int * retlen;
793 {
794     asn1_setup();
795     int i;
796   
797     if (val == NULL) return ASN1_MISSING_FIELD;
798   
799     for(i=0; val[i] != NULL; i++); /* get to the end of the array */
800     for(i--; i>=0; i--){
801         retval = asn1_encode_etype_info_entry(buf,val[i],&length);
802         if(retval) return retval;
803         sum += length;
804     }
805     asn1_makeseq();
806     asn1_cleanup();
807 }
808
809 asn1_error_code asn1_encode_sequence_of_passwdsequence(buf, val, retlen)
810      asn1buf * buf;
811      const passwd_phrase_element ** val;
812      int * retlen;
813 {
814   asn1_setup();
815   int i;
816   
817   if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
818   
819   for(i=0; val[i] != NULL; i++); /* get to the end of the array */
820   for(i--; i>=0; i--){
821     retval = asn1_encode_passwdsequence(buf,val[i],&length);
822     if(retval) return retval;
823     sum += length;
824   }
825   asn1_makeseq();
826   asn1_cleanup();
827 }
828
829 asn1_error_code asn1_encode_passwdsequence(buf, val, retlen)
830      asn1buf * buf;
831      const passwd_phrase_element * val;
832      int * retlen;
833 {
834   asn1_setup();
835   asn1_addlenfield(val->phrase->length,val->phrase->data,1,asn1_encode_charstring);
836   asn1_addlenfield(val->passwd->length,val->passwd->data,0,asn1_encode_charstring);
837   asn1_makeseq();
838   asn1_cleanup();
839 }
840