picky_krb/
data_types.rs

1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
2use picky_asn1::wrapper::{
3    Asn1SequenceOf, BitStringAsn1, ExplicitContextTag0, ExplicitContextTag1, ExplicitContextTag2, ExplicitContextTag3,
4    ExplicitContextTag4, ExplicitContextTag5, ExplicitContextTag6, ExplicitContextTag7, ExplicitContextTag8,
5    ExplicitContextTag9, ExplicitContextTag10, GeneralStringAsn1, GeneralizedTimeAsn1, IntegerAsn1, OctetStringAsn1,
6    Optional,
7};
8use picky_asn1_der::application_tag::ApplicationTag;
9use serde::de::Error;
10use serde::{Deserialize, Deserializer, Serialize, de};
11
12use std::fmt::Debug;
13use std::io::{Read, Write};
14use std::marker::PhantomData;
15use std::{fmt, io};
16
17use crate::constants::types::{
18    AUTHENTICATOR_TYPE, ENC_AP_REP_PART_TYPE, ENC_TICKET_PART_TYPE, KRB_PRIV_ENC_PART, TICKET_TYPE,
19};
20use crate::messages::KrbError;
21
22/// [RFC 4120 5.2.1](https://www.rfc-editor.org/rfc/rfc4120.txt)
23///
24/// ```not-rust
25/// KerberosString  ::= GeneralString (IA5String)
26/// ```
27pub type KerberosStringAsn1 = GeneralStringAsn1;
28
29/// [2.2.2 KDC_PROXY_MESSAGE](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-kkdcp/5778aff5-b182-4b97-a970-29c7f911eef2)
30pub type Realm = KerberosStringAsn1;
31
32/// [RFC 4120 5.2.2](https://www.rfc-editor.org/rfc/rfc4120.txt)
33///
34/// ```not_rust
35/// PrincipalName   ::= SEQUENCE {
36///         name-type       [0] Int32,
37///         name-string     [1] SEQUENCE OF KerberosString
38/// }
39/// ```
40#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
41pub struct PrincipalName {
42    pub name_type: ExplicitContextTag0<IntegerAsn1>,
43    pub name_string: ExplicitContextTag1<Asn1SequenceOf<KerberosStringAsn1>>,
44}
45
46/// [RFC 4120 5.2.3](https://www.rfc-editor.org/rfc/rfc4120.txt)
47///
48/// ```not_rust
49/// KerberosTime    ::= GeneralizedTime -- with no fractional seconds
50/// ```
51pub type KerberosTime = GeneralizedTimeAsn1;
52
53/// [RFC 4120 5.2.4](https://www.rfc-editor.org/rfc/rfc4120.txt)
54///
55/// ```not_rust
56/// Microseconds    ::= INTEGER (0..999999)
57/// ```
58pub type Microseconds = IntegerAsn1;
59
60/// [RFC 4120 5.2.5](https://www.rfc-editor.org/rfc/rfc4120.txt)
61///
62/// ```not_rust
63/// HostAddress   ::= SEQUENCE {
64///         addr-type       [0] Int32,
65///         address         [1] OCTET STRING
66/// }
67/// ```
68#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
69pub struct HostAddress {
70    pub addr_type: ExplicitContextTag0<IntegerAsn1>,
71    pub address: ExplicitContextTag1<OctetStringAsn1>,
72}
73
74/// [RFC 4120 5.2.5](https://www.rfc-editor.org/rfc/rfc4120.txt)
75///
76/// ```not_rust
77/// HostAddresses   -- NOTE: subtly different from rfc1510,
78///                 -- but has a value mapping and encodes the same
79///         ::= SEQUENCE OF HostAddress
80/// ```
81pub type HostAddresses = Asn1SequenceOf<HostAddress>;
82
83/// [RFC 4120 5.2.6](https://www.rfc-editor.org/rfc/rfc4120.txt)
84///
85/// ```not_rust
86/// AuthorizationData       ::= SEQUENCE OF SEQUENCE {
87///         ad-type         [0] Int32,
88///         ad-data         [1] OCTET STRING
89/// }
90/// ```
91#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
92pub struct AuthorizationDataInner {
93    pub ad_type: ExplicitContextTag0<IntegerAsn1>,
94    pub ad_data: ExplicitContextTag1<OctetStringAsn1>,
95}
96
97pub type AuthorizationData = Asn1SequenceOf<AuthorizationDataInner>;
98
99/// [RFC 4120 5.2.7](https://www.rfc-editor.org/rfc/rfc4120.txt)
100///
101/// ```not_rust
102/// PA-DATA         ::= SEQUENCE {
103///         padata-type     [1] Int32,
104///         padata-value    [2] OCTET STRING
105/// }
106/// ```
107#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
108pub struct PaData {
109    pub padata_type: ExplicitContextTag1<IntegerAsn1>,
110    pub padata_data: ExplicitContextTag2<OctetStringAsn1>,
111}
112
113/// [RFC 4120 5.2.8](https://www.rfc-editor.org/rfc/rfc4120.txt)
114///
115/// ```not_rust
116/// KerberosFlags   ::= BIT STRING (SIZE (32..MAX))
117/// ```
118pub type KerberosFlags = BitStringAsn1;
119
120/// [RFC 4120 5.2.9](https://www.rfc-editor.org/rfc/rfc4120.txt)
121///
122/// ```not_rust
123/// EncryptedData   ::= SEQUENCE {
124///         etype   [0] Int32 -- EncryptionType --,
125///         kvno    [1] UInt32 OPTIONAL,
126///         cipher  [2] OCTET STRING -- ciphertext
127/// }
128/// ```
129#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
130pub struct EncryptedData {
131    pub etype: ExplicitContextTag0<IntegerAsn1>,
132    pub kvno: Optional<Option<ExplicitContextTag1<IntegerAsn1>>>,
133    pub cipher: ExplicitContextTag2<OctetStringAsn1>,
134}
135
136/// [RFC 4120 5.2.9](https://www.rfc-editor.org/rfc/rfc4120.txt)
137///
138/// ```not_rust
139/// EncryptionKey   ::= SEQUENCE {
140///         keytype         [0] Int32 -- actually encryption type --,
141///         keyvalue        [1] OCTET STRING
142/// }
143/// ```
144#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
145pub struct EncryptionKey {
146    pub key_type: ExplicitContextTag0<IntegerAsn1>,
147    pub key_value: ExplicitContextTag1<OctetStringAsn1>,
148}
149
150/// [RFC 4120 5.3](https://www.rfc-editor.org/rfc/rfc4120.txt)
151///
152/// ```not_rust
153/// Ticket          ::= [APPLICATION 1] SEQUENCE {
154///         tkt-vno         [0] INTEGER (5),
155///         realm           [1] Realm,
156///         sname           [2] PrincipalName,
157///         enc-part        [3] EncryptedData
158/// }
159/// ```
160#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
161pub struct TicketInner {
162    pub tkt_vno: ExplicitContextTag0<IntegerAsn1>,
163    pub realm: ExplicitContextTag1<Realm>,
164    pub sname: ExplicitContextTag2<PrincipalName>,
165    pub enc_part: ExplicitContextTag3<EncryptedData>,
166}
167
168pub type Ticket = ApplicationTag<TicketInner, TICKET_TYPE>;
169
170/// [RFC 4120 5.3](https://www.rfc-editor.org/rfc/rfc4120.txt)
171///
172/// ```not_rust
173/// TransitedEncoding       ::= SEQUENCE {
174///         tr-type         [0] Int32 -- must be registered --,
175///         contents        [1] OCTET STRING
176/// }
177/// ```
178#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
179pub struct TransitedEncoding {
180    pub tr_type: ExplicitContextTag0<IntegerAsn1>,
181    pub contents: ExplicitContextTag1<OctetStringAsn1>,
182}
183
184/// [RFC 4120 5.3](https://www.rfc-editor.org/rfc/rfc4120.txt)
185///
186/// ```not_rust
187/// EncTicketPart   ::= [APPLICATION 3] SEQUENCE {
188///         flags                   [0] TicketFlags,
189///         key                     [1] EncryptionKey,
190///         crealm                  [2] Realm,
191///         cname                   [3] PrincipalName,
192///         transited               [4] TransitedEncoding,
193///         authtime                [5] KerberosTime,
194///         starttime               [6] KerberosTime OPTIONAL,
195///         endtime                 [7] KerberosTime,
196///         renew-till              [8] KerberosTime OPTIONAL,
197///         caddr                   [9] HostAddresses OPTIONAL,
198///         authorization-data      [10] AuthorizationData OPTIONAL
199/// }
200/// ```
201#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
202pub struct EncTicketPartInner {
203    pub flags: ExplicitContextTag0<KerberosFlags>,
204    pub key: ExplicitContextTag1<EncryptionKey>,
205    pub crealm: ExplicitContextTag2<Realm>,
206    pub cname: ExplicitContextTag3<PrincipalName>,
207    pub transited: ExplicitContextTag4<TransitedEncoding>,
208    pub auth_time: ExplicitContextTag5<KerberosTime>,
209    pub starttime: Optional<Option<ExplicitContextTag6<KerberosTime>>>,
210    pub endtime: ExplicitContextTag7<KerberosTime>,
211    #[serde(default)]
212    pub renew_till: Optional<Option<ExplicitContextTag8<KerberosTime>>>,
213    #[serde(default)]
214    pub caddr: Optional<Option<ExplicitContextTag9<HostAddresses>>>,
215    #[serde(default)]
216    pub authorization_data: Optional<Option<ExplicitContextTag10<AuthorizationData>>>,
217}
218
219pub type EncTicketPart = ApplicationTag<EncTicketPartInner, ENC_TICKET_PART_TYPE>;
220
221/// [RFC 4120 5.4.2](https://www.rfc-editor.org/rfc/rfc4120.txt)
222///
223/// ```not_rust
224/// LastReq         ::=     SEQUENCE OF SEQUENCE {
225///         lr-type         [0] Int32,
226///         lr-value        [1] KerberosTime
227/// }
228/// ```
229#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
230pub struct LastReqInner {
231    pub lr_type: ExplicitContextTag0<IntegerAsn1>,
232    pub lr_value: ExplicitContextTag1<KerberosTime>,
233}
234pub type LastReq = Asn1SequenceOf<LastReqInner>;
235
236/// [MS-KILE 2.2.2](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-KILE/%5bMS-KILE%5d.pdf)
237///
238/// ```not_rust
239/// KERB-ERROR-DATA ::= SEQUENCE {
240///     data-type [1] INTEGER,
241///     data-value [2] OCTET STRING OPTIONAL
242/// }
243/// ```
244#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
245pub struct KerbErrorData {
246    pub data_type: ExplicitContextTag1<IntegerAsn1>,
247    #[serde(default)]
248    pub data_value: Optional<Option<ExplicitContextTag2<BitStringAsn1>>>,
249}
250
251/// [RFC 4120 ](https://datatracker.ietf.org/doc/html/rfc4120#section-5.2.7.2)
252///
253/// ```not_rust
254/// PA-ENC-TS-ENC           ::= SEQUENCE {
255///         patimestamp     [0] KerberosTime -- client's time --,
256///         pausec          [1] Microseconds OPTIONAL
257/// }
258/// ```
259#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
260pub struct PaEncTsEnc {
261    pub patimestamp: ExplicitContextTag0<KerberosTime>,
262    #[serde(default)]
263    pub pausec: Optional<Option<ExplicitContextTag1<Microseconds>>>,
264}
265
266/// [RFC 4120 ](https://datatracker.ietf.org/doc/html/rfc4120#section-5.2.7.2)
267///
268/// ```not_rust
269/// PA-ENC-TIMESTAMP        ::= EncryptedData -- PA-ENC-TS-ENC
270/// ```
271pub type PaEncTimestamp = EncryptedData;
272
273/// [MS-KILE 2.2.3](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-KILE/%5bMS-KILE%5d.pdf)
274///
275/// ```not_rust
276/// KERB-PA-PAC-REQUEST ::= SEQUENCE {
277///     include-pac[0] BOOLEAN
278/// }
279/// ```
280#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
281pub struct KerbPaPacRequest {
282    pub include_pac: ExplicitContextTag0<bool>,
283}
284
285/// [MS-KILE 2.2.10](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-KILE/%5bMS-KILE%5d.pdf)
286///
287/// ```not_rust
288/// PA-PAC-OPTIONS ::= SEQUENCE {
289///     flags                ::= KerberosFlags
290/// }
291/// ```
292#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
293pub struct PaPacOptions {
294    pub flags: ExplicitContextTag0<KerberosFlags>,
295}
296
297/// [RFC 4120](https://datatracker.ietf.org/doc/html/rfc4120#section-5.5.1)
298///
299/// ```not_rust
300/// APOptions       ::= KerberosFlags
301/// ```
302pub type ApOptions = KerberosFlags;
303
304/// [RFC 4120](https://datatracker.ietf.org/doc/html/rfc4120#section-5.2.9)
305///
306/// ```not_rust
307/// Checksum        ::= SEQUENCE {
308///         cksumtype       [0] Int32,
309///         checksum        [1] OCTET STRING
310/// }
311/// ```
312#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
313pub struct Checksum {
314    pub cksumtype: ExplicitContextTag0<IntegerAsn1>,
315    pub checksum: ExplicitContextTag1<OctetStringAsn1>,
316}
317
318/// [RFC 4120](https://datatracker.ietf.org/doc/html/rfc4120#section-5.5.1)
319///
320/// ```not_rust
321/// Authenticator   ::= [APPLICATION 2] SEQUENCE  {
322///         authenticator-vno       [0] INTEGER (5),
323///         crealm                  [1] Realm,
324///         cname                   [2] PrincipalName,
325///         cksum                   [3] Checksum OPTIONAL,
326///         cusec                   [4] Microseconds,
327///         ctime                   [5] KerberosTime,
328///         subkey                  [6] EncryptionKey OPTIONAL,
329///         seq-number              [7] UInt32 OPTIONAL,
330///         authorization-data      [8] AuthorizationData OPTIONAL
331/// }
332/// ```
333#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
334pub struct AuthenticatorInner {
335    pub authenticator_vno: ExplicitContextTag0<IntegerAsn1>,
336    pub crealm: ExplicitContextTag1<Realm>,
337    pub cname: ExplicitContextTag2<PrincipalName>,
338    pub cksum: Optional<Option<ExplicitContextTag3<Checksum>>>,
339    pub cusec: ExplicitContextTag4<Microseconds>,
340    pub ctime: ExplicitContextTag5<KerberosTime>,
341    #[serde(default)]
342    pub subkey: Optional<Option<ExplicitContextTag6<EncryptionKey>>>,
343    #[serde(default)]
344    pub seq_number: Optional<Option<ExplicitContextTag7<IntegerAsn1>>>,
345    #[serde(default)]
346    pub authorization_data: Optional<Option<ExplicitContextTag8<AuthorizationData>>>,
347}
348pub type Authenticator = ApplicationTag<AuthenticatorInner, AUTHENTICATOR_TYPE>;
349
350/// [RFC 4120](https://datatracker.ietf.org/doc/html/rfc4120#section-5.5.2)
351///
352/// ```not_rust
353/// EncAPRepPart    ::= [APPLICATION 27] SEQUENCE {
354///         ctime           [0] KerberosTime,
355///         cusec           [1] Microseconds,
356///         subkey          [2] EncryptionKey OPTIONAL,
357///         seq-number      [3] UInt32 OPTIONAL
358/// }
359/// ```
360#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
361pub struct EncApRepPartInner {
362    pub ctime: ExplicitContextTag0<KerberosTime>,
363    pub cusec: ExplicitContextTag1<Microseconds>,
364    #[serde(default)]
365    pub subkey: Optional<Option<ExplicitContextTag2<EncryptionKey>>>,
366    #[serde(default)]
367    pub seq_number: Optional<Option<ExplicitContextTag3<IntegerAsn1>>>,
368}
369pub type EncApRepPart = ApplicationTag<EncApRepPartInner, ENC_AP_REP_PART_TYPE>;
370
371/// [RFC 4120](https://datatracker.ietf.org/doc/html/rfc4120#section-5.2.7.5)
372///
373/// ```not_rust
374/// ETYPE-INFO2-ENTRY       ::= SEQUENCE {
375///         etype           [0] Int32,
376///         salt            [1] KerberosString OPTIONAL,
377///         s2kparams       [2] OCTET STRING OPTIONAL
378/// }
379/// ```
380#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
381pub struct EtypeInfo2Entry {
382    pub etype: ExplicitContextTag0<IntegerAsn1>,
383    #[serde(default)]
384    pub salt: Optional<Option<ExplicitContextTag1<KerberosStringAsn1>>>,
385    #[serde(default)]
386    pub s2kparams: Optional<Option<ExplicitContextTag2<OctetStringAsn1>>>,
387}
388
389/// [RFC 4120](https://datatracker.ietf.org/doc/html/rfc4120#section-5.2.7.5)
390///
391/// ```not_rust
392/// ETYPE-INFO2              ::= SEQUENCE SIZE (1..MAX) OF ETYPE-INFO2-ENTRY
393/// ```
394pub type EtypeInfo2 = Asn1SequenceOf<EtypeInfo2Entry>;
395
396/// [RFC 4120](https://datatracker.ietf.org/doc/html/rfc4120#section-5.7.1)
397///
398/// ```not_rust
399/// EncKrbPrivPart  ::= [APPLICATION 28] SEQUENCE {
400///         user-data       [0] OCTET STRING,
401///         timestamp       [1] KerberosTime OPTIONAL,
402///         usec            [2] Microseconds OPTIONAL,
403///         seq-number      [3] UInt32 OPTIONAL,
404///         s-address       [4] HostAddress -- sender's addr --,
405///         r-address       [5] HostAddress OPTIONAL -- recip's addr
406/// }
407/// ```
408#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
409pub struct EncKrbPrivPartInner {
410    pub user_data: ExplicitContextTag0<OctetStringAsn1>,
411    pub timestamp: Optional<Option<ExplicitContextTag1<KerberosTime>>>,
412    pub usec: Optional<Option<ExplicitContextTag2<KerberosTime>>>,
413    pub seq_number: Optional<Option<ExplicitContextTag3<IntegerAsn1>>>,
414    pub s_address: ExplicitContextTag4<HostAddress>,
415    #[serde(default)]
416    pub r_address: Optional<Option<ExplicitContextTag5<HostAddress>>>,
417}
418
419pub type EncKrbPrivPart = ApplicationTag<EncKrbPrivPartInner, KRB_PRIV_ENC_PART>;
420
421/// [RFC 3244](https://datatracker.ietf.org/doc/html/rfc3244.html#section-2)
422///
423/// ```not_rust
424/// ChangePasswdData ::=  SEQUENCE {
425///     newpasswd[0]   OCTET STRING,
426///     targname[1]    PrincipalName OPTIONAL,
427///     targrealm[2]   Realm OPTIONAL
428/// }
429/// ```
430#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
431pub struct ChangePasswdData {
432    pub new_passwd: ExplicitContextTag0<OctetStringAsn1>,
433    pub target_name: Optional<Option<ExplicitContextTag1<PrincipalName>>>,
434    pub target_realm: Optional<Option<ExplicitContextTag2<Realm>>>,
435}
436
437pub trait ResultExt<'a, T>
438where
439    T: Deserialize<'a>,
440{
441    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
442    where
443        D: Deserializer<'a>,
444        Self: Sized;
445}
446
447impl<'de, T: Deserialize<'de>> ResultExt<'de, T> for Result<T, KrbError> {
448    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
449    where
450        D: Deserializer<'de>,
451        Self: Sized,
452    {
453        struct Visitor<V>(PhantomData<V>);
454
455        impl<'de, V: de::Deserialize<'de>> de::Visitor<'de> for Visitor<V> {
456            type Value = Result<V, KrbError>;
457
458            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
459                formatter.write_str("a valid DER-encoded KbResult")
460            }
461
462            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
463            where
464                A: de::SeqAccess<'de>,
465            {
466                match seq.next_element() {
467                    Ok(value) => value
468                        .ok_or_else(|| A::Error::missing_field("Missing KrbResult value"))
469                        .map(|value| Ok(value)),
470                    Err(_) => match seq.next_element() {
471                        Ok(error_value) => error_value
472                            .ok_or_else(|| A::Error::missing_field("Missing KrbResult value"))
473                            .map(|error_value| Err(error_value)),
474                        Err(err) => Err(err),
475                    },
476                }
477            }
478        }
479
480        deserializer.deserialize_enum("KrbResult", &["Ok", "Err"], Visitor::<T>(PhantomData))
481    }
482}
483
484pub type KrbResult<T> = Result<T, KrbError>;
485
486/// [2.2.6 KERB-AD-RESTRICTION-ENTRY](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-KILE/%5bMS-KILE%5d.pdf)
487///
488/// ```not_rust
489/// KERB-AD-RESTRICTION-ENTRY ::= SEQUENCE {
490/// restriction-type [0] Int32,
491/// restriction [1] OCTET STRING
492/// }
493/// ```
494#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
495pub struct KerbAdRestrictionEntry {
496    pub restriction_type: ExplicitContextTag0<IntegerAsn1>,
497    pub restriction: ExplicitContextTag1<OctetStringAsn1>,
498}
499
500/// [3.1.1.4 Machine ID](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-KILE/%5bMS-KILE%5d.pdf)
501/// KILE implements a 32-byte binary random string machine ID
502pub const MACHINE_ID_LENGTH: usize = 32;
503
504/// [2.2.5 LSAP_TOKEN_INFO_INTEGRITY](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-KILE/%5bMS-KILE%5d.pdf)
505///
506/// ```not_rust
507/// typedef struct _LSAP_TOKEN_INFO_INTEGRITY {
508///     unsigned long Flags;
509///     unsigned long TokenIL;
510///     unsigned char MachineID[32];
511/// } LSAP_TOKEN_INFO_INTEGRITY,
512/// ```
513#[derive(Debug, PartialEq, Eq, Clone)]
514pub struct LsapTokenInfoIntegrity {
515    pub flags: u32,
516    pub token_il: u32,
517    pub machine_id: [u8; MACHINE_ID_LENGTH],
518}
519
520impl LsapTokenInfoIntegrity {
521    pub fn encode(&self, mut to: impl Write) -> io::Result<()> {
522        to.write_u32::<LittleEndian>(self.flags)?;
523        to.write_u32::<LittleEndian>(self.token_il)?;
524        to.write_all(&self.machine_id)?;
525
526        Ok(())
527    }
528
529    pub fn decode(mut from: impl Read) -> io::Result<Self> {
530        let flags = from.read_u32::<LittleEndian>()?;
531        let token_il = from.read_u32::<LittleEndian>()?;
532
533        let mut machine_id = [0; MACHINE_ID_LENGTH];
534        from.read_exact(&mut machine_id)?;
535
536        Ok(Self {
537            flags,
538            token_il,
539            machine_id,
540        })
541    }
542}
543
544#[cfg(test)]
545mod tests {
546    use crate::constants::error_codes::KDC_ERR_C_PRINCIPAL_UNKNOWN;
547    use crate::data_types::{
548        AuthenticatorInner, AuthorizationData, AuthorizationDataInner, Checksum, EncApRepPart, EncApRepPartInner,
549        EncKrbPrivPart, EncKrbPrivPartInner, EncryptedData, EncryptionKey, EtypeInfo2Entry, HostAddress,
550        KerbPaPacRequest, KerberosStringAsn1, KerberosTime, LastReqInner, PaData, PrincipalName,
551    };
552    use crate::messages::{AsReq, KdcReq, KdcReqBody, KrbError, KrbErrorInner};
553    use picky_asn1::bit_string::BitString;
554    use picky_asn1::date::Date;
555    use picky_asn1::restricted_string::Ia5String;
556    use picky_asn1::wrapper::{
557        Asn1SequenceOf, BitStringAsn1, ExplicitContextTag0, ExplicitContextTag1, ExplicitContextTag2,
558        ExplicitContextTag3, ExplicitContextTag4, ExplicitContextTag5, ExplicitContextTag6, ExplicitContextTag7,
559        ExplicitContextTag8, ExplicitContextTag9, ExplicitContextTag10, ExplicitContextTag11, GeneralStringAsn1,
560        GeneralizedTimeAsn1, IntegerAsn1, OctetStringAsn1, Optional,
561    };
562    use picky_asn1_der::application_tag::ApplicationTag;
563
564    use super::{ChangePasswdData, Microseconds, PaEncTsEnc};
565
566    #[test]
567    fn change_passwd_data() {
568        let expected_raw = [
569            48, 47, 160, 14, 4, 12, 113, 119, 101, 81, 87, 69, 49, 50, 51, 33, 64, 35, 161, 14, 48, 12, 160, 2, 2, 0,
570            161, 6, 48, 4, 27, 2, 101, 51, 162, 13, 27, 11, 69, 88, 65, 77, 80, 76, 69, 46, 67, 79, 77,
571        ];
572        let expected = ChangePasswdData {
573            // qweQWE123!@#
574            new_passwd: ExplicitContextTag0::from(OctetStringAsn1::from(vec![
575                113, 119, 101, 81, 87, 69, 49, 50, 51, 33, 64, 35,
576            ])),
577            target_name: Optional::from(Some(ExplicitContextTag1::from(PrincipalName {
578                name_type: ExplicitContextTag0::from(IntegerAsn1::from(vec![])),
579                name_string: ExplicitContextTag1::from(Asn1SequenceOf::from(vec![KerberosStringAsn1::from(
580                    Ia5String::from_string("e3".into()).unwrap(),
581                )])),
582            }))),
583            target_realm: Optional::from(Some(ExplicitContextTag2::from(KerberosStringAsn1::from(
584                Ia5String::from_string("EXAMPLE.COM".into()).unwrap(),
585            )))),
586        };
587
588        let change_password_data: ChangePasswdData = picky_asn1_der::from_bytes(&expected_raw).unwrap();
589        let raw_change_password_data = picky_asn1_der::to_vec(&change_password_data).unwrap();
590
591        assert_eq!(change_password_data, expected);
592        assert_eq!(raw_change_password_data, expected_raw);
593    }
594
595    #[test]
596    fn enc_krb_priv_part() {
597        let expected_raw = [
598            124, 25, 48, 23, 160, 4, 4, 2, 0, 0, 164, 15, 48, 13, 160, 3, 2, 1, 2, 161, 6, 4, 4, 192, 168, 0, 108,
599        ];
600        let expected = EncKrbPrivPart::from(EncKrbPrivPartInner {
601            user_data: ExplicitContextTag0::from(OctetStringAsn1::from(vec![0, 0])),
602            timestamp: Optional::from(None),
603            usec: Optional::from(None),
604            seq_number: Optional::from(None),
605            s_address: ExplicitContextTag4::from(HostAddress {
606                addr_type: ExplicitContextTag0::from(IntegerAsn1::from(vec![0x02])),
607                address: ExplicitContextTag1::from(OctetStringAsn1::from(vec![0xc0, 0xa8, 0x00, 0x6c])),
608            }),
609            r_address: Optional::from(None),
610        });
611
612        let enc_krb_priv: EncKrbPrivPart = picky_asn1_der::from_bytes(&expected_raw).unwrap();
613        let raw_enc_krb_priv = picky_asn1_der::to_vec(&enc_krb_priv).unwrap();
614
615        assert_eq!(enc_krb_priv, expected);
616        assert_eq!(raw_enc_krb_priv, expected_raw);
617    }
618
619    #[test]
620    fn kerberos_string_decode() {
621        // EXAMPLE.COM
622        let expected = [27, 11, 69, 88, 65, 77, 80, 76, 69, 46, 67, 79, 77];
623
624        let s: KerberosStringAsn1 = picky_asn1_der::from_bytes(&expected).unwrap();
625        let data = picky_asn1_der::to_vec(&s).unwrap();
626
627        assert_eq!(data, expected);
628    }
629
630    #[test]
631    fn pa_data() {
632        let expected_raw = [
633            48, 39, 161, 3, 2, 1, 19, 162, 32, 4, 30, 48, 28, 48, 26, 160, 3, 2, 1, 18, 161, 19, 27, 17, 69, 88, 65,
634            77, 80, 76, 69, 46, 67, 79, 77, 109, 121, 117, 115, 101, 114,
635        ];
636        let expected = PaData {
637            padata_type: ExplicitContextTag1::from(IntegerAsn1(vec![19])),
638            padata_data: ExplicitContextTag2::from(OctetStringAsn1::from(vec![
639                48, 28, 48, 26, 160, 3, 2, 1, 18, 161, 19, 27, 17, 69, 88, 65, 77, 80, 76, 69, 46, 67, 79, 77, 109,
640                121, 117, 115, 101, 114,
641            ])),
642        };
643
644        let pa_data: PaData = picky_asn1_der::from_bytes(&expected_raw).unwrap();
645        let pa_data_raw = picky_asn1_der::to_vec(&pa_data).unwrap();
646
647        assert_eq!(pa_data, expected);
648        assert_eq!(pa_data_raw, expected_raw);
649    }
650
651    #[test]
652    fn simple_principal_name() {
653        let expected_raw = [
654            48, 17, 160, 3, 2, 1, 1, 161, 10, 48, 8, 27, 6, 109, 121, 117, 115, 101, 114,
655        ];
656        let expected = PrincipalName {
657            name_type: ExplicitContextTag0::from(IntegerAsn1(vec![1])),
658            name_string: ExplicitContextTag1::from(Asn1SequenceOf::from(vec![GeneralStringAsn1::from(
659                Ia5String::from_string("myuser".to_owned()).unwrap(),
660            )])),
661        };
662
663        let principal_name: PrincipalName = picky_asn1_der::from_bytes(&expected_raw).unwrap();
664        let principal_name_raw = picky_asn1_der::to_vec(&principal_name).unwrap();
665
666        assert_eq!(principal_name, expected);
667        assert_eq!(principal_name_raw, expected_raw);
668    }
669
670    #[test]
671    fn principal_name_with_two_names() {
672        let expected_raw = [
673            48, 30, 160, 3, 2, 1, 2, 161, 23, 48, 21, 27, 6, 107, 114, 98, 116, 103, 116, 27, 11, 69, 88, 65, 77, 80,
674            76, 69, 46, 67, 79, 77,
675        ];
676        let expected = PrincipalName {
677            name_type: ExplicitContextTag0::from(IntegerAsn1(vec![2])),
678            name_string: ExplicitContextTag1::from(Asn1SequenceOf::from(vec![
679                GeneralStringAsn1::from(Ia5String::from_string("krbtgt".to_owned()).unwrap()),
680                GeneralStringAsn1::from(Ia5String::from_string("EXAMPLE.COM".to_owned()).unwrap()),
681            ])),
682        };
683
684        let principal_name: PrincipalName = picky_asn1_der::from_bytes(&expected_raw).unwrap();
685        let principal_name_raw = picky_asn1_der::to_vec(&principal_name).unwrap();
686
687        assert_eq!(principal_name, expected);
688        assert_eq!(principal_name_raw, expected_raw);
689    }
690
691    #[test]
692    fn encrypted_data() {
693        let expected_raw = [
694            48, 129, 252, 160, 3, 2, 1, 18, 161, 3, 2, 1, 1, 162, 129, 239, 4, 129, 236, 166, 11, 233, 202, 198, 160,
695            29, 10, 87, 131, 189, 15, 170, 61, 216, 210, 116, 104, 91, 174, 27, 255, 246, 126, 9, 92, 141, 206, 172,
696            100, 96, 56, 84, 172, 9, 156, 37, 4, 92, 135, 41, 130, 246, 8, 54, 42, 41, 176, 92, 106, 237, 35, 183, 179,
697            141, 35, 17, 246, 38, 42, 131, 226, 151, 25, 155, 134, 251, 197, 4, 209, 223, 122, 135, 145, 113, 169, 139,
698            100, 130, 4, 142, 227, 213, 137, 187, 187, 116, 173, 88, 35, 219, 206, 106, 232, 35, 124, 199, 228, 153,
699            170, 194, 86, 183, 67, 40, 142, 56, 178, 201, 25, 33, 213, 76, 70, 189, 240, 217, 22, 78, 147, 70, 0, 176,
700            78, 67, 33, 216, 37, 52, 200, 21, 104, 186, 190, 171, 60, 13, 250, 138, 135, 27, 159, 235, 29, 163, 193, 2,
701            67, 193, 141, 29, 199, 166, 251, 18, 114, 237, 192, 174, 207, 150, 33, 219, 215, 79, 157, 85, 132, 250,
702            159, 108, 151, 54, 134, 207, 119, 91, 132, 123, 47, 36, 56, 24, 110, 26, 7, 182, 219, 17, 220, 11, 44, 181,
703            227, 25, 25, 244, 14, 56, 130, 82, 227, 114, 54, 167, 75, 202, 140, 245, 136, 61, 29, 22, 247, 154, 5, 33,
704            161, 145, 60, 203, 132, 37, 17, 134, 162, 141, 159, 46, 146, 88, 115, 114, 245, 76, 57,
705        ];
706        let expected = EncryptedData {
707            etype: ExplicitContextTag0::from(IntegerAsn1(vec![18])),
708            kvno: Optional::from(Option::Some(ExplicitContextTag1::from(IntegerAsn1(vec![1])))),
709            cipher: ExplicitContextTag2::from(OctetStringAsn1(vec![
710                166, 11, 233, 202, 198, 160, 29, 10, 87, 131, 189, 15, 170, 61, 216, 210, 116, 104, 91, 174, 27, 255,
711                246, 126, 9, 92, 141, 206, 172, 100, 96, 56, 84, 172, 9, 156, 37, 4, 92, 135, 41, 130, 246, 8, 54, 42,
712                41, 176, 92, 106, 237, 35, 183, 179, 141, 35, 17, 246, 38, 42, 131, 226, 151, 25, 155, 134, 251, 197,
713                4, 209, 223, 122, 135, 145, 113, 169, 139, 100, 130, 4, 142, 227, 213, 137, 187, 187, 116, 173, 88, 35,
714                219, 206, 106, 232, 35, 124, 199, 228, 153, 170, 194, 86, 183, 67, 40, 142, 56, 178, 201, 25, 33, 213,
715                76, 70, 189, 240, 217, 22, 78, 147, 70, 0, 176, 78, 67, 33, 216, 37, 52, 200, 21, 104, 186, 190, 171,
716                60, 13, 250, 138, 135, 27, 159, 235, 29, 163, 193, 2, 67, 193, 141, 29, 199, 166, 251, 18, 114, 237,
717                192, 174, 207, 150, 33, 219, 215, 79, 157, 85, 132, 250, 159, 108, 151, 54, 134, 207, 119, 91, 132,
718                123, 47, 36, 56, 24, 110, 26, 7, 182, 219, 17, 220, 11, 44, 181, 227, 25, 25, 244, 14, 56, 130, 82,
719                227, 114, 54, 167, 75, 202, 140, 245, 136, 61, 29, 22, 247, 154, 5, 33, 161, 145, 60, 203, 132, 37, 17,
720                134, 162, 141, 159, 46, 146, 88, 115, 114, 245, 76, 57,
721            ])),
722        };
723
724        let encrypted_data: EncryptedData = picky_asn1_der::from_bytes(&expected_raw).unwrap();
725        let encrypted_data_raw = picky_asn1_der::to_vec(&encrypted_data).unwrap();
726
727        assert_eq!(encrypted_data, expected);
728        assert_eq!(encrypted_data_raw, expected_raw);
729    }
730
731    #[test]
732    fn encrypted_data_without_kvno() {
733        let expected_raw = [
734            48, 130, 1, 21, 160, 3, 2, 1, 18, 162, 130, 1, 12, 4, 130, 1, 8, 198, 68, 255, 54, 137, 75, 224, 202, 101,
735            33, 67, 17, 110, 98, 71, 39, 211, 155, 248, 29, 67, 235, 64, 135, 38, 247, 252, 121, 38, 244, 112, 7, 92,
736            223, 58, 122, 21, 75, 1, 183, 126, 177, 187, 35, 220, 164, 120, 191, 136, 112, 166, 111, 34, 115, 221, 212,
737            207, 236, 145, 74, 218, 228, 6, 251, 150, 88, 5, 199, 157, 87, 69, 191, 129, 114, 240, 96, 216, 115, 34,
738            43, 124, 147, 144, 154, 148, 221, 49, 107, 4, 38, 242, 48, 80, 144, 188, 74, 23, 0, 113, 223, 172, 60, 185,
739            84, 71, 18, 174, 116, 47, 53, 194, 8, 111, 184, 62, 178, 21, 231, 245, 102, 113, 15, 224, 32, 92, 108, 177,
740            22, 114, 31, 14, 147, 34, 77, 69, 90, 30, 77, 83, 75, 223, 245, 140, 148, 243, 39, 224, 51, 228, 101, 36,
741            221, 5, 255, 184, 46, 254, 218, 229, 175, 41, 207, 229, 107, 247, 160, 6, 83, 91, 1, 77, 195, 201, 148, 27,
742            184, 197, 93, 255, 58, 101, 70, 225, 253, 247, 20, 247, 1, 31, 209, 47, 198, 35, 201, 28, 24, 188, 189,
743            177, 198, 141, 65, 249, 178, 224, 27, 79, 183, 238, 206, 181, 94, 0, 116, 114, 244, 155, 83, 88, 3, 10,
744            223, 2, 215, 133, 201, 99, 136, 211, 56, 105, 144, 140, 196, 232, 216, 54, 173, 195, 10, 92, 161, 233, 13,
745            170, 136, 25, 162, 203, 75, 83, 149, 180, 47, 66, 147, 10, 206, 211, 146, 253, 18, 212, 17,
746        ];
747        let expected = EncryptedData {
748            etype: ExplicitContextTag0::from(IntegerAsn1(vec![18])),
749            kvno: Optional::from(Option::None),
750            cipher: ExplicitContextTag2::from(OctetStringAsn1(vec![
751                198, 68, 255, 54, 137, 75, 224, 202, 101, 33, 67, 17, 110, 98, 71, 39, 211, 155, 248, 29, 67, 235, 64,
752                135, 38, 247, 252, 121, 38, 244, 112, 7, 92, 223, 58, 122, 21, 75, 1, 183, 126, 177, 187, 35, 220, 164,
753                120, 191, 136, 112, 166, 111, 34, 115, 221, 212, 207, 236, 145, 74, 218, 228, 6, 251, 150, 88, 5, 199,
754                157, 87, 69, 191, 129, 114, 240, 96, 216, 115, 34, 43, 124, 147, 144, 154, 148, 221, 49, 107, 4, 38,
755                242, 48, 80, 144, 188, 74, 23, 0, 113, 223, 172, 60, 185, 84, 71, 18, 174, 116, 47, 53, 194, 8, 111,
756                184, 62, 178, 21, 231, 245, 102, 113, 15, 224, 32, 92, 108, 177, 22, 114, 31, 14, 147, 34, 77, 69, 90,
757                30, 77, 83, 75, 223, 245, 140, 148, 243, 39, 224, 51, 228, 101, 36, 221, 5, 255, 184, 46, 254, 218,
758                229, 175, 41, 207, 229, 107, 247, 160, 6, 83, 91, 1, 77, 195, 201, 148, 27, 184, 197, 93, 255, 58, 101,
759                70, 225, 253, 247, 20, 247, 1, 31, 209, 47, 198, 35, 201, 28, 24, 188, 189, 177, 198, 141, 65, 249,
760                178, 224, 27, 79, 183, 238, 206, 181, 94, 0, 116, 114, 244, 155, 83, 88, 3, 10, 223, 2, 215, 133, 201,
761                99, 136, 211, 56, 105, 144, 140, 196, 232, 216, 54, 173, 195, 10, 92, 161, 233, 13, 170, 136, 25, 162,
762                203, 75, 83, 149, 180, 47, 66, 147, 10, 206, 211, 146, 253, 18, 212, 17,
763            ])),
764        };
765
766        let encrypted_data: EncryptedData = picky_asn1_der::from_bytes(&expected_raw).unwrap();
767        let encrypted_data_raw = picky_asn1_der::to_vec(&encrypted_data).unwrap();
768
769        assert_eq!(encrypted_data, expected);
770        assert_eq!(encrypted_data_raw, expected_raw);
771    }
772
773    #[test]
774    fn host_address() {
775        let expected_raw = [
776            0x30, 0x19, 0xa0, 0x03, 0x02, 0x01, 0x14, 0xa1, 0x12, 0x04, 0x10, 0x48, 0x4f, 0x4c, 0x4c, 0x4f, 0x57, 0x42,
777            0x41, 0x53, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x20, 0x20,
778        ];
779        let expected = HostAddress {
780            addr_type: ExplicitContextTag0::from(IntegerAsn1(vec![20])),
781            address: ExplicitContextTag1::from(OctetStringAsn1(vec![
782                72, 79, 76, 76, 79, 87, 66, 65, 83, 84, 73, 79, 78, 32, 32, 32,
783            ])),
784        };
785
786        let host_address: HostAddress = picky_asn1_der::from_bytes(&expected_raw).unwrap();
787        let host_address_raw = picky_asn1_der::to_vec(&host_address).unwrap();
788
789        assert_eq!(host_address, expected);
790        assert_eq!(host_address_raw, expected_raw);
791    }
792
793    #[test]
794    fn encryption_key() {
795        let expected_raw = [
796            48, 41, 160, 3, 2, 1, 18, 161, 34, 4, 32, 23, 138, 210, 243, 7, 121, 117, 180, 99, 86, 230, 62, 222, 63,
797            251, 46, 242, 161, 37, 67, 254, 103, 199, 93, 74, 174, 166, 64, 17, 198, 242, 144,
798        ];
799        let expected = EncryptionKey {
800            key_type: ExplicitContextTag0::from(IntegerAsn1(vec![18])),
801            key_value: ExplicitContextTag1::from(OctetStringAsn1(vec![
802                23, 138, 210, 243, 7, 121, 117, 180, 99, 86, 230, 62, 222, 63, 251, 46, 242, 161, 37, 67, 254, 103,
803                199, 93, 74, 174, 166, 64, 17, 198, 242, 144,
804            ])),
805        };
806
807        let encryption_key: EncryptionKey = picky_asn1_der::from_bytes(&expected_raw).unwrap();
808        let encryption_key_raw = picky_asn1_der::to_vec(&encryption_key).unwrap();
809
810        assert_eq!(encryption_key, expected);
811        assert_eq!(encryption_key_raw, expected_raw);
812    }
813
814    #[test]
815    fn last_req_inner() {
816        let expected_raw = [
817            48, 24, 160, 3, 2, 1, 0, 161, 17, 24, 15, 49, 57, 55, 48, 48, 49, 48, 49, 48, 48, 48, 48, 48, 48, 90,
818        ];
819        let expected = LastReqInner {
820            lr_type: ExplicitContextTag0::from(IntegerAsn1(vec![0])),
821            lr_value: ExplicitContextTag1::from(KerberosTime::from(Date::new(1970, 1, 1, 0, 0, 0).unwrap())),
822        };
823
824        let last_req_inner: LastReqInner = picky_asn1_der::from_bytes(&expected_raw).unwrap();
825        let last_req_inner_raw = picky_asn1_der::to_vec(&last_req_inner).unwrap();
826
827        assert_eq!(last_req_inner, expected);
828        assert_eq!(last_req_inner_raw, expected_raw);
829    }
830
831    #[test]
832    fn authenticator() {
833        let expected_raw = [
834            98, 130, 1, 14, 48, 130, 1, 10, 160, 3, 2, 1, 5, 161, 13, 27, 11, 69, 88, 65, 77, 80, 76, 69, 46, 67, 79,
835            77, 162, 15, 48, 13, 160, 3, 2, 1, 1, 161, 6, 48, 4, 27, 2, 112, 51, 163, 37, 48, 35, 160, 5, 2, 3, 0, 128,
836            3, 161, 26, 4, 24, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 164, 3, 2, 1,
837            8, 165, 17, 24, 15, 50, 48, 50, 50, 48, 52, 48, 53, 48, 56, 49, 57, 52, 54, 90, 166, 43, 48, 41, 160, 3, 2,
838            1, 18, 161, 34, 4, 32, 137, 180, 229, 144, 148, 18, 158, 111, 110, 0, 13, 63, 21, 116, 77, 186, 198, 9,
839            166, 152, 141, 83, 211, 88, 142, 95, 34, 169, 63, 91, 71, 97, 167, 6, 2, 4, 104, 244, 223, 174, 168, 111,
840            48, 109, 48, 107, 160, 3, 2, 1, 1, 161, 100, 4, 98, 48, 96, 48, 14, 160, 4, 2, 2, 0, 143, 161, 6, 4, 4, 0,
841            64, 0, 0, 48, 78, 160, 4, 2, 2, 0, 144, 161, 70, 4, 68, 84, 0, 69, 0, 82, 0, 77, 0, 83, 0, 82, 0, 86, 0,
842            47, 0, 112, 0, 51, 0, 46, 0, 113, 0, 107, 0, 97, 0, 116, 0, 105, 0, 111, 0, 110, 0, 46, 0, 99, 0, 111, 0,
843            109, 0, 64, 0, 81, 0, 75, 0, 65, 0, 84, 0, 73, 0, 79, 0, 78, 0, 46, 0, 67, 0, 79, 0, 77, 0,
844        ];
845
846        let expected: ApplicationTag<_, 2> = ApplicationTag(AuthenticatorInner {
847            authenticator_vno: ExplicitContextTag0::from(IntegerAsn1(vec![5])),
848            crealm: ExplicitContextTag1::from(GeneralStringAsn1::from(
849                Ia5String::from_string("EXAMPLE.COM".to_owned()).unwrap(),
850            )),
851            cname: ExplicitContextTag2::from(PrincipalName {
852                name_type: ExplicitContextTag0::from(IntegerAsn1(vec![1])),
853                name_string: ExplicitContextTag1::from(Asn1SequenceOf::from(vec![KerberosStringAsn1::from(
854                    Ia5String::from_string("p3".to_owned()).unwrap(),
855                )])),
856            }),
857            cksum: Optional::from(Some(ExplicitContextTag3::from(Checksum {
858                cksumtype: ExplicitContextTag0::from(IntegerAsn1(vec![0x00, 0x80, 0x03])),
859                checksum: ExplicitContextTag1::from(OctetStringAsn1::from(vec![
860                    0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
861                    0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00,
862                ])),
863            }))),
864            cusec: ExplicitContextTag4::from(IntegerAsn1::from(vec![0x08])),
865            ctime: ExplicitContextTag5::from(KerberosTime::from(Date::new(2022, 4, 5, 8, 19, 46).unwrap())),
866            subkey: Optional::from(Some(ExplicitContextTag6::from(EncryptionKey {
867                key_type: ExplicitContextTag0::from(IntegerAsn1::from(vec![0x12])),
868                key_value: ExplicitContextTag1::from(OctetStringAsn1::from(vec![
869                    0x89, 0xB4, 0xE5, 0x90, 0x94, 0x12, 0x9E, 0x6F, 0x6E, 0x00, 0x0D, 0x3F, 0x15, 0x74, 0x4D, 0xBA,
870                    0xC6, 0x09, 0xA6, 0x98, 0x8D, 0x53, 0xD3, 0x58, 0x8E, 0x5F, 0x22, 0xA9, 0x3F, 0x5B, 0x47, 0x61,
871                ])),
872            }))),
873            seq_number: Optional::from(Some(ExplicitContextTag7::from(IntegerAsn1::from(vec![
874                0x68, 0xf4, 0xdf, 0xae,
875            ])))),
876            authorization_data: Optional::from(Some(ExplicitContextTag8::from(AuthorizationData::from(vec![
877                AuthorizationDataInner {
878                    ad_type: ExplicitContextTag0::from(IntegerAsn1::from(vec![0x01])),
879                    ad_data: ExplicitContextTag1::from(OctetStringAsn1::from(vec![
880                        48, 96, 48, 14, 160, 4, 2, 2, 0, 143, 161, 6, 4, 4, 0, 64, 0, 0, 48, 78, 160, 4, 2, 2, 0, 144,
881                        161, 70, 4, 68, 84, 0, 69, 0, 82, 0, 77, 0, 83, 0, 82, 0, 86, 0, 47, 0, 112, 0, 51, 0, 46, 0,
882                        113, 0, 107, 0, 97, 0, 116, 0, 105, 0, 111, 0, 110, 0, 46, 0, 99, 0, 111, 0, 109, 0, 64, 0, 81,
883                        0, 75, 0, 65, 0, 84, 0, 73, 0, 79, 0, 78, 0, 46, 0, 67, 0, 79, 0, 77, 0,
884                    ])),
885                },
886            ])))),
887        });
888
889        let authenticator: ApplicationTag<AuthenticatorInner, 2> = picky_asn1_der::from_bytes(&expected_raw).unwrap();
890        let authenticator_raw = picky_asn1_der::to_vec(&authenticator).unwrap();
891
892        assert_eq!(authenticator, expected);
893        assert_eq!(authenticator_raw, expected_raw);
894    }
895
896    #[test]
897    fn kerb_pa_pac_request() {
898        let expected_raw = [48, 5, 160, 3, 1, 1, 255];
899        let expected = KerbPaPacRequest {
900            include_pac: ExplicitContextTag0::from(true),
901        };
902
903        let kerb_pa_pac_request: KerbPaPacRequest = picky_asn1_der::from_bytes(&expected_raw).unwrap();
904        let kerb_pa_pac_request_raw = picky_asn1_der::to_vec(&kerb_pa_pac_request).unwrap();
905
906        assert_eq!(kerb_pa_pac_request, expected);
907        assert_eq!(kerb_pa_pac_request_raw, expected_raw);
908    }
909
910    #[test]
911    fn etype_info2_entry() {
912        let expected_raw = [
913            48, 22, 160, 3, 2, 1, 18, 161, 15, 27, 13, 69, 88, 65, 77, 80, 76, 69, 46, 67, 79, 77, 112, 51,
914        ];
915        let expected = EtypeInfo2Entry {
916            etype: ExplicitContextTag0::from(IntegerAsn1::from(vec![0x12])),
917            salt: Optional::from(Some(ExplicitContextTag1::from(KerberosStringAsn1::from(
918                Ia5String::from_string("EXAMPLE.COMp3".to_owned()).unwrap(),
919            )))),
920            s2kparams: Optional::from(None),
921        };
922
923        let etype_info2_entry: EtypeInfo2Entry = picky_asn1_der::from_bytes(&expected_raw).unwrap();
924        let etype_info2_entry_raw = picky_asn1_der::to_vec(&etype_info2_entry).unwrap();
925
926        assert_eq!(etype_info2_entry, expected);
927        assert_eq!(etype_info2_entry_raw, expected_raw);
928    }
929
930    #[test]
931    fn pa_enc_ts_enc() {
932        let expected_raw = vec![
933            48, 24, 160, 17, 24, 15, 50, 48, 50, 50, 48, 52, 48, 53, 48, 56, 49, 57, 52, 54, 90, 161, 3, 2, 1, 32,
934        ];
935        let expected = PaEncTsEnc {
936            patimestamp: ExplicitContextTag0::from(KerberosTime::from(Date::new(2022, 4, 5, 8, 19, 46).unwrap())),
937            pausec: Optional::from(Some(ExplicitContextTag1::from(Microseconds::from(vec![32])))),
938        };
939
940        let pa_enc_ts_enc: PaEncTsEnc = picky_asn1_der::from_bytes(&expected_raw).unwrap();
941        let pa_enc_ts_enc_raw = picky_asn1_der::to_vec(&expected).unwrap();
942
943        assert_eq!(pa_enc_ts_enc, expected);
944        assert_eq!(pa_enc_ts_enc_raw, expected_raw);
945    }
946
947    #[test]
948    fn enc_ap_rep_part() {
949        let expected_raw = vec![
950            123, 79, 48, 77, 160, 17, 24, 15, 50, 48, 50, 50, 48, 52, 48, 57, 49, 49, 49, 54, 52, 52, 90, 161, 3, 2, 1,
951            43, 162, 43, 48, 41, 160, 3, 2, 1, 18, 161, 34, 4, 32, 225, 45, 62, 116, 165, 142, 214, 44, 102, 216, 202,
952            158, 12, 78, 40, 121, 161, 178, 118, 68, 81, 178, 188, 246, 235, 201, 45, 41, 17, 64, 189, 185, 163, 6, 2,
953            4, 74, 244, 122, 62,
954        ];
955        let expected = EncApRepPart::from(EncApRepPartInner {
956            ctime: ExplicitContextTag0::from(KerberosTime::from(Date::new(2022, 4, 9, 11, 16, 44).unwrap())),
957            cusec: ExplicitContextTag1::from(Microseconds::from(vec![0x2b])),
958            subkey: Optional::from(Some(ExplicitContextTag2::from(EncryptionKey {
959                key_type: ExplicitContextTag0::from(IntegerAsn1::from(vec![0x12])),
960                key_value: ExplicitContextTag1::from(OctetStringAsn1::from(vec![
961                    0xe1, 0x2d, 0x3e, 0x74, 0xa5, 0x8e, 0xd6, 0x2c, 0x66, 0xd8, 0xca, 0x9e, 0x0c, 0x4e, 0x28, 0x79,
962                    0xa1, 0xb2, 0x76, 0x44, 0x51, 0xb2, 0xbc, 0xf6, 0xeb, 0xc9, 0x2d, 0x29, 0x11, 0x40, 0xbd, 0xb9,
963                ])),
964            }))),
965            seq_number: Optional::from(Some(ExplicitContextTag3::from(IntegerAsn1::from(vec![
966                0x4a, 0xf4, 0x7a, 0x3e,
967            ])))),
968        });
969
970        let enc_ap_rep_part: EncApRepPart = picky_asn1_der::from_bytes(&expected_raw).unwrap();
971        let enc_ap_rep_part_raw = picky_asn1_der::to_vec(&expected).unwrap();
972
973        assert_eq!(enc_ap_rep_part, expected);
974        assert_eq!(enc_ap_rep_part_raw, expected_raw);
975    }
976
977    #[test]
978    fn krb_result_decode() {
979        use super::ResultExt;
980        let raw_as_req = vec![
981            106, 129, 181, 48, 129, 178, 161, 3, 2, 1, 5, 162, 3, 2, 1, 10, 163, 26, 48, 24, 48, 10, 161, 4, 2, 2, 0,
982            150, 162, 2, 4, 0, 48, 10, 161, 4, 2, 2, 0, 149, 162, 2, 4, 0, 164, 129, 137, 48, 129, 134, 160, 7, 3, 5,
983            0, 0, 0, 0, 16, 161, 19, 48, 17, 160, 3, 2, 1, 1, 161, 10, 48, 8, 27, 6, 109, 121, 117, 115, 101, 114, 162,
984            13, 27, 11, 69, 88, 65, 77, 80, 76, 69, 46, 67, 79, 77, 163, 32, 48, 30, 160, 3, 2, 1, 2, 161, 23, 48, 21,
985            27, 6, 107, 114, 98, 116, 103, 116, 27, 11, 69, 88, 65, 77, 80, 76, 69, 46, 67, 79, 77, 165, 17, 24, 15,
986            50, 48, 50, 49, 49, 50, 50, 57, 49, 48, 51, 54, 48, 54, 90, 167, 6, 2, 4, 29, 32, 235, 11, 168, 26, 48, 24,
987            2, 1, 18, 2, 1, 17, 2, 1, 20, 2, 1, 19, 2, 1, 16, 2, 1, 23, 2, 1, 25, 2, 1, 26,
988        ];
989        let expected_ap_req = Ok(AsReq::from(KdcReq {
990            pvno: ExplicitContextTag1::from(IntegerAsn1(vec![5])),
991            msg_type: ExplicitContextTag2::from(IntegerAsn1(vec![10])),
992            padata: Optional::from(Some(ExplicitContextTag3::from(Asn1SequenceOf::from(vec![
993                PaData {
994                    padata_type: ExplicitContextTag1::from(IntegerAsn1(vec![0, 150])),
995                    padata_data: ExplicitContextTag2::from(OctetStringAsn1(Vec::new())),
996                },
997                PaData {
998                    padata_type: ExplicitContextTag1::from(IntegerAsn1(vec![0, 149])),
999                    padata_data: ExplicitContextTag2::from(OctetStringAsn1(Vec::new())),
1000                },
1001            ])))),
1002            req_body: ExplicitContextTag4::from(KdcReqBody {
1003                kdc_options: ExplicitContextTag0::from(BitStringAsn1::from(BitString::with_bytes(vec![0, 0, 0, 16]))),
1004                cname: Optional::from(Some(ExplicitContextTag1::from(PrincipalName {
1005                    name_type: ExplicitContextTag0::from(IntegerAsn1(vec![1])),
1006                    name_string: ExplicitContextTag1::from(Asn1SequenceOf::from(vec![GeneralStringAsn1::from(
1007                        Ia5String::from_string("myuser".to_owned()).unwrap(),
1008                    )])),
1009                }))),
1010                realm: ExplicitContextTag2::from(GeneralStringAsn1::from(
1011                    Ia5String::from_string("EXAMPLE.COM".to_owned()).unwrap(),
1012                )),
1013                sname: Optional::from(Some(ExplicitContextTag3::from(PrincipalName {
1014                    name_type: ExplicitContextTag0::from(IntegerAsn1(vec![2])),
1015                    name_string: ExplicitContextTag1::from(Asn1SequenceOf::from(vec![
1016                        KerberosStringAsn1::from(Ia5String::from_string("krbtgt".to_owned()).unwrap()),
1017                        KerberosStringAsn1::from(Ia5String::from_string("EXAMPLE.COM".to_owned()).unwrap()),
1018                    ])),
1019                }))),
1020                from: Optional::from(None),
1021                till: ExplicitContextTag5::from(KerberosTime::from(Date::new(2021, 12, 29, 10, 36, 6).unwrap())),
1022                rtime: Optional::from(None),
1023                nonce: ExplicitContextTag7::from(IntegerAsn1(vec![29, 32, 235, 11])),
1024                etype: ExplicitContextTag8::from(Asn1SequenceOf::from(vec![
1025                    IntegerAsn1(vec![18]),
1026                    IntegerAsn1(vec![17]),
1027                    IntegerAsn1(vec![20]),
1028                    IntegerAsn1(vec![19]),
1029                    IntegerAsn1(vec![16]),
1030                    IntegerAsn1(vec![23]),
1031                    IntegerAsn1(vec![25]),
1032                    IntegerAsn1(vec![26]),
1033                ])),
1034                addresses: Optional::from(None),
1035                enc_authorization_data: Optional::from(None),
1036                additional_tickets: Optional::from(None),
1037            }),
1038        }));
1039        let raw_error = vec![
1040            126, 129, 151, 48, 129, 148, 160, 3, 2, 1, 5, 161, 3, 2, 1, 30, 164, 17, 24, 15, 50, 48, 50, 49, 49, 50,
1041            50, 56, 49, 51, 52, 48, 49, 49, 90, 165, 5, 2, 3, 12, 139, 242, 166, 3, 2, 1, 6, 167, 13, 27, 11, 69, 88,
1042            65, 77, 80, 76, 69, 46, 67, 79, 77, 168, 21, 48, 19, 160, 3, 2, 1, 1, 161, 12, 48, 10, 27, 8, 98, 97, 100,
1043            95, 117, 115, 101, 114, 169, 13, 27, 11, 69, 88, 65, 77, 80, 76, 69, 46, 67, 79, 77, 170, 32, 48, 30, 160,
1044            3, 2, 1, 2, 161, 23, 48, 21, 27, 6, 107, 114, 98, 116, 103, 116, 27, 11, 69, 88, 65, 77, 80, 76, 69, 46,
1045            67, 79, 77, 171, 18, 27, 16, 67, 76, 73, 69, 78, 84, 95, 78, 79, 84, 95, 70, 79, 85, 78, 68,
1046        ];
1047        let expected_error = Err(KrbError::from(KrbErrorInner {
1048            pvno: ExplicitContextTag0::from(IntegerAsn1(vec![5])),
1049            msg_type: ExplicitContextTag1::from(IntegerAsn1(vec![30])),
1050            ctime: Optional::from(None),
1051            cusec: Optional::from(None),
1052            stime: ExplicitContextTag4::from(GeneralizedTimeAsn1::from(Date::new(2021, 12, 28, 13, 40, 11).unwrap())),
1053            susec: ExplicitContextTag5::from(IntegerAsn1(vec![12, 139, 242])),
1054            error_code: ExplicitContextTag6::from(KDC_ERR_C_PRINCIPAL_UNKNOWN),
1055            crealm: Optional::from(Some(ExplicitContextTag7::from(GeneralStringAsn1::from(
1056                Ia5String::from_string("EXAMPLE.COM".to_owned()).unwrap(),
1057            )))),
1058            cname: Optional::from(Some(ExplicitContextTag8::from(PrincipalName {
1059                name_type: ExplicitContextTag0::from(IntegerAsn1(vec![1])),
1060                name_string: ExplicitContextTag1::from(Asn1SequenceOf::from(vec![GeneralStringAsn1::from(
1061                    Ia5String::from_string("bad_user".to_owned()).unwrap(),
1062                )])),
1063            }))),
1064            realm: ExplicitContextTag9::from(GeneralStringAsn1::from(
1065                Ia5String::from_string("EXAMPLE.COM".to_owned()).unwrap(),
1066            )),
1067            sname: ExplicitContextTag10::from(PrincipalName {
1068                name_type: ExplicitContextTag0::from(IntegerAsn1(vec![2])),
1069                name_string: ExplicitContextTag1::from(Asn1SequenceOf::from(vec![
1070                    KerberosStringAsn1::from(Ia5String::from_string("krbtgt".to_owned()).unwrap()),
1071                    KerberosStringAsn1::from(Ia5String::from_string("EXAMPLE.COM".to_owned()).unwrap()),
1072                ])),
1073            }),
1074            e_text: Optional::from(Some(ExplicitContextTag11::from(GeneralStringAsn1::from(
1075                Ia5String::from_string("CLIENT_NOT_FOUND".to_owned()).unwrap(),
1076            )))),
1077            e_data: Optional::from(None),
1078        }));
1079
1080        let mut d = picky_asn1_der::Deserializer::new_from_bytes(&raw_as_req);
1081        let krb_result: Result<AsReq, KrbError> = Result::deserialize(&mut d).unwrap();
1082        assert_eq!(expected_ap_req, krb_result);
1083
1084        let mut d = picky_asn1_der::Deserializer::new_from_bytes(&raw_error);
1085        let krb_result: Result<AsReq, KrbError> = Result::deserialize(&mut d).unwrap();
1086        assert_eq!(expected_error, krb_result);
1087    }
1088}