Coverage Report

Created: 2026-06-07 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/rust/src/pgsql/parser.rs
Line
Count
Source
1
/* Copyright (C) 2022 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
// Author: Juliana Fajardini <jufajardini@oisf.net>
19
20
//! PostgreSQL nom parsers
21
22
use crate::common::nom7::take_until_and_consume;
23
use nom7::branch::alt;
24
use nom7::bytes::streaming::{tag, take, take_until, take_until1};
25
use nom7::character::streaming::{alphanumeric1, char};
26
use nom7::combinator::{all_consuming, cond, eof, map_parser, opt, peek, verify};
27
use nom7::error::{make_error, ErrorKind};
28
use nom7::multi::{many1, many_m_n, many_till};
29
use nom7::number::streaming::{be_i16, be_i32};
30
use nom7::number::streaming::{be_u16, be_u32, be_u8};
31
use nom7::sequence::{terminated, tuple};
32
use nom7::{Err, IResult};
33
34
pub const PGSQL_LENGTH_FIELD: u32 = 4;
35
36
pub const PGSQL_DUMMY_PROTO_MAJOR: u16 = 1234; // 0x04d2
37
pub const PGSQL_DUMMY_PROTO_CANCEL_REQUEST: u16 = 5678; // 0x162e
38
pub const PGSQL_DUMMY_PROTO_MINOR_SSL: u16 = 5679; //0x162f
39
pub const _PGSQL_DUMMY_PROTO_MINOR_GSSAPI: u16 = 5680; // 0x1630
40
41
6.41M
fn parse_length(i: &[u8]) -> IResult<&[u8], u32> {
42
6.41M
    verify(be_u32, |&x| x >= PGSQL_LENGTH_FIELD)(i)
43
6.41M
}
44
45
#[derive(Debug, PartialEq, Eq)]
46
pub enum PgsqlParameters {
47
    // startup parameters
48
    User,
49
    Database,
50
    Options,
51
    Replication,
52
    // runtime parameters
53
    ServerVersion,
54
    ServerEncoding,
55
    ClientEncoding,
56
    ApplicationName,
57
    DefaultTransactionReadOnly,
58
    InHotStandby,
59
    IsSuperuser,
60
    SessionAuthorization,
61
    DateStyle,
62
    IntervalStyle,
63
    TimeZone,
64
    IntegerDatetimes,
65
    StandardConformingStrings,
66
    UnknownParameter(Vec<u8>),
67
}
68
69
impl PgsqlParameters {
70
0
    pub fn to_str(&self) -> &str {
71
0
        match self {
72
0
            PgsqlParameters::User => "user",
73
0
            PgsqlParameters::Database => "database",
74
0
            PgsqlParameters::Options => "options",
75
0
            PgsqlParameters::Replication => "replication",
76
0
            PgsqlParameters::ServerVersion => "server_version",
77
0
            PgsqlParameters::ServerEncoding => "server_encoding",
78
0
            PgsqlParameters::ClientEncoding => "client_encoding",
79
0
            PgsqlParameters::ApplicationName => "application_name",
80
0
            PgsqlParameters::DefaultTransactionReadOnly => "default_transaction_read_only",
81
0
            PgsqlParameters::InHotStandby => "in_hot_standby",
82
0
            PgsqlParameters::IsSuperuser => "is_superuser",
83
0
            PgsqlParameters::SessionAuthorization => "session_authorization",
84
0
            PgsqlParameters::DateStyle => "date_style",
85
0
            PgsqlParameters::IntervalStyle => "interval_style",
86
0
            PgsqlParameters::TimeZone => "time_zone",
87
0
            PgsqlParameters::IntegerDatetimes => "integer_datetimes",
88
0
            PgsqlParameters::StandardConformingStrings => "standard_conforming_strings",
89
0
            PgsqlParameters::UnknownParameter(name) => {
90
0
                std::str::from_utf8(name).unwrap_or("unknown_parameter")
91
            }
92
        }
93
0
    }
94
}
95
96
impl From<&[u8]> for PgsqlParameters {
97
2.43M
    fn from(name: &[u8]) -> Self {
98
2.43M
        match name {
99
2.43M
            br#"user"# => PgsqlParameters::User,
100
2.33M
            br#"database"# => PgsqlParameters::Database,
101
2.32M
            br#"options"# => PgsqlParameters::Options,
102
2.31M
            br#"replication"# => PgsqlParameters::Replication,
103
2.29M
            br#"server_version"# => PgsqlParameters::ServerVersion,
104
2.27M
            br#"server_encoding"# => PgsqlParameters::ServerEncoding,
105
781
            br#"client_encoding"# => PgsqlParameters::ClientEncoding,
106
2.25M
            br#"application_name"# => PgsqlParameters::ApplicationName,
107
2.25M
            br#"default_transaction_read_only"# => PgsqlParameters::DefaultTransactionReadOnly,
108
395
            br#"in_hot_standby"# => PgsqlParameters::InHotStandby,
109
2.23M
            br#"is_superuser"# => PgsqlParameters::IsSuperuser,
110
2.22M
            br#"session_authorization"# => PgsqlParameters::SessionAuthorization,
111
2.21M
            br#"DateStyle"# => PgsqlParameters::DateStyle,
112
2.20M
            br#"IntervalStyle"# => PgsqlParameters::IntervalStyle,
113
470
            br#"TimeZone"# => PgsqlParameters::TimeZone,
114
2.19M
            br#"integer_datetimes"# => PgsqlParameters::IntegerDatetimes,
115
2.18M
            br#"standard_conforming_strings"# => PgsqlParameters::StandardConformingStrings,
116
2.34M
            _ => PgsqlParameters::UnknownParameter(name.to_vec()),
117
        }
118
2.43M
    }
119
}
120
121
#[derive(Debug, PartialEq, Eq)]
122
pub struct PgsqlParameter {
123
    pub name: PgsqlParameters,
124
    pub value: Vec<u8>,
125
}
126
127
#[derive(Debug, PartialEq, Eq)]
128
pub struct PgsqlStartupParameters {
129
    pub user: PgsqlParameter,
130
    pub optional_params: Option<Vec<PgsqlParameter>>,
131
}
132
133
#[derive(Debug, PartialEq, Eq)]
134
pub struct DummyStartupPacket {
135
    length: u32,
136
    proto_major: u16,
137
    proto_minor: u16,
138
}
139
140
#[derive(Debug, PartialEq, Eq)]
141
pub struct StartupPacket {
142
    pub length: u32,
143
    pub proto_major: u16,
144
    pub proto_minor: u16,
145
    pub params: PgsqlStartupParameters,
146
}
147
148
#[derive(Debug, PartialEq, Eq)]
149
pub struct RegularPacket {
150
    pub identifier: u8,
151
    pub length: u32,
152
    pub payload: Vec<u8>,
153
}
154
155
#[derive(Debug, PartialEq, Eq)]
156
pub struct PgsqlErrorNoticeMessageField {
157
    pub field_type: PgsqlErrorNoticeFieldType,
158
    pub field_value: Vec<u8>,
159
}
160
161
#[derive(Debug, PartialEq, Eq)]
162
pub struct ErrorNoticeMessage {
163
    pub identifier: u8,
164
    pub length: u32,
165
    pub message_body: Vec<PgsqlErrorNoticeMessageField>,
166
}
167
168
#[derive(Debug, PartialEq, Eq)]
169
pub enum SSLResponseMessage {
170
    SSLAccepted,
171
    SSLRejected,
172
    InvalidResponse,
173
}
174
175
impl From<u8> for SSLResponseMessage {
176
0
    fn from(identifier: u8) -> Self {
177
0
        match identifier {
178
0
            b'S' => Self::SSLAccepted,
179
0
            b'N' => Self::SSLRejected,
180
0
            _ => Self::InvalidResponse,
181
        }
182
0
    }
183
}
184
185
impl From<char> for SSLResponseMessage {
186
1.81k
    fn from(identifier: char) -> Self {
187
1.81k
        match identifier {
188
345
            'S' => Self::SSLAccepted,
189
1.46k
            'N' => Self::SSLRejected,
190
0
            _ => Self::InvalidResponse,
191
        }
192
1.81k
    }
193
}
194
195
#[derive(Debug, PartialEq, Eq)]
196
pub struct ParameterStatusMessage {
197
    pub identifier: u8,
198
    pub length: u32,
199
    pub param: PgsqlParameter,
200
}
201
202
#[derive(Debug, PartialEq, Eq)]
203
pub struct BackendKeyDataMessage {
204
    pub identifier: u8,
205
    pub length: u32,
206
    pub backend_pid: u32,
207
    pub secret_key: u32,
208
}
209
210
#[derive(Debug, PartialEq, Eq)]
211
pub struct ConsolidatedDataRowPacket {
212
    pub identifier: u8,
213
    pub row_cnt: u64,
214
    pub data_size: u64,
215
}
216
217
#[derive(Debug, PartialEq, Eq)]
218
pub struct ReadyForQueryMessage {
219
    pub identifier: u8,
220
    pub length: u32,
221
    pub transaction_status: u8,
222
}
223
224
#[derive(Debug, PartialEq, Eq)]
225
pub struct NotificationResponse {
226
    pub identifier: u8,
227
    pub length: u32,
228
    pub pid: u32,
229
    // two str fields, one right after the other
230
    pub channel_name: Vec<u8>,
231
    pub payload: Vec<u8>,
232
}
233
234
#[derive(Debug, PartialEq, Eq)]
235
pub enum PgsqlBEMessage {
236
    SSLResponse(SSLResponseMessage),
237
    ErrorResponse(ErrorNoticeMessage),
238
    NoticeResponse(ErrorNoticeMessage),
239
    AuthenticationOk(AuthenticationMessage),
240
    AuthenticationCleartextPassword(AuthenticationMessage),
241
    AuthenticationMD5Password(AuthenticationMessage),
242
    AuthenticationSSPI(AuthenticationMessage),
243
    AuthenticationSASL(AuthenticationSASLMechanismMessage),
244
    AuthenticationSASLContinue(AuthenticationMessage),
245
    AuthenticationSASLFinal(AuthenticationMessage),
246
    ParameterStatus(ParameterStatusMessage),
247
    BackendKeyData(BackendKeyDataMessage),
248
    CommandComplete(RegularPacket),
249
    ReadyForQuery(ReadyForQueryMessage),
250
    RowDescription(RowDescriptionMessage),
251
    ConsolidatedDataRow(ConsolidatedDataRowPacket),
252
    NotificationResponse(NotificationResponse),
253
    UnknownMessageType(RegularPacket),
254
}
255
256
impl PgsqlBEMessage {
257
0
    pub fn to_str(&self) -> &'static str {
258
0
        match self {
259
0
            PgsqlBEMessage::SSLResponse(SSLResponseMessage::SSLAccepted) => "ssl_accepted",
260
0
            PgsqlBEMessage::SSLResponse(SSLResponseMessage::SSLRejected) => "ssl_rejected",
261
0
            PgsqlBEMessage::ErrorResponse(_) => "error_response",
262
0
            PgsqlBEMessage::NoticeResponse(_) => "notice_response",
263
0
            PgsqlBEMessage::AuthenticationOk(_) => "authentication_ok",
264
            PgsqlBEMessage::AuthenticationCleartextPassword(_) => {
265
0
                "authentication_cleartext_password"
266
            }
267
0
            PgsqlBEMessage::AuthenticationMD5Password(_) => "authentication_md5_password",
268
0
            PgsqlBEMessage::AuthenticationSSPI(_) => "authentication_sspi",
269
0
            PgsqlBEMessage::AuthenticationSASL(_) => "authentication_sasl",
270
0
            PgsqlBEMessage::AuthenticationSASLContinue(_) => "authentication_sasl_continue",
271
0
            PgsqlBEMessage::AuthenticationSASLFinal(_) => "authentication_sasl_final",
272
0
            PgsqlBEMessage::ParameterStatus(_) => "parameter_status",
273
0
            PgsqlBEMessage::BackendKeyData(_) => "backend_key_data",
274
0
            PgsqlBEMessage::CommandComplete(_) => "command_completed",
275
0
            PgsqlBEMessage::ReadyForQuery(_) => "ready_for_query",
276
0
            PgsqlBEMessage::RowDescription(_) => "row_description",
277
            PgsqlBEMessage::SSLResponse(SSLResponseMessage::InvalidResponse) => {
278
0
                "invalid_be_message"
279
            }
280
0
            PgsqlBEMessage::ConsolidatedDataRow(_) => "data_row",
281
0
            PgsqlBEMessage::NotificationResponse(_) => "notification_response",
282
0
            PgsqlBEMessage::UnknownMessageType(_) => "unknown_message_type"
283
        }
284
0
    }
285
286
10.1k
    pub fn get_backendkey_info(&self) -> (u32, u32) {
287
10.1k
        match self {
288
10.1k
            PgsqlBEMessage::BackendKeyData(message) => {
289
10.1k
                return (message.backend_pid, message.secret_key);
290
            }
291
0
            _ => (0, 0),
292
        }
293
10.1k
    }
294
}
295
296
#[derive(Debug, PartialEq, Eq, Clone)]
297
pub enum SASLAuthenticationMechanism {
298
    ScramSha256,
299
    ScramSha256Plus,
300
    // UnknownMechanism,
301
}
302
303
impl SASLAuthenticationMechanism {
304
0
    pub fn to_str(&self) -> &'static str {
305
0
        match self {
306
0
            SASLAuthenticationMechanism::ScramSha256 => "scram_SHA256",
307
0
            SASLAuthenticationMechanism::ScramSha256Plus => "scram_SHA256_plus",
308
        }
309
0
    }
310
}
311
312
#[derive(Debug, PartialEq, Eq)]
313
pub struct TerminationMessage {
314
    pub identifier: u8,
315
    pub length: u32,
316
}
317
318
#[derive(Debug, PartialEq, Eq)]
319
pub struct CancelRequestMessage {
320
    pub pid: u32,
321
    pub backend_key: u32,
322
}
323
324
#[derive(Debug, PartialEq, Eq)]
325
pub enum PgsqlFEMessage {
326
    SSLRequest(DummyStartupPacket),
327
    StartupMessage(StartupPacket),
328
    PasswordMessage(RegularPacket),
329
    SASLInitialResponse(SASLInitialResponsePacket),
330
    SASLResponse(RegularPacket),
331
    SimpleQuery(RegularPacket),
332
    CancelRequest(CancelRequestMessage),
333
    Terminate(TerminationMessage),
334
    UnknownMessageType(RegularPacket),
335
}
336
337
impl PgsqlFEMessage {
338
4
    pub fn to_str(&self) -> &'static str {
339
4
        match self {
340
0
            PgsqlFEMessage::StartupMessage(_) => "startup_message",
341
0
            PgsqlFEMessage::SSLRequest(_) => "ssl_request",
342
0
            PgsqlFEMessage::PasswordMessage(_) => "password_message",
343
0
            PgsqlFEMessage::SASLInitialResponse(_) => "sasl_initial_response",
344
0
            PgsqlFEMessage::SASLResponse(_) => "sasl_response",
345
1
            PgsqlFEMessage::SimpleQuery(_) => "simple_query",
346
0
            PgsqlFEMessage::CancelRequest(_) => "cancel_request",
347
3
            PgsqlFEMessage::Terminate(_) => "termination_message",
348
0
            PgsqlFEMessage::UnknownMessageType(_) => "unknown_message_type",
349
        }
350
4
    }
351
}
352
353
#[derive(Debug, PartialEq, Eq)]
354
pub struct AuthenticationMessage {
355
    pub identifier: u8,
356
    pub length: u32,
357
    pub auth_type: u32,
358
    pub payload: Vec<u8>,
359
}
360
361
#[derive(Debug, PartialEq, Eq)]
362
pub struct SASLInitialResponsePacket {
363
    pub identifier: u8,
364
    pub length: u32,
365
    pub auth_mechanism: SASLAuthenticationMechanism,
366
    pub param_length: u32,
367
    pub sasl_param: Vec<u8>,
368
}
369
370
#[derive(Debug, PartialEq, Eq)]
371
pub struct AuthenticationSASLMechanismMessage {
372
    identifier: u8,
373
    length: u32,
374
    auth_type: u32,
375
    auth_mechanisms: Vec<SASLAuthenticationMechanism>,
376
}
377
378
#[derive(Debug, PartialEq, Eq)]
379
pub struct RowField {
380
    pub field_name: Vec<u8>,
381
    pub table_oid: u32,
382
    pub column_index: u16,
383
    pub data_type_oid: u32,
384
    // "see pg_type.typlen. Note that negative values denote variable-width types"
385
    pub data_type_size: i16,
386
    // "The value will generally be -1 for types that do not need pg_attribute.atttypmod."
387
    pub type_modifier: i32,
388
    // "The format code being used for the field. Currently will be zero (text) or one (binary). In a RowDescription returned from the variant of Describe, will always be zero"
389
    pub format_code: u16,
390
}
391
392
#[derive(Debug, PartialEq, Eq)]
393
pub struct RowDescriptionMessage {
394
    pub identifier: u8,
395
    pub length: u32,
396
    pub field_count: u16,
397
    pub fields: Vec<RowField>,
398
}
399
400
#[derive(Debug, PartialEq, Eq)]
401
pub struct ColumnFieldValue {
402
    // Can be 0, or -1 as a special NULL column value
403
    pub value_length: i32,
404
    pub value: Vec<u8>,
405
}
406
407
#[derive(Debug, PartialEq, Eq)]
408
pub enum PgsqlErrorNoticeFieldType {
409
    SeverityLocalizable,
410
    SeverityNonLocalizable,
411
    CodeSqlStateCode,
412
    Message,
413
    Detail,
414
    Hint,
415
    Position,
416
    InternalPosition,
417
    InternalQuery,
418
    Where,
419
    SchemaName,
420
    TableName,
421
    ColumnName,
422
    DataType,
423
    ConstraintName,
424
    File,
425
    Line,
426
    Routine,
427
    // Indicates end of message
428
    TerminatorToken,
429
    // From the documentation: "Since more field types might be added in future, frontends should silently ignore fields of unrecognized type." For us, then, I think the best option is actually to print it as we parse it, so it is readable?
430
    UnknownFieldType,
431
}
432
433
impl PgsqlErrorNoticeFieldType {
434
0
    pub fn to_str(&self) -> &'static str {
435
0
        match self {
436
0
            PgsqlErrorNoticeFieldType::SeverityLocalizable => "severity_localizable",
437
0
            PgsqlErrorNoticeFieldType::SeverityNonLocalizable => "severity_non_localizable",
438
0
            PgsqlErrorNoticeFieldType::CodeSqlStateCode => "code",
439
0
            PgsqlErrorNoticeFieldType::Message => "message",
440
0
            PgsqlErrorNoticeFieldType::Detail => "detail",
441
0
            PgsqlErrorNoticeFieldType::Hint => "hint",
442
0
            PgsqlErrorNoticeFieldType::Position => "position",
443
0
            PgsqlErrorNoticeFieldType::InternalPosition => "internal_position",
444
0
            PgsqlErrorNoticeFieldType::InternalQuery => "internal_query",
445
0
            PgsqlErrorNoticeFieldType::Where => "where",
446
0
            PgsqlErrorNoticeFieldType::SchemaName => "schema_name",
447
0
            PgsqlErrorNoticeFieldType::TableName => "table_name",
448
0
            PgsqlErrorNoticeFieldType::ColumnName => "column_name",
449
0
            PgsqlErrorNoticeFieldType::DataType => "data_type",
450
0
            PgsqlErrorNoticeFieldType::ConstraintName => "constraint_name",
451
0
            PgsqlErrorNoticeFieldType::File => "file",
452
0
            PgsqlErrorNoticeFieldType::Line => "line",
453
0
            PgsqlErrorNoticeFieldType::Routine => "routine",
454
0
            PgsqlErrorNoticeFieldType::TerminatorToken => "",
455
0
            PgsqlErrorNoticeFieldType::UnknownFieldType => "unknown_field_type",
456
        }
457
0
    }
458
}
459
460
impl From<char> for PgsqlErrorNoticeFieldType {
461
6.25k
    fn from(identifier: char) -> PgsqlErrorNoticeFieldType {
462
6.25k
        match identifier {
463
0
            'S' => PgsqlErrorNoticeFieldType::SeverityLocalizable,
464
6.25k
            'V' => PgsqlErrorNoticeFieldType::SeverityNonLocalizable,
465
0
            'C' => PgsqlErrorNoticeFieldType::CodeSqlStateCode,
466
0
            'M' => PgsqlErrorNoticeFieldType::Message,
467
0
            'D' => PgsqlErrorNoticeFieldType::Detail,
468
0
            'H' => PgsqlErrorNoticeFieldType::Hint,
469
0
            'P' => PgsqlErrorNoticeFieldType::Position,
470
0
            'p' => PgsqlErrorNoticeFieldType::InternalPosition,
471
0
            'q' => PgsqlErrorNoticeFieldType::InternalQuery,
472
0
            'W' => PgsqlErrorNoticeFieldType::Where,
473
0
            's' => PgsqlErrorNoticeFieldType::SchemaName,
474
0
            't' => PgsqlErrorNoticeFieldType::TableName,
475
0
            'c' => PgsqlErrorNoticeFieldType::ColumnName,
476
0
            'd' => PgsqlErrorNoticeFieldType::DataType,
477
0
            'n' => PgsqlErrorNoticeFieldType::ConstraintName,
478
0
            'F' => PgsqlErrorNoticeFieldType::File,
479
0
            'L' => PgsqlErrorNoticeFieldType::Line,
480
0
            'R' => PgsqlErrorNoticeFieldType::Routine,
481
0
            '\u{0}' => PgsqlErrorNoticeFieldType::TerminatorToken,
482
            // Pgsql documentation says "frontends should silently ignore fields of unrecognized type."
483
0
            _ => PgsqlErrorNoticeFieldType::UnknownFieldType,
484
        }
485
6.25k
    }
486
}
487
488
impl From<u8> for PgsqlErrorNoticeFieldType {
489
2.11M
    fn from(identifier: u8) -> PgsqlErrorNoticeFieldType {
490
2.11M
        match identifier {
491
884
            b'S' => PgsqlErrorNoticeFieldType::SeverityLocalizable,
492
0
            b'V' => PgsqlErrorNoticeFieldType::SeverityNonLocalizable,
493
0
            b'C' => PgsqlErrorNoticeFieldType::CodeSqlStateCode,
494
534
            b'M' => PgsqlErrorNoticeFieldType::Message,
495
860
            b'D' => PgsqlErrorNoticeFieldType::Detail,
496
1.38k
            b'H' => PgsqlErrorNoticeFieldType::Hint,
497
1.68k
            b'P' => PgsqlErrorNoticeFieldType::Position,
498
1.10k
            b'p' => PgsqlErrorNoticeFieldType::InternalPosition,
499
1.97k
            b'q' => PgsqlErrorNoticeFieldType::InternalQuery,
500
966
            b'W' => PgsqlErrorNoticeFieldType::Where,
501
3.31k
            b's' => PgsqlErrorNoticeFieldType::SchemaName,
502
685
            b't' => PgsqlErrorNoticeFieldType::TableName,
503
981
            b'c' => PgsqlErrorNoticeFieldType::ColumnName,
504
3.37k
            b'd' => PgsqlErrorNoticeFieldType::DataType,
505
1.41k
            b'n' => PgsqlErrorNoticeFieldType::ConstraintName,
506
1.43k
            b'F' => PgsqlErrorNoticeFieldType::File,
507
1.53k
            b'L' => PgsqlErrorNoticeFieldType::Line,
508
2.12k
            b'R' => PgsqlErrorNoticeFieldType::Routine,
509
0
            b'\0' => PgsqlErrorNoticeFieldType::TerminatorToken,
510
            // Pgsql documentation says "frontends should silently ignore fields of unrecognized type."
511
2.08M
            _ => PgsqlErrorNoticeFieldType::UnknownFieldType,
512
        }
513
2.11M
    }
514
}
515
516
// Currently the set of parameters that could trigger a ParameterStatus message is fixed:
517
// server_version
518
// server_encoding
519
// client_encoding
520
// application_name
521
// default_transaction_read_only
522
// in_hot_standby
523
// is_superuser
524
// session_authorization
525
// DateStyle
526
// IntervalStyle
527
// TimeZone
528
// integer_datetimes
529
// standard_conforming_strings
530
// (source: PostgreSQL documentation)
531
// We may be interested, then, in controling this, somehow, to prevent weird things?
532
2.54M
fn pgsql_parse_generic_parameter(i: &[u8]) -> IResult<&[u8], PgsqlParameter> {
533
2.54M
    let (i, param_name) = take_until1("\x00")(i)?;
534
2.44M
    let (i, _) = tag("\x00")(i)?;
535
2.44M
    let (i, param_value) = take_until("\x00")(i)?;
536
2.43M
    let (i, _) = tag("\x00")(i)?;
537
2.43M
    Ok((i, PgsqlParameter {
538
2.43M
        name: PgsqlParameters::from(param_name),
539
2.43M
        value: param_value.to_vec(),
540
2.43M
    }))
541
2.54M
}
542
543
101k
pub fn pgsql_parse_startup_parameters(i: &[u8]) -> IResult<&[u8], PgsqlStartupParameters> {
544
101k
    let (i, mut optional) = opt(terminated(many1(pgsql_parse_generic_parameter), tag("\x00")))(i)?;
545
61.6k
    if let Some(ref mut params) = optional {
546
61.6k
        let mut user = PgsqlParameter{name: PgsqlParameters::User, value: Vec::new() };
547
61.6k
        let mut index: usize = 0;
548
2.26M
        for (j, p) in params.iter().enumerate() {
549
2.26M
            if p.name == PgsqlParameters::User {
550
80.3k
                user.value.extend_from_slice(&p.value);
551
80.3k
                index = j;
552
2.18M
            }
553
        }
554
61.6k
        params.remove(index);
555
61.6k
        if user.value.is_empty() {
556
1.11k
            return Err(Err::Error(make_error(i, ErrorKind::Tag)));
557
60.5k
        }
558
60.5k
        return Ok((i, PgsqlStartupParameters{
559
60.5k
            user,
560
60.5k
            optional_params: if !params.is_empty() {
561
55.9k
                optional
562
4.61k
            } else { None },
563
        }));
564
11
    }
565
11
    return Err(Err::Error(make_error(i, ErrorKind::Tag)));
566
101k
}
567
568
984
fn parse_sasl_initial_response_payload(i: &[u8]) -> IResult<&[u8], (SASLAuthenticationMechanism, u32, Vec<u8>)> {
569
984
    let (i, sasl_mechanism) = parse_sasl_mechanism(i)?;
570
974
    let (i, param_length) = be_u32(i)?;
571
    // From RFC 5802 - the client-first-message will always start w/
572
    // 'n', 'y' or 'p', otherwise it's invalid, I think we should check that, at some point
573
780
    let (i, param) = terminated(take(param_length), eof)(i)?;
574
359
    Ok((i, (sasl_mechanism, param_length, param.to_vec())))
575
984
}
576
577
17.0k
pub fn parse_sasl_initial_response(i: &[u8]) -> IResult<&[u8], PgsqlFEMessage> {
578
17.0k
    let (i, identifier) = verify(be_u8, |&x| x == b'p')(i)?;
579
17.0k
    let (i, length) = parse_length(i)?;
580
16.4k
    let (i, payload) = map_parser(take(length - PGSQL_LENGTH_FIELD), parse_sasl_initial_response_payload)(i)?;
581
359
    Ok((i, PgsqlFEMessage::SASLInitialResponse(
582
359
                SASLInitialResponsePacket {
583
359
                    identifier,
584
359
                    length,
585
359
                    auth_mechanism: payload.0,
586
359
                    param_length: payload.1,
587
359
                    sasl_param: payload.2,
588
359
                })))
589
17.0k
}
590
591
10.7k
pub fn parse_sasl_response(i: &[u8]) -> IResult<&[u8], PgsqlFEMessage> {
592
10.7k
    let (i, identifier) = verify(be_u8, |&x| x == b'p')(i)?;
593
10.6k
    let (i, length) = parse_length(i)?;
594
9.75k
    let (i, payload) = take(length - PGSQL_LENGTH_FIELD)(i)?;
595
1.74k
    let resp = PgsqlFEMessage::SASLResponse(
596
1.74k
        RegularPacket {
597
1.74k
            identifier,
598
1.74k
            length,
599
1.74k
            payload: payload.to_vec(),
600
1.74k
        });
601
1.74k
    Ok((i, resp))
602
10.7k
}
603
604
515k
pub fn pgsql_parse_startup_packet(i: &[u8]) -> IResult<&[u8], PgsqlFEMessage> {
605
515k
    let (i, len) = verify(be_u32, |&x| x >= 8)(i)?;
606
495k
    let (i, proto_major) = peek(be_u16)(i)?;
607
488k
    let (i, b) = take(len - PGSQL_LENGTH_FIELD)(i)?;
608
275k
    let (_, message) =
609
317k
        match proto_major {
610
317k
            1..=3 => {
611
101k
                let (b, proto_major) = be_u16(b)?;
612
101k
                let (b, proto_minor) = be_u16(b)?;
613
101k
                let (b, params) = pgsql_parse_startup_parameters(b)?;
614
60.5k
                (b, PgsqlFEMessage::StartupMessage(StartupPacket{
615
60.5k
                    length: len,
616
60.5k
                    proto_major,
617
60.5k
                    proto_minor,
618
60.5k
                    params}))
619
            },
620
            PGSQL_DUMMY_PROTO_MAJOR => {
621
215k
                let (b, proto_major) = be_u16(b)?;
622
215k
                let (b, proto_minor) = be_u16(b)?;
623
215k
                let (b, message) = match proto_minor {
624
                    PGSQL_DUMMY_PROTO_CANCEL_REQUEST => {
625
1.26k
                        parse_cancel_request(b)?
626
                    },
627
214k
                    PGSQL_DUMMY_PROTO_MINOR_SSL => (b, PgsqlFEMessage::SSLRequest(DummyStartupPacket{
628
214k
                        length: len,
629
214k
                        proto_major,
630
214k
                        proto_minor
631
214k
                    })),
632
67
                    _ => return Err(Err::Error(make_error(b, ErrorKind::Switch))),
633
                };
634
635
214k
                (b, message)
636
            }
637
87
            _ => return Err(Err::Error(make_error(b, ErrorKind::Switch))),
638
        };
639
275k
    Ok((i, message))
640
515k
}
641
642
// TODO Decide if it's a good idea to offer GSS encryption support right now, as the documentation seems to have conflicting information...
643
// If we do:
644
// To initiate a GSSAPI-encrypted connection, the frontend initially sends a GSSENCRequest message rather than a
645
// StartupMessage. The server then responds with a single byte containing G or N, indicating that it is willing or unwilling to perform GSSAPI encryption, respectively. The frontend might close the connection at this point if it is
646
// dissatisfied with the response. To continue after G, using the GSSAPI C bindings as discussed in RFC2744 or equivalent,
647
// perform a GSSAPI initialization by calling gss_init_sec_context() in a loop and sending the result to the server,
648
// starting with an empty input and then with each result from the server, until it returns no output. When sending the
649
// results of gss_init_sec_context() to the server, prepend the length of the message as a four byte integer in network
650
// byte order. To continue after N, send the usual StartupMessage and proceed without encryption. (Alternatively, it is
651
// permissible to issue an SSLRequest message after an N response to try to use SSL encryption instead of GSSAPI.)
652
// Source: https://www.postgresql.org/docs/13/protocol-flow.html#id-1.10.5.7.11, GSSAPI Session Encryption
653
654
// Password can be encrypted or in cleartext
655
2.84k
pub fn parse_password_message(i: &[u8]) -> IResult<&[u8], PgsqlFEMessage> {
656
2.84k
    let (i, identifier) = verify(be_u8, |&x| x == b'p')(i)?;
657
2.82k
    let (i, length) = parse_length(i)?;
658
1.76k
    let (i, password) = map_parser(
659
1.76k
        take(length - PGSQL_LENGTH_FIELD),
660
1.76k
        take_until1("\x00")
661
1.76k
        )(i)?;
662
322
    Ok((i, PgsqlFEMessage::PasswordMessage(
663
322
                RegularPacket{
664
322
                    identifier,
665
322
                    length,
666
322
                    payload: password.to_vec(),
667
322
                })))
668
2.84k
}
669
670
320k
fn parse_simple_query(i: &[u8]) -> IResult<&[u8], PgsqlFEMessage> {
671
320k
    let (i, identifier) = verify(be_u8, |&x| x == b'Q')(i)?;
672
320k
    let (i, length) = parse_length(i)?;
673
317k
    let (i, query) = map_parser(take(length - PGSQL_LENGTH_FIELD), take_until1("\x00"))(i)?;
674
278k
    Ok((i, PgsqlFEMessage::SimpleQuery(RegularPacket {
675
278k
        identifier,
676
278k
        length,
677
278k
        payload: query.to_vec(),
678
278k
    })))
679
320k
}
680
681
1.26k
fn parse_cancel_request(i: &[u8]) -> IResult<&[u8], PgsqlFEMessage> {
682
1.26k
    let (i, pid) = be_u32(i)?;
683
854
    let (i, backend_key) = be_u32(i)?;
684
625
    Ok((i, PgsqlFEMessage::CancelRequest(CancelRequestMessage {
685
625
        pid,
686
625
        backend_key,
687
625
    })))
688
1.26k
}
689
690
5.20M
fn parse_terminate_message(i: &[u8]) -> IResult<&[u8], PgsqlFEMessage> {
691
5.20M
    let (i, identifier) = verify(be_u8, |&x| x == b'X')(i)?;
692
5.20M
    let (i, length) = parse_length(i)?;
693
5.20M
    Ok((i, PgsqlFEMessage::Terminate(TerminationMessage { identifier, length })))
694
5.20M
}
695
696
// Messages that begin with 'p' but are not password ones are not parsed here
697
6.39M
pub fn parse_request(i: &[u8]) -> IResult<&[u8], PgsqlFEMessage> {
698
6.39M
    let (i, tag) = peek(be_u8)(i)?;
699
6.39M
    let (i, message) = match tag {
700
515k
        b'\0' => pgsql_parse_startup_packet(i)?,
701
320k
        b'Q' => parse_simple_query(i)?,
702
5.20M
        b'X' => parse_terminate_message(i)?,
703
        _ => {
704
347k
            let (i, identifier) = be_u8(i)?;
705
347k
            let (i, length) = verify(be_u32, |&x| x > PGSQL_LENGTH_FIELD)(i)?;
706
327k
            let (i, payload) = take(length - PGSQL_LENGTH_FIELD)(i)?;
707
191k
            let unknown = PgsqlFEMessage::UnknownMessageType (RegularPacket{
708
191k
                identifier,
709
191k
                length,
710
191k
                payload: payload.to_vec(),
711
191k
            });
712
191k
            (i, unknown)
713
        }
714
    };
715
5.95M
    Ok((i, message))
716
6.39M
}
717
718
96.2k
fn pgsql_parse_authentication_message<'a>(i: &'a [u8]) -> IResult<&'a [u8], PgsqlBEMessage> {
719
96.2k
    let (i, identifier) = verify(be_u8, |&x| x == b'R')(i)?;
720
96.2k
    let (i, length) = verify(be_u32, |&x| x >= 8)(i)?;
721
96.2k
    let (i, auth_type) = be_u32(i)?;
722
94.9k
    let (i, message) = map_parser(
723
94.9k
        take(length - 8),
724
88.7k
        |b: &'a [u8]| {
725
88.7k
            match auth_type {
726
5.83k
                0 => Ok((b, PgsqlBEMessage::AuthenticationOk(
727
5.83k
                            AuthenticationMessage {
728
5.83k
                                identifier,
729
5.83k
                                length,
730
5.83k
                                auth_type,
731
5.83k
                                payload: b.to_vec(),
732
5.83k
                            }))),
733
2.65k
                3 => Ok((b, PgsqlBEMessage::AuthenticationCleartextPassword(
734
2.65k
                            AuthenticationMessage {
735
2.65k
                                identifier,
736
2.65k
                                length,
737
2.65k
                                auth_type,
738
2.65k
                                payload: b.to_vec(),
739
2.65k
                            }))),
740
                5 => {
741
797
                    let (b, salt) = all_consuming(take(4_usize))(b)?;
742
413
                    Ok((b, PgsqlBEMessage::AuthenticationMD5Password(
743
413
                                AuthenticationMessage {
744
413
                                    identifier,
745
413
                                    length,
746
413
                                    auth_type,
747
413
                                    payload: salt.to_vec(),
748
413
                                })))
749
                }
750
71.9k
                9 => Ok((b, PgsqlBEMessage::AuthenticationSSPI(
751
71.9k
                            AuthenticationMessage {
752
71.9k
                                identifier,
753
71.9k
                                length,
754
71.9k
                                auth_type,
755
71.9k
                                payload: b.to_vec(),
756
71.9k
                            }))),
757
                // TODO - For SASL, should we parse specific details of the challenge itself? (as seen in: https://github.com/launchbadge/sqlx/blob/master/sqlx-core/src/postgres/message/authentication.rs )
758
                10 => {
759
1.76k
                    let (b, auth_mechanisms) = parse_sasl_mechanisms(b)?;
760
1.22k
                    Ok((b, PgsqlBEMessage::AuthenticationSASL(
761
1.22k
                                AuthenticationSASLMechanismMessage {
762
1.22k
                                    identifier,
763
1.22k
                                    length,
764
1.22k
                                    auth_type,
765
1.22k
                                    auth_mechanisms,
766
1.22k
                                })))
767
                }
768
                11 => {
769
4.91k
                    Ok((b, PgsqlBEMessage::AuthenticationSASLContinue(
770
4.91k
                                AuthenticationMessage {
771
4.91k
                                    identifier,
772
4.91k
                                    length,
773
4.91k
                                    auth_type,
774
4.91k
                                    payload: b.to_vec(),
775
4.91k
                                })))
776
                },
777
                12 => {
778
902
                    Ok((b, PgsqlBEMessage::AuthenticationSASLFinal(
779
902
                                AuthenticationMessage {
780
902
                                    identifier,
781
902
                                    length,
782
902
                                    auth_type,
783
902
                                    payload: b.to_vec(),
784
902
                                }
785
902
                                )))
786
                }
787
                // TODO add other authentication messages
788
25
                _ => return Err(Err::Error(make_error(i, ErrorKind::Switch))),
789
            }
790
88.7k
        }
791
94.9k
    )(i)?;
792
87.8k
    Ok((i, message))
793
96.2k
}
794
795
16.6k
fn parse_parameter_status_message(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
796
16.6k
    let (i, identifier) = verify(be_u8, |&x| x == b'S')(i)?;
797
16.6k
    let (i, length) = parse_length(i)?;
798
16.6k
    let (i, param) = map_parser(take(length - PGSQL_LENGTH_FIELD), pgsql_parse_generic_parameter)(i)?;
799
9.64k
    Ok((i, PgsqlBEMessage::ParameterStatus(ParameterStatusMessage {
800
9.64k
        identifier,
801
9.64k
        length,
802
9.64k
        param,
803
9.64k
    })))
804
16.6k
}
805
806
282k
pub fn parse_ssl_response(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
807
282k
    let (i, tag) = alt((char('N'), char('S')))(i)?;
808
1.81k
    Ok((i, PgsqlBEMessage::SSLResponse(
809
1.81k
                SSLResponseMessage::from(tag))
810
1.81k
       ))
811
282k
}
812
813
61.0k
fn parse_backend_key_data_message(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
814
61.0k
    let (i, identifier) = verify(be_u8, |&x| x == b'K')(i)?;
815
61.0k
    let (i, length) = verify(be_u32, |&x| x == 12)(i)?;
816
60.9k
    let (i, pid) = be_u32(i)?;
817
59.9k
    let (i, secret_key) = be_u32(i)?;
818
58.8k
    Ok((i, PgsqlBEMessage::BackendKeyData(BackendKeyDataMessage {
819
58.8k
        identifier,
820
58.8k
        length,
821
58.8k
        backend_pid: pid,
822
58.8k
        secret_key,
823
58.8k
    })))
824
61.0k
}
825
826
834k
fn parse_command_complete(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
827
834k
    let (i, identifier) = verify(be_u8, |&x| x == b'C')(i)?;
828
834k
    let (i, length) = parse_length(i)?;
829
834k
    let (i, payload) = map_parser(take(length - PGSQL_LENGTH_FIELD), take_until("\x00"))(i)?;
830
819k
    Ok((i, PgsqlBEMessage::CommandComplete(RegularPacket {
831
819k
        identifier,
832
819k
        length,
833
819k
        payload: payload.to_vec(),
834
819k
    })))
835
834k
}
836
837
24.0k
fn parse_ready_for_query(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
838
24.0k
    let (i, identifier) = verify(be_u8, |&x| x == b'Z')(i)?;
839
24.0k
    let (i, length) = verify(be_u32, |&x| x == 5)(i)?;
840
24.0k
    let (i, status) = verify(be_u8, |&x| x == b'I' || x == b'T' || x == b'E')(i)?;
841
23.7k
    Ok((i, PgsqlBEMessage::ReadyForQuery(ReadyForQueryMessage {
842
23.7k
        identifier,
843
23.7k
        length,
844
23.7k
        transaction_status: status,
845
23.7k
    })))
846
24.0k
}
847
848
292k
fn parse_row_field(i: &[u8]) -> IResult<&[u8], RowField> {
849
292k
    let (i, field_name) = take_until1("\x00")(i)?;
850
280k
    let (i, _) = tag("\x00")(i)?;
851
280k
    let (i, table_oid) = be_u32(i)?;
852
280k
    let (i, column_index) = be_u16(i)?;
853
279k
    let (i, data_type_oid) = be_u32(i)?;
854
278k
    let (i, data_type_size) = be_i16(i)?;
855
276k
    let (i, type_modifier) = be_i32(i)?;
856
276k
    let (i, format_code) = be_u16(i)?;
857
275k
    Ok((i, RowField {
858
275k
        field_name: field_name.to_vec(),
859
275k
        table_oid,
860
275k
        column_index,
861
275k
        data_type_oid,
862
275k
        data_type_size,
863
275k
        type_modifier,
864
275k
        format_code,
865
275k
    }))
866
292k
}
867
868
72.1k
pub fn parse_row_description(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
869
72.1k
    let (i, identifier) = verify(be_u8, |&x| x == b'T')(i)?;
870
72.1k
    let (i, length) = verify(be_u32, |&x| x > 6)(i)?;
871
72.1k
    let (i, field_count) = be_u16(i)?;
872
71.1k
    let (i, fields) = map_parser(
873
71.1k
        take(length - 6),
874
71.1k
        many_m_n(0, field_count.into(), parse_row_field)
875
71.1k
    )(i)?;
876
12.4k
    Ok((i, PgsqlBEMessage::RowDescription(
877
12.4k
                RowDescriptionMessage {
878
12.4k
                    identifier,
879
12.4k
                    length,
880
12.4k
                    field_count,
881
12.4k
                    fields,
882
12.4k
                })))
883
72.1k
}
884
885
606k
fn parse_data_row_value(i: &[u8]) -> IResult<&[u8], ColumnFieldValue> {
886
606k
    let (i, value_length) = be_i32(i)?;
887
601k
    let (i, value) = cond(value_length >= 0, take(value_length as usize))(i)?;
888
598k
    Ok((i, ColumnFieldValue {
889
598k
        value_length,
890
        value: {
891
598k
            match value {
892
18.6k
                Some(data) => data.to_vec(),
893
579k
                None => [].to_vec(),
894
            }
895
        },
896
    }))
897
606k
}
898
899
/// For each column, add up the data size. Return the total
900
144k
fn add_up_data_size(columns: Vec<ColumnFieldValue>) -> u64 {
901
144k
    let mut data_size: u64 = 0;
902
600k
    for field in columns {
903
        // -1 value means data value is NULL, let's not add that up
904
455k
        if field.value_length > 0 {
905
1.18k
            data_size += field.value_length as u64;
906
454k
        }
907
    }
908
144k
    data_size
909
144k
}
910
911
// Currently, we don't store the actual DataRow messages, as those could easily become a burden, memory-wise
912
// We use ConsolidatedDataRow to store info we still want to log: message size.
913
// Later on, we calculate the number of lines the command actually returned by counting ConsolidatedDataRow messages
914
182k
pub fn parse_consolidated_data_row(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
915
182k
    let (i, identifier) = verify(be_u8, |&x| x == b'D')(i)?;
916
182k
    let (i, length) = verify(be_u32, |&x| x >= 6)(i)?;
917
182k
    let (i, field_count) = be_u16(i)?;
918
    // 6 here is for skipping length + field_count
919
181k
    let (i, rows) = map_parser(take(length - 6), many_m_n(0, field_count.into(), parse_data_row_value))(i)?;
920
144k
    Ok((i, PgsqlBEMessage::ConsolidatedDataRow(
921
144k
                ConsolidatedDataRowPacket {
922
144k
                    identifier,
923
144k
                    row_cnt: 1,
924
144k
                    data_size: add_up_data_size(rows),
925
144k
                }
926
144k
                )))
927
182k
}
928
929
6.33k
fn parse_sasl_mechanism(i: &[u8]) -> IResult<&[u8], SASLAuthenticationMechanism> {
930
6.33k
    let res: IResult<_, _, ()> = terminated(tag("SCRAM-SHA-256-PLUS"), tag("\x00"))(i);
931
6.33k
    if let Ok((i, _)) = res {
932
2
        return Ok((i, SASLAuthenticationMechanism::ScramSha256Plus));
933
6.33k
    }
934
6.33k
    let res: IResult<_, _, ()> = terminated(tag("SCRAM-SHA-256"), tag("\x00"))(i);
935
6.33k
    if let Ok((i, _)) = res {
936
4.55k
        return Ok((i, SASLAuthenticationMechanism::ScramSha256));
937
1.77k
    }
938
1.77k
    return Err(Err::Error(make_error(i, ErrorKind::Alt)));
939
6.33k
}
940
941
1.76k
fn parse_sasl_mechanisms(i: &[u8]) -> IResult<&[u8], Vec<SASLAuthenticationMechanism>> {
942
1.76k
    terminated(many1(parse_sasl_mechanism), tag("\x00"))(i)
943
1.76k
}
944
945
13.4k
pub fn parse_error_response_code(i: &[u8]) -> IResult<&[u8], PgsqlErrorNoticeMessageField> {
946
13.4k
    let (i, _field_type) = char('C')(i)?;
947
13.4k
    let (i, field_value) = map_parser(take(6_usize), alphanumeric1)(i)?;
948
10.1k
    Ok((i, PgsqlErrorNoticeMessageField{
949
10.1k
        field_type: PgsqlErrorNoticeFieldType::CodeSqlStateCode,
950
10.1k
        field_value: field_value.to_vec(),
951
10.1k
    }))
952
13.4k
}
953
954
// Parse an error response with non-localizeable severity message.
955
// Possible values: ERROR, FATAL, or PANIC
956
6.95k
pub fn parse_error_response_severity(i: &[u8]) -> IResult<&[u8], PgsqlErrorNoticeMessageField> {
957
6.95k
    let (i, field_type) = char('V')(i)?;
958
6.95k
    let (i, field_value) = alt((tag("ERROR"), tag("FATAL"), tag("PANIC")))(i)?;
959
4.97k
    let (i, _) = tag("\x00")(i)?;
960
4.27k
    Ok((i, PgsqlErrorNoticeMessageField{
961
4.27k
        field_type: PgsqlErrorNoticeFieldType::from(field_type),
962
4.27k
        field_value: field_value.to_vec(),
963
4.27k
    }))
964
6.95k
}
965
966
// The non-localizable version of Severity field has different values,
967
// in case of a notice: 'WARNING', 'NOTICE', 'DEBUG', 'INFO' or 'LOG'
968
5.85k
pub fn parse_notice_response_severity(i: &[u8]) -> IResult<&[u8], PgsqlErrorNoticeMessageField> {
969
5.85k
    let (i, field_type) = char('V')(i)?;
970
5.85k
    let (i, field_value) = alt((
971
5.85k
            tag("WARNING"),
972
5.85k
            tag("NOTICE"),
973
5.85k
            tag("DEBUG"),
974
5.85k
            tag("INFO"),
975
5.85k
            tag("LOG")))(i)?;
976
3.64k
    let (i, _) = tag("\x00")(i)?;
977
1.98k
    Ok((i, PgsqlErrorNoticeMessageField{
978
1.98k
        field_type: PgsqlErrorNoticeFieldType::from(field_type),
979
1.98k
        field_value: field_value.to_vec(),
980
1.98k
    }))
981
5.85k
}
982
983
2.14M
pub fn parse_error_response_field(
984
2.14M
    i: &[u8], is_err_msg: bool,
985
2.14M
) -> IResult<&[u8], PgsqlErrorNoticeMessageField> {
986
2.14M
    let (i, field_type) = peek(be_u8)(i)?;
987
2.14M
    let (i, data) = match field_type {
988
        b'V' => {
989
12.8k
            if is_err_msg {
990
6.95k
                parse_error_response_severity(i)?
991
            } else {
992
5.85k
                parse_notice_response_severity(i)?
993
            }
994
        }
995
13.4k
        b'C' => parse_error_response_code(i)?,
996
        _ => {
997
2.11M
            let (i, field_type) = be_u8(i)?;
998
2.11M
            let (i, field_value) = take_until("\x00")(i)?;
999
2.11M
            let (i, _just_tag) = tag("\x00")(i)?;
1000
2.11M
            let message = PgsqlErrorNoticeMessageField {
1001
2.11M
                field_type: PgsqlErrorNoticeFieldType::from(field_type),
1002
2.11M
                field_value: field_value.to_vec(),
1003
2.11M
            };
1004
2.11M
            return Ok((i, message));
1005
        }
1006
    };
1007
16.3k
    Ok((i, data))
1008
2.14M
}
1009
1010
39.2k
pub fn parse_error_notice_fields(i: &[u8], is_err_msg: bool) -> IResult<&[u8], Vec<PgsqlErrorNoticeMessageField>> {
1011
2.14M
    let (i, data) = many_till(|b| parse_error_response_field(b, is_err_msg), tag("\x00"))(i)?;
1012
18.5k
    Ok((i, data.0))
1013
39.2k
}
1014
1015
115k
fn pgsql_parse_error_response(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
1016
115k
    let (i, identifier) = verify(be_u8, |&x| x == b'E')(i)?;
1017
115k
    let (i, length) = verify(be_u32, |&x| x > 10)(i)?;
1018
115k
    let (i, message_body) = map_parser(
1019
115k
        take(length - PGSQL_LENGTH_FIELD),
1020
27.4k
        |b| parse_error_notice_fields(b, true)
1021
115k
        )(i)?;
1022
1023
12.6k
    Ok((i, PgsqlBEMessage::ErrorResponse(ErrorNoticeMessage {
1024
12.6k
        identifier,
1025
12.6k
        length,
1026
12.6k
        message_body,
1027
12.6k
    })))
1028
115k
}
1029
1030
17.9k
fn pgsql_parse_notice_response(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
1031
17.9k
    let (i, identifier) = verify(be_u8, |&x| x == b'N')(i)?;
1032
17.9k
    let (i, length) = verify(be_u32, |&x| x > 10)(i)?;
1033
17.9k
    let (i, message_body) = map_parser(
1034
17.9k
        take(length - PGSQL_LENGTH_FIELD),
1035
11.7k
        |b| parse_error_notice_fields(b, false)
1036
17.9k
        )(i)?;
1037
5.90k
    Ok((i, PgsqlBEMessage::NoticeResponse(ErrorNoticeMessage {
1038
5.90k
        identifier,
1039
5.90k
        length,
1040
5.90k
        message_body,
1041
5.90k
    })))
1042
17.9k
}
1043
1044
51.1k
fn parse_notification_response(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
1045
51.1k
    let (i, identifier) = verify(be_u8, |&x| x == b'A')(i)?;
1046
    // length (u32) + pid (u32) + at least one byte, for we have two str fields
1047
51.1k
    let (i, length) = verify(be_u32, |&x| x > 9)(i)?;
1048
51.1k
    let (i, data) = map_parser(
1049
51.1k
        take(length - PGSQL_LENGTH_FIELD),
1050
7.29k
        |b| {
1051
7.29k
            let (b, pid) = be_u32(b)?;
1052
7.29k
            let (b, channel_name) = take_until_and_consume(b"\x00")(b)?;
1053
6.23k
            let (b, payload) = take_until_and_consume(b"\x00")(b)?;
1054
5.81k
            Ok((b, (pid, channel_name, payload)))
1055
51.1k
        })(i)?;
1056
5.81k
    let msg = PgsqlBEMessage::NotificationResponse(NotificationResponse{
1057
5.81k
        identifier,
1058
5.81k
        length,
1059
5.81k
        pid: data.0,
1060
5.81k
        channel_name: data.1.to_vec(),
1061
5.81k
        payload: data.2.to_vec(),
1062
5.81k
    });
1063
5.81k
    Ok((i, msg))
1064
51.1k
}
1065
1066
1.67M
pub fn pgsql_parse_response(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
1067
1.67M
    let (i, pseudo_header) = peek(tuple((be_u8, be_u32)))(i)?;
1068
1.18M
    let (i, message) =
1069
1.62M
            match pseudo_header.0 {
1070
115k
                b'E' => pgsql_parse_error_response(i)?,
1071
61.0k
                b'K' => parse_backend_key_data_message(i)?,
1072
17.9k
                b'N' => pgsql_parse_notice_response(i)?,
1073
96.2k
                b'R' => pgsql_parse_authentication_message(i)?,
1074
16.6k
                b'S' => parse_parameter_status_message(i)?,
1075
834k
                b'C' => parse_command_complete(i)?,
1076
24.0k
                b'Z' => parse_ready_for_query(i)?,
1077
72.1k
                b'T' => parse_row_description(i)?,
1078
51.1k
                b'A' => parse_notification_response(i)?,
1079
182k
                b'D' => parse_consolidated_data_row(i)?,
1080
                _ => {
1081
156k
                    let (i, identifier) = be_u8(i)?;
1082
156k
                    let (i, length) = verify(be_u32, |&x| x > PGSQL_LENGTH_FIELD)(i)?;
1083
156k
                    let (i, payload) = take(length - PGSQL_LENGTH_FIELD)(i)?;
1084
5.38k
                    let unknown = PgsqlBEMessage::UnknownMessageType (RegularPacket{
1085
5.38k
                        identifier,
1086
5.38k
                        length,
1087
5.38k
                        payload: payload.to_vec(),
1088
5.38k
                    });
1089
5.38k
                    (i, unknown)
1090
                }
1091
1092
            };
1093
1.18M
    Ok((i, message))
1094
1.67M
}
1095
1096
#[cfg(test)]
1097
#[allow(clippy::vec_init_then_push)]
1098
mod tests {
1099
1100
    use super::*;
1101
    use nom7::Needed;
1102
1103
    impl ErrorNoticeMessage {
1104
        pub fn new(identifier: u8, length: u32) -> Self {
1105
            ErrorNoticeMessage {
1106
                identifier,
1107
                length,
1108
                message_body: Vec::new(),
1109
            }
1110
        }
1111
    }
1112
1113
    #[test]
1114
    fn test_parse_request() {
1115
        // An SSLRequest
1116
        let buf: &[u8] = &[0x00, 0x00, 0x00, 0x08, 0x04, 0xd2, 0x16, 0x2f];
1117
        let ssl_request = DummyStartupPacket {
1118
            length: 8,
1119
            proto_major: PGSQL_DUMMY_PROTO_MAJOR,
1120
            proto_minor: PGSQL_DUMMY_PROTO_MINOR_SSL,
1121
        };
1122
        let request_ok = PgsqlFEMessage::SSLRequest(ssl_request);
1123
1124
        let (_remainder, result) = parse_request(buf).unwrap();
1125
        assert_eq!(result, request_ok);
1126
1127
        // incomplete message
1128
        let result = parse_request(&buf[0..7]);
1129
        assert!(result.is_err());
1130
1131
        // Same request, but length is wrong
1132
        let buf: &[u8] = &[0x00, 0x00, 0x00, 0x07, 0x04, 0xd2, 0x16, 0x2f];
1133
        let result = parse_request(buf);
1134
        assert!(result.is_err());
1135
1136
        let buf: &[u8] = &[
1137
            /* Length 85 */ 0x00, 0x00, 0x00, 0x55, /* Proto version */ 0x00, 0x03, 0x00,
