extensions = attr-val *("," attr-val) ;; All extensions are optional, ;; i.e., unrecognized attributes ;; not defined in this document ;; MUST be ignored. reserved-mext = "m=" 1*(value-char) ;; Reserved for signaling mandatory extensions. ;; The exact syntax will be defined in ;; the future. gs2-cbind-flag = ("p=" cb-name) / "n" / "y" ;; "n" -> client doesn't support channel binding. ;; "y" -> c
(mut buf: Cursor)
| 644 | // client-first-message = |
| 645 | // gs2-header client-first-message-bare |
| 646 | pub fn decode_sasl_client_first_message(mut buf: Cursor) -> Result<SASLInitialResponse, io::Error> { |
| 647 | // 1) GS2 cbind flag |
| 648 | let cbind_flag = match buf.read_byte()? { |
| 649 | b'n' => ChannelBinding::None, |
| 650 | b'y' => ChannelBinding::ClientSupported, |
| 651 | b'p' => { |
| 652 | // must be "p=" then cbname up to next comma |
| 653 | expect(&mut buf, b"=")?; |
| 654 | let cbname = String::from_utf8(read_until_comma(&mut buf)?) |
| 655 | .map_err(|_| input_err("invalid cbname utf8"))?; |
| 656 | ChannelBinding::Required(cbname) |
| 657 | } |
| 658 | other => { |
| 659 | return Err(input_err(format!( |
| 660 | "Invalid channel binding flag: {}", |
| 661 | other |
| 662 | ))); |
| 663 | } |
| 664 | }; |
| 665 | expect(&mut buf, b",")?; |
| 666 | |
| 667 | // 2) Optional authzid: either empty, or "a=" up to next comma |
| 668 | let mut authzid = None; |
| 669 | if buf.peek_byte()? == b'a' { |
| 670 | expect(&mut buf, b"a=")?; |
| 671 | let a = String::from_utf8(read_until_comma(&mut buf)?) |
| 672 | .map_err(|_| input_err("invalid authzid utf8"))?; |
| 673 | authzid = Some(a); |
| 674 | } |
| 675 | expect(&mut buf, b",")?; |
| 676 | |
| 677 | let mut client_first_message_bare_raw = String::new(); |
| 678 | |
| 679 | // 3) Optional reserved "m=" extension before n= |
| 680 | let mut reserved_mext = None; |
| 681 | if buf.peek_byte()? == b'm' { |
| 682 | expect(&mut buf, b"m=")?; |
| 683 | let mext_val = String::from_utf8(read_until_comma(&mut buf)?) |
| 684 | .map_err(|_| input_err("invalid m ext utf8"))?; |
| 685 | client_first_message_bare_raw.push_str(&format!("m={},", mext_val)); |
| 686 | reserved_mext = Some(mext_val); |
| 687 | expect(&mut buf, b",")?; |
| 688 | } |
| 689 | |
| 690 | // 4) Username: must be "n=" then saslname |
| 691 | expect(&mut buf, b"n=")?; |
| 692 | // Postgres doesn't use the username here, so we just consume |
| 693 | let username = String::from_utf8(read_until_comma(&mut buf)?) |
| 694 | .map_err(|_| input_err("invalid username utf8"))?; |
| 695 | expect(&mut buf, b",")?; |
| 696 | client_first_message_bare_raw.push_str(&format!("n={},", username)); |
| 697 | |
| 698 | // 5) Nonce: must be "r=" then value up to next comma or end |
| 699 | expect(&mut buf, b"r=")?; |
| 700 | let nonce = String::from_utf8(read_until_comma(&mut buf)?) |
| 701 | .map_err(|_| input_err("invalid nonce utf8"))?; |
| 702 | client_first_message_bare_raw.push_str(&format!("r={}", nonce)); |
| 703 |
no test coverage detected