1use crate::spnego_oid;
2use crate::NegTokenInit2;
3use crate::NegTokenResp;
4use red_asn1::{
5 build_length, parse_length, Asn1Object, Oid, Tag, TagClass, TagType,
6};
7
8#[derive(Clone, Debug, PartialEq)]
9pub enum NegToken {
10 Init2(NegTokenInit2),
11 Resp(NegTokenResp),
12}
13
14impl NegToken {
15 pub fn build(&self) -> Vec<u8> {
16 match self {
17 Self::Init2(init2) => {
18 let mut raw = Vec::new();
19 raw.extend(spnego_oid().build());
20
21 raw.extend(
22 Tag::new(0, TagType::Constructed, TagClass::Context)
23 .build(),
24 );
25
26 let raw_init2 = init2.build();
27 raw.extend(build_length(raw_init2.len()));
28 raw.extend(raw_init2);
29
30 let mut ext_raw =
31 Tag::new(0, TagType::Constructed, TagClass::Application)
32 .build();
33 ext_raw.extend(build_length(raw.len()));
34 ext_raw.extend(raw);
35
36 return ext_raw;
37 }
38 Self::Resp(resp) => {
39 let mut ext_raw =
40 Tag::new(1, TagType::Constructed, TagClass::Context)
41 .build();
42
43 let raw_resp = resp.build();
44 ext_raw.extend(build_length(raw_resp.len()));
45 ext_raw.extend(raw_resp);
46
47 return ext_raw;
48 }
49 }
50 }
51
52 pub fn parse(raw: &[u8]) -> red_asn1::Result<Self> {
53 let (raw, initial_tag) = Tag::parse(raw)?;
54 let (raw, _) = parse_length(raw)?;
55
56 if initial_tag
57 == Tag::new(0, TagType::Constructed, TagClass::Application)
58 {
59 let (raw, _) = Oid::parse(raw)?;
60
61 let (raw, _) = Tag::parse(raw)?;
62
63 let (raw, _) = parse_length(raw)?;
64
65 let (_, token_init) = NegTokenInit2::parse(raw)?;
66 return Ok(Self::Init2(token_init));
67 }
68
69 let (_, token_resp) = NegTokenResp::parse(raw)?;
70 return Ok(Self::Resp(token_resp));
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use crate::ntlmssp_oid;
78 use crate::ACCEPT_INCOMPLETE;
79
80 const RAW_SPNEGO_INIT_MSG: &'static [u8] = &[
81 0x60, 0x40, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02, 0xa0, 0x36,
82 0x30, 0x34, 0xa0, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
83 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa2, 0x22, 0x04, 0x20, 0x4e, 0x54,
84 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x02,
85 0x88, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 ];
88
89 #[test]
90 fn test_build_spnego_init_msg() {
91 let mut init = NegTokenInit2::default();
92 init.mech_types = vec![ntlmssp_oid()];
93 init.mech_token = Some(vec![
94 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00,
95 0x00, 0x05, 0x02, 0x88, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 ]);
98
99 assert_eq!(RAW_SPNEGO_INIT_MSG.to_vec(), NegToken::Init2(init).build(),);
100 }
101
102 #[test]
103 fn test_parse_spnego_init_msg() {
104 let mut init = NegTokenInit2::default();
105 init.mech_types = vec![ntlmssp_oid()];
106 init.mech_token = Some(vec![
107 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00,
108 0x00, 0x05, 0x02, 0x88, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 ]);
111
112 assert_eq!(
113 NegToken::Init2(init),
114 NegToken::parse(RAW_SPNEGO_INIT_MSG).unwrap()
115 );
116 }
117
118 const RAW_SPNEGO_RESP_MSG: &'static [u8] = &[
119 0xa1, 0x82, 0x01, 0x00, 0x30, 0x81, 0xfd, 0xa0, 0x03, 0x0a, 0x01, 0x01,
120 0xa1, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02,
121 0x02, 0x0a, 0xa2, 0x81, 0xe7, 0x04, 0x81, 0xe4, 0x4e, 0x54, 0x4c, 0x4d,
122 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
123 0x38, 0x00, 0x00, 0x00, 0x05, 0x02, 0x89, 0xa2, 0x29, 0x4d, 0xc3, 0x21,
124 0x91, 0x96, 0x86, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x9e, 0x00, 0x9e, 0x00, 0x46, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x61, 0x4a,
126 0x00, 0x00, 0x00, 0x0f, 0x43, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00,
127 0x4f, 0x00, 0x53, 0x00, 0x4f, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x43, 0x00,
128 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x4f, 0x00,
129 0x01, 0x00, 0x0e, 0x00, 0x57, 0x00, 0x53, 0x00, 0x30, 0x00, 0x31, 0x00,
130 0x2d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x63, 0x00,
131 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00,
132 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00,
133 0x03, 0x00, 0x2a, 0x00, 0x77, 0x00, 0x73, 0x00, 0x30, 0x00, 0x31, 0x00,
134 0x2d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00,
135 0x6e, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x2e, 0x00,
136 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x05, 0x00,
137 0x1a, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x6f, 0x00,
138 0x73, 0x00, 0x6f, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00,
139 0x61, 0x00, 0x6c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x4d, 0x01, 0xec, 0x80,
140 0x9a, 0xf0, 0xd6, 0x01, 0x00, 0x00, 0x00, 0x00,
141 ];
142
143 #[test]
144 fn test_parse_spnego_resp_msg() {
145 let mut neg_token_resp = NegTokenResp::default();
146 *neg_token_resp.neg_state = ACCEPT_INCOMPLETE;
147 neg_token_resp.supported_mech = Some(ntlmssp_oid());
148 neg_token_resp.response_token = Some(vec![
149 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00,
150 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x38, 0x00, 0x00, 0x00, 0x05, 0x02,
151 0x89, 0xa2, 0x29, 0x4d, 0xc3, 0x21, 0x91, 0x96, 0x86, 0xd1, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x9e, 0x00,
153 0x46, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x61, 0x4a, 0x00, 0x00, 0x00,
154 0x0f, 0x43, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x4f, 0x00,
155 0x53, 0x00, 0x4f, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x43, 0x00, 0x4f,
156 0x00, 0x4e, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x4f, 0x00,
157 0x01, 0x00, 0x0e, 0x00, 0x57, 0x00, 0x53, 0x00, 0x30, 0x00, 0x31,
158 0x00, 0x2d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x04, 0x00, 0x1a, 0x00,
159 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x73,
160 0x00, 0x6f, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00,
161 0x61, 0x00, 0x6c, 0x00, 0x03, 0x00, 0x2a, 0x00, 0x77, 0x00, 0x73,
162 0x00, 0x30, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x30, 0x00,
163 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x6f,
164 0x00, 0x73, 0x00, 0x6f, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00,
165 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x63,
166 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x73, 0x00,
167 0x6f, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61,
168 0x00, 0x6c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x4d, 0x01, 0xec, 0x80,
169 0x9a, 0xf0, 0xd6, 0x01, 0x00, 0x00, 0x00, 0x00,
170 ]);
171
172 assert_eq!(
173 NegToken::Resp(neg_token_resp),
174 NegToken::parse(RAW_SPNEGO_RESP_MSG).unwrap()
175 );
176 }
177
178 #[test]
179 fn test_build_spnego_resp_msg() {
180 let mut neg_token_resp = NegTokenResp::default();
181 *neg_token_resp.neg_state = ACCEPT_INCOMPLETE;
182 neg_token_resp.supported_mech = Some(ntlmssp_oid());
183 neg_token_resp.response_token = Some(vec![
184 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00,
185 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x38, 0x00, 0x00, 0x00, 0x05, 0x02,
186 0x89, 0xa2, 0x29, 0x4d, 0xc3, 0x21, 0x91, 0x96, 0x86, 0xd1, 0x00,
187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x9e, 0x00,
188 0x46, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x61, 0x4a, 0x00, 0x00, 0x00,
189 0x0f, 0x43, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x4f, 0x00,
190 0x53, 0x00, 0x4f, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x43, 0x00, 0x4f,
191 0x00, 0x4e, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x4f, 0x00,
192 0x01, 0x00, 0x0e, 0x00, 0x57, 0x00, 0x53, 0x00, 0x30, 0x00, 0x31,
193 0x00, 0x2d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x04, 0x00, 0x1a, 0x00,
194 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x73,
195 0x00, 0x6f, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00,
196 0x61, 0x00, 0x6c, 0x00, 0x03, 0x00, 0x2a, 0x00, 0x77, 0x00, 0x73,
197 0x00, 0x30, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x30, 0x00,
198 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x6f,
199 0x00, 0x73, 0x00, 0x6f, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00,
200 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x63,
201 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x73, 0x00,
202 0x6f, 0x00, 0x2e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61,
203 0x00, 0x6c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x4d, 0x01, 0xec, 0x80,
204 0x9a, 0xf0, 0xd6, 0x01, 0x00, 0x00, 0x00, 0x00,
205 ]);
206
207 assert_eq!(
208 RAW_SPNEGO_RESP_MSG.to_vec(),
209 NegToken::Resp(neg_token_resp).build(),
210 );
211 }
212}