1138
            0x00, /* user */ 0x75, 0x73, 0x65, 0x72, 0x00, /* [value] rep */ 0x72, 0x65,
1139
            0x70, 0x00, /* database */ 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x00,
1140
            /* [optional] */ 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63,
1141
            /* replication replication true application_name walreceiver */
1142
            0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74,
1143
            0x69, 0x6f, 0x6e, 0x00, 0x74, 0x72, 0x75, 0x65, 0x00, 0x61, 0x70, 0x70, 0x6c, 0x69,
1144
            0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x77, 0x61,
1145
            0x6c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x00, 0x00,
1146
        ];
1147
        let result = parse_request(buf);
1148
        match result {
1149
            Ok((remainder, _message)) => {
1150
                // there should be nothing left
1151
                assert_eq!(remainder.len(), 0);
1152
            }
1153
            Err(Err::Error(err)) => {
1154
                panic!("Result should not be an error: {:?}.", err.code);
1155
            }
1156
            Err(Err::Incomplete(_)) => {
1157
                panic!("Result should not have been incomplete.");
1158
            }
1159
            _ => {
1160
                panic!("Unexpected behavior!");
1161
            }
1162
        }
1163
1164
        // A valid startup message/request without optional parameters
1165
        // ...&....user.oryx.database.mailstore..
