1#![forbid(unsafe_code)]
2
3use super::*;
4
5pub fn append_auth_phase_one(
6 out: &mut Vec<u8>,
7 user: &str,
8 program: &str,
9 machine: &str,
10 osuser: &str,
11 terminal: &str,
12 pid: u32,
13) -> Result<()> {
14 let mut writer = TtcWriter::new();
15 writer.write_function_code(TNS_FUNC_AUTH_PHASE_ONE);
16 write_auth_header(&mut writer, user, TNS_AUTH_MODE_LOGON, 5)?;
17 write_key_value(&mut writer, "AUTH_TERMINAL", terminal, 0)?;
18 write_key_value(&mut writer, "AUTH_PROGRAM_NM", program, 0)?;
19 write_key_value(&mut writer, "AUTH_MACHINE", machine, 0)?;
20 write_key_value(&mut writer, "AUTH_PID", &pid.to_string(), 0)?;
21 write_key_value(&mut writer, "AUTH_SID", osuser, 0)?;
22 out.extend_from_slice(&writer.into_bytes());
23 Ok(())
24}
25
26pub fn build_auth_phase_two_payload(
27 user: &str,
28 encrypted: &crate::crypto::EncryptedPassword,
29 driver_name: &str,
30 version_num: u32,
31 connect_string: &str,
32) -> Result<Vec<u8>> {
33 build_auth_phase_two_payload_with_seq(
34 user,
35 encrypted,
36 driver_name,
37 version_num,
38 connect_string,
39 1,
40 )
41}
42
43pub fn build_auth_phase_two_payload_with_seq(
44 user: &str,
45 encrypted: &crate::crypto::EncryptedPassword,
46 driver_name: &str,
47 version_num: u32,
48 connect_string: &str,
49 seq_num: u8,
50) -> Result<Vec<u8>> {
51 build_auth_phase_two_payload_with_context_with_seq(
52 user,
53 encrypted,
54 driver_name,
55 version_num,
56 connect_string,
57 seq_num,
58 &[],
59 )
60}
61
62pub fn build_auth_phase_two_payload_with_context_with_seq(
63 user: &str,
64 encrypted: &crate::crypto::EncryptedPassword,
65 driver_name: &str,
66 version_num: u32,
67 connect_string: &str,
68 seq_num: u8,
69 app_context: &[(String, String, String)],
70) -> Result<Vec<u8>> {
71 build_auth_phase_two_payload_with_proxy_with_seq(
72 user,
73 encrypted,
74 driver_name,
75 version_num,
76 connect_string,
77 seq_num,
78 app_context,
79 None,
80 )
81}
82
83#[allow(clippy::too_many_arguments)]
87pub fn build_auth_phase_two_payload_with_proxy_with_seq(
88 user: &str,
89 encrypted: &crate::crypto::EncryptedPassword,
90 driver_name: &str,
91 version_num: u32,
92 connect_string: &str,
93 seq_num: u8,
94 app_context: &[(String, String, String)],
95 proxy_user: Option<&str>,
96) -> Result<Vec<u8>> {
97 let mut writer = TtcWriter::new();
98 writer.write_function_code_with_seq(TNS_FUNC_AUTH_PHASE_TWO, seq_num);
99 writer.write_ub8(0);
100 let mut num_pairs = 6u32;
101 if encrypted.speedy_key.is_some() {
102 num_pairs += 1;
103 }
104 if proxy_user.is_some() {
105 num_pairs += 1;
106 }
107 if !connect_string.is_empty() {
108 num_pairs += 1;
109 }
110 let app_context_pairs =
111 app_context
112 .len()
113 .checked_mul(3)
114 .ok_or(ProtocolError::InvalidPacketLength {
115 length: app_context.len(),
116 minimum: 0,
117 })?;
118 num_pairs +=
119 u32::try_from(app_context_pairs).map_err(|_| ProtocolError::InvalidPacketLength {
120 length: app_context.len(),
121 minimum: 0,
122 })?;
123 write_auth_header(
124 &mut writer,
125 user,
126 TNS_AUTH_MODE_LOGON | TNS_AUTH_MODE_WITH_PASSWORD,
127 num_pairs,
128 )?;
129 if let Some(proxy_user) = proxy_user {
130 write_key_value(&mut writer, "PROXY_CLIENT_NAME", proxy_user, 0)?;
131 }
132 write_key_value(&mut writer, "AUTH_SESSKEY", &encrypted.session_key, 1)?;
133 if let Some(speedy_key) = &encrypted.speedy_key {
134 write_key_value(&mut writer, "AUTH_PBKDF2_SPEEDY_KEY", speedy_key, 0)?;
135 }
136 write_key_value(&mut writer, "AUTH_PASSWORD", &encrypted.password, 0)?;
137 write_key_value(&mut writer, "SESSION_CLIENT_CHARSET", "873", 0)?;
138 write_key_value(&mut writer, "SESSION_CLIENT_DRIVER_NAME", driver_name, 0)?;
139 write_key_value(
140 &mut writer,
141 "SESSION_CLIENT_VERSION",
142 &version_num.to_string(),
143 0,
144 )?;
145 write_key_value(
146 &mut writer,
147 "AUTH_ALTER_SESSION",
148 "ALTER SESSION SET TIME_ZONE='+00:00'\0",
149 1,
150 )?;
151 for (namespace, name, value) in app_context {
152 write_key_value(&mut writer, "AUTH_APPCTX_NSPACE\0", namespace, 0)?;
153 write_key_value(&mut writer, "AUTH_APPCTX_ATTR\0", name, 0)?;
154 write_key_value(&mut writer, "AUTH_APPCTX_VALUE\0", value, 0)?;
155 }
156 if !connect_string.is_empty() {
157 write_key_value(&mut writer, "AUTH_CONNECT_STRING", connect_string, 0)?;
158 }
159 Ok(writer.into_bytes())
160}
161
162pub fn build_change_password_payload_with_seq(
167 user: &str,
168 encoded_password: &str,
169 encoded_newpassword: &str,
170 seq_num: u8,
171) -> Result<Vec<u8>> {
172 let mut writer = TtcWriter::new();
173 writer.write_function_code_with_seq(TNS_FUNC_AUTH_PHASE_TWO, seq_num);
174 writer.write_ub8(0);
175 write_auth_header(
176 &mut writer,
177 user,
178 TNS_AUTH_MODE_WITH_PASSWORD | TNS_AUTH_MODE_CHANGE_PASSWORD,
179 2,
180 )?;
181 write_key_value(&mut writer, "AUTH_PASSWORD", encoded_password, 0)?;
182 write_key_value(&mut writer, "AUTH_NEWPASSWORD", encoded_newpassword, 0)?;
183 Ok(writer.into_bytes())
184}
185
186pub fn parse_auth_response(payload: &[u8]) -> Result<AuthResponse> {
187 let mut reader = TtcReader::new(payload);
188 let mut response = AuthResponse::default();
189 while reader.remaining() > 0 {
190 let message_type = reader.read_u8()?;
191 match message_type {
192 TNS_MSG_TYPE_PROTOCOL => {
193 if let Some(capabilities) = skip_protocol_message(&mut reader)? {
194 response.capabilities = Some(capabilities);
195 }
196 }
197 TNS_MSG_TYPE_DATA_TYPES => skip_data_types_response(&mut reader)?,
198 TNS_MSG_TYPE_PARAMETER => {
199 let mut parsed = parse_return_parameters(&mut reader)?;
200 response.session_data.append(&mut parsed.session_data);
201 if parsed.verifier_type.is_some() {
202 response.verifier_type = parsed.verifier_type;
203 }
204 }
205 TNS_MSG_TYPE_STATUS => {
206 let _call_status = reader.read_ub4()?;
207 let _seq = reader.read_ub2()?;
208 }
209 TNS_MSG_TYPE_SERVER_SIDE_PIGGYBACK => {
210 let _ = skip_server_side_piggyback(&mut reader)?;
211 }
212 TNS_MSG_TYPE_END_OF_RESPONSE => break,
213 TNS_MSG_TYPE_ERROR => {
214 if let Some(message) = parse_server_error(&mut reader, 13)? {
215 return Err(ProtocolError::ServerError(message));
216 }
217 }
218 _ => {
219 return Err(ProtocolError::UnknownMessageType {
220 message_type,
221 position: reader.position().saturating_sub(1),
222 })
223 }
224 }
225 }
226 Ok(response)
227}
228
229pub(crate) fn write_auth_header(
230 writer: &mut TtcWriter,
231 user: &str,
232 auth_mode: u32,
233 num_pairs: u32,
234) -> Result<()> {
235 let user_bytes = user.as_bytes();
236 writer.write_u8(u8::from(!user_bytes.is_empty()));
237 writer.write_ub4(u32::try_from(user_bytes.len()).map_err(|_| {
238 ProtocolError::InvalidPacketLength {
239 length: user_bytes.len(),
240 minimum: 0,
241 }
242 })?);
243 writer.write_ub4(auth_mode);
244 writer.write_u8(1);
245 writer.write_ub4(num_pairs);
246 writer.write_u8(1);
247 writer.write_u8(1);
248 if !user_bytes.is_empty() {
249 writer.write_bytes_with_length(user_bytes)?;
250 }
251 Ok(())
252}
253
254pub(crate) fn write_key_value(
255 writer: &mut TtcWriter,
256 key: &str,
257 value: &str,
258 flags: u32,
259) -> Result<()> {
260 writer.write_str_two_lengths(key)?;
261 writer.write_str_two_lengths(value)?;
262 writer.write_ub4(flags);
263 Ok(())
264}
265
266pub(crate) fn parse_return_parameters(reader: &mut TtcReader<'_>) -> Result<AuthResponse> {
267 let num_params = reader.read_ub2()?;
268 let mut response = AuthResponse::default();
269 for _ in 0..num_params {
270 let key = reader
271 .read_string_with_length()?
272 .ok_or(ProtocolError::TtcDecode("missing auth response key"))?;
273 let value = reader.read_string_with_length()?.unwrap_or_default();
274 if key == "AUTH_VFR_DATA" {
275 response.verifier_type = Some(reader.read_ub4()?);
276 } else {
277 let _flags = reader.read_ub4()?;
278 }
279 response.session_data.insert(key, value);
280 }
281 Ok(response)
282}