oracledb_protocol/thin/
connect.rs1#![forbid(unsafe_code)]
2
3use super::*;
4
5pub fn build_connect_packet_payload(connect_data: &str, sdu: u16) -> Result<Vec<u8>> {
6 let connect_bytes = connect_data.as_bytes();
7 let connect_len =
8 u16::try_from(connect_bytes.len()).map_err(|_| ProtocolError::PacketTooLarge {
9 length: connect_bytes.len(),
10 })?;
11
12 let mut writer = TtcWriter::new();
13 writer.write_u16be(TNS_VERSION_DESIRED);
14 writer.write_u16be(TNS_VERSION_MIN);
15 writer.write_u16be(TNS_GSO_DONT_CARE);
16 writer.write_u16be(sdu);
17 writer.write_u16be(sdu);
18 writer.write_u16be(TNS_PROTOCOL_CHARACTERISTICS);
19 writer.write_u16be(0);
20 writer.write_u16be(1);
21 writer.write_u16be(connect_len);
22 writer.write_u16be(74);
23 writer.write_u32be(0);
24 let nsi_flags = TNS_NSI_SUPPORT_SECURITY_RENEG | TNS_NSI_DISABLE_NA;
25 writer.write_u8(nsi_flags);
26 writer.write_u8(nsi_flags);
27 writer.write_u64be(0);
28 writer.write_u64be(0);
29 writer.write_u64be(0);
30 writer.write_u32be(u32::from(sdu));
31 writer.write_u32be(u32::from(sdu));
32 writer.write_u32be(0);
33 writer.write_u32be(0);
34 writer.write_raw(connect_bytes);
35 Ok(writer.into_bytes())
36}
37
38pub fn parse_accept_payload(payload: &[u8]) -> Result<AcceptInfo> {
39 let mut reader = TtcReader::new(payload);
40 let protocol_version = reader.read_u16be()?;
41 let protocol_options = reader.read_u16be()?;
42 reader.skip(10)?;
43 let flags1 = reader.read_u8()?;
44 if has_u8_flag(flags1, TNS_NSI_NA_REQUIRED) {
45 return Err(ProtocolError::UnsupportedFeature(
46 "Native Network Encryption and Data Integrity",
47 ));
48 }
49 reader.skip(9)?;
50 let sdu = reader.read_u32be()?;
51 let mut flags2 = 0;
52 if protocol_version >= 318 {
53 reader.skip(5)?;
54 flags2 = reader.read_u32be()?;
55 }
56
57 Ok(AcceptInfo {
58 protocol_version,
59 protocol_options,
60 sdu,
61 supports_fast_auth: has_u32_flag(flags2, TNS_ACCEPT_FLAG_FAST_AUTH),
62 supports_oob_check: has_u32_flag(flags2, TNS_ACCEPT_FLAG_CHECK_OOB),
63 supports_oob: protocol_options & TNS_GSO_CAN_RECV_ATTENTION != 0,
66 supports_end_of_response: protocol_version >= 319
67 && has_u32_flag(flags2, TNS_ACCEPT_FLAG_HAS_END_OF_RESPONSE),
68 })
69}
70
71pub fn build_fast_auth_phase_one_payload(
72 user: &str,
73 program: &str,
74 machine: &str,
75 osuser: &str,
76 terminal: &str,
77 pid: u32,
78) -> Result<Vec<u8>> {
79 let mut out = Vec::from_hex(FAST_AUTH_PREFIX_HEX)
80 .map_err(|_| ProtocolError::TtcDecode("invalid static fast-auth prefix"))?;
81 append_auth_phase_one(&mut out, user, program, machine, osuser, terminal, pid)?;
82 Ok(out)
83}
84
85pub fn build_fast_auth_token_payload(
90 user: &str,
91 token: &str,
92 driver_name: &str,
93 version_num: u32,
94 connect_string: &str,
95 edition: Option<&str>,
96) -> Result<Vec<u8>> {
97 let mut out = Vec::from_hex(FAST_AUTH_PREFIX_HEX)
98 .map_err(|_| ProtocolError::TtcDecode("invalid static fast-auth prefix"))?;
99 append_auth_phase_two_token(
100 &mut out,
101 user,
102 token,
103 driver_name,
104 version_num,
105 connect_string,
106 edition,
107 )?;
108 Ok(out)
109}
110
111pub fn build_function_payload(function_code: u8) -> Vec<u8> {
112 build_function_payload_with_seq(function_code, 1)
113}
114
115pub fn build_function_payload_with_seq(function_code: u8, seq_num: u8) -> Vec<u8> {
116 build_function_payload_with_seq_and_token(function_code, seq_num, 0)
117}
118
119pub fn build_function_payload_with_seq_and_token(
123 function_code: u8,
124 seq_num: u8,
125 token_num: u64,
126) -> Vec<u8> {
127 let mut writer = TtcWriter::new();
128 writer.write_function_code_with_seq(function_code, seq_num);
129 writer.write_ub8(token_num);
130 writer.into_bytes()
131}
132
133pub(crate) fn skip_protocol_message(
134 reader: &mut TtcReader<'_>,
135) -> Result<Option<ClientCapabilities>> {
136 let _server_version = reader.read_u8()?;
137 reader.skip(1)?;
138 loop {
139 if reader.read_u8()? == 0 {
140 break;
141 }
142 }
143 let charset_id = reader.read_u16le()?;
144 let _server_flags = reader.read_u8()?;
145 let num_elem = reader.read_u16le()?;
146 reader.skip(usize::from(num_elem) * 5)?;
147 let fdo_len = reader.read_u16be()?;
148 reader.skip(usize::from(fdo_len))?;
149 let compile_caps = reader.read_bytes()?;
150 let runtime_caps = reader.read_bytes()?;
151 let Some(compile_caps) = compile_caps else {
152 return Ok(None);
153 };
154 let server_ttc_field_version = compile_caps
155 .get(TNS_CCAP_FIELD_VERSION)
156 .copied()
157 .unwrap_or_else(|| ClientCapabilities::default().ttc_field_version);
158 let ttc_field_version =
159 server_ttc_field_version.max(ClientCapabilities::default().ttc_field_version);
160 let max_string_size = if runtime_caps
161 .as_deref()
162 .and_then(|caps| caps.get(TNS_RCAP_TTC))
163 .is_some_and(|flags| flags & TNS_RCAP_TTC_32K != 0)
164 {
165 32_767
166 } else {
167 4_000
168 };
169 Ok(Some(ClientCapabilities {
170 ttc_field_version,
171 max_string_size,
172 charset_id,
173 }))
174}
175
176pub(crate) fn skip_data_types_response(reader: &mut TtcReader<'_>) -> Result<()> {
177 loop {
178 let data_type = reader.read_u16be()?;
179 if data_type == 0 {
180 break;
181 }
182 let conv_data_type = reader.read_u16be()?;
183 if conv_data_type != 0 {
184 reader.skip(4)?;
185 }
186 }
187 Ok(())
188}