1 //! Kerberos 5 parsing functions
2 
3 use der_parser::ber::*;
4 use der_parser::der::*;
5 use der_parser::error::*;
6 use nom::error::ErrorKind;
7 use nom::{Err, IResult};
8 use std::str;
9 
10 use crate::krb5::*;
11 
12 /// Parse a signed 32 bits integer
13 ///
14 /// <pre>
15 /// Int32           ::= INTEGER (-2147483648..2147483647)
16 ///                     -- signed values representable in 32 bits
17 /// </pre>
parse_der_int32(i: &[u8]) -> IResult<&[u8], i32, BerError>18 pub fn parse_der_int32(i: &[u8]) -> IResult<&[u8], i32, BerError> {
19     map_res!(i, parse_der_integer, |x: DerObject| {
20         match x.content {
21             BerObjectContent::Integer(i) => match i.len() {
22                 1 => Ok(i[0] as i8 as i32),
23                 2 => Ok((i[0] as i8 as i32) << 8 | (i[1] as i32)),
24                 3 => Ok((i[0] as i8 as i32) << 16 | (i[1] as i32) << 8 | (i[2] as i32)),
25                 4 => Ok((i[0] as i8 as i32) << 24
26                     | (i[1] as i32) << 16
27                     | (i[2] as i32) << 8
28                     | (i[3] as i32)),
29                 _ => Err(BerError::IntegerTooLarge),
30             },
31             _ => Err(BerError::BerTypeError),
32         }
33     })
34 }
35 
36 //  Microseconds    ::= INTEGER (0..999999)
37 //                      -- microseconds
parse_der_microseconds(i: &[u8]) -> IResult<&[u8], u32, BerError>38 fn parse_der_microseconds(i: &[u8]) -> IResult<&[u8], u32, BerError> {
39     verify!(i, parse_der_u32, |x: &u32| *x <= 999_999)
40 }
41 
42 // helper macro to give same result as opt!(complete!(parse_der_tagged!(i,tag,fn) but with
43 // less complexity, and faster
44 macro_rules! opt_parse_der_tagged(
45     ($i:expr, EXPLICIT $tag:expr, $submac:ident!( $($args:tt)*)) => ({
46         use der_parser::der::der_read_element_header;
47         use nom::{Err, Needed};
48         match der_read_element_header($i) {
49             Ok((rem,hdr)) => {
50                 if $tag != hdr.tag.0 {
51                     Ok(($i,None))
52                 } else {
53                     let len = hdr.len as usize;
54                     if rem.len() < len { Err(Err::Incomplete(Needed::Size(len))) } // tag was correct, this really is an error
55                     else {
56                         match $submac!(&rem[0..len], $($args)*) {
57                             Ok((_,res)) => Ok((&rem[len..],Some(res))),
58                             _           => Ok(($i,None))
59                         }
60                     }
61                 }
62             },
63             _ => Ok(($i,None))
64         }
65     });
66     ($i:expr, EXPLICIT $tag:expr, $f:ident) => ({
67         opt_parse_der_tagged!($i, EXPLICIT $tag, call!($f))
68     });
69 );
70 
71 /// Parse a Kerberos string object
72 ///
73 /// <pre>
74 /// KerberosString  ::= GeneralString (IA5String)
75 /// </pre>
parse_kerberos_string(i: &[u8]) -> IResult<&[u8], String, BerError>76 pub fn parse_kerberos_string(i: &[u8]) -> IResult<&[u8], String, BerError> {
77     match parse_der_generalstring(i) {
78         Ok((rem, ref obj)) => {
79             if let BerObjectContent::GeneralString(s) = obj.content {
80                 match str::from_utf8(s) {
81                     Ok(r) => Ok((rem, r.to_owned())),
82                     Err(_) => Err(Err::Error(error_position!(i, ErrorKind::IsNot))),
83                 }
84             } else {
85                 Err(Err::Error(error_position!(i, ErrorKind::Tag)))
86             }
87         }
88         Err(e) => Err(e),
89     }
90 }
91 
parse_kerberos_string_sequence(i: &[u8]) -> IResult<&[u8], Vec<String>, BerError>92 fn parse_kerberos_string_sequence(i: &[u8]) -> IResult<&[u8], Vec<String>, BerError> {
93     parse_der_struct!(
94         i,
95         TAG DerTag::Sequence,
96         v: many0!(complete!(parse_kerberos_string)) >>
97         ( v )
98     )
99     .map(|(rem, x)| (rem, x.1))
100 }
101 
102 /// Parse Kerberos flags
103 ///
104 /// <pre>
105 /// KerberosFlags   ::= BIT STRING (SIZE (32..MAX))
106 ///                     -- minimum number of bits shall be sent,
107 ///                     -- but no fewer than 32
108 /// </pre>
109 #[inline]
parse_kerberos_flags(i: &[u8]) -> IResult<&[u8], DerObject, BerError>110 pub fn parse_kerberos_flags(i: &[u8]) -> IResult<&[u8], DerObject, BerError> {
111     parse_der_bitstring(i)
112 }
113 
114 /// Parse of a Kerberos Realm
115 ///
116 /// <pre>
117 /// Realm           ::= KerberosString
118 /// </pre>
119 #[inline]
parse_krb5_realm(i: &[u8]) -> IResult<&[u8], Realm, BerError>120 pub fn parse_krb5_realm(i: &[u8]) -> IResult<&[u8], Realm, BerError> {
121     map!(i, parse_kerberos_string, Realm)
122 }
123 
124 /// Parse Kerberos PrincipalName
125 ///
126 /// <pre>
127 /// PrincipalName   ::= SEQUENCE {
128 ///         name-type       [0] Int32,
129 ///         name-string     [1] SEQUENCE OF KerberosString
130 /// }
131 /// </pre>
parse_krb5_principalname(i: &[u8]) -> IResult<&[u8], PrincipalName, BerError>132 pub fn parse_krb5_principalname(i: &[u8]) -> IResult<&[u8], PrincipalName, BerError> {
133     map_res!(
134         i,
135         parse_der_struct!(
136             t: parse_der_tagged!(EXPLICIT 0, parse_der_int32)
137                 >> s: parse_der_tagged!(EXPLICIT 1, parse_kerberos_string_sequence)
138                 >> (PrincipalName {
139                     name_type: NameType(t),
140                     name_string: s,
141                 })
142         ),
143         |(hdr, t): (BerObjectHeader, PrincipalName)| {
144             if hdr.tag != BerTag::Sequence {
145                 return Err("not a sequence!");
146             }
147             Ok(t)
148         }
149     )
150 }
151 
152 /// Parse of a Kerberos Time
153 ///
154 /// <pre>
155 /// KerberosTime    ::= GeneralizedTime -- with no fractional seconds
156 /// </pre>
157 #[inline]
parse_kerberos_time(i: &[u8]) -> IResult<&[u8], DerObject, BerError>158 pub fn parse_kerberos_time(i: &[u8]) -> IResult<&[u8], DerObject, BerError> {
159     parse_der_generalizedtime(i)
160 }
161 
162 /// Parse Kerberos HostAddress
163 ///
164 /// <pre>
165 /// HostAddress     ::= SEQUENCE  {
166 ///         addr-type       [0] Int32,
167 ///         address         [1] OCTET STRING
168 /// }
169 /// </pre>
parse_krb5_hostaddress<'a>(i: &'a [u8]) -> IResult<&'a [u8], HostAddress<'a>, BerError>170 pub fn parse_krb5_hostaddress<'a>(i: &'a [u8]) -> IResult<&'a [u8], HostAddress<'a>, BerError> {
171     parse_der_struct!(
172         i,
173         TAG DerTag::Sequence,
174         t: parse_der_tagged!(EXPLICIT 0, parse_der_int32) >>
175         a: map_res!(parse_der_tagged!(EXPLICIT 1, parse_der_octetstring),|x: DerObject<'a>| x.as_slice()) >>
176         ( HostAddress{
177             addr_type: AddressType(t),
178             address: a,
179         })
180     ).map(|(rem,x)| (rem,x.1))
181 }
182 
183 /// Parse Kerberos HostAddresses
184 ///
185 /// <pre>
186 /// -- NOTE: HostAddresses is always used as an OPTIONAL field and
187 /// -- should not be empty.
188 /// HostAddresses   -- NOTE: subtly different from rfc1510,
189 ///                 -- but has a value mapping and encodes the same
190 ///         ::= SEQUENCE OF HostAddress
191 /// </pre>
parse_krb5_hostaddresses(i: &[u8]) -> IResult<&[u8], Vec<HostAddress>, BerError>192 pub fn parse_krb5_hostaddresses(i: &[u8]) -> IResult<&[u8], Vec<HostAddress>, BerError> {
193     parse_der_struct!(
194         i,
195         TAG DerTag::Sequence,
196         v: many0!(complete!(parse_krb5_hostaddress)) >>
197         ( v )
198     )
199     .map(|(rem, x)| (rem, x.1))
200 }
201 
202 /// Parse Kerberos Ticket
203 ///
204 /// <pre>
205 /// Ticket          ::= [APPLICATION 1] SEQUENCE {
206 ///         tkt-vno         [0] INTEGER (5),
207 ///         realm           [1] Realm,
208 ///         sname           [2] PrincipalName,
209 ///         enc-part        [3] EncryptedData -- EncTicketPart
210 /// }
211 /// </pre>
parse_krb5_ticket<'a>(i: &'a [u8]) -> IResult<&'a [u8], Ticket<'a>, BerError>212 pub fn parse_krb5_ticket<'a>(i: &'a [u8]) -> IResult<&'a [u8], Ticket<'a>, BerError> {
213     parse_der_application!(
214         i,
215         APPLICATION 1,
216         st: parse_der_struct!(
217             TAG DerTag::Sequence,
218             no: parse_der_tagged!(EXPLICIT 0, parse_der_u32) >>
219                 error_if!(no != 5, ErrorKind::Tag) >>
220             r:  parse_der_tagged!(EXPLICIT 1, parse_krb5_realm) >>
221             s:  parse_der_tagged!(EXPLICIT 2, parse_krb5_principalname) >>
222             e:  map_res!(parse_der,|x: DerObject<'a>| x.as_slice()) >>
223             ( Ticket{
224                 tkt_vno: no,
225                 realm: r,
226                 sname: s,
227                 enc_part: e
228             })
229         ) >> (st)
230     )
231     .map(|(rem, t)| (rem, (t.1).1))
232 }
233 
234 /// Parse Kerberos EncryptedData
235 ///
236 /// <pre>
237 /// EncryptedData   ::= SEQUENCE {
238 ///         etype   [0] Int32 -- EncryptionType --,
239 ///         kvno    [1] UInt32 OPTIONAL,
240 ///         cipher  [2] OCTET STRING -- ciphertext
241 /// }
242 /// </pre>
parse_encrypted<'a>(i: &'a [u8]) -> IResult<&'a [u8], EncryptedData<'a>, BerError>243 pub fn parse_encrypted<'a>(i: &'a [u8]) -> IResult<&'a [u8], EncryptedData<'a>, BerError> {
244     parse_der_struct!(
245         i,
246         TAG DerTag::Sequence,
247         e: parse_der_tagged!(EXPLICIT 0, parse_der_int32) >>
248         k: opt_parse_der_tagged!(EXPLICIT 1, parse_der_u32) >>
249         c: map_res!(parse_der_tagged!(EXPLICIT 2, parse_der_octetstring), |x: DerObject<'a>| x.as_slice()) >>
250            eof!() >>
251         ( EncryptedData{
252             etype: EncryptionType(e),
253             kvno: k,
254             cipher: c
255         })
256     ).map(|(rem,t)| (rem,t.1))
257 }
258 
259 /// Parse a Kerberos KDC Request
260 ///
261 /// <pre>
262 /// KDC-REQ         ::= SEQUENCE {
263 ///         -- NOTE: first tag is [1], not [0]
264 ///         pvno            [1] INTEGER (5) ,
265 ///         msg-type        [2] INTEGER (10 -- AS -- | 12 -- TGS --),
266 ///         padata          [3] SEQUENCE OF PA-DATA OPTIONAL
267 ///                             -- NOTE: not empty --,
268 ///         req-body        [4] KDC-REQ-BODY
269 /// }
270 /// </pre>
parse_kdc_req(i: &[u8]) -> IResult<&[u8], KdcReq, BerError>271 pub fn parse_kdc_req(i: &[u8]) -> IResult<&[u8], KdcReq, BerError> {
272     parse_der_struct!(
273         i,
274         TAG DerTag::Sequence,
275         pvno:     parse_der_tagged!(EXPLICIT 1, parse_der_u32) >>
276         t:        parse_der_tagged!(EXPLICIT 2, parse_der_u32) >>
277         d:        opt_parse_der_tagged!(EXPLICIT 3, parse_krb5_padata_sequence) >>
278         req_body: parse_der_tagged!(EXPLICIT 4, parse_kdc_req_body) >>
279                   eof!() >>
280         ( KdcReq{
281             pvno,
282             msg_type: MessageType(t),
283             padata: d.unwrap_or_default(),
284             req_body
285         })
286     )
287     .map(|(rem, t)| (rem, t.1))
288 }
289 
290 /// Parse the body of a Kerberos KDC Request
291 ///
292 /// <pre>
293 /// KDC-REQ-BODY    ::= SEQUENCE {
294 ///         kdc-options             [0] KDCOptions,
295 ///         cname                   [1] PrincipalName OPTIONAL
296 ///                                     -- Used only in AS-REQ --,
297 ///         realm                   [2] Realm
298 ///                                     -- Server's realm
299 ///                                     -- Also client's in AS-REQ --,
300 ///         sname                   [3] PrincipalName OPTIONAL,
301 ///         from                    [4] KerberosTime OPTIONAL,
302 ///         till                    [5] KerberosTime,
303 ///         rtime                   [6] KerberosTime OPTIONAL,
304 ///         nonce                   [7] UInt32,
305 ///         etype                   [8] SEQUENCE OF Int32 -- EncryptionType
306 ///                                     -- in preference order --,
307 ///         addresses               [9] HostAddresses OPTIONAL,
308 ///         enc-authorization-data  [10] EncryptedData OPTIONAL
309 ///                                     -- AuthorizationData --,
310 ///         additional-tickets      [11] SEQUENCE OF Ticket OPTIONAL
311 ///                                        -- NOTE: not empty
312 /// }
313 /// </pre>
parse_kdc_req_body(i: &[u8]) -> IResult<&[u8], KdcReqBody, BerError>314 pub fn parse_kdc_req_body(i: &[u8]) -> IResult<&[u8], KdcReqBody, BerError> {
315     parse_der_struct!(
316         i,
317         TAG DerTag::Sequence,
318         o:     parse_der_tagged!(EXPLICIT 0,parse_kerberos_flags) >>
319         cname: opt_parse_der_tagged!(EXPLICIT 1,parse_krb5_principalname) >>
320         realm: parse_der_tagged!(EXPLICIT 2,parse_krb5_realm) >>
321         sname: opt_parse_der_tagged!(EXPLICIT 3,parse_krb5_principalname) >>
322         from:  opt_parse_der_tagged!(EXPLICIT 4,parse_kerberos_time) >>
323         till:  parse_der_tagged!(EXPLICIT 5,parse_kerberos_time) >>
324         rtime: opt_parse_der_tagged!(EXPLICIT 6,parse_kerberos_time) >>
325         nonce: parse_der_tagged!(EXPLICIT 7, parse_der_u32) >>
326         etype: parse_der_tagged!(EXPLICIT 8,
327                                  parse_der_struct!(v: many1!(complete!(parse_der_int32)) >> (v.iter().map(|&x| EncryptionType(x)).collect()))
328                                  ) >>
329         addr:  opt_parse_der_tagged!(EXPLICIT 9,parse_krb5_hostaddresses) >>
330         ead:   opt_parse_der_tagged!(EXPLICIT 10,parse_encrypted) >>
331         atkts: opt_parse_der_tagged!(EXPLICIT 11,
332                                  parse_der_struct!(v: many1!(complete!(parse_krb5_ticket)) >> (v))
333                                  ) >>
334                eof!() >>
335         ( KdcReqBody{
336             kdc_options: o,
337             cname,
338             realm,
339             sname,
340             from,
341             till,
342             rtime,
343             nonce,
344             etype: etype.1,
345             addresses: addr.unwrap_or_default(),
346             enc_authorization_data: ead,
347             additional_tickets: if atkts.is_some() { atkts.unwrap().1 } else { vec![] }
348         })
349     ).map(|(rem,t)| (rem,t.1))
350 }
351 
352 /// Parse a Kerberos AS Request
353 ///
354 /// <pre>
355 /// AS-REQ          ::= [APPLICATION 10] KDC-REQ
356 /// </pre>
parse_as_req(i: &[u8]) -> IResult<&[u8], KdcReq, BerError>357 pub fn parse_as_req(i: &[u8]) -> IResult<&[u8], KdcReq, BerError> {
358     parse_der_application!(
359         i,
360         APPLICATION 10,
361         req: parse_kdc_req >> (req)
362     )
363     .map(|(rem, t)| (rem, t.1))
364 }
365 
366 /// Parse a Kerberos TGS Request
367 ///
368 /// <pre>
369 /// TGS-REQ          ::= [APPLICATION 12] KDC-REQ
370 /// </pre>
parse_tgs_req(i: &[u8]) -> IResult<&[u8], KdcReq, BerError>371 pub fn parse_tgs_req(i: &[u8]) -> IResult<&[u8], KdcReq, BerError> {
372     parse_der_application!(
373         i,
374         APPLICATION 12,
375         req: parse_kdc_req >> (req)
376     )
377     .map(|(rem, t)| (rem, t.1))
378 }
379 
380 /// Parse a Kerberos KDC Reply
381 ///
382 /// <pre>
383 /// KDC-REP         ::= SEQUENCE {
384 ///         pvno            [0] INTEGER (5),
385 ///         msg-type        [1] INTEGER (11 -- AS -- | 13 -- TGS --),
386 ///         padata          [2] SEQUENCE OF PA-DATA OPTIONAL
387 ///                                 -- NOTE: not empty --,
388 ///         crealm          [3] Realm,
389 ///         cname           [4] PrincipalName,
390 ///         ticket          [5] Ticket,
391 ///         enc-part        [6] EncryptedData
392 ///                                 -- EncASRepPart or EncTGSRepPart,
393 ///                                 -- as appropriate
394 /// }
395 /// </pre>
parse_kdc_rep(i: &[u8]) -> IResult<&[u8], KdcRep, BerError>396 pub fn parse_kdc_rep(i: &[u8]) -> IResult<&[u8], KdcRep, BerError> {
397     parse_der_struct!(
398         i,
399         TAG DerTag::Sequence,
400         pvno:     parse_der_tagged!(EXPLICIT 0,parse_der_u32) >>
401         msgtype:  parse_der_tagged!(EXPLICIT 1,parse_der_u32) >>
402         padata:   opt_parse_der_tagged!(EXPLICIT 2,parse_krb5_padata_sequence) >>
403         crealm:   parse_der_tagged!(EXPLICIT 3,parse_krb5_realm) >>
404         cname:    parse_der_tagged!(EXPLICIT 4,parse_krb5_principalname) >>
405         ticket:   parse_der_tagged!(EXPLICIT 5,parse_krb5_ticket) >>
406         enc_part: parse_der_tagged!(EXPLICIT 6,parse_encrypted) >>
407                   eof!() >>
408         ( KdcRep{
409             pvno,
410             msg_type: MessageType(msgtype),
411             padata: padata.unwrap_or_default(),
412             crealm,
413             cname,
414             ticket,
415             enc_part,
416         })
417     )
418     .map(|(rem, t)| (rem, t.1))
419 }
420 
421 /// Parse a Kerberos AS Reply
422 ///
423 /// <pre>
424 /// AS-REP          ::= [APPLICATION 11] KDC-REP
425 /// </pre>
parse_as_rep(i: &[u8]) -> IResult<&[u8], KdcRep, BerError>426 pub fn parse_as_rep(i: &[u8]) -> IResult<&[u8], KdcRep, BerError> {
427     parse_der_application!(
428         i,
429         APPLICATION 11,
430         rep: parse_kdc_rep >> (rep)
431     )
432     .map(|(rem, t)| (rem, t.1))
433 }
434 
435 /// Parse a Kerberos TGS Reply
436 ///
437 /// <pre>
438 /// TGS-REP          ::= [APPLICATION 13] KDC-REP
439 /// </pre>
parse_tgs_rep(i: &[u8]) -> IResult<&[u8], KdcRep, BerError>440 pub fn parse_tgs_rep(i: &[u8]) -> IResult<&[u8], KdcRep, BerError> {
441     parse_der_application!(
442         i,
443         APPLICATION 13,
444         rep: parse_kdc_rep >> (rep)
445     )
446     .map(|(rem, t)| (rem, t.1))
447 }
448 
449 /// Parse a Kerberos Error
450 ///
451 /// <pre>
452 /// KRB-ERROR       ::= [APPLICATION 30] SEQUENCE {
453 ///         pvno            [0] INTEGER (5),
454 ///         msg-type        [1] INTEGER (30),
455 ///         ctime           [2] KerberosTime OPTIONAL,
456 ///         cusec           [3] Microseconds OPTIONAL,
457 ///         stime           [4] KerberosTime,
458 ///         susec           [5] Microseconds,
459 ///         error-code      [6] Int32,
460 ///         crealm          [7] Realm OPTIONAL,
461 ///         cname           [8] PrincipalName OPTIONAL,
462 ///         realm           [9] Realm -- service realm --,
463 ///         sname           [10] PrincipalName -- service name --,
464 ///         e-text          [11] KerberosString OPTIONAL,
465 ///         e-data          [12] OCTET STRING OPTIONAL
466 /// }
467 /// </pre>
parse_krb_error(i: &[u8]) -> IResult<&[u8], KrbError, BerError>468 pub fn parse_krb_error(i: &[u8]) -> IResult<&[u8], KrbError, BerError> {
469     parse_der_application!(
470         i,
471         APPLICATION 30,
472         st: parse_der_struct!(
473             TAG DerTag::Sequence,
474             pvno:    parse_der_tagged!(EXPLICIT 0,parse_der_u32) >>
475             msgtype: parse_der_tagged!(EXPLICIT 1,parse_der_u32) >>
476                      error_if!(pvno != 5 || msgtype != 30, ErrorKind::Tag) >>
477             ctime:   opt_parse_der_tagged!(EXPLICIT 2,parse_kerberos_time) >>
478             cusec:   opt_parse_der_tagged!(EXPLICIT 3,parse_der_microseconds) >>
479             stime:   parse_der_tagged!(EXPLICIT 4,parse_kerberos_time) >>
480             susec:   parse_der_tagged!(EXPLICIT 5,parse_der_microseconds) >>
481             errorc:  parse_der_tagged!(EXPLICIT 6,parse_der_int32) >>
482             crealm:  opt_parse_der_tagged!(EXPLICIT 7,parse_krb5_realm) >>
483             cname:   opt_parse_der_tagged!(EXPLICIT 8,parse_krb5_principalname) >>
484             realm:   parse_der_tagged!(EXPLICIT 9,parse_krb5_realm) >>
485             sname:   parse_der_tagged!(EXPLICIT 10,parse_krb5_principalname) >>
486             etext:   opt_parse_der_tagged!(EXPLICIT 11,parse_kerberos_string) >>
487             edata:   opt_parse_der_tagged!(EXPLICIT 12,parse_der_octetstring) >>
488             (KrbError{
489                 pvno,
490                 msg_type: MessageType(msgtype),
491                 ctime,
492                 cusec,
493                 stime,
494                 susec,
495                 error_code: ErrorCode(errorc),
496                 crealm,
497                 cname,
498                 realm,
499                 sname,
500                 etext,
501                 edata,
502             })
503         )
504         >> (st)
505     )
506     .map(|(rem, t)| (rem, (t.1).1))
507 }
508 
509 /// Parse Kerberos PA-Data
510 ///
511 /// <pre>
512 /// PA-DATA         ::= SEQUENCE {
513 ///         -- NOTE: first tag is [1], not [0]
514 ///         padata-type     [1] Int32,
515 ///         padata-value    [2] OCTET STRING -- might be encoded AP-REQ
516 /// }
517 /// </pre>
parse_krb5_padata<'a>(i: &'a [u8]) -> IResult<&'a [u8], PAData<'a>, BerError>518 pub fn parse_krb5_padata<'a>(i: &'a [u8]) -> IResult<&'a [u8], PAData<'a>, BerError> {
519     parse_der_struct!(
520         i,
521         TAG DerTag::Sequence,
522         t: parse_der_tagged!(EXPLICIT 1, parse_der_int32) >>
523         s: map_res!(parse_der_tagged!(EXPLICIT 2, parse_der_octetstring),|x: DerObject<'a>| x.as_slice()) >>
524         ( PAData{
525             padata_type:  PAType(t),
526             padata_value: s,
527         })
528     ).map(|(rem,x)| (rem,x.1))
529 }
530 
parse_krb5_padata_sequence(i: &[u8]) -> IResult<&[u8], Vec<PAData>, BerError>531 fn parse_krb5_padata_sequence(i: &[u8]) -> IResult<&[u8], Vec<PAData>, BerError> {
532     parse_der_struct!(
533         i,
534         TAG DerTag::Sequence,
535         v: many0!(complete!(parse_krb5_padata)) >>
536         ( v )
537     )
538     .map(|(rem, x)| (rem, x.1))
539 }
540 
541 /// Parse a Kerberos AP Request
542 ///
543 /// <pre>
544 /// AP-REQ          ::= [APPLICATION 14] SEQUENCE {
545 ///         pvno            [0] INTEGER (5),
546 ///         msg-type        [1] INTEGER (14),
547 ///         ap-options      [2] APOptions,
548 ///         ticket          [3] Ticket,
549 ///         authenticator   [4] EncryptedData -- Authenticator
550 /// }
551 ///
552 /// APOptions       ::= KerberosFlags
553 ///         -- reserved(0),
554 ///         -- use-session-key(1),
555 ///         -- mutual-required(2)
556 /// </pre>
parse_ap_req(i: &[u8]) -> IResult<&[u8], ApReq, BerError>557 pub fn parse_ap_req(i: &[u8]) -> IResult<&[u8], ApReq, BerError> {
558     parse_der_application!(
559         i,
560         APPLICATION 14,
561         st: parse_der_struct!(
562             TAG DerTag::Sequence,
563             pvno:    parse_der_tagged!(EXPLICIT 0,parse_der_u32) >>
564             msgtype: parse_der_tagged!(EXPLICIT 1,parse_der_u32) >>
565                      error_if!(pvno != 5 || msgtype != 14, ErrorKind::Tag) >>
566             flags:   parse_der_tagged!(EXPLICIT 2,parse_kerberos_flags) >>
567             ticket:  parse_der_tagged!(EXPLICIT 3,parse_krb5_ticket) >>
568             auth:    parse_der_tagged!(EXPLICIT 4,parse_encrypted) >>
569             ( ApReq{
570                 pvno,
571                 msg_type: MessageType(msgtype),
572                 ap_options: flags,
573                 ticket,
574                 authenticator: auth,
575             })
576         )
577         >> (st)
578     )
579     .map(|(rem, t)| (rem, (t.1).1))
580 }
581 
582 /// Parse a Kerberos AP Reply
583 ///
584 /// <pre>
585 /// AP-REP          ::= [APPLICATION 15] SEQUENCE {
586 ///         pvno            [0] INTEGER (5),
587 ///         msg-type        [1] INTEGER (15),
588 ///         enc-part        [2] EncryptedData -- EncAPRepPart
589 /// }
590 /// </pre>
parse_ap_rep(i: &[u8]) -> IResult<&[u8], ApRep, BerError>591 pub fn parse_ap_rep(i: &[u8]) -> IResult<&[u8], ApRep, BerError> {
592     parse_der_application!(
593         i,
594         APPLICATION 15,
595         st: parse_der_struct!(
596             TAG DerTag::Sequence,
597             pvno:    parse_der_tagged!(EXPLICIT 0,parse_der_u32) >>
598             msgtype: parse_der_tagged!(EXPLICIT 1,parse_der_u32) >>
599                      error_if!(pvno != 5 || msgtype != 15, ErrorKind::Tag) >>
600             edata:   parse_der_tagged!(EXPLICIT 4,parse_encrypted) >>
601             ( ApRep{
602                 pvno,
603                 msg_type: MessageType(msgtype),
604                 enc_part: edata,
605             })
606         )
607         >> (st)
608     )
609     .map(|(rem, t)| (rem, (t.1).1))
610 }
611