1166
        let buf: &[u8] = &[
1167
            0x00, 0x00, 0x00, 0x26, 0x00, 0x03, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x00, 0x6f,
1168
            0x72, 0x79, 0x78, 0x00, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x00, 0x6d,
1169
            0x61, 0x69, 0x6c, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x00, 0x00,
1170
        ];
1171
        let user = PgsqlParameter {
1172
            name: PgsqlParameters::User,
1173
            value: br#"oryx"#.to_vec(),
1174
        };
1175
        let database = PgsqlParameter {
1176
            name: PgsqlParameters::Database,
1177
            value: br#"mailstore"#.to_vec(),
1178
        };
1179
        let mut database_param: Vec<PgsqlParameter> = Vec::new();
1180
        database_param.push(database);
1181
        let params = PgsqlStartupParameters {
1182
            user,
1183
            optional_params: Some(database_param),
1184
        };
1185
        let expected_result = PgsqlFEMessage::StartupMessage(StartupPacket {
1186
            length: 38,
1187
            proto_major: 3,
1188
            proto_minor: 0,
1189
            params,
1190
        });
1191
        let result = parse_request(buf);
1192
        match result {
1193
            Ok((remainder, message)) => {
1194
                assert_eq!(message, expected_result);
1195
                assert_eq!(remainder.len(), 0);
1196
            }
1197
            Err(Err::Error(err)) => {
1198
                panic!("Shouldn't be error: {:?}", err.code);
1199
            }
1200
            Err(Err::Incomplete(needed)) => {
1201
                panic!("Should not be Incomplete! Needed: {:?}", needed);
1202
            }
1203
            _ => {
1204
                panic!("Unexpected behavior");
1205
            }
1206
        }
