diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/vendor/kerberos-parser | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'rust/vendor/kerberos-parser')
19 files changed, 1851 insertions, 0 deletions
diff --git a/rust/vendor/kerberos-parser/.cargo-checksum.json b/rust/vendor/kerberos-parser/.cargo-checksum.json new file mode 100644 index 0000000..50073e6 --- /dev/null +++ b/rust/vendor/kerberos-parser/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".travis.yml":"6707873f357a13c413711ca71d73f55ace176cfc9f508e633f4f63560c6d37b0","Cargo.toml":"780ee5ec8f7bffb4be90586fa871e1fd32f66df13ebdce2c46b4746e26b0ad50","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a5c61b93b6ee1d104af9920cf020ff3c7efe818e31fe562c72261847a728f513","README.md":"af4d42f26c82971b246d04dd99ad0398f5ce7a90af0156fb221d7a8396e8b51d","assets/ap-req.bin":"67e9c04a5fb580ca72b4da19ad554af43c127ce56ca4ce309c8afb2dc8cbe790","assets/as-rep.bin":"0a1af2b2204721e22aca58861410f56b271a48f960a4f12872e3b6f86e5ddc9c","assets/as-req.bin":"4256f675abf77424ad2c0eb17504e2602f0b702ba5ea2f0e61643755a9ef33a5","assets/krb-error.bin":"3a2cecf108a82e6048342b18954afd126a90bcc1362c528a45e4bb36ca461db6","assets/krb5-ticket.bin":"5ece64076dd0aac8fc1b4d4c93e4fb625119400584df598cbf26516dec2688c9","assets/tgs-rep-no-padata.bin":"76e8fe3b7cea6d5140433f9668cf798edce5a0b5e594f06a1638b0ae07d9793f","benches/b_krb5_parser.rs":"5669b5d8f2cb9c18a5b65c163530bb5d49a66328d2ee7f2646e9318b8848782c","src/krb5.rs":"dbbda40dbeb106b3bac5b0cee60ce0de9812a8b111af78458f50cca2c3e4038b","src/krb5_constants.rs":"981f0937dcbf4ec3b8d7b45430c1d1916a6eb582bf656cef59742ca76259fdfd","src/krb5_errors.rs":"8d88e1e123649f74a24c55950e725da18dd287fc197400161a447b928f2707ee","src/krb5_parser.rs":"647c39b34c7bda01c422c788d32b97d81a63852335471e2c7e42881920ad7778","src/lib.rs":"47ef411516eb15edf6136a4f8d158d2b3c54675abf5a8f4ce89b3854a4299611","tests/krb5_parser.rs":"667afa9083193757ffe8e8dd4e3e00642e793a650003870bdf401d42552e0863"},"package":"c10e7cfd4759cbce37ea65e2f48caebd695c246196a38e97ba4f731da48996da"}
\ No newline at end of file diff --git a/rust/vendor/kerberos-parser/.travis.yml b/rust/vendor/kerberos-parser/.travis.yml new file mode 100644 index 0000000..62bc4f2 --- /dev/null +++ b/rust/vendor/kerberos-parser/.travis.yml @@ -0,0 +1,25 @@ +language: rust +sudo: false +matrix: + include: + - rust: stable + env: + - NAME="stable" + - FEATURES='' + - rust: stable + env: + - NAME="stable,fmt" + - FEATURES='' + - RUSTFMT=yes + - rust: nightly + env: + - NAME="nightly" + - FEATURES='' +before_script: + - ([ "$RUSTFMT" != yes ] || rustup component add rustfmt) +script: + - ([ "$RUSTFMT" != yes ] || cargo fmt --all -- --check) + - | + cargo build --verbose --features "$FEATURES" && + cargo test --verbose --features "$FEATURES" && + ([ "$BENCH" != 1 ] || cargo bench --verbose --features "$FEATURES") diff --git a/rust/vendor/kerberos-parser/Cargo.toml b/rust/vendor/kerberos-parser/Cargo.toml new file mode 100644 index 0000000..023a8be --- /dev/null +++ b/rust/vendor/kerberos-parser/Cargo.toml @@ -0,0 +1,34 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "kerberos-parser" +version = "0.7.1" +authors = ["Pierre Chifflier <chifflier@wzdftpd.net>"] +include = ["LICENSE-*", "README.md", ".gitignore", ".travis.yml", "Cargo.toml", "assets/*.bin", "benches/*.rs", "src/*.rs", "tests/*.rs"] +description = "Parser for the Kerberos protocol" +homepage = "https://github.com/rusticata/kerberos-parser" +readme = "README.md" +keywords = ["Kerberos", "parser", "nom"] +categories = ["parser-implementations"] +license = "MIT/Apache-2.0" +repository = "https://github.com/rusticata/kerberos-parser.git" +[dependencies.der-parser] +version = "6.0.0" + +[dependencies.nom] +version = "7.0" + +[dependencies.rusticata-macros] +version = "4.0" +[badges.travis-ci] +repository = "rusticata/kerberos-parser" diff --git a/rust/vendor/kerberos-parser/LICENSE-APACHE b/rust/vendor/kerberos-parser/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/rust/vendor/kerberos-parser/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/rust/vendor/kerberos-parser/LICENSE-MIT b/rust/vendor/kerberos-parser/LICENSE-MIT new file mode 100644 index 0000000..290e7b9 --- /dev/null +++ b/rust/vendor/kerberos-parser/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2017 Pierre Chifflier + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/rust/vendor/kerberos-parser/README.md b/rust/vendor/kerberos-parser/README.md new file mode 100644 index 0000000..9205644 --- /dev/null +++ b/rust/vendor/kerberos-parser/README.md @@ -0,0 +1,71 @@ +# Kerberos parser + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE-MIT) +[![Apache License 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE-APACHE) +[![Build Status](https://travis-ci.org/rusticata/kerberos-parser.svg?branch=master)](https://travis-ci.org/rusticata/kerberos-parser) +[![Crates.io Version](https://img.shields.io/crates/v/kerberos-parser.svg)](https://crates.io/crates/kerberos-parser) + +<!-- cargo-sync-readme start --> + +# Kerberos Parser + +A Kerberos v5 ([RFC4120]) parser, implemented with the [nom](https://github.com/Geal/nom) +parser combinator framework. + +The code is available on [Github](https://github.com/rusticata/kerberos-parser). + +Specific parsing functions are provided for Kerberos message types. For ex. to parse a +KRB_AS_REQ message, use [`parse_as_req`](krb5_parser/fn.parse_as_req.html). + +# Examples + +Parsing a KRB_AS_REQ message: + +```rust,no_run +use kerberos_parser::krb5::MessageType; +use kerberos_parser::krb5_parser::parse_as_req; + +static AS_REQ: &'static [u8] = include_bytes!("../assets/as-req.bin"); + +let res = parse_as_req(AS_REQ); +match res { + Ok((rem, kdc_req)) => { + assert!(rem.is_empty()); + // + assert_eq!(kdc_req.msg_type, MessageType::KRB_AS_REQ); + }, + _ => panic!("KRB_AS_REQ parsing failed: {:?}", res), +} +``` + +[RFC4120]: https://tools.ietf.org/html/rfc4120 + +<!-- cargo-sync-readme end --> + +## Rusticata + +This parser is part of the [rusticata](https://github.com/rusticata) project. +The goal of this project is to provide **safe** parsers, that can be used in other projects. + +Testing of the parser is done manually, and also using unit tests and +[cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). Please fill a bugreport if you find any issue. + +Feel free to contribute: tests, feedback, doc, suggestions (or code) of new parsers etc. are welcome. + +## License + +Licensed under either of + + * Apache License, Version 2.0 + ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license + ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + diff --git a/rust/vendor/kerberos-parser/assets/ap-req.bin b/rust/vendor/kerberos-parser/assets/ap-req.bin Binary files differnew file mode 100644 index 0000000..39386ec --- /dev/null +++ b/rust/vendor/kerberos-parser/assets/ap-req.bin diff --git a/rust/vendor/kerberos-parser/assets/as-rep.bin b/rust/vendor/kerberos-parser/assets/as-rep.bin Binary files differnew file mode 100644 index 0000000..43d0560 --- /dev/null +++ b/rust/vendor/kerberos-parser/assets/as-rep.bin diff --git a/rust/vendor/kerberos-parser/assets/as-req.bin b/rust/vendor/kerberos-parser/assets/as-req.bin Binary files differnew file mode 100644 index 0000000..6d503b3 --- /dev/null +++ b/rust/vendor/kerberos-parser/assets/as-req.bin diff --git a/rust/vendor/kerberos-parser/assets/krb-error.bin b/rust/vendor/kerberos-parser/assets/krb-error.bin new file mode 100644 index 0000000..b9c7645 --- /dev/null +++ b/rust/vendor/kerberos-parser/assets/krb-error.bin @@ -0,0 +1 @@ +~–0“ ¡¤20050816094029Z¥(|¦©DENYDCª0 ¡0krbtgtDENYDC¬A?0=0;¡¢42000 ¡
DENYDC.COMdes0 ¡
DENYDC.COMdes
\ No newline at end of file diff --git a/rust/vendor/kerberos-parser/assets/krb5-ticket.bin b/rust/vendor/kerberos-parser/assets/krb5-ticket.bin Binary files differnew file mode 100644 index 0000000..8536896 --- /dev/null +++ b/rust/vendor/kerberos-parser/assets/krb5-ticket.bin diff --git a/rust/vendor/kerberos-parser/assets/tgs-rep-no-padata.bin b/rust/vendor/kerberos-parser/assets/tgs-rep-no-padata.bin Binary files differnew file mode 100644 index 0000000..25d6270 --- /dev/null +++ b/rust/vendor/kerberos-parser/assets/tgs-rep-no-padata.bin diff --git a/rust/vendor/kerberos-parser/benches/b_krb5_parser.rs b/rust/vendor/kerberos-parser/benches/b_krb5_parser.rs new file mode 100644 index 0000000..d9becf9 --- /dev/null +++ b/rust/vendor/kerberos-parser/benches/b_krb5_parser.rs @@ -0,0 +1,25 @@ +#![feature(test)] + +extern crate test; +use test::Bencher; + +extern crate kerberos_parser; +extern crate nom; + +use kerberos_parser::krb5_parser::*; + +static KRB5_TICKET: &[u8] = include_bytes!("../assets/krb5-ticket.bin"); + +#[bench] +fn bench_parse_ticket(b: &mut Bencher) { + b.iter(|| { + let res = parse_krb5_ticket(KRB5_TICKET); + match res { + Ok((rem, tkt)) => { + assert!(rem.is_empty()); + assert_eq!(tkt.tkt_vno, 5); + } + _ => assert!(false), + } + }); +} diff --git a/rust/vendor/kerberos-parser/src/krb5.rs b/rust/vendor/kerberos-parser/src/krb5.rs new file mode 100644 index 0000000..378c5d1 --- /dev/null +++ b/rust/vendor/kerberos-parser/src/krb5.rs @@ -0,0 +1,172 @@ +//! Kerberos 5 structures +//! +//! - [RFC1510](https://tools.ietf.org/html/rfc1510) The Kerberos Network Authentication Service (V5) +//! - [RFC3961](https://tools.ietf.org/html/rfc3961) Encryption and Checksum Specifications for Kerberos 5 +//! - [RFC3962](https://tools.ietf.org/html/rfc3962) Advanced Encryption Standard (AES) Encryption for Kerberos 5 +//! - [RFC4120](https://tools.ietf.org/html/rfc4120) The Kerberos Network Authentication Service (V5) +//! - [RFC6803](https://tools.ietf.org/html/rfc6803) Camellia Encryption for Kerberos 5 +//! - [RFC8009](https://tools.ietf.org/html/rfc8009) AES Encryption with HMAC-SHA2 for Kerberos 5 + +use der_parser::der::DerObject; +use std::fmt; + +pub use crate::krb5_constants::*; +pub use crate::krb5_errors::*; + +/// Kerberos Realm +/// +/// A Kerberos realm is a set of managed nodes that share the same Kerberos database. +#[derive(Debug, PartialEq)] +pub struct Realm(pub String); + +/// Kerberos PrincipalName +/// +/// A Kerberos principal is a service or user that is known to the Kerberos system. Each Kerberos +/// principal is identified by its principal name. Principal names consist of three parts: a +/// service or user name, an instance name, and a realm name in the following form: +/// +/// <pre> +/// principal-name.instance-name@realm-name +/// </pre> +#[derive(Debug, PartialEq)] +pub struct PrincipalName { + pub name_type: NameType, + pub name_string: Vec<String>, +} + +impl fmt::Display for PrincipalName { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.name_string.join("/")) + } +} + +/// Kerberos Ticket +/// +/// A record that helps a client authenticate itself to a server; it +/// contains the client's identity, a session key, a timestamp, and +/// other information, all sealed using the server's secret key. It +/// only serves to authenticate a client when presented along with a +/// fresh Authenticator. +#[derive(Debug, PartialEq)] +pub struct Ticket<'a> { + /// Version number for the ticket format (5) + pub tkt_vno: u32, + /// Realm that issued a ticket + pub realm: Realm, + /// Components of the name part of the server's identity + pub sname: PrincipalName, + /// Encrypted encoding of the EncTicketPart sequence + pub enc_part: EncryptedData<'a>, +} + +/// Kerberos EncryptedData +#[derive(Debug, PartialEq)] +pub struct EncryptedData<'a> { + /// EncryptionType + pub etype: EncryptionType, + /// Version number of the key under which data is encrypted + pub kvno: Option<u32>, + /// Ciphertext + pub cipher: &'a [u8], +} + +/// Key Distribution Center (KDC) Request Message +#[derive(Debug, PartialEq)] +pub struct KdcReq<'a> { + pub pvno: u32, + pub msg_type: MessageType, + pub padata: Vec<PAData<'a>>, + pub req_body: KdcReqBody<'a>, +} + +/// Key Distribution Center (KDC) Request Message Body +#[derive(Debug, PartialEq)] +pub struct KdcReqBody<'a> { + /// Options requested by the client + pub kdc_options: DerObject<'a>, + /// Client name (only for AS-REQ) + pub cname: Option<PrincipalName>, + /// Server's realm + pub realm: Realm, + /// Server name + pub sname: Option<PrincipalName>, + /// Desired starttime for the requested ticket + pub from: Option<DerObject<'a>>, + /// Expiration date requested by the client + pub till: DerObject<'a>, + /// Requested renew-till time + pub rtime: Option<DerObject<'a>>, + /// Random number generated by the client + pub nonce: u32, + /// Desired encryption algorithm to be used in the response + pub etype: Vec<EncryptionType>, + /// Addresses from which the requested ticket is to be valid + pub addresses: Vec<HostAddress<'a>>, + /// Encoding of the desired authorization-data encrypted under the sub-session key if present + /// in the Authenticator, or alternatively from the session key in the TGT + pub enc_authorization_data: Option<EncryptedData<'a>>, + /// Additional tickets MAY be optionally included in a request to the ticket-granting server + pub additional_tickets: Vec<Ticket<'a>>, +} + +/// Kerberos HostAddress +#[derive(Debug, PartialEq)] +pub struct HostAddress<'a> { + pub addr_type: AddressType, + pub address: &'a [u8], +} + +/// Key Distribution Center (KDC) Reply Message +#[derive(Debug, PartialEq)] +pub struct KdcRep<'a> { + pub pvno: u32, + pub msg_type: MessageType, + pub padata: Vec<PAData<'a>>, + pub crealm: Realm, + pub cname: PrincipalName, + pub ticket: Ticket<'a>, + pub enc_part: EncryptedData<'a>, +} + +/// Kerberos Error message +#[derive(Debug, PartialEq)] +pub struct KrbError<'a> { + pub pvno: u32, + pub msg_type: MessageType, + pub ctime: Option<DerObject<'a>>, + pub cusec: Option<u32>, + pub stime: DerObject<'a>, + pub susec: u32, + pub error_code: ErrorCode, + pub crealm: Option<Realm>, + pub cname: Option<PrincipalName>, + pub realm: Realm, + pub sname: PrincipalName, + pub etext: Option<String>, + pub edata: Option<DerObject<'a>>, +} + +/// Kerberos PA-Data +#[derive(Debug, PartialEq)] +pub struct PAData<'a> { + pub padata_type: PAType, + pub padata_value: &'a [u8], +} + +/// Kerberos AP Request +#[derive(Debug, PartialEq)] +pub struct ApReq<'a> { + pub pvno: u32, + pub msg_type: MessageType, + pub ap_options: DerObject<'a>, // KerberosFlags + pub ticket: Ticket<'a>, + pub authenticator: EncryptedData<'a>, +} + +/// Kerberos AP Reply +#[derive(Debug, PartialEq)] +pub struct ApRep<'a> { + pub pvno: u32, + pub msg_type: MessageType, + pub enc_part: EncryptedData<'a>, +} diff --git a/rust/vendor/kerberos-parser/src/krb5_constants.rs b/rust/vendor/kerberos-parser/src/krb5_constants.rs new file mode 100644 index 0000000..c95b438 --- /dev/null +++ b/rust/vendor/kerberos-parser/src/krb5_constants.rs @@ -0,0 +1,258 @@ +// See https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml + +use std::fmt; + +/// Address type +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct AddressType(pub i32); + +#[rustfmt::skip] +impl AddressType { + pub const IPV4 : AddressType = AddressType(2); + pub const DIRECTIONAL : AddressType = AddressType(3); + pub const CHAOSNET : AddressType = AddressType(5); + pub const XNS : AddressType = AddressType(6); + pub const ISO : AddressType = AddressType(7); + pub const DECNET_P4 : AddressType = AddressType(12); + pub const APPLETALK_DDP : AddressType = AddressType(16); + pub const NETBIOS : AddressType = AddressType(20); + pub const IPV6 : AddressType = AddressType(24); +} + +impl fmt::Debug for AddressType { + #[rustfmt::skip] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 2 => f.write_str("IPv4"), + 3 => f.write_str("Directional"), + 5 => f.write_str("ChaosNet"), + 6 => f.write_str("XNS"), + 7 => f.write_str("ISO"), + 12 => f.write_str("DECNET Phase IV"), + 16 => f.write_str("Appletalk DDP"), + 20 => f.write_str("Netbios"), + 24 => f.write_str("IPv6"), + n => f.debug_tuple("AddressType").field(&n).finish(), + } + } +} + +/// Encryption type +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct EncryptionType(pub i32); + +#[rustfmt::skip] +impl EncryptionType { + pub const DES_CBC_CRC : EncryptionType = EncryptionType(1); + pub const DES_CBC_MD4 : EncryptionType = EncryptionType(2); + pub const DES_CBC_MD5 : EncryptionType = EncryptionType(3); + pub const DES3_CBC_MD5 : EncryptionType = EncryptionType(5); + pub const DES3_CBC_SHA1 : EncryptionType = EncryptionType(7); + pub const DSAWITHSHA1_CMSOID : EncryptionType = EncryptionType(9); + pub const MD5WITHRSAENCRYPTION_CMSOID : EncryptionType = EncryptionType(10); + pub const SHA1WITHRSAENCRYPTION_CMSOID : EncryptionType = EncryptionType(11); + pub const RC2CBC_ENVOID : EncryptionType = EncryptionType(12); + pub const RSAENCRYPTION_ENVOID : EncryptionType = EncryptionType(13); + pub const RSAES_OAEP_ENV_OID : EncryptionType = EncryptionType(14); + pub const DES_EDE3_CBC_ENV_OID : EncryptionType = EncryptionType(15); + pub const DES3_CBC_SHA1_KD : EncryptionType = EncryptionType(16); + pub const AES128_CTS_HMAC_SHA1_96 : EncryptionType = EncryptionType(17); + pub const AES256_CTS_HMAC_SHA1_96 : EncryptionType = EncryptionType(18); + pub const AES128_CTS_HMAC_SHA256_128 : EncryptionType = EncryptionType(19); + pub const AES256_CTS_HMAC_SHA384_192 : EncryptionType = EncryptionType(20); + pub const RC4_HMAC : EncryptionType = EncryptionType(23); + pub const RC4_HMAC_EXP : EncryptionType = EncryptionType(24); + pub const CAMELLIA128_CTS_CMAC : EncryptionType = EncryptionType(25); + pub const CAMELLIA256_CTS_CMAC : EncryptionType = EncryptionType(26); + pub const SUBKEY_KEYMATERIAL : EncryptionType = EncryptionType(65); + // negative values + pub const RC4_MD4 : EncryptionType = EncryptionType(-128); + pub const RC4_PLAIN2 : EncryptionType = EncryptionType(-129); + pub const RC4_LM : EncryptionType = EncryptionType(-130); + pub const RC4_SHA : EncryptionType = EncryptionType(-131); + pub const DES_PLAIN : EncryptionType = EncryptionType(-132); + pub const RC4_HMAC_OLD : EncryptionType = EncryptionType(-133); + pub const RC4_PLAIN_OLD : EncryptionType = EncryptionType(-134); + pub const RC4_HMAC_OLD_EXP : EncryptionType = EncryptionType(-135); + pub const RC4_PLAIN_OLD_EXP : EncryptionType = EncryptionType(-136); + pub const RC4_PLAIN : EncryptionType = EncryptionType(-140); + pub const RC4_PLAIN_EXP : EncryptionType = EncryptionType(-141); +} + +impl fmt::Debug for EncryptionType { + #[rustfmt::skip] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => f.write_str("des-cbc-crc"), + 2 => f.write_str("des-cbc-md4"), + 3 => f.write_str("des-cbc-md5"), + 5 => f.write_str("des3-cbc-md5"), + 7 => f.write_str("des3-cbc-sha1"), + 9 => f.write_str("dsaWithSHA1-CmsOID"), + 10 => f.write_str("md5WithRSAEncryption-CmsOID"), + 11 => f.write_str("sha1WithRSAEncryption-CmsOID"), + 12 => f.write_str("rc2CBC-EnvOID"), + 13 => f.write_str("rsaEncryption-EnvOID"), + 14 => f.write_str("rsaES-OAEP-ENV-OID"), + 15 => f.write_str("des-ede3-cbc-Env-OID"), + 16 => f.write_str("des3-cbc-sha1-kd"), + 17 => f.write_str("aes128-cts-hmac-sha1-96"), + 18 => f.write_str("aes256-cts-hmac-sha1-96"), + 19 => f.write_str("aes128-cts-hmac-sha256-128"), + 20 => f.write_str("aes256-cts-hmac-sha384-192"), + 23 => f.write_str("rc4-hmac"), + 24 => f.write_str("rc4-hmac-exp"), + 25 => f.write_str("camellia128-cts-cmac"), + 26 => f.write_str("camellia256-cts-cmac"), + 65 => f.write_str("subkey-keymaterial"), + // negative values + -128 => f.write_str("rc4-md4"), + -129 => f.write_str("rc4-plain2"), + -130 => f.write_str("rc4-lm"), + -131 => f.write_str("rc4-sha"), + -132 => f.write_str("des-plain"), + -133 => f.write_str("rc4-hmac-OLD"), + -134 => f.write_str("rc4-plain-OLD"), + -135 => f.write_str("rc4-hmac-OLD-exp"), + -136 => f.write_str("rc4-plain-OLD-exp"), + -140 => f.write_str("rc4-plain"), + -141 => f.write_str("rc4-plain-exp"), + n => f.debug_tuple("EncryptionType").field(&n).finish(), + } + } +} + +/// Message type +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct MessageType(pub u32); + +#[rustfmt::skip] +impl MessageType { + /// Request for initial authentication + pub const KRB_AS_REQ : MessageType = MessageType(10); + /// Response to KRB_AS_REQ request + pub const KRB_AS_REP : MessageType = MessageType(11); + /// Request for authentication based on TGT + pub const KRB_TGS_REQ : MessageType = MessageType(12); + /// Response to KRB_TGS_REQ request + pub const KRB_TGS_REP : MessageType = MessageType(13); + /// Application request to server + pub const KRB_AP_REQ : MessageType = MessageType(14); + /// Response to KRB_AP_REQ_MUTUAL + pub const KRB_AP_REP : MessageType = MessageType(15); + /// Reserved for user-to-user krb_tgt_request + pub const KRB_RESERVED16 : MessageType = MessageType(16); + /// Reserved for user-to-user krb_tgt_reply + pub const KRB_RESERVED17 : MessageType = MessageType(17); + /// Safe (checksummed) application message + pub const KRB_SAFE : MessageType = MessageType(20); + /// Private (encrypted) application message + pub const KRB_PRIV : MessageType = MessageType(21); + /// Private (encrypted) message to forward credentials + pub const KRB_CRED : MessageType = MessageType(22); + /// Error response + pub const KRB_ERROR : MessageType = MessageType(30); +} + +impl fmt::Debug for MessageType { + #[rustfmt::skip] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 10 => f.write_str("KRB_AS_REQ"), + 11 => f.write_str("KRB_AS_REP"), + 12 => f.write_str("KRB_TGS_REQ"), + 13 => f.write_str("KRB_TGS_REP"), + 14 => f.write_str("KRB_AP_REQ"), + 15 => f.write_str("KRB_AP_REP"), + 16 => f.write_str("KRB_RESERVED16"), + 17 => f.write_str("KRB_RESERVED17"), + 20 => f.write_str("KRB_SAFE"), + 21 => f.write_str("KRB_PRIV"), + 22 => f.write_str("KRB_CRED"), + 30 => f.write_str("KRB_ERROR"), + n => f.debug_tuple("MessageType").field(&n).finish(), + } + } +} + +/// Name type +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct NameType(pub i32); + +#[rustfmt::skip] +impl NameType { + /// Name type not known + pub const KRB_NT_UNKNOWN : NameType = NameType(0); + /// Just the name of the principal as in DCE, or for users + pub const KRB_NT_PRINCIPAL : NameType = NameType(1); + /// Service and other unique instance (krbtgt) + pub const KRB_NT_SRV_INST : NameType = NameType(2); + /// Service with host name as instance (telnet, rcommands) + pub const KRB_NT_SRV_HST : NameType = NameType(3); + /// Service with host as remaining components + pub const KRB_NT_SRV_XHST : NameType = NameType(4); + /// Unique ID + pub const KRB_NT_UID : NameType = NameType(5); + /// Encoded X.509 Distinguished name [RFC2253] + pub const KRB_NT_X500_PRINCIPAL : NameType = NameType(6); + /// Name in form of SMTP email name (e.g., user@example.com) + pub const KRB_NT_SMTP_NAME : NameType = NameType(7); + /// Enterprise name; may be mapped to principal name + pub const KRB_NT_ENTERPRISE : NameType = NameType(10); +} + +impl fmt::Debug for NameType { + #[rustfmt::skip] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => f.write_str("KRB_NT_UNKNOWN"), + 1 => f.write_str("KRB_NT_PRINCIPAL"), + 2 => f.write_str("KRB_NT_SRV_INST"), + 3 => f.write_str("KRB_NT_SRV_HST"), + 4 => f.write_str("KRB_NT_SRV_XHST"), + 5 => f.write_str("KRB_NT_UID"), + 6 => f.write_str("KRB_NT_X500_PRINCIPAL"), + 7 => f.write_str("KRB_NT_SMTP_NAME"), + 10 => f.write_str("KRB_NT_ENTERPRISE"), + n => f.debug_tuple("NameType").field(&n).finish(), + } + } +} + +/// PA-Data type +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct PAType(pub i32); + +#[rustfmt::skip] +impl PAType { + /// DER encoding of AP-REQ + pub const PA_TGS_REQ : PAType = PAType(1); + /// DER encoding of PA-ENC-TIMESTAMP + pub const PA_ENC_TS : PAType = PAType(2); + /// salt (not ASN.1 encoded) + pub const PA_PW_SALT : PAType = PAType(3); + /// DER encoding of ETYPE-INFO + pub const PA_ETYPE_INFO : PAType = PAType(11); + /// DER encoding of ETYPE-INFO2 + pub const PA_ETYPE_INFO2 : PAType = PAType(19); + /// Windows PAC request + pub const PA_PAC_REQUEST : PAType = PAType(128); + /// Support for FAST pre-auth mechanism + pub const PA_REQ_ENC_PA_REP : PAType = PAType(149); +} + +impl fmt::Debug for PAType { + #[rustfmt::skip] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => f.write_str("pa-tgs-req"), + 2 => f.write_str("pa-enc-timestamp"), + 3 => f.write_str("pa-pw-salt"), + 11 => f.write_str("pa-etype-info"), + 19 => f.write_str("pa-etype-info2"), + 128 => f.write_str("pa-pac-request"), + 149 => f.write_str("pa-req-enc-pa-rep"), + n => f.debug_tuple("PAType").field(&n).finish(), + } + } +} diff --git a/rust/vendor/kerberos-parser/src/krb5_errors.rs b/rust/vendor/kerberos-parser/src/krb5_errors.rs new file mode 100644 index 0000000..989986d --- /dev/null +++ b/rust/vendor/kerberos-parser/src/krb5_errors.rs @@ -0,0 +1,153 @@ +use std::fmt; + +#[derive(Clone, Copy, Eq, PartialEq)] +pub struct ErrorCode(pub i32); + +#[rustfmt::skip] +impl ErrorCode { + pub const KDC_ERR_NONE : ErrorCode = ErrorCode(0); + pub const KDC_ERR_NAME_EXP : ErrorCode = ErrorCode(1); + pub const KDC_ERR_SERVICE_EXP : ErrorCode = ErrorCode(2); + pub const KDC_ERR_BAD_PVNO : ErrorCode = ErrorCode(3); + pub const KDC_ERR_C_OLD_MAST_KVNO : ErrorCode = ErrorCode(4); + pub const KDC_ERR_S_OLD_MAST_KVNO : ErrorCode = ErrorCode(5); + pub const KDC_ERR_C_PRINCIPAL_UNKNOWN : ErrorCode = ErrorCode(6); + pub const KDC_ERR_S_PRINCIPAL_UNKNOWN : ErrorCode = ErrorCode(7); + pub const KDC_ERR_PRINCIPAL_NOT_UNIQUE : ErrorCode = ErrorCode(8); + pub const KDC_ERR_NULL_KEY : ErrorCode = ErrorCode(9); + pub const KDC_ERR_CANNOT_POSTDATE : ErrorCode = ErrorCode(10); + pub const KDC_ERR_NEVER_VALID : ErrorCode = ErrorCode(11); + pub const KDC_ERR_POLICY : ErrorCode = ErrorCode(12); + pub const KDC_ERR_BADOPTION : ErrorCode = ErrorCode(13); + pub const KDC_ERR_ETYPE_NOSUPP : ErrorCode = ErrorCode(14); + pub const KDC_ERR_SUMTYPE_NOSUPP : ErrorCode = ErrorCode(15); + pub const KDC_ERR_PADATA_TYPE_NOSUPP : ErrorCode = ErrorCode(16); + pub const KDC_ERR_TRTYPE_NOSUPP : ErrorCode = ErrorCode(17); + pub const KDC_ERR_CLIENT_REVOKED : ErrorCode = ErrorCode(18); + pub const KDC_ERR_SERVICE_REVOKED : ErrorCode = ErrorCode(19); + pub const KDC_ERR_TGT_REVOKED : ErrorCode = ErrorCode(20); + pub const KDC_ERR_CLIENT_NOTYET : ErrorCode = ErrorCode(21); + pub const KDC_ERR_SERVICE_NOTYET : ErrorCode = ErrorCode(22); + pub const KDC_ERR_KEY_EXPIRED : ErrorCode = ErrorCode(23); + pub const KDC_ERR_PREAUTH_FAILED : ErrorCode = ErrorCode(24); + pub const KDC_ERR_PREAUTH_REQUIRED : ErrorCode = ErrorCode(25); + pub const KDC_ERR_SERVER_NOMATCH : ErrorCode = ErrorCode(26); + pub const KDC_ERR_MUST_USE_USER2USER : ErrorCode = ErrorCode(27); + pub const KDC_ERR_PATH_NOT_ACCEPTED : ErrorCode = ErrorCode(28); + pub const KDC_ERR_SVC_UNAVAILABLE : ErrorCode = ErrorCode(29); + pub const KRB_AP_ERR_BAD_INTEGRITY : ErrorCode = ErrorCode(31); + pub const KRB_AP_ERR_TKT_EXPIRED : ErrorCode = ErrorCode(32); + pub const KRB_AP_ERR_TKT_NYV : ErrorCode = ErrorCode(33); + pub const KRB_AP_ERR_REPEAT : ErrorCode = ErrorCode(34); + pub const KRB_AP_ERR_NOT_US : ErrorCode = ErrorCode(35); + pub const KRB_AP_ERR_BADMATCH : ErrorCode = ErrorCode(36); + pub const KRB_AP_ERR_SKEW : ErrorCode = ErrorCode(37); + pub const KRB_AP_ERR_BADADDR : ErrorCode = ErrorCode(38); + pub const KRB_AP_ERR_BADVERSION : ErrorCode = ErrorCode(39); + pub const KRB_AP_ERR_MSG_TYPE : ErrorCode = ErrorCode(40); + pub const KRB_AP_ERR_MODIFIED : ErrorCode = ErrorCode(41); + pub const KRB_AP_ERR_BADORDER : ErrorCode = ErrorCode(42); + pub const KRB_AP_ERR_BADKEYVER : ErrorCode = ErrorCode(44); + pub const KRB_AP_ERR_NOKEY : ErrorCode = ErrorCode(45); + pub const KRB_AP_ERR_MUT_FAIL : ErrorCode = ErrorCode(46); + pub const KRB_AP_ERR_BADDIRECTION : ErrorCode = ErrorCode(47); + pub const KRB_AP_ERR_METHOD : ErrorCode = ErrorCode(48); + pub const KRB_AP_ERR_BADSEQ : ErrorCode = ErrorCode(49); + pub const KRB_AP_ERR_INAPP_CKSUM : ErrorCode = ErrorCode(50); + pub const KRB_AP_PATH_NOT_ACCEPTED : ErrorCode = ErrorCode(51); + pub const KRB_ERR_RESPONSE_TOO_BIG : ErrorCode = ErrorCode(52); + pub const KRB_ERR_GENERIC : ErrorCode = ErrorCode(60); + pub const KRB_ERR_FIELD_TOOLONG : ErrorCode = ErrorCode(61); + pub const KDC_ERROR_CLIENT_NOT_TRUSTED : ErrorCode = ErrorCode(62); + pub const KDC_ERROR_KDC_NOT_TRUSTED : ErrorCode = ErrorCode(63); + pub const KDC_ERROR_INVALID_SIG : ErrorCode = ErrorCode(64); + pub const KDC_ERR_KEY_TOO_WEAK : ErrorCode = ErrorCode(65); + pub const KDC_ERR_CERTIFICATE_MISMATCH : ErrorCode = ErrorCode(66); + pub const KRB_AP_ERR_NO_TGT : ErrorCode = ErrorCode(67); + pub const KDC_ERR_WRONG_REALM : ErrorCode = ErrorCode(68); + pub const KRB_AP_ERR_USER_TO_USER_REQUIRED : ErrorCode = ErrorCode(69); + pub const KDC_ERR_CANT_VERIFY_CERTIFICATE : ErrorCode = ErrorCode(70); + pub const KDC_ERR_INVALID_CERTIFICATE : ErrorCode = ErrorCode(71); + pub const KDC_ERR_REVOKED_CERTIFICATE : ErrorCode = ErrorCode(72); + pub const KDC_ERR_REVOCATION_STATUS_UNKNOWN : ErrorCode = ErrorCode(73); + pub const KDC_ERR_REVOCATION_STATUS_UNAVAILABLE : ErrorCode = ErrorCode(74); + pub const KDC_ERR_CLIENT_NAME_MISMATCH : ErrorCode = ErrorCode(75); + pub const KDC_ERR_KDC_NAME_MISMATCH : ErrorCode = ErrorCode(76); +} + +impl fmt::Debug for ErrorCode { + #[rustfmt::skip] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => f.write_str("KDC_ERR_NONE"), + 1 => f.write_str("KDC_ERR_NAME_EXP"), + 2 => f.write_str("KDC_ERR_SERVICE_EXP"), + 3 => f.write_str("KDC_ERR_BAD_PVNO"), + 4 => f.write_str("KDC_ERR_C_OLD_MAST_KVNO"), + 5 => f.write_str("KDC_ERR_S_OLD_MAST_KVNO"), + 6 => f.write_str("KDC_ERR_C_PRINCIPAL_UNKNOWN"), + 7 => f.write_str("KDC_ERR_S_PRINCIPAL_UNKNOWN"), + 8 => f.write_str("KDC_ERR_PRINCIPAL_NOT_UNIQUE"), + 9 => f.write_str("KDC_ERR_NULL_KEY"), + 10 => f.write_str("KDC_ERR_CANNOT_POSTDATE"), + 11 => f.write_str("KDC_ERR_NEVER_VALID"), + 12 => f.write_str("KDC_ERR_POLICY"), + 13 => f.write_str("KDC_ERR_BADOPTION"), + 14 => f.write_str("KDC_ERR_ETYPE_NOSUPP"), + 15 => f.write_str("KDC_ERR_SUMTYPE_NOSUPP"), + 16 => f.write_str("KDC_ERR_PADATA_TYPE_NOSUPP"), + 17 => f.write_str("KDC_ERR_TRTYPE_NOSUPP"), + 18 => f.write_str("KDC_ERR_CLIENT_REVOKED"), + 19 => f.write_str("KDC_ERR_SERVICE_REVOKED"), + 20 => f.write_str("KDC_ERR_TGT_REVOKED"), + 21 => f.write_str("KDC_ERR_CLIENT_NOTYET"), + 22 => f.write_str("KDC_ERR_SERVICE_NOTYET"), + 23 => f.write_str("KDC_ERR_KEY_EXPIRED"), + 24 => f.write_str("KDC_ERR_PREAUTH_FAILED"), + 25 => f.write_str("KDC_ERR_PREAUTH_REQUIRED"), + 26 => f.write_str("KDC_ERR_SERVER_NOMATCH"), + 27 => f.write_str("KDC_ERR_MUST_USE_USER2USER"), + 28 => f.write_str("KDC_ERR_PATH_NOT_ACCEPTED"), + 29 => f.write_str("KDC_ERR_SVC_UNAVAILABLE"), + 31 => f.write_str("KRB_AP_ERR_BAD_INTEGRITY"), + 32 => f.write_str("KRB_AP_ERR_TKT_EXPIRED"), + 33 => f.write_str("KRB_AP_ERR_TKT_NYV"), + 34 => f.write_str("KRB_AP_ERR_REPEAT"), + 35 => f.write_str("KRB_AP_ERR_NOT_US"), + 36 => f.write_str("KRB_AP_ERR_BADMATCH"), + 37 => f.write_str("KRB_AP_ERR_SKEW"), + 38 => f.write_str("KRB_AP_ERR_BADADDR"), + 39 => f.write_str("KRB_AP_ERR_BADVERSION"), + 40 => f.write_str("KRB_AP_ERR_MSG_TYPE"), + 41 => f.write_str("KRB_AP_ERR_MODIFIED"), + 42 => f.write_str("KRB_AP_ERR_BADORDER"), + 44 => f.write_str("KRB_AP_ERR_BADKEYVER"), + 45 => f.write_str("KRB_AP_ERR_NOKEY"), + 46 => f.write_str("KRB_AP_ERR_MUT_FAIL"), + 47 => f.write_str("KRB_AP_ERR_BADDIRECTION"), + 48 => f.write_str("KRB_AP_ERR_METHOD"), + 49 => f.write_str("KRB_AP_ERR_BADSEQ"), + 50 => f.write_str("KRB_AP_ERR_INAPP_CKSUM"), + 51 => f.write_str("KRB_AP_PATH_NOT_ACCEPTED"), + 52 => f.write_str("KRB_ERR_RESPONSE_TOO_BIG"), + 60 => f.write_str("KRB_ERR_GENERIC"), + 61 => f.write_str("KRB_ERR_FIELD_TOOLONG"), + 62 => f.write_str("KDC_ERROR_CLIENT_NOT_TRUSTED"), + 63 => f.write_str("KDC_ERROR_KDC_NOT_TRUSTED"), + 64 => f.write_str("KDC_ERROR_INVALID_SIG"), + 65 => f.write_str("KDC_ERR_KEY_TOO_WEAK"), + 66 => f.write_str("KDC_ERR_CERTIFICATE_MISMATCH"), + 67 => f.write_str("KRB_AP_ERR_NO_TGT"), + 68 => f.write_str("KDC_ERR_WRONG_REALM"), + 69 => f.write_str("KRB_AP_ERR_USER_TO_USER_REQUIRED"), + 70 => f.write_str("KDC_ERR_CANT_VERIFY_CERTIFICATE"), + 71 => f.write_str("KDC_ERR_INVALID_CERTIFICATE"), + 72 => f.write_str("KDC_ERR_REVOKED_CERTIFICATE"), + 73 => f.write_str("KDC_ERR_REVOCATION_STATUS_UNKNOWN"), + 74 => f.write_str("KDC_ERR_REVOCATION_STATUS_UNAVAILABLE"), + 75 => f.write_str("KDC_ERR_CLIENT_NAME_MISMATCH"), + 76 => f.write_str("KDC_ERR_KDC_NAME_MISMATCH"), + n => f.debug_tuple("ErrorCode").field(&n).finish(), + } + } +} diff --git a/rust/vendor/kerberos-parser/src/krb5_parser.rs b/rust/vendor/kerberos-parser/src/krb5_parser.rs new file mode 100644 index 0000000..3244ba6 --- /dev/null +++ b/rust/vendor/kerberos-parser/src/krb5_parser.rs @@ -0,0 +1,587 @@ +//! Kerberos 5 parsing functions + +use der_parser::ber::*; +use der_parser::der::*; +use der_parser::error::*; +use nom::combinator::{complete, map, map_res, opt, verify}; +use nom::error::{make_error, ErrorKind}; +use nom::multi::many1; +use nom::{Err, IResult}; +use std::str; + +use crate::krb5::*; + +/// Parse a signed 32 bits integer +/// +/// <pre> +/// Int32 ::= INTEGER (-2147483648..2147483647) +/// -- signed values representable in 32 bits +/// </pre> +pub fn parse_der_int32(i: &[u8]) -> IResult<&[u8], i32, BerError> { + map_res(parse_der_integer, |x: DerObject| match x.content { + BerObjectContent::Integer(i) => match i.len() { + 1 => Ok(i[0] as i8 as i32), + 2 => Ok((i[0] as i8 as i32) << 8 | (i[1] as i32)), + 3 => Ok((i[0] as i8 as i32) << 16 | (i[1] as i32) << 8 | (i[2] as i32)), + 4 => Ok((i[0] as i8 as i32) << 24 + | (i[1] as i32) << 16 + | (i[2] as i32) << 8 + | (i[3] as i32)), + _ => Err(BerError::IntegerTooLarge), + }, + _ => Err(BerError::BerTypeError), + })(i) +} + +// Microseconds ::= INTEGER (0..999999) +// -- microseconds +fn parse_der_microseconds(i: &[u8]) -> IResult<&[u8], u32, BerError> { + verify(parse_der_u32, |x: &u32| *x <= 999_999)(i) +} + +/// Parse a Kerberos string object +/// +/// <pre> +/// KerberosString ::= GeneralString (IA5String) +/// </pre> +pub fn parse_kerberos_string(i: &[u8]) -> IResult<&[u8], String, BerError> { + match parse_der_generalstring(i) { + Ok((rem, ref obj)) => { + if let BerObjectContent::GeneralString(s) = obj.content { + match str::from_utf8(s) { + Ok(r) => Ok((rem, r.to_owned())), + Err(_) => Err(Err::Error(make_error(i, ErrorKind::IsNot))), + } + } else { + Err(Err::Error(make_error(i, ErrorKind::Tag))) + } + } + Err(e) => Err(e), + } +} + +fn parse_kerberos_string_sequence(i: &[u8]) -> IResult<&[u8], Vec<String>, BerError> { + parse_ber_sequence_of_v(parse_kerberos_string)(i) +} + +/// Parse Kerberos flags +/// +/// <pre> +/// KerberosFlags ::= BIT STRING (SIZE (32..MAX)) +/// -- minimum number of bits shall be sent, +/// -- but no fewer than 32 +/// </pre> +#[inline] +pub fn parse_kerberos_flags(i: &[u8]) -> IResult<&[u8], DerObject, BerError> { + parse_der_bitstring(i) +} + +/// Parse of a Kerberos Realm +/// +/// <pre> +/// Realm ::= KerberosString +/// </pre> +#[inline] +pub fn parse_krb5_realm(i: &[u8]) -> IResult<&[u8], Realm, BerError> { + map(parse_kerberos_string, Realm)(i) +} + +/// Parse Kerberos PrincipalName +/// +/// <pre> +/// PrincipalName ::= SEQUENCE { +/// name-type [0] Int32, +/// name-string [1] SEQUENCE OF KerberosString +/// } +/// </pre> +pub fn parse_krb5_principalname(i: &[u8]) -> IResult<&[u8], PrincipalName, BerError> { + parse_ber_sequence_defined_g(|i, _| { + let (i, name_type) = + parse_ber_tagged_explicit_g(0, |a, _| map(parse_der_int32, NameType)(a))(i)?; + let (i, name_string) = + parse_ber_tagged_explicit_g(1, |a, _| parse_kerberos_string_sequence(a))(i)?; + Ok(( + i, + PrincipalName { + name_type, + name_string, + }, + )) + })(i) +} + +/// Parse of a Kerberos Time +/// +/// <pre> +/// KerberosTime ::= GeneralizedTime -- with no fractional seconds +/// </pre> +#[inline] +pub fn parse_kerberos_time(i: &[u8]) -> IResult<&[u8], DerObject, BerError> { + parse_der_generalizedtime(i) +} + +/// Parse Kerberos HostAddress +/// +/// <pre> +/// HostAddress ::= SEQUENCE { +/// addr-type [0] Int32, +/// address [1] OCTET STRING +/// } +/// </pre> +pub fn parse_krb5_hostaddress(i: &[u8]) -> IResult<&[u8], HostAddress, BerError> { + parse_ber_sequence_defined_g(|i, _| { + let (i, addr_type) = + parse_ber_tagged_explicit_g(0, |a, _| map(parse_der_int32, AddressType)(a))(i)?; + let (i, address) = parse_ber_tagged_explicit_g(1, |a, _| { + map_res(parse_ber_octetstring, |o| o.as_slice())(a) + })(i)?; + Ok((i, HostAddress { addr_type, address })) + })(i) +} + +/// Parse Kerberos HostAddresses +/// +/// <pre> +/// -- NOTE: HostAddresses is always used as an OPTIONAL field and +/// -- should not be empty. +/// HostAddresses -- NOTE: subtly different from rfc1510, +/// -- but has a value mapping and encodes the same +/// ::= SEQUENCE OF HostAddress +/// </pre> +pub fn parse_krb5_hostaddresses(i: &[u8]) -> IResult<&[u8], Vec<HostAddress>, BerError> { + parse_ber_sequence_of_v(parse_krb5_hostaddress)(i) +} + +/// Parse Kerberos Ticket +/// +/// <pre> +/// Ticket ::= [APPLICATION 1] SEQUENCE { +/// tkt-vno [0] INTEGER (5), +/// realm [1] Realm, +/// sname [2] PrincipalName, +/// enc-part [3] EncryptedData -- EncTicketPart +/// } +/// </pre> +pub fn parse_krb5_ticket(i: &[u8]) -> IResult<&[u8], Ticket, BerError> { + parse_ber_tagged_explicit_g(BerTag(1), |i, hdr| { + if !hdr.is_application() { + return Err(Err::Error(BerError::InvalidTag)); + } + parse_ber_sequence_defined_g(|i, _| { + let (i, tkt_vno) = parse_ber_tagged_explicit_g(0, |a, _| parse_der_u32(a))(i)?; + if tkt_vno != 5 { + return Err(Err::Error(BerError::Custom(5))); + } + let (i, realm) = parse_ber_tagged_explicit_g(1, |a, _| parse_krb5_realm(a))(i)?; + let (i, sname) = parse_ber_tagged_explicit_g(2, |a, _| parse_krb5_principalname(a))(i)?; + let (i, enc_part) = parse_ber_tagged_explicit_g(3, |a, _| parse_encrypted(a))(i)?; + let tkt = Ticket { + tkt_vno, + realm, + sname, + enc_part, + }; + Ok((i, tkt)) + })(i) + })(i) +} + +/// Parse Kerberos EncryptedData +/// +/// <pre> +/// EncryptedData ::= SEQUENCE { +/// etype [0] Int32 -- EncryptionType --, +/// kvno [1] UInt32 OPTIONAL, +/// cipher [2] OCTET STRING -- ciphertext +/// } +/// </pre> +pub fn parse_encrypted(i: &[u8]) -> IResult<&[u8], EncryptedData, BerError> { + parse_ber_sequence_defined_g(|i, _| { + let (i, etype) = + parse_ber_tagged_explicit_g(0, |a, _| map(parse_der_int32, EncryptionType)(a))(i)?; + let (i, kvno) = opt(complete(parse_ber_tagged_explicit_g(1, |a, _| { + parse_der_u32(a) + })))(i)?; + let (i, cipher) = + parse_ber_tagged_explicit_g(2, |a, _| map_res(parse_der, |o| o.as_slice())(a))(i)?; + let enc = EncryptedData { + etype, + kvno, + cipher, + }; + Ok((i, enc)) + })(i) +} + +/// Parse a Kerberos KDC Request +/// +/// <pre> +/// KDC-REQ ::= SEQUENCE { +/// -- NOTE: first tag is [1], not [0] +/// pvno [1] INTEGER (5) , +/// msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), +/// padata [3] SEQUENCE OF PA-DATA OPTIONAL +/// -- NOTE: not empty --, +/// req-body [4] KDC-REQ-BODY +/// } +/// </pre> +pub fn parse_kdc_req(i: &[u8]) -> IResult<&[u8], KdcReq, BerError> { + parse_ber_sequence_defined_g(|i, _| { + let (i, pvno) = parse_ber_tagged_explicit_g(1, |a, _| parse_der_u32(a))(i)?; + let (i, msg_type) = + parse_ber_tagged_explicit_g(2, |a, _| map(parse_der_u32, MessageType)(a))(i)?; + let (i, padata) = parse_ber_tagged_explicit_g(3, |a, _| parse_krb5_padata_sequence(a))(i) + .unwrap_or_else(|_| (i, Vec::new())); + let (i, req_body) = parse_ber_tagged_explicit_g(4, |a, _| parse_kdc_req_body(a))(i)?; + let req = KdcReq { + pvno, + msg_type, + padata, + req_body, + }; + Ok((i, req)) + })(i) +} + +/// Parse the body of a Kerberos KDC Request +/// +/// <pre> +/// KDC-REQ-BODY ::= SEQUENCE { +/// kdc-options [0] KDCOptions, +/// cname [1] PrincipalName OPTIONAL +/// -- Used only in AS-REQ --, +/// realm [2] Realm +/// -- Server's realm +/// -- Also client's in AS-REQ --, +/// sname [3] PrincipalName OPTIONAL, +/// from [4] KerberosTime OPTIONAL, +/// till [5] KerberosTime, +/// rtime [6] KerberosTime OPTIONAL, +/// nonce [7] UInt32, +/// etype [8] SEQUENCE OF Int32 -- EncryptionType +/// -- in preference order --, +/// addresses [9] HostAddresses OPTIONAL, +/// enc-authorization-data [10] EncryptedData OPTIONAL +/// -- AuthorizationData --, +/// additional-tickets [11] SEQUENCE OF Ticket OPTIONAL +/// -- NOTE: not empty +/// } +/// </pre> +pub fn parse_kdc_req_body(i: &[u8]) -> IResult<&[u8], KdcReqBody, BerError> { + parse_ber_sequence_defined_g(|i, _| { + let (i, kdc_options) = parse_ber_tagged_explicit_g(0, |a, _| parse_kerberos_flags(a))(i)?; + let (i, cname) = opt(complete(parse_ber_tagged_explicit_g(1, |a, _| { + parse_krb5_principalname(a) + })))(i)?; + let (i, realm) = parse_ber_tagged_explicit_g(2, |a, _| parse_krb5_realm(a))(i)?; + let (i, sname) = opt(complete(parse_ber_tagged_explicit_g(3, |a, _| { + parse_krb5_principalname(a) + })))(i)?; + let (i, from) = opt(complete(parse_ber_tagged_explicit_g(4, |a, _| { + parse_kerberos_time(a) + })))(i)?; + let (i, till) = parse_ber_tagged_explicit_g(5, |a, _| parse_kerberos_time(a))(i)?; + let (i, rtime) = opt(complete(parse_ber_tagged_explicit_g(6, |a, _| { + parse_kerberos_time(a) + })))(i)?; + let (i, nonce) = parse_ber_tagged_explicit_g(7, |a, _| parse_der_u32(a))(i)?; + let (i, etype) = parse_ber_tagged_explicit_g(8, |a, _| { + map(parse_ber_sequence_of_v(parse_der_int32), |v| { + v.iter().map(|&x| EncryptionType(x)).collect() + })(a) + })(i)?; + let (i, addresses) = opt(complete(parse_ber_tagged_explicit_g(9, |a, _| { + parse_krb5_hostaddresses(a) + })))(i)?; + let addresses = addresses.unwrap_or_default(); + let (i, enc_authorization_data) = + opt(complete(parse_ber_tagged_explicit_g(10, |a, _| { + parse_encrypted(a) + })))(i)?; + let (i, additional_tickets) = opt(complete(parse_ber_tagged_explicit_g(11, |a, _| { + many1(complete(parse_krb5_ticket))(a) + })))(i)?; + let additional_tickets = additional_tickets.unwrap_or_default(); + let body = KdcReqBody { + kdc_options, + cname, + realm, + sname, + from, + till, + rtime, + nonce, + etype, + addresses, + enc_authorization_data, + additional_tickets, + }; + Ok((i, body)) + })(i) +} + +/// Parse a Kerberos AS Request +/// +/// <pre> +/// AS-REQ ::= [APPLICATION 10] KDC-REQ +/// </pre> +pub fn parse_as_req(i: &[u8]) -> IResult<&[u8], KdcReq, BerError> { + parse_ber_tagged_explicit_g(BerTag(10), |i, hdr| { + if !hdr.is_application() { + return Err(Err::Error(BerError::InvalidTag)); + } + parse_kdc_req(i) + })(i) +} + +/// Parse a Kerberos TGS Request +/// +/// <pre> +/// TGS-REQ ::= [APPLICATION 12] KDC-REQ +/// </pre> +pub fn parse_tgs_req(i: &[u8]) -> IResult<&[u8], KdcReq, BerError> { + parse_ber_tagged_explicit_g(BerTag(12), |i, hdr| { + if !hdr.is_application() { + return Err(Err::Error(BerError::InvalidTag)); + } + parse_kdc_req(i) + })(i) +} + +/// Parse a Kerberos KDC Reply +/// +/// <pre> +/// KDC-REP ::= SEQUENCE { +/// pvno [0] INTEGER (5), +/// msg-type [1] INTEGER (11 -- AS -- | 13 -- TGS --), +/// padata [2] SEQUENCE OF PA-DATA OPTIONAL +/// -- NOTE: not empty --, +/// crealm [3] Realm, +/// cname [4] PrincipalName, +/// ticket [5] Ticket, +/// enc-part [6] EncryptedData +/// -- EncASRepPart or EncTGSRepPart, +/// -- as appropriate +/// } +/// </pre> +pub fn parse_kdc_rep(i: &[u8]) -> IResult<&[u8], KdcRep, BerError> { + parse_ber_sequence_defined_g(|i, _| { + let (i, pvno) = parse_ber_tagged_explicit_g(0, |a, _| parse_der_u32(a))(i)?; + let (i, msg_type) = + parse_ber_tagged_explicit_g(1, |a, _| map(parse_der_u32, MessageType)(a))(i)?; + let (i, padata) = parse_ber_tagged_explicit_g(2, |a, _| parse_krb5_padata_sequence(a))(i) + .unwrap_or_else(|_| (i, Vec::new())); + let (i, crealm) = parse_ber_tagged_explicit_g(3, |a, _| parse_krb5_realm(a))(i)?; + let (i, cname) = parse_ber_tagged_explicit_g(4, |a, _| parse_krb5_principalname(a))(i)?; + let (i, ticket) = parse_ber_tagged_explicit_g(5, |a, _| parse_krb5_ticket(a))(i)?; + let (i, enc_part) = parse_ber_tagged_explicit_g(6, |a, _| parse_encrypted(a))(i)?; + let rep = KdcRep { + pvno, + msg_type, + padata, + crealm, + cname, + ticket, + enc_part, + }; + Ok((i, rep)) + })(i) +} + +/// Parse a Kerberos AS Reply +/// +/// <pre> +/// AS-REP ::= [APPLICATION 11] KDC-REP +/// </pre> +pub fn parse_as_rep(i: &[u8]) -> IResult<&[u8], KdcRep, BerError> { + parse_ber_tagged_explicit_g(BerTag(11), |i, hdr| { + if !hdr.is_application() { + return Err(Err::Error(BerError::InvalidTag)); + } + parse_kdc_rep(i) + })(i) +} + +/// Parse a Kerberos TGS Reply +/// +/// <pre> +/// TGS-REP ::= [APPLICATION 13] KDC-REP +/// </pre> +pub fn parse_tgs_rep(i: &[u8]) -> IResult<&[u8], KdcRep, BerError> { + parse_ber_tagged_explicit_g(BerTag(13), |i, hdr| { + if !hdr.is_application() { + return Err(Err::Error(BerError::InvalidTag)); + } + parse_kdc_rep(i) + })(i) +} + +/// Parse a Kerberos Error +/// +/// <pre> +/// KRB-ERROR ::= [APPLICATION 30] SEQUENCE { +/// pvno [0] INTEGER (5), +/// msg-type [1] INTEGER (30), +/// ctime [2] KerberosTime OPTIONAL, +/// cusec [3] Microseconds OPTIONAL, +/// stime [4] KerberosTime, +/// susec [5] Microseconds, +/// error-code [6] Int32, +/// crealm [7] Realm OPTIONAL, +/// cname [8] PrincipalName OPTIONAL, +/// realm [9] Realm -- service realm --, +/// sname [10] PrincipalName -- service name --, +/// e-text [11] KerberosString OPTIONAL, +/// e-data [12] OCTET STRING OPTIONAL +/// } +/// </pre> +pub fn parse_krb_error(i: &[u8]) -> IResult<&[u8], KrbError, BerError> { + parse_ber_tagged_explicit_g(BerTag(30), |i, hdr| { + if !hdr.is_application() { + return Err(Err::Error(BerError::InvalidTag)); + } + parse_ber_sequence_defined_g(|i, _| { + let (i, pvno) = parse_ber_tagged_explicit_g(0, |a, _| parse_der_u32(a))(i)?; + let (i, msg_type) = + parse_ber_tagged_explicit_g(1, |a, _| map(parse_der_u32, MessageType)(a))(i)?; + let (i, ctime) = opt(complete(parse_ber_tagged_explicit_g(2, |a, _| { + parse_kerberos_time(a) + })))(i)?; + let (i, cusec) = opt(complete(parse_ber_tagged_explicit_g(3, |a, _| { + parse_der_microseconds(a) + })))(i)?; + let (i, stime) = parse_ber_tagged_explicit_g(4, |a, _| parse_kerberos_time(a))(i)?; + let (i, susec) = parse_ber_tagged_explicit_g(5, |a, _| parse_der_microseconds(a))(i)?; + let (i, error_code) = + parse_ber_tagged_explicit_g(6, |a, _| map(parse_der_int32, ErrorCode)(a))(i)?; + let (i, crealm) = opt(complete(parse_ber_tagged_explicit_g(7, |a, _| { + parse_krb5_realm(a) + })))(i)?; + let (i, cname) = opt(complete(parse_ber_tagged_explicit_g(8, |a, _| { + parse_krb5_principalname(a) + })))(i)?; + let (i, realm) = parse_ber_tagged_explicit_g(9, |a, _| parse_krb5_realm(a))(i)?; + let (i, sname) = + parse_ber_tagged_explicit_g(10, |a, _| parse_krb5_principalname(a))(i)?; + let (i, etext) = opt(complete(parse_ber_tagged_explicit_g(11, |a, _| { + parse_kerberos_string(a) + })))(i)?; + let (i, edata) = opt(complete(parse_ber_tagged_explicit_g(12, |a, _| { + parse_der_octetstring(a) + })))(i)?; + let err = KrbError { + pvno, + msg_type, + ctime, + cusec, + stime, + susec, + error_code, + crealm, + cname, + realm, + sname, + etext, + edata, + }; + Ok((i, err)) + })(i) + })(i) +} + +/// Parse Kerberos PA-Data +/// +/// <pre> +/// PA-DATA ::= SEQUENCE { +/// -- NOTE: first tag is [1], not [0] +/// padata-type [1] Int32, +/// padata-value [2] OCTET STRING -- might be encoded AP-REQ +/// } +/// </pre> +pub fn parse_krb5_padata(i: &[u8]) -> IResult<&[u8], PAData, BerError> { + parse_ber_sequence_defined_g(|i, _| { + let (i, padata_type) = + parse_ber_tagged_explicit_g(1, |a, _| map(parse_der_int32, PAType)(a))(i)?; + let (i, padata_value) = + parse_ber_tagged_explicit_g(2, |a, _| map_res(parse_der, |o| o.as_slice())(a))(i)?; + let padata = PAData { + padata_type, + padata_value, + }; + Ok((i, padata)) + })(i) +} + +fn parse_krb5_padata_sequence(i: &[u8]) -> IResult<&[u8], Vec<PAData>, BerError> { + parse_ber_sequence_of_v(parse_krb5_padata)(i) +} + +/// Parse a Kerberos AP Request +/// +/// <pre> +/// AP-REQ ::= [APPLICATION 14] SEQUENCE { +/// pvno [0] INTEGER (5), +/// msg-type [1] INTEGER (14), +/// ap-options [2] APOptions, +/// ticket [3] Ticket, +/// authenticator [4] EncryptedData -- Authenticator +/// } +/// +/// APOptions ::= KerberosFlags +/// -- reserved(0), +/// -- use-session-key(1), +/// -- mutual-required(2) +/// </pre> +pub fn parse_ap_req(i: &[u8]) -> IResult<&[u8], ApReq, BerError> { + parse_ber_tagged_explicit_g(BerTag(14), |i, hdr| { + if !hdr.is_application() { + return Err(Err::Error(BerError::InvalidTag)); + } + parse_ber_sequence_defined_g(|i, _| { + let (i, pvno) = parse_ber_tagged_explicit_g(0, |a, _| parse_der_u32(a))(i)?; + let (i, msg_type) = + parse_ber_tagged_explicit_g(1, |a, _| map(parse_der_u32, MessageType)(a))(i)?; + let (i, ap_options) = + parse_ber_tagged_explicit_g(2, |a, _| parse_kerberos_flags(a))(i)?; + let (i, ticket) = parse_ber_tagged_explicit_g(3, |a, _| parse_krb5_ticket(a))(i)?; + let (i, authenticator) = parse_ber_tagged_explicit_g(4, |a, _| parse_encrypted(a))(i)?; + let req = ApReq { + pvno, + msg_type, + ap_options, + ticket, + authenticator, + }; + Ok((i, req)) + })(i) + })(i) +} + +/// Parse a Kerberos AP Reply +/// +/// <pre> +/// AP-REP ::= [APPLICATION 15] SEQUENCE { +/// pvno [0] INTEGER (5), +/// msg-type [1] INTEGER (15), +/// enc-part [2] EncryptedData -- EncAPRepPart +/// } +/// </pre> +pub fn parse_ap_rep(i: &[u8]) -> IResult<&[u8], ApRep, BerError> { + parse_ber_tagged_explicit_g(BerTag(15), |i, hdr| { + if !hdr.is_application() { + return Err(Err::Error(BerError::InvalidTag)); + } + parse_ber_sequence_defined_g(|i, _| { + let (i, pvno) = parse_ber_tagged_explicit_g(0, |a, _| parse_der_u32(a))(i)?; + let (i, msg_type) = + parse_ber_tagged_explicit_g(1, |a, _| map(parse_der_u32, MessageType)(a))(i)?; + let (i, enc_part) = parse_ber_tagged_explicit_g(2, |a, _| parse_encrypted(a))(i)?; + let rep = ApRep { + pvno, + msg_type, + enc_part, + }; + Ok((i, rep)) + })(i) + })(i) +} diff --git a/rust/vendor/kerberos-parser/src/lib.rs b/rust/vendor/kerberos-parser/src/lib.rs new file mode 100644 index 0000000..d2d6794 --- /dev/null +++ b/rust/vendor/kerberos-parser/src/lib.rs @@ -0,0 +1,45 @@ +//! # Kerberos Parser +//! +//! A Kerberos v5 ([RFC4120]) parser, implemented with the [nom](https://github.com/Geal/nom) +//! parser combinator framework. +//! +//! The code is available on [Github](https://github.com/rusticata/kerberos-parser). +//! +//! Specific parsing functions are provided for Kerberos message types. For ex. to parse a +//! KRB_AS_REQ message, use [`parse_as_req`](krb5_parser/fn.parse_as_req.html). +//! +//! # Examples +//! +//! Parsing a KRB_AS_REQ message: +//! +//! ```rust,no_run +//! use kerberos_parser::krb5::MessageType; +//! use kerberos_parser::krb5_parser::parse_as_req; +//! +//! static AS_REQ: &'static [u8] = include_bytes!("../assets/as-req.bin"); +//! +//! # fn main() { +//! let res = parse_as_req(AS_REQ); +//! match res { +//! Ok((rem, kdc_req)) => { +//! assert!(rem.is_empty()); +//! // +//! assert_eq!(kdc_req.msg_type, MessageType::KRB_AS_REQ); +//! }, +//! _ => panic!("KRB_AS_REQ parsing failed: {:?}", res), +//! } +//! # } +//! ``` +//! +//! [RFC4120]: https://tools.ietf.org/html/rfc4120 + +#![deny(/*missing_docs,*/unsafe_code, + unstable_features, + unused_import_braces, unused_qualifications)] + +pub mod krb5; +pub mod krb5_parser; + +mod krb5_constants; +mod krb5_errors; +pub use krb5_errors::*; diff --git a/rust/vendor/kerberos-parser/tests/krb5_parser.rs b/rust/vendor/kerberos-parser/tests/krb5_parser.rs new file mode 100644 index 0000000..012c8c3 --- /dev/null +++ b/rust/vendor/kerberos-parser/tests/krb5_parser.rs @@ -0,0 +1,253 @@ +use kerberos_parser::krb5::*; +use kerberos_parser::krb5_parser::*; + +#[test] +fn test_parse_kerberos_string() { + let bytes = &[0x1b, 0x04, 0x63, 0x69, 0x66, 0x73]; + let empty = &b""[..]; + let expected = Realm(String::from("cifs")); + + let res = parse_krb5_realm(bytes); + assert_eq!(res, Ok((empty, expected))); +} + +#[test] +fn test_parse_realm() { + let bytes = &[0x1b, 0x05, 0x4a, 0x6f, 0x6e, 0x65, 0x73]; + let empty = &b""[..]; + let expected = Realm(String::from("Jones")); + + let res = parse_krb5_realm(bytes); + assert_eq!(res, Ok((empty, expected))); +} + +#[test] +fn test_parse_principalname() { + let bytes = &[ + 0x30, 0x81, 0x11, 0xa0, 0x03, 0x02, 0x01, 0x00, 0xa1, 0x0a, 0x30, 0x81, 0x07, 0x1b, 0x05, + 0x4a, 0x6f, 0x6e, 0x65, 0x73, + ]; + let empty = &b""[..]; + let expected = PrincipalName { + name_type: NameType(0), + name_string: vec![String::from("Jones")], + }; + + let res = parse_krb5_principalname(bytes); + assert_eq!(res, Ok((empty, expected))); +} + +#[test] +fn test_parse_principalname2() { + let bytes = &[ + 0x30, 0x27, 0xa0, 0x03, 0x02, 0x01, 0x02, 0xa1, 0x20, 0x30, 0x1e, 0x1b, 0x04, 0x63, 0x69, + 0x66, 0x73, 0x1b, 0x16, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x2d, 0x50, 0x43, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x6f, 0x73, 0x6f, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + ]; + let empty = &b""[..]; + let expected = PrincipalName { + name_type: NameType::KRB_NT_SRV_INST, + name_string: vec![String::from("cifs"), String::from("Admin-PC.contoso.local")], + }; + + let res = parse_krb5_principalname(bytes); + assert_eq!(res, Ok((empty, expected))); +} + +static KRB5_TICKET: &[u8] = include_bytes!("../assets/krb5-ticket.bin"); +#[test] +fn test_parse_ticket() { + let bytes = KRB5_TICKET; + + let res = parse_krb5_ticket(bytes); + // println!("parse_krb5_ticket: {:?}", res); + match res { + Ok((rem, tkt)) => { + assert!(rem.is_empty()); + assert_eq!(tkt.tkt_vno, 5); + assert_eq!(tkt.realm, Realm(String::from("CONTOSO.LOCAL"))); + assert_eq!( + tkt.sname, + PrincipalName { + name_type: NameType::KRB_NT_SRV_INST, + name_string: vec![String::from("cifs"), String::from("Admin-PC.contoso.local")] + } + ); + let enc = &tkt.enc_part; + // println!("enc: {:?}", enc); + assert_eq!(enc.etype, EncryptionType::AES256_CTS_HMAC_SHA1_96); + assert_eq!(enc.kvno, Some(1)); + } + _ => panic!("parsing failed"), + } +} + +static AS_REQ: &[u8] = include_bytes!("../assets/as-req.bin"); +#[test] +fn test_parse_as_req() { + let bytes = AS_REQ; + + let res = parse_as_req(bytes); + // println!("parse_as_req: {:?}", res); + match res { + Ok((rem, req)) => { + assert!(rem.is_empty()); + assert_eq!(req.pvno, 5); + assert_eq!(req.msg_type, MessageType::KRB_AS_REQ); + assert_eq!(req.req_body.realm, Realm(String::from("DENYDC"))); + assert_eq!( + req.req_body.cname, + Some(PrincipalName { + name_type: NameType::KRB_NT_PRINCIPAL, + name_string: vec![String::from("des")] + }) + ); + assert_eq!( + req.req_body.sname, + Some(PrincipalName { + name_type: NameType::KRB_NT_SRV_INST, + name_string: vec![String::from("krbtgt"), String::from("DENYDC")] + }) + ); + } + _ => panic!("parsing failed"), + } +} + +static AS_REP: &[u8] = include_bytes!("../assets/as-rep.bin"); +#[test] +fn test_parse_as_rep() { + let bytes = AS_REP; + + let res = parse_as_rep(bytes); + // println!("parse_as_rep: {:?}", res); + match res { + Ok((rem, req)) => { + assert!(rem.is_empty()); + assert_eq!(req.pvno, 5); + assert_eq!(req.msg_type, MessageType::KRB_AS_REP); + assert_eq!(req.crealm, Realm(String::from("DENYDC.COM"))); + assert_eq!( + req.cname, + PrincipalName { + name_type: NameType::KRB_NT_PRINCIPAL, + name_string: vec![String::from("des")] + } + ); + } + _ => panic!("parsing failed"), + } +} + +static AP_REQ: &[u8] = include_bytes!("../assets/ap-req.bin"); +#[test] +fn test_parse_ap_req() { + let bytes = AP_REQ; + + let res = parse_ap_req(bytes); + // println!("parse_ap_req: {:?}", res); + match res { + Ok((rem, req)) => { + assert!(rem.is_empty()); + assert_eq!(req.pvno, 5); + assert_eq!(req.msg_type, MessageType::KRB_AP_REQ); + assert_eq!(req.ticket.realm, Realm(String::from("DENYDC.COM"))); + assert_eq!( + req.ticket.sname, + PrincipalName { + name_type: NameType::KRB_NT_SRV_INST, + name_string: vec![String::from("krbtgt"), String::from("DENYDC.COM")] + } + ); + } + _ => panic!("parsing failed"), + } +} + +static KRB_ERROR: &[u8] = include_bytes!("../assets/krb-error.bin"); +#[test] +fn test_parse_krb_error() { + let bytes = KRB_ERROR; + + let res = parse_krb_error(bytes); + // println!("parse_krb_error: {:?}", res); + match res { + Ok((rem, err)) => { + assert!(rem.is_empty()); + assert_eq!(err.pvno, 5); + assert_eq!(err.msg_type, MessageType::KRB_ERROR); + assert_eq!(err.error_code, ErrorCode::KDC_ERR_ETYPE_NOSUPP); + assert_eq!(err.realm, Realm(String::from("DENYDC"))); + assert_eq!( + err.sname, + PrincipalName { + name_type: NameType::KRB_NT_SRV_INST, + name_string: vec![String::from("krbtgt"), String::from("DENYDC")] + } + ); + } + _ => panic!("parsing failed"), + } +} + +static TGS_REP_NO_PADATA: &[u8] = include_bytes!("../assets/tgs-rep-no-padata.bin"); +#[test] +fn test_parse_tgs_rep_no_padata() { + let bytes = TGS_REP_NO_PADATA; + + let res = parse_tgs_rep(bytes); + match res { + Ok((rem, rep)) => { + assert!(rem.is_empty()); + assert_eq!(rep.pvno, 5); + assert_eq!(rep.msg_type, MessageType::KRB_TGS_REP); + assert!(rep.padata.is_empty()); + assert_eq!(rep.crealm, Realm(String::from("DENYDC.COM"))); + assert_eq!( + rep.cname, + PrincipalName { + name_type: NameType::KRB_NT_PRINCIPAL, + name_string: vec![String::from("des")] + } + ); + } + _ => panic!("parsing failed"), + } +} + +#[test] +fn test_parse_int32() { + let empty = &b""[..]; + assert_eq!(parse_der_int32(&[0x02, 0x01, 0xff]), Ok((empty, -1))); + assert_eq!(parse_der_int32(&[0x02, 0x01, 0x01]), Ok((empty, 1))); + assert_eq!(parse_der_int32(&[0x02, 0x02, 0xff, 0xff]), Ok((empty, -1))); + assert_eq!( + parse_der_int32(&[0x02, 0x02, 0x01, 0x23]), + Ok((empty, 0x123)) + ); + assert_eq!( + parse_der_int32(&[0x02, 0x03, 0xff, 0xff, 0xff]), + Ok((empty, -1)) + ); + assert_eq!( + parse_der_int32(&[0x02, 0x03, 0x01, 0x23, 0x45]), + Ok((empty, 0x12345)) + ); + assert_eq!( + parse_der_int32(&[0x02, 0x04, 0xff, 0xff, 0xff, 0xff]), + Ok((empty, -1)) + ); + assert_eq!( + parse_der_int32(&[0x02, 0x04, 0x01, 0x23, 0x45, 0x67]), + Ok((empty, 0x1234567)) + ); +} + +#[test] +fn test_principalname_display() { + let pn = PrincipalName { + name_type: NameType::KRB_NT_SRV_INST, + name_string: vec!["krb5".to_string(), "DOMAIN.COM".to_string()], + }; + assert_eq!("krb5/DOMAIN.COM", format!("{}", pn)); +} |