1207
1208
        // A valid startup message/request without any optional parameters
1209
        // ........user.oryx..
1210
        let buf: &[u8] = &[
1211
            0x00, 0x00, 0x00, 0x13, 0x00, 0x03, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x00, 0x6f,
1212
            0x72, 0x79, 0x78, 0x00, 0x00,
1213
        ];
1214
        let user = PgsqlParameter {
1215
            name: PgsqlParameters::User,
1216
            value: br#"oryx"#.to_vec(),
1217
        };
1218
        let params = PgsqlStartupParameters {
1219
            user,
1220
            optional_params: None,
1221
        };
1222
        let expected_result = PgsqlFEMessage::StartupMessage(StartupPacket {
1223
            length: 19,
1224
            proto_major: 3,
1225
            proto_minor: 0,
1226
            params,
1227
        });
1228
        let result = parse_request(buf);
1229
        match result {
1230
            Ok((remainder, message)) => {
1231
                assert_eq!(message, expected_result);
1232
                assert_eq!(remainder.len(), 0);
1233
            }
1234
            Err(Err::Error(err)) => {
1235
                panic!("Shouldn't be error: {:?}", err.code);
1236
            }
1237
            Err(Err::Incomplete(needed)) => {
1238
                panic!("Should not be Incomplete! Needed: {:?}", needed);
1239
            }
1240
            _ => {
1241
                panic!("Unexpected behavior");
1242
            }
1243
        }
1244
1245
        // A startup message/request with length off by one
1246
        let buf: &[u8] = &[
1247
            0x00, 0x00, 0x00, 0x12, 0x00, 0x03, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x00, 0x6f,
1248
            0x72, 0x79, 0x78, 0x00, 0x00,
1249
        ];
1250
        let result = parse_request(buf);
1251
        assert!(result.is_err());
1252
1253
        // A startup message/request with bad length
1254
        let buf: &[u8] = &[
1255
            0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x00, 0x6f,
1256
            0x72, 0x79, 0x78, 0x00, 0x00,
1257
        ];
1258
        let result = parse_request(buf);
1259
        assert!(result.is_err());
1260
1261
        // A startup message/request with corrupted user param
1262
        let buf: &[u8] = &[
1263
            0x00, 0x00, 0x00, 0x013, 0x00, 0x03, 0x00, 0x00, 0x75, 0x73, 0x65, 0x00, 0x6f, 0x72,
1264
            0x79, 0x78, 0x00, 0x00,
1265
        ];
1266
        let result = parse_request(buf);
1267
        assert!(result.is_err());
1268
1269
        // A startup message/request missing the terminator
1270
        let buf: &[u8] = &[
1271
            0x00, 0x00, 0x00, 0x013, 0x00, 0x03, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x00, 0x6f,
1272
            0x72, 0x79, 0x78, 0x00,
1273
        ];
1274
        let result = parse_request(buf);
1275
        assert!(result.is_err());
1276
1277
        // A termination message
1278
        let buf: &[u8] = &[0x58, 0x00, 0x00, 0x00, 0x04];
1279
        let result = parse_request(buf);
1280
        assert!(result.is_ok());
1281
1282
        let result = parse_request(&buf[0..3]);
1283
        assert!(result.is_err());
1284
1285
    }
1286
1287
    #[test]
1288
    fn test_cancel_request_message() {
1289
        // A cancel request message
1290
        let buf: &[u8] = &[
1291
            0x00, 0x00, 0x00, 0x10, // length: 16 (fixed)
1292
            0x04, 0xd2, 0x16, 0x2e, // 1234.5678 - identifies a cancel request
1293
            0x00, 0x00, 0x76, 0x31, // PID: 30257
1294
            0x23, 0x84, 0xf7, 0x2d]; // Backend key: 595916589
1295
        let result = parse_cancel_request(buf);
1296
        assert!(result.is_ok());
1297
1298
        let result = parse_cancel_request(&buf[0..3]);
1299
        assert!(result.is_err());
1300
1301
        let result = pgsql_parse_startup_packet(buf);
1302
        assert!(result.is_ok());
1303
1304
        let fail_result = pgsql_parse_startup_packet(&buf[0..3]);
1305
        assert!(fail_result.is_err());
1306
1307
        let result = parse_request(buf);
1308
        assert!(result.is_ok());
1309
1310
        let fail_result = parse_request(&buf[0..3]);
1311
        assert!(fail_result.is_err());
1312
    }
1313
1314
1315
1316
    #[test]
1317
    fn test_parse_error_response_code() {
1318
        let buf: &[u8] = &[0x43, 0x32, 0x38, 0x30, 0x30, 0x30, 0x00];
1319
        let value_str = "28000".as_bytes();
1320
        let ok_res = PgsqlErrorNoticeMessageField {
1321
            field_type: PgsqlErrorNoticeFieldType::CodeSqlStateCode,
1322
            field_value: value_str.to_vec(),
1323
        };
1324
        let result = parse_error_response_code(buf);
1325
        assert!(result.is_ok());
1326
1327
        let (remainder, result) = parse_error_response_code(buf).unwrap();
1328
        assert_eq!(result, ok_res);
1329
        assert_eq!(remainder.len(), 0);
1330
1331
        let result = parse_error_response_code(&buf[0..5]);
1332
        assert!(result.is_err());
1333
    }
1334
1335
    #[test]
1336
    fn test_parse_password_messages() {
1337
        // A password message (MD5)
1338
        let buf: &[u8] = &[
1339
            0x70, 0x00, 0x00, 0x00, 0x28, 0x6d, 0x64, 0x35, 0x63, 0x65, 0x66, 0x66, 0x63, 0x30,
1340
            0x31, 0x64, 0x63, 0x64, 0x65, 0x37, 0x35, 0x34, 0x31, 0x38, 0x32, 0x39, 0x64, 0x65,
1341
            0x65, 0x66, 0x36, 0x62, 0x35, 0x65, 0x39, 0x63, 0x39, 0x31, 0x34, 0x32, 0x00,
1342
        ];
1343
        let ok_result = PgsqlFEMessage::PasswordMessage(RegularPacket {
1344
            identifier: b'p',
1345
            length: 40,
1346
            payload: br#"md5ceffc01dcde7541829deef6b5e9c9142"#.to_vec(),
1347
        });
1348
        let (_remainder, result) = parse_password_message(buf).unwrap();
1349
        assert_eq!(result, ok_result);
1350
1351
        // Length is off by one here
1352
        let buf: &[u8] = &[
1353
            0x70, 0x00, 0x00, 0x00, 0x27, 0x6d, 0x64, 0x35, 0x63, 0x65, 0x66, 0x66, 0x63, 0x30,
1354
            0x31, 0x64, 0x63, 0x64, 0x65, 0x37, 0x35, 0x34, 0x31, 0x38, 0x32, 0x39, 0x64, 0x65,
1355
            0x65, 0x66, 0x36, 0x62, 0x35, 0x65, 0x39, 0x63, 0x39, 0x31, 0x34, 0x32, 0x00,
1356
        ];
1357
        let result = parse_password_message(buf);
1358
        assert!(result.is_err());
1359
1360
        // Length also off by one, but now bigger than it should
1361
        let buf: &[u8] = &[
1362
            0x70, 0x00, 0x00, 0x00, 0x29, 0x6d, 0x64, 0x35, 0x63, 0x65, 0x66, 0x66, 0x63, 0x30,
1363
            0x31, 0x64, 0x63, 0x64, 0x65, 0x37, 0x35, 0x34, 0x31, 0x38, 0x32, 0x39, 0x64, 0x65,
1364
            0x65, 0x66, 0x36, 0x62, 0x35, 0x65, 0x39, 0x63, 0x39, 0x31, 0x34, 0x32, 0x00,
1365
        ];
1366
        let result = parse_password_message(buf);
1367
        assert!(result.is_err());
1368
1369
        // Incomplete payload
1370
        let buf: &[u8] = &[
1371
            0x70, 0x00, 0x00, 0x00, 0x28, 0x6d, 0x64, 0x35, 0x63, 0x65, 0x66, 0x66, 0x63, 0x30,
1372
            0x31, 0x64, 0x63, 0x64, 0x65, 0x37, 0x35, 0x34, 0x31, 0x38, 0x32, 0x39, 0x64, 0x65,
1373
            0x65, 0x66, 0x36, 0x62, 0x35, 0x65, 0x39, 0x63, 0x39, 0x31, 0x34, 0x32,
1374
        ];
1375
        let result = parse_password_message(buf);
1376
        assert!(result.is_err());
1377
    }
1378
1379
    #[test]
1380
    fn test_parse_error_response_field() {
1381
        // VFATAL
1382
        let input: &[u8] = &[0x56, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x00];
1383
1384
        let value_str = "FATAL".as_bytes();
1385
        let ok_res = PgsqlErrorNoticeMessageField {
1386
            field_type: PgsqlErrorNoticeFieldType::SeverityNonLocalizable,
1387
            field_value: value_str.to_vec(),
1388
        };
1389
1390
        let (remainder, result) = parse_error_response_field(input, true).unwrap();
1391
        assert_eq!(result, ok_res);
1392
        assert_eq!(remainder.len(), 0);
1393
1394
        // "Mno pg_hba.conf entry for replication connection from host "192.168.50.11", user "rep", SSL off "
1395
        let input: &[u8] = &[
1396
            0x4d, 0x6e, 0x6f, 0x20, 0x70, 0x67, 0x5f, 0x68, 0x62, 0x61, 0x2e, 0x63, 0x6f, 0x6e,
1397
            0x66, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65,
1398
            0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e,
1399
            0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x6f,
1400
            0x73, 0x74, 0x20, 0x22, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x35, 0x30,
1401
            0x2e, 0x31, 0x31, 0x22, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x22, 0x72, 0x65,
1402
            0x70, 0x22, 0x2c, 0x20, 0x53, 0x53, 0x4c, 0x20, 0x6f, 0x66, 0x66, 0x00,
1403
        ];
1404
1405
        let value_str = br#"no pg_hba.conf entry for replication connection from host "192.168.50.11", user "rep", SSL off"#;
1406
        let ok_res = PgsqlErrorNoticeMessageField {
1407
            field_type: PgsqlErrorNoticeFieldType::Message,
1408
            field_value: value_str.to_vec(),
1409
        };
1410
1411
        let (remainder, result) = parse_error_response_field(input, true).unwrap();
1412
        assert_eq!(result, ok_res);
1413
        assert_eq!(remainder.len(), 0);
1414
1415
        // if incomplete, here we should get an error
1416
        let result = parse_error_response_field(&input[0..12], true);
1417
        assert!(result.is_err());
1418
1419
        // C28000
1420
        let input: &[u8] = &[0x43, 0x32, 0x38, 0x30, 0x30, 0x30, 0x00];
1421
        let value_str = "28000".as_bytes();
1422
        let ok_res = PgsqlErrorNoticeMessageField {
1423
            field_type: PgsqlErrorNoticeFieldType::CodeSqlStateCode,
1424
            field_value: value_str.to_vec(),
1425
        };
1426
        let (remainder, result) = parse_error_response_field(input, true).unwrap();
1427
        assert_eq!(result, ok_res);
1428
        assert_eq!(remainder.len(), 0);
1429
    }
1430
1431
    // After sending AuthenticationOk, the backend will send a series of messages with parameters, a backend key message, and finally a ready for query message
1432
    #[test]
1433
    fn test_parse_startup_phase_wrapup() {
1434
        // S   .application_name psql
1435
        let buf: &[u8] = &[
1436
            0x53, 0x00, 0x00, 0x00, 0x1a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69,
1437
            0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x70, 0x73, 0x71, 0x6c, 0x00,
1438
        ];
1439
1440
        let ok_res = PgsqlBEMessage::ParameterStatus(ParameterStatusMessage {
1441
            identifier: b'S',
1442
            length: 26,
1443
            param: PgsqlParameter {
1444
                name: PgsqlParameters::ApplicationName,
1445
                value: br#"psql"#.to_vec(),
1446
            },
1447
        });
1448
1449
        let (_remainder, result) = parse_parameter_status_message(buf).unwrap();
1450
        assert_eq!(result, ok_res);
1451
1452
        let result = pgsql_parse_response(buf);
1453
        match result {
1454
            Ok((_remainder, message)) => {
1455
                assert_eq!(message, ok_res);
1456
            }
1457
            Err(Err::Error(err)) => {
1458
                panic!(
1459
                    "Shouldn't be err {:?}, expected Ok(_). Remainder is: {:?} ",
1460
                    err.code, err.input
1461
                );
1462
            }
1463
            Err(Err::Incomplete(needed)) => {
1464
                panic!("Should not be incomplete {:?}, expected Ok(_)", needed);
1465
            }
1466
            _ => panic!("Unexpected behavior, expected Ok(_)"),
1467
        }
1468
1469
        // S   .integer_datetimes on
1470
        let buf: &[u8] = &[
1471
            0x53, 0x00, 0x00, 0x00, 0x19, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x5f, 0x64,
1472
            0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x00, 0x6f, 0x6e, 0x00,
1473
        ];
1474
        let result = parse_parameter_status_message(buf);
1475
        assert!(result.is_ok());
1476
1477
        // K       =.... // PID 61 Key 3152142766
1478
        let buf: &[u8] = &[
1479
            0x4b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0xe1, 0xe1, 0xae,
1480
        ];
1481
1482
        let result = parse_backend_key_data_message(buf);
1483
        assert!(result.is_ok());
1484
1485
        // Z   .I
1486
        let buf: &[u8] = &[0x5a, 0x00, 0x00, 0x00, 0x05, 0x49];
1487
        let result = parse_ready_for_query(buf);
1488
        assert!(result.is_ok());
1489
    }
1490
1491
    #[test]
1492
    fn test_parse_error_notice_fields() {
1493
        let input: &[u8] = &[0x53, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x00, 0x00];
1494
1495
        let field1 = PgsqlErrorNoticeMessageField {
1496
            field_type: PgsqlErrorNoticeFieldType::SeverityLocalizable,
1497
            field_value: br#"FATAL"#.to_vec(),
1498
        };
1499
        let field2 = PgsqlErrorNoticeMessageField {
1500
            field_type: PgsqlErrorNoticeFieldType::CodeSqlStateCode,
1501
            field_value: br#"28000"#.to_vec(),
1502
        };
1503
        let field3 = PgsqlErrorNoticeMessageField{
1504
            field_type: PgsqlErrorNoticeFieldType::Message,
1505
            field_value: br#"no pg_hba.conf entry for replication connection from host "192.168.50.11", user "rep", SSL off"#.to_vec(),
1506
        };
1507
        // let field4 = PgsqlErrorNoticeMessageField {
1508
        //     field_type: PgsqlErrorNoticeFieldType::TerminatorToken,
1509
        //     field_value: br#""#.to_vec(),
1510
        // };
1511
1512
        let mut ok_res: Vec<PgsqlErrorNoticeMessageField> = Vec::new();
1513
        ok_res.push(field1);
1514
        // ok_res.push(field4);
1515
1516
        let (remainder, result) = parse_error_notice_fields(input, true).unwrap();
1517
        assert_eq!(result, ok_res);
1518
        assert_eq!(remainder.len(), 0);
1519
        // ok_res.pop();
1520
1521
        ok_res.push(field2);
1522
        ok_res.push(field3);
1523
1524
        // let field4 = PgsqlErrorNoticeMessageField {
1525
        //     field_type: PgsqlErrorNoticeFieldType::TerminatorToken,
1526
        //     field_value: br#""#.to_vec(),
1527
        // };
1528
1529
        // ok_res.push(field4);
1530
1531
        let input: &[u8] = &[
1532
            0x53, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x00, 0x43, 0x32, 0x38, 0x30, 0x30, 0x30, 0x00,
1533
            0x4d, 0x6e, 0x6f, 0x20, 0x70, 0x67, 0x5f, 0x68, 0x62, 0x61, 0x2e, 0x63, 0x6f, 0x6e,
1534
            0x66, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65,
1535
            0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e,
1536
            0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x6f,
1537
            0x73, 0x74, 0x20, 0x22, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x35, 0x30,
1538
            0x2e, 0x31, 0x31, 0x22, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x22, 0x72, 0x65,
1539
            0x70, 0x22, 0x2c, 0x20, 0x53, 0x53, 0x4c, 0x20, 0x6f, 0x66, 0x66, 0x00, 0x00,
1540
        ];
1541
1542
        let (remainder, result) = parse_error_notice_fields(input, true).unwrap();
1543
        assert_eq!(result, ok_res);
1544
        assert_eq!(remainder.len(), 0);
1545
1546
        let input: &[u8] = &[
1547
            0x53, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x00, 0x43, 0x32, 0x38, 0x30, 0x30, 0x30, 0x00,
1548
            0x4d, 0x6e, 0x6f, 0x20, 0x70, 0x67, 0x5f, 0x68, 0x62, 0x61, 0x2e, 0x63, 0x6f, 0x6e,
1549
            0x66, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65,
1550
            0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e,
1551
            0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x6f,
1552
            0x73, 0x74, 0x20, 0x22, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x35, 0x30,
1553
            0x2e, 0x31, 0x31, 0x22, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x22, 0x72, 0x65,
1554
            0x70, 0x22, 0x2c, 0x20, 0x53, 0x53, 0x4c, 0x20, 0x6f, 0x66, 0x66, 0x00, 0x46, 0x61,
1555
            0x75, 0x74, 0x68, 0x2e, 0x63, 0x00, 0x4c, 0x34, 0x38, 0x31, 0x00, 0x52, 0x43, 0x6c,
1556
            0x69, 0x65, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
1557
            0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
1558
        ];
1559
1560
        let result = parse_error_notice_fields(input, true);
1561
        assert!(result.is_ok());
1562
1563
        let result = parse_error_notice_fields(&input[0..12], true);
1564
        match result {
1565
            Ok((_remainder, _message)) => panic!("Result should not be ok, but incomplete."),
1566
1567
            Err(Err::Error(err)) => {
1568
                panic!("Shouldn't be error: {:?}", err.code);
1569
            }
1570
            Err(Err::Incomplete(needed)) => {
1571
                assert_eq!(needed, Needed::new(2));
1572
            }
1573
            _ => panic!("Unexpected behavior."),
1574
        }
1575
    }
1576
1577
    #[test]
1578
    fn test_parse_error_notice_response() {
1579
        // test case buffer
1580
        let buf: &[u8] = &[
1581
            /* identifier */ 0x45, /* length */ 0x00, 0x00, 0x00, 0x96,
1582
            /* Severity */ 0x53, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x00, /* Code */ 0x43,
1583
            0x32, 0x38, 0x30, 0x30, 0x30, 0x00, /* Message */ 0x4d, 0x6e, 0x6f, 0x20, 0x70,
1584
            0x67, 0x5f, 0x68, 0x62, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20, 0x65, 0x6e, 0x74,
1585
            0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61,
1586
            0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
1587
            0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x22, 0x31,
1588
            0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x35, 0x30, 0x2e, 0x31, 0x31, 0x22, 0x2c,
1589
            0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x22, 0x72, 0x65, 0x70, 0x22, 0x2c, 0x20, 0x53,
1590
            0x53, 0x4c, 0x20, 0x6f, 0x66, 0x66, 0x00, /* File */ 0x46, 0x61, 0x75, 0x74, 0x68,
1591
            0x2e, 0x63, 0x00, /* Line */ 0x4c, 0x34, 0x38, 0x31, 0x00,
1592
            /* Routine */ 0x52, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68,
1593
            0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
1594
        ];
1595
1596
        // expected result
1597
        let field1 = PgsqlErrorNoticeMessageField {
1598
            field_type: PgsqlErrorNoticeFieldType::SeverityLocalizable,
1599
            field_value: br#"FATAL"#.to_vec(),
1600
        };
1601
        let field2 = PgsqlErrorNoticeMessageField {
1602
            field_type: PgsqlErrorNoticeFieldType::CodeSqlStateCode,
1603
            field_value: br#"28000"#.to_vec(),
1604
        };
1605
        let field3 = PgsqlErrorNoticeMessageField {
1606
            field_type: PgsqlErrorNoticeFieldType::Message,
1607
            field_value: br#"no pg_hba.conf entry for replication connection from host "192.168.50.11", user "rep", SSL off"#.to_vec(),
1608
        };
1609
        let field4 = PgsqlErrorNoticeMessageField {
1610
            field_type: PgsqlErrorNoticeFieldType::File,
1611
            field_value: br#"auth.c"#.to_vec(),
1612
        };
1613
        let field5 = PgsqlErrorNoticeMessageField {
1614
            field_type: PgsqlErrorNoticeFieldType::Line,
1615
            field_value: br#"481"#.to_vec(),
1616
        };
1617
        let field6 = PgsqlErrorNoticeMessageField {
1618
            field_type: PgsqlErrorNoticeFieldType::Routine,
1619
            field_value: br#"ClientAuthentication"#.to_vec(),
1620
        };
1621
1622
        let mut payload = ErrorNoticeMessage::new(b'E', 150);
1623
        payload.message_body.push(field1);
1624
        payload.message_body.push(field2);
1625
        payload.message_body.push(field3);
1626
        payload.message_body.push(field4);
1627
        payload.message_body.push(field5);
1628
        payload.message_body.push(field6);
1629
1630
        let ok_res = PgsqlBEMessage::ErrorResponse(payload);
1631
1632
        let result = pgsql_parse_response(buf);
1633
        match result {
1634
            Ok((remainder, message)) => {
1635
                assert_eq!(message, ok_res);
1636
                assert_eq!(remainder.len(), 0);
1637
            }
1638
            Err(Err::Error(err)) => {
1639
                panic!("Shouldn't be error: {:?}", err.code);
1640
            }
1641
            Err(Err::Incomplete(needed)) => {
1642
                panic!("Should not be Incomplete! Needed: {:?}", needed);
1643
            }
1644
            _ => {
1645
                panic!("Unexpected behavior");
1646
            }
1647
        }
1648
1649
        let result_incomplete = pgsql_parse_response(&buf[0..22]);
1650
        match result_incomplete {
1651
            Err(Err::Incomplete(needed)) => {
1652
                // parser first tries to take whole message (length + identifier = 151), but buffer is incomplete
1653
                assert_eq!(needed, Needed::new(129));
1654
            }
1655
            _ => {
1656
                panic!("Unexpected behavior. Should be incomplete.");
1657
            }
1658
        }
1659
1660
        //repeat for different case-scenarios:
1661
        // - message is valid
1662
        // some invalid character
1663
    }
1664
1665
    #[test]
1666
    fn test_parse_notice_response() {
1667
        // N   .SDEBUG VDEBUG C23505 Mduplicate key value violates unique constraint "unique_a" DKey (a)=(mea5) already exists. Fnbtinsert.c L397 R_bt_check_unique
1668
        let buf: &[u8] = &[
1669
            0x4e, 0x00, 0x00, 0x00, 0x99, 0x53, 0x44, 0x45, 0x42, 0x55, 0x47, 0x00, 0x56, 0x44,
1670
            0x45, 0x42, 0x55, 0x47, 0x00, 0x43, 0x32, 0x33, 0x35, 0x30, 0x35, 0x00, 0x4d, 0x64,
1671
            0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x76,
1672
            0x61, 0x6c, 0x75, 0x65, 0x20, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x20,
1673
            0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61,
1674
            0x69, 0x6e, 0x74, 0x20, 0x22, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x5f, 0x61, 0x22,
1675
            0x00, 0x44, 0x4b, 0x65, 0x79, 0x20, 0x28, 0x61, 0x29, 0x3d, 0x28, 0x6d, 0x65, 0x61,
1676
            0x35, 0x29, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x65, 0x78, 0x69,
1677
            0x73, 0x74, 0x73, 0x2e, 0x00, 0x46, 0x6e, 0x62, 0x74, 0x69, 0x6e, 0x73, 0x65, 0x72,
1678
            0x74, 0x2e, 0x63, 0x00, 0x4c, 0x33, 0x39, 0x37, 0x00, 0x52, 0x5f, 0x62, 0x74, 0x5f,
1679
            0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x00, 0x00,
1680
        ];
1681
1682
        // expected result
1683
        let field1 = PgsqlErrorNoticeMessageField {
1684
            field_type: PgsqlErrorNoticeFieldType::SeverityLocalizable,
1685
            field_value: br#"DEBUG"#.to_vec(),
1686
        };
1687
        let field2 = PgsqlErrorNoticeMessageField {
1688
            field_type: PgsqlErrorNoticeFieldType::SeverityNonLocalizable,
1689
            field_value: br#"DEBUG"#.to_vec(),
1690
        };
1691
        let field3 = PgsqlErrorNoticeMessageField {
1692
            field_type: PgsqlErrorNoticeFieldType::CodeSqlStateCode,
1693
            field_value: br#"23505"#.to_vec(),
1694
        };
1695
        let field4 = PgsqlErrorNoticeMessageField {
1696
            field_type: PgsqlErrorNoticeFieldType::Message,
1697
            field_value: br#"duplicate key value violates unique constraint "unique_a""#.to_vec(),
1698
        };
1699
        let field5 = PgsqlErrorNoticeMessageField {
1700
            field_type: PgsqlErrorNoticeFieldType::Detail,
1701
            field_value: br#"Key (a)=(mea5) already exists."#.to_vec(),
1702
        };
1703
        let field6 = PgsqlErrorNoticeMessageField {
1704
            field_type: PgsqlErrorNoticeFieldType::File,
1705
            field_value: br#"nbtinsert.c"#.to_vec(),
1706
        };
1707
        let field7 = PgsqlErrorNoticeMessageField {
1708
            field_type: PgsqlErrorNoticeFieldType::Line,
1709
            field_value: br#"397"#.to_vec(),
1710
        };
1711
        let field8 = PgsqlErrorNoticeMessageField {
1712
            field_type: PgsqlErrorNoticeFieldType::Routine,
1713
            field_value: br#"_bt_check_unique"#.to_vec(),
1714
        };
1715
1716
        let mut payload = ErrorNoticeMessage::new(b'N', 153);
1717
        payload.message_body.push(field1);
1718
        payload.message_body.push(field2);
1719
        payload.message_body.push(field3);
1720
        payload.message_body.push(field4);
1721
        payload.message_body.push(field5);
1722
        payload.message_body.push(field6);
1723
        payload.message_body.push(field7);
1724
        payload.message_body.push(field8);
1725
1726
        let ok_res = PgsqlBEMessage::NoticeResponse(payload);
1727
1728
        let result = pgsql_parse_response(buf);
1729
        match result {
1730
            Ok((remainder, message)) => {
1731
                assert_eq!(message, ok_res);
1732
                assert_eq!(remainder.len(), 0);
1733
            }
1734
            Err(Err::Error(err)) => {
1735
                panic!("Shouldn't be error: {:?}", err.code);
1736
            }
1737
            Err(Err::Incomplete(needed)) => {
1738
                panic!("Should not be Incomplete! Needed: {:?} ", needed);
1739
            }
1740
            _ => {
1741
                panic!("Unexpected behavior");
1742
            }
1743
        }
1744
    }
1745
1746
    #[test]
1747
    fn test_parse_sasl_authentication_message() {
1748
        let buf: &[u8] = &[
1749
            /* identifier R */ 0x52, /* length 28 */ 0x00, 0x00, 0x00, 0x1c,
1750
            /* auth_type */ 0x00, 0x00, 0x00, 0x0a, /* SCRAM-SHA-256-PLUS */ 0x53, 0x43,
1751
            0x52, 0x41, 0x4d, 0x2d, 0x53, 0x48, 0x41, 0x2d, 0x32, 0x35, 0x36, 0x2d, 0x50, 0x4c,
1752
            0x55, 0x53, 0x00, 0x00,
1753
        ];
1754
        let mechanism = vec![SASLAuthenticationMechanism::ScramSha256Plus];
1755
        let ok_res = PgsqlBEMessage::AuthenticationSASL(AuthenticationSASLMechanismMessage {
1756
            identifier: b'R',
1757
            length: 28,
1758
            auth_type: 10,
1759
            auth_mechanisms: mechanism,
1760
        });
1761
1762
        let result = pgsql_parse_response(buf);
1763
        match result {
1764
            Ok((remainder, message)) => {
1765
                assert_eq!(message, ok_res);
1766
                assert_eq!(remainder.len(), 0);
1767
            }
1768
            Err(Err::Error(err)) => {
1769
                panic!("Shouldn't be error: {:?}", err.code);
1770
            }
1771
            Err(Err::Incomplete(needed)) => {
1772
                panic!("Should not be Incomplete! Needed: {:?}", needed);
1773
            }
1774
            _ => {
1775
                panic!("Unexpected behavior");
1776
            }
1777
        }
1778
1779
        let buf: &[u8] = &[
1780
            /* identifier R */ 0x52, /* length 42 */ 0x00, 0x00, 0x00, 0x2a,
1781
            /* auth_type */ 0x00, 0x00, 0x00, 0x0a, /* SCRAM-SHA-256-PLUS */ 0x53, 0x43,
1782
            0x52, 0x41, 0x4d, 0x2d, 0x53, 0x48, 0x41, 0x2d, 0x32, 0x35, 0x36, 0x2d, 0x50, 0x4c,
1783
            0x55, 0x53, 0x00, /* SCRAM-SHA-256 */ 0x53, 0x43, 0x52, 0x41, 0x4d, 0x2d, 0x53,
1784
            0x48, 0x41, 0x2d, 0x32, 0x35, 0x36, 0x00, 0x00,
1785
        ];
1786
        let mechanism = vec![
1787
            SASLAuthenticationMechanism::ScramSha256Plus,
1788
            SASLAuthenticationMechanism::ScramSha256,
1789
        ];
1790
        let ok_res = PgsqlBEMessage::AuthenticationSASL(AuthenticationSASLMechanismMessage {
1791
            identifier: b'R',
1792
            length: 42,
1793
            auth_type: 10,
1794
            auth_mechanisms: mechanism,
1795
        });
1796
1797
        let result = pgsql_parse_response(buf);
1798
        match result {
1799
            Ok((remainder, message)) => {
1800
                assert_eq!(message, ok_res);
1801
                assert_eq!(remainder.len(), 0);
1802
            }
1803
            Err(Err::Error(err)) => {
1804
                panic!("Shouldn't be error: {:?}", err.code);
1805
            }
1806
            Err(Err::Incomplete(needed)) => {
1807
                panic!("Should not be Incomplete! Needed: {:?}", needed);
1808
            }
1809
            _ => {
1810
                panic!("Unexpected behavior");
1811
            }
1812
        }
1813
1814
        let incomplete_result = pgsql_parse_response(&buf[0..27]);
1815
        match incomplete_result {
1816
            Ok((_remainder, _message)) => panic!("Should not be Ok(_), expected Incomplete!"),
1817
            Err(Err::Error(err)) => {
1818
                panic!("Should not be error {:?}, expected Incomplete!", err.code)
1819
            }
1820
            Err(Err::Incomplete(needed)) => assert_eq!(needed, Needed::new(16)),
1821
            _ => panic!("Unexpected behavior, expected Incomplete."),
1822
        }
1823
    }
1824
1825
    #[test]
1826
    fn test_parse_sasl_continue_authentication_message() {
1827
        // As found in: https://blog.hackeriet.no/Better-password-hashing-in-PostgreSQL/
1828
        let buf: &[u8] = &[
1829
            /* 'R' */ 0x52, /* 92 */ 0x00, 0x00, 0x00, 0x5c, /* 11 */ 0x00, 0x00,
1830
            0x00, 0x0b, /* challenge data*/ 0x72, 0x3d, 0x2f, 0x7a, 0x2b, 0x67, 0x69, 0x5a,
1831
            0x69, 0x54, 0x78, 0x41, 0x48, 0x37, 0x72, 0x38, 0x73, 0x4e, 0x41, 0x65, 0x48, 0x72,
1832
            0x37, 0x63, 0x76, 0x70, 0x71, 0x56, 0x33, 0x75, 0x6f, 0x37, 0x47, 0x2f, 0x62, 0x4a,
1833
            0x42, 0x49, 0x4a, 0x4f, 0x33, 0x70, 0x6a, 0x56, 0x4d, 0x37, 0x74, 0x33, 0x6e, 0x67,
1834
            0x2c, 0x73, 0x3d, 0x34, 0x55, 0x56, 0x36, 0x38, 0x62, 0x49, 0x6b, 0x43, 0x38, 0x66,
1835
            0x39, 0x2f, 0x58, 0x38, 0x78, 0x48, 0x37, 0x61, 0x50, 0x68, 0x67, 0x3d, 0x3d, 0x2c,
1836
            0x69, 0x3d, 0x34, 0x30, 0x39, 0x36,
1837
        ];
1838
1839
        let ok_res = PgsqlBEMessage::AuthenticationSASLContinue(
1840
            AuthenticationMessage {
1841
                identifier: b'R',
1842
                length: 92,
1843
                auth_type: 11,
1844
                payload: br#"r=/z+giZiTxAH7r8sNAeHr7cvpqV3uo7G/bJBIJO3pjVM7t3ng,s=4UV68bIkC8f9/X8xH7aPhg==,i=4096"#.to_vec(),
1845
        });
1846
1847
        let result = pgsql_parse_response(buf);
1848
        match result {
1849
            Ok((remainder, message)) => {
1850
                assert_eq!(message, ok_res);
1851
                assert_eq!(remainder.len(), 0);
1852
            }
1853
            Err(Err::Error(err)) => {
1854
                panic!("Shouldn't be error {:?} expected Ok(_)", err.code)
1855
            }
1856
            Err(Err::Incomplete(needed)) => {
1857
                panic!("shouldn't be incomplete {:?}, expected Ok(_)", needed)
1858
            }
1859
            _ => panic!("Unexpected behavior, expected Ok(_)"),
1860
        }
1861
1862
        let result_incomplete = pgsql_parse_response(&buf[0..31]);
1863
        match result_incomplete {
1864
            Ok((_remainder, _message)) => panic!("Should not be Ok(_), expected Incomplete!"),
1865
            Err(Err::Error(err)) => {
1866
                panic!("Shouldn't be error {:?} expected Incomplete!", err.code)
1867
            }
1868
            Err(Err::Incomplete(needed)) => {
1869
                assert_eq!(needed, Needed::new(62));
1870
            }
1871
            _ => panic!("Unexpected behavior, expected Ok(_)"),
1872
        }
1873
    }
1874
1875
    #[test]
1876
    fn test_parse_sasl_final_authentication_message() {
1877
        let buf: &[u8] = &[
1878
            /* R */ 0x52, /* 54 */ 0x00, 0x00, 0x00, 0x36, /* 12 */ 0x00, 0x00,
1879
            0x00, 0x0c, /* signature */ 0x76, 0x3d, 0x64, 0x31, 0x50, 0x58, 0x61, 0x38, 0x54,
1880
            0x4b, 0x46, 0x50, 0x5a, 0x72, 0x52, 0x33, 0x4d, 0x42, 0x52, 0x6a, 0x4c, 0x79, 0x33,
1881
            0x2b, 0x4a, 0x36, 0x79, 0x78, 0x72, 0x66, 0x77, 0x2f, 0x7a, 0x7a, 0x70, 0x38, 0x59,
1882
            0x54, 0x39, 0x65, 0x78, 0x56, 0x37, 0x73, 0x38, 0x3d,
1883
        ];
1884
        let ok_res = PgsqlBEMessage::AuthenticationSASLFinal(AuthenticationMessage {
1885
            identifier: b'R',
1886
            length: 54,
1887
            auth_type: 12,
1888
            payload: br#"v=d1PXa8TKFPZrR3MBRjLy3+J6yxrfw/zzp8YT9exV7s8="#.to_vec(),
1889
        });
1890
1891
        let result = pgsql_parse_response(buf);
1892
        match result {
1893
            Ok((remainder, message)) => {
1894
                assert_eq!(message, ok_res);
1895
                assert_eq!(remainder.len(), 0);
1896
            }
1897
            Err(Err::Error(err)) => {
1898
                panic!("Shouldn't be error {:?}, expected Ok(_)", err.code);
1899
            }
1900
            Err(Err::Incomplete(needed)) => {
1901
                panic!("Shouldn't be incomplete {:?}, expected OK(_)", needed);
1902
            }
1903
            _ => panic!("Unexpected behavior, expected Ok(_)"),
1904
        }
1905
1906
        let result_incomplete = pgsql_parse_response(&buf[0..34]);
1907
        match result_incomplete {
1908
            Err(Err::Incomplete(needed)) => {
1909
                assert_eq!(needed, Needed::new(21));
1910
            }
1911
            _ => panic!("Unexpected behavior, expected incomplete."),
1912
        }
1913
1914
        let bad_buf: &[u8] = &[
1915
            /* ` */ 0x60, /* 54 */ 0x00, 0x00, 0x00, 0x36, /* 12 */ 0x00, 0x00,
1916
            0x00, 0x0c, /* signature */ 0x76, 0x3d, 0x64, 0x31, 0x50, 0x58, 0x61, 0x38, 0x54,
1917
            0x4b, 0x46, 0x50, 0x5a, 0x72, 0x52, 0x33, 0x4d, 0x42, 0x52, 0x6a, 0x4c, 0x79, 0x33,
1918
            0x2b, 0x4a, 0x36, 0x79, 0x78, 0x72, 0x66, 0x77, 0x2f, 0x7a, 0x7a, 0x70, 0x38, 0x59,
1919
            0x54, 0x39, 0x65, 0x78, 0x56, 0x37, 0x73, 0x38, 0x3d,
1920
        ];
1921
        let (remainder, result) = pgsql_parse_response(bad_buf).expect("parsing sasl final response failed");
1922
        let res = PgsqlBEMessage::UnknownMessageType(RegularPacket {
1923
            identifier: b'`',
1924
            length: 54,
1925
            payload: bad_buf[5..].to_vec(),
1926
        });
1927
        assert_eq!(result, res);
1928
        assert!(remainder.is_empty());
1929
    }
1930
1931
    #[test]
1932
    fn test_parse_sasl_frontend_messages() {
1933
        // SASL Initial Response
1934
        // (as seen in https://blog.hackeriet.no/Better-password-hashing-in-PostgreSQL/)
1935
        let buf: &[u8] = &[
1936
            /* p */ 0x70, /* 54 */ 0x00, 0x00, 0x00, 0x36,
1937
            /* sasl mechanism */ 0x53, 0x43, 0x52, 0x41, 0x4d, 0x2d, 0x53, 0x48, 0x41, 0x2d,
1938
            0x32, 0x35, 0x36, 0x00, /* 32 */ 0x00, 0x00, 0x00, 0x20,
1939
            /* FE 1st msg */ 0x6e, 0x2c, 0x2c, 0x6e, 0x3d, 0x2c, 0x72, 0x3d, 0x2f, 0x7a, 0x2b,
1940
            0x67, 0x69, 0x5a, 0x69, 0x54, 0x78, 0x41, 0x48, 0x37, 0x72, 0x38, 0x73, 0x4e, 0x41,
1941
            0x65, 0x48, 0x72, 0x37, 0x63, 0x76, 0x70,
1942
        ];
1943
        let ok_res = PgsqlFEMessage::SASLInitialResponse(SASLInitialResponsePacket {
1944
            identifier: b'p',
1945
            length: 54,
1946
            auth_mechanism: SASLAuthenticationMechanism::ScramSha256,
1947
            param_length: 32,
1948
            sasl_param: br#"n,,n=,r=/z+giZiTxAH7r8sNAeHr7cvp"#.to_vec(),
1949
        });
1950
1951
        let result = parse_sasl_initial_response(buf);
1952
        match result {
1953
            Ok((remainder, message)) => {
1954
                assert_eq!(message, ok_res);
1955
                assert_eq!(remainder.len(), 0);
1956
            }
1957
            Err(Err::Error(err)) => {
1958
                panic!("Shouldn't be error {:?}, expected Ok(_)", err.code)
1959
            }
1960
            Err(Err::Incomplete(needed)) => {
1961
                panic!("Shouldn't be incomplete: {:?}, expected Ok(_)", needed)
1962
            }
1963
            _ => panic!("Unexpected behavior, expected Ok(_)"),
1964
        }
1965
1966
        let buf: &[u8] = &[
1967
            /* p */ 0x70, /* 108 */ 0x00, 0x00, 0x00, 0x6c, /* final msg*/ 0x63,
1968
            0x3d, 0x62, 0x69, 0x77, 0x73, 0x2c, 0x72, 0x3d, 0x2f, 0x7a, 0x2b, 0x67, 0x69, 0x5a,
1969
            0x69, 0x54, 0x78, 0x41, 0x48, 0x37, 0x72, 0x38, 0x73, 0x4e, 0x41, 0x65, 0x48, 0x72,
1970
            0x37, 0x63, 0x76, 0x70, 0x71, 0x56, 0x33, 0x75, 0x6f, 0x37, 0x47, 0x2f, 0x62, 0x4a,
1971
            0x42, 0x49, 0x4a, 0x4f, 0x33, 0x70, 0x6a, 0x56, 0x4d, 0x37, 0x74, 0x33, 0x6e, 0x67,
1972
            0x2c, 0x70, 0x3d, 0x41, 0x46, 0x70, 0x53, 0x59, 0x48, 0x2f, 0x4b, 0x2f, 0x38, 0x62,
1973
            0x75, 0x78, 0x31, 0x6d, 0x52, 0x50, 0x55, 0x77, 0x78, 0x54, 0x65, 0x38, 0x6c, 0x42,
1974
            0x75, 0x49, 0x50, 0x45, 0x79, 0x68, 0x69, 0x2f, 0x37, 0x55, 0x46, 0x50, 0x51, 0x70,
1975
            0x53, 0x72, 0x34, 0x41, 0x3d,
1976
        ];
1977
1978
        let ok_res = PgsqlFEMessage::SASLResponse(
1979
            RegularPacket {
1980
                identifier: b'p',
1981
                length: 108,
1982
                payload: br#"c=biws,r=/z+giZiTxAH7r8sNAeHr7cvpqV3uo7G/bJBIJO3pjVM7t3ng,p=AFpSYH/K/8bux1mRPUwxTe8lBuIPEyhi/7UFPQpSr4A="#.to_vec(),
1983
            });
1984
1985
        let result = parse_sasl_response(buf);
1986
        match result {
1987
            Ok((_remainder, message)) => {
1988
                assert_eq!(message, ok_res);
1989
            }
1990
            Err(Err::Error(err)) => {
1991
                panic!("Shouldn't be error: {:?} expected Ok(_)", err.code)
1992
            }
1993
            Err(Err::Incomplete(needed)) => {
1994
                panic!("Shouldn't be incomplete: {:?}, expected Ok(_)", needed)
1995
            }
1996
            _ => panic!("Unexpected behavior, should be Ok(_)"),
1997
        }
1998
    }
1999
2000
    // Test messages with fixed formats, like AuthenticationSSPI
2001
    #[test]
2002
    fn test_parse_simple_authentication_requests() {
2003
        let buf: &[u8] = &[
2004
            /* R */ 0x52, /* 8 */ 0x00, 0x00, 0x00, 0x08, /* 9 */ 0x00, 0x00, 0x00,
2005
            0x09,
2006
        ];
2007
2008
        let ok_res = PgsqlBEMessage::AuthenticationSSPI(AuthenticationMessage {
2009
            identifier: b'R',
2010
            length: 8,
2011
            auth_type: 9,
2012
            payload: Vec::<u8>::new(),
2013
        });
2014
2015
        let (_remainder, result) = pgsql_parse_response(buf).unwrap();
2016
        assert_eq!(result, ok_res);
2017
    }
2018
2019
    #[test]
2020
    fn test_parse_response() {
2021
        // An SSL response - N
2022
        let buf: &[u8] = &[0x4e];
2023
        let response_ok = PgsqlBEMessage::SSLResponse(SSLResponseMessage::SSLRejected);
2024
        let (_remainder, result) = parse_ssl_response(buf).unwrap();
2025
        assert_eq!(result, response_ok);
2026
2027
        // An SSL response - S
2028
        let buf: &[u8] = &[0x53];
2029
        let response_ok = PgsqlBEMessage::SSLResponse(SSLResponseMessage::SSLAccepted);
2030
2031
        let (_remainder, result) = parse_ssl_response(buf).unwrap();
2032
        assert_eq!(result, response_ok);
2033
2034
        // Not an SSL response
2035
        let buf: &[u8] = &[0x52];
2036
        let result = parse_ssl_response(buf);
2037
        assert!(result.is_err());
2038
2039
        // - auth MD5
2040
        let buf: &[u8] = &[
2041
            0x52, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x05, 0xf2, 0x11, 0xa3, 0xed,
2042
        ];
2043
        let ok_res = PgsqlBEMessage::AuthenticationMD5Password(AuthenticationMessage {
2044
            identifier: b'R',
2045
            length: 12,
2046
            auth_type: 5,
2047
            payload: vec![0xf2, 0x11, 0xa3, 0xed],
2048
        });
2049
        let result = pgsql_parse_response(buf);
2050
        match result {
2051
            Ok((remainder, message)) => {
2052
                assert_eq!(message, ok_res);
2053
                assert_eq!(remainder.len(), 0);
2054
            }
2055
            Err(Err::Error(err)) => {
2056
                panic!("Shouldn't be error: {:?}", err.code);
2057
            }
2058
            Err(Err::Incomplete(needed)) => {
2059
                panic!("Should not be Incomplete! Needed: {:?}", needed);
2060
            }
2061
            _ => {
2062
                panic!("Unexpected behavior");
2063
            }
2064
        }
2065
2066
        // - auth clear text...
2067
        let buf: &[u8] = &[0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03];
2068
        let ok_res = PgsqlBEMessage::AuthenticationCleartextPassword(AuthenticationMessage {
2069
            identifier: b'R',
2070
            length: 8,
2071
            auth_type: 3,
2072
            payload: Vec::<u8>::new(),
2073
        });
2074
        let result = pgsql_parse_response(buf);
2075
        match result {
2076
            Ok((remainder, message)) => {
2077
                assert_eq!(remainder.len(), 0);
2078
                assert_eq!(message, ok_res);
2079
            }
2080
            Err(Err::Error(err)) => {
2081
                panic!("Shouldn't be error: {:?}", err.code);
2082
            }
2083
            Err(Err::Incomplete(needed)) => {
2084
                panic!("Should not be incomplete. Needed {:?}", needed);
2085
            }
2086
            _ => {
2087
                panic!("Unexpected behavior");
2088
            }
2089
        }
2090
2091
        let result = pgsql_parse_response(&buf[0..6]);
2092
        assert!(result.is_err());
2093
2094
        let buf: &[u8] = &[0x52, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03];
2095
        let result = pgsql_parse_response(buf);
2096
        assert!(result.is_err());
2097
2098
        // - auth Ok
2099
        let buf: &[u8] = &[0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00];
2100
        let ok_res = PgsqlBEMessage::AuthenticationOk(AuthenticationMessage {
2101
            identifier: b'R',
2102
            length: 8,
2103
            auth_type: 0,
2104
            payload: Vec::<u8>::new(),
2105
        });
2106
        let result = pgsql_parse_response(buf);
2107
        match result {
2108
            Ok((remainder, message)) => {
2109
                assert_eq!(message, ok_res);
2110
                assert_eq!(remainder.len(), 0);
2111
            }
2112
            Err(Err::Error(err)) => {
2113
                panic!("Should not be error {:?}", err.code);
2114
            }
2115
            Err(Err::Incomplete(needed)) => {
2116
                panic!("Should not be incomplete. Needed: {:?}", needed);
2117
            }
2118
            _ => {
2119
                panic!("Unexpected behavior!");
2120
            }
2121
        }
2122
2123
        //A series of response messages from the backend:
2124
        // R   ·    S   ·application_name
2125
        // S   ·client_encoding UTF8 S   ·DateStyle ISO, MDY
2126
        // S   &default_transaction_read_only off S   ·in_hot_standby off
2127
        // S   ·integer_datetimes on S   ·IntervalStyle postgres
2128
        // S   ·is_superuser off S   ·server_encoding UTF8
2129
        // S   ·server_version 14.5 S   "session_authorization ctfpost
2130
        // S   #standard_conforming_strings on S   ·TimeZone Europe/Paris
2131
        // K      ···O··Z   ·I
2132
        let buf = &[
2133
            0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2134
            0x00, 0x53, 0x00, 0x00, 0x00, 0x16, 0x61, 0x70,
2135
            0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
2136
            0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00,
2137
            0x53, 0x00, 0x00, 0x00, 0x19, 0x63, 0x6c, 0x69,
2138
            0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x63, 0x6f,
2139
            0x64, 0x69, 0x6e, 0x67, 0x00, 0x55, 0x54, 0x46,
2140
            0x38, 0x00, 0x53, 0x00, 0x00, 0x00, 0x17, 0x44,
2141
            0x61, 0x74, 0x65, 0x53, 0x74, 0x79, 0x6c, 0x65,
2142
            0x00, 0x49, 0x53, 0x4f, 0x2c, 0x20, 0x4d, 0x44,
2143
            0x59, 0x00, 0x53, 0x00, 0x00, 0x00, 0x26, 0x64,
2144
            0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x74,
2145
            0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
2146
            0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x5f,
2147
            0x6f, 0x6e, 0x6c, 0x79, 0x00, 0x6f, 0x66, 0x66,
2148
            0x00, 0x53, 0x00, 0x00, 0x00, 0x17, 0x69, 0x6e,
2149
            0x5f, 0x68, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61,
2150
            0x6e, 0x64, 0x62, 0x79, 0x00, 0x6f, 0x66, 0x66,
2151
            0x00, 0x53, 0x00, 0x00, 0x00, 0x19, 0x69, 0x6e,
2152
            0x74, 0x65, 0x67, 0x65, 0x72, 0x5f, 0x64, 0x61,
2153
            0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x00,
2154
            0x6f, 0x6e, 0x00, 0x53, 0x00, 0x00, 0x00, 0x1b,
2155
            0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
2156
            0x53, 0x74, 0x79, 0x6c, 0x65, 0x00, 0x70, 0x6f,
2157
            0x73, 0x74, 0x67, 0x72, 0x65, 0x73, 0x00, 0x53,
2158
            0x00, 0x00, 0x00, 0x15, 0x69, 0x73, 0x5f, 0x73,
2159
            0x75, 0x70, 0x65, 0x72, 0x75, 0x73, 0x65, 0x72,
2160
            0x00, 0x6f, 0x66, 0x66, 0x00, 0x53, 0x00, 0x00,
2161
            0x00, 0x19, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
2162
            0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e,
2163
            0x67, 0x00, 0x55, 0x54, 0x46, 0x38, 0x00, 0x53,
2164
            0x00, 0x00, 0x00, 0x18, 0x73, 0x65, 0x72, 0x76,
2165
            0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69,
2166
            0x6f, 0x6e, 0x00, 0x31, 0x34, 0x2e, 0x35, 0x00,
2167
            0x53, 0x00, 0x00, 0x00, 0x22, 0x73, 0x65, 0x73,
2168
            0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x75, 0x74,
2169
            0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69,
2170
            0x6f, 0x6e, 0x00, 0x63, 0x74, 0x66, 0x70, 0x6f,
2171
            0x73, 0x74, 0x00, 0x53, 0x00, 0x00, 0x00, 0x23,
2172
            0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
2173
            0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x72, 0x6d,
2174
            0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x72, 0x69,
2175
            0x6e, 0x67, 0x73, 0x00, 0x6f, 0x6e, 0x00, 0x53,
2176
            0x00, 0x00, 0x00, 0x1a, 0x54, 0x69, 0x6d, 0x65,
2177
            0x5a, 0x6f, 0x6e, 0x65, 0x00, 0x45, 0x75, 0x72,
2178
            0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72, 0x69,
2179
            0x73, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x0c, 0x00,
2180
            0x00, 0x0b, 0x8d, 0xcf, 0x4f, 0xb6, 0xcf, 0x5a,
2181
            0x00, 0x00, 0x00, 0x05, 0x49
2182
        ];
2183
2184
        let result = pgsql_parse_response(buf);
2185
        assert!(result.is_ok());
2186
    }
2187
2188
    #[test]
2189
    fn test_parse_row_description() {
2190
        // RowDescription message
2191
        // T  ..
2192
        // source   @  .   .......  version   @  .   .......  sid   @  .   . .....
2193
        let buffer: &[u8] = &[
2194
            0x54, 0x00, 0x00, 0x00, 0x50, 0x00, 0x03, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00,
2195
            0x00, 0x00, 0x40, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0xff, 0xff, 0xff, 0xff,
2196
            0xff, 0xff, 0x00, 0x00, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00,
2197
            0x40, 0x09, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2198
            0x00, 0x00, 0x73, 0x69, 0x64, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0x03, 0x00, 0x00,
2199
            0x00, 0x14, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
2200
        ];
2201
2202
        let field1 = RowField {
2203
            field_name: br#"source"#.to_vec(),
2204
            table_oid: 16393,
2205
            column_index: 1,
2206
            data_type_oid: 25,
2207
            data_type_size: -1,
2208
            type_modifier: -1,
2209
            format_code: 0,
2210
        };
2211
2212
        let field2 = RowField {
2213
            field_name: br#"version"#.to_vec(),
2214
            table_oid: 16393,
2215
            column_index: 2,
2216
            data_type_oid: 25,
2217
            data_type_size: -1,
2218
            type_modifier: -1,
2219
            format_code: 0,
2220
        };
2221
2222
        let field3 = RowField {
2223
            field_name: br#"sid"#.to_vec(),
2224
            table_oid: 16393,
2225
            column_index: 3,
2226
            data_type_oid: 20,
2227
            data_type_size: 8,
2228
            type_modifier: -1,
2229
            format_code: 0,
2230
        };
2231
2232
        let mut fields_vec = Vec::<RowField>::new();
2233
        fields_vec.push(field1);
2234
        fields_vec.push(field2);
2235
        fields_vec.push(field3);
2236
2237
        let ok_res = PgsqlBEMessage::RowDescription(RowDescriptionMessage {
2238
            identifier: b'T',
2239
            length: 80,
2240
            field_count: 3,
2241
            fields: fields_vec,
2242
        });
2243
2244
        let result = parse_row_description(buffer);
2245
2246
        match result {
2247
            Ok((rem, response)) => {
2248
                assert_eq!(response, ok_res);
2249
                assert!(rem.is_empty());
2250
            }
2251
            Err(Err::Incomplete(needed)) => {
2252
                panic!("Should not be Incomplete! Needed: {:?}", needed);
2253
            }
2254
            Err(Err::Error(err)) => {
2255
                println!("Remainder is: {:?}", err.input);
2256
                panic!("Shouldn't be error: {:?}", err.code);
2257
            }
2258
            _ => {
2259
                panic!("Unexpected behavior");
2260
            }
2261
        }
2262
    }
2263
2264
    #[test]
2265
    fn test_parse_data_row() {
2266
        let buffer: &[u8] = &[
2267
            0x44, 0x00, 0x00, 0x00, 0x23, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x65, 0x74, 0x2f,
2268
            0x6f, 0x70, 0x65, 0x6e, 0x00, 0x00, 0x00, 0x03, 0x36, 0x2e, 0x30, 0x00, 0x00, 0x00,
2269
            0x07, 0x32, 0x30, 0x32, 0x31, 0x37, 0x30, 0x31,
2270
        ];
2271
2272
        let result = parse_consolidated_data_row(buffer);
2273
        assert!(result.is_ok());
2274
    }
2275
2276
    #[test]
2277
    fn test_command_complete() {
2278
        let buffer: &[u8] = &[
2279
            0x43, 0x00, 0x00, 0x00, 0x0d, 0x53, 0x45, 0x4c, 0x45, 0x43, 0x54, 0x20, 0x33, 0x00,
2280
        ];
2281
2282
        let ok_res = PgsqlBEMessage::CommandComplete(RegularPacket {
2283
            identifier: b'C',
2284
            length: 13,
2285
            payload: b"SELECT 3".to_vec(),
2286
        });
2287
2288
        let result = pgsql_parse_response(buffer);
2289
2290
        match result {
2291
            Ok((rem, message)) => {
2292
                assert_eq!(ok_res, message);
2293
                assert!(rem.is_empty());
2294
            }
2295
            Err(Err::Incomplete(needed)) => {
2296
                panic!(
2297
                    "Shouldn't be Incomplete! Expected Ok(). Needed: {:?}",
2298
                    needed
2299
                );
2300
            }
2301
            Err(Err::Error(err)) => {
2302
                println!("Unparsed slice: {:?}", err.input);
2303
                panic!("Shouldn't be Error: {:?}, expected Ok()", err.code);
2304
            }
2305
            _ => {
2306
                panic!("Unexpected behavior, should be Ok()");
2307
            }
2308
        }
2309
    }
2310
2311
    #[test]
2312
    fn test_parse_notification_response() {
2313
        // Handcrafted notification response message, based on documentation specification
2314
        // identifier: 'A'
2315
        // length: 39
2316
        // pid: 61
2317
        // channel_name: test_channel
2318
        // payload: Test notification
2319
        let buf: &[u8] = &[
2320
            0x41, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x3d, // test_channel
2321
            0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x00,
2322
            // Test notification
2323
            0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
2324
            0x69, 0x6f, 0x6e, 0x00,
2325
        ];
2326
2327
        let ok_res = PgsqlBEMessage::NotificationResponse(NotificationResponse {
2328
            identifier: b'A',
2329
            length: 39,
2330
            pid: 61,
2331
            channel_name: br#"test_channel"#.to_vec(),
2332
            payload: br#"Test notification"#.to_vec(),
2333
        });
2334
2335
        let (_rem, result) = pgsql_parse_response(buf).unwrap();
2336
2337
        assert_eq!(ok_res, result);
2338
    }
2339
}