// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {fidl_fuchsia_ssh::MAX_SSH_KEY_LENGTH, std::str::FromStr, thiserror::Error};

#[derive(Error, Debug, PartialEq)]
/// Errors that occur while parsing a key.
pub enum ParseKeyError {
    #[error("Wrong number of fields in key")]
    WrongNumberOfFields,
    #[error("Key too long")]
    KeyTooLong,
    #[error("Invalid key type")]
    InvalidKeyType,
    #[error("Key is a comment or empty")]
    InvalidKey,
}

/// See //third_party/openssh-portable/sshd.8
const VALID_KEY_TYPES: [&str; 8] = [
    "sk-ecdsa-sha2-nistp256@openssh.com",
    "ecdsa-sha2-nistp256",
    "ecdsa-sha2-nistp384",
    "ecdsa-sha2-nistp521",
    "sk-ssh-ed25519@openssh.com",
    "ssh-ed25519",
    "ssh-dss",
    "ssh-rsa",
];

fn is_valid_key_type(typ: &str) -> bool {
    VALID_KEY_TYPES.iter().any(|v| *v == typ)
}

#[derive(Debug, Clone)]
/// Represents a single SSH key. Some (minimal) validation occurs (e.g. ensuring the claimed key
/// type is supported), but otherwise a key is largely opaque.
/// Keys are equal so long as their "key type" and "key value" is valid. The comment and options
/// are disregarded when comparisons are done.
pub struct KeyEntry {
    options: Option<String>,
    key_type: String,
    key: String,
    comment: Option<String>,
}

impl PartialEq for KeyEntry {
    fn eq(&self, other: &KeyEntry) -> bool {
        return self.key_type == other.key_type && self.key == other.key;
    }
}

impl FromStr for KeyEntry {
    type Err = ParseKeyError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.len() == 0 || s.starts_with('#') {
            return Err(ParseKeyError::InvalidKey);
        }
        if s.len() > MAX_SSH_KEY_LENGTH as usize {
            return Err(ParseKeyError::KeyTooLong);
        }

        let parts: Vec<&str> = s.split(' ').collect();
        // The sshd docs say that authorized_keys fields are space-separated, but in practice the
        // tools seem to accept comments with multiple spaces in them.
        if parts.len() < 2 {
            return Err(ParseKeyError::WrongNumberOfFields);
        }

        // This is fairly naive. We simply try and find a field that looks like a valid key type,
        // and base our assumption on the rest of the line off that.
        // We don't attempt to parse any of the other fields.
        let (options, key_type, key, comment_start) = if is_valid_key_type(parts[0]) {
            // If the first field is a key type, the next field is key type, and the last field is
            // comment.
            (None, parts[0], parts[1], 2)
        } else if is_valid_key_type(parts[1]) {
            // If the second field is a key type, there should be at least 3 fields: options,
            // key-type, and key.
            if parts.len() < 3 {
                return Err(ParseKeyError::WrongNumberOfFields);
            }
            (Some(parts[0]), parts[1], parts[2], 3)
        } else {
            return Err(ParseKeyError::InvalidKeyType);
        };

        let comment =
            if parts.len() > comment_start { Some(parts[comment_start..].join(" ")) } else { None };

        Ok(KeyEntry {
            options: options.map(|v| v.to_string()),
            key_type: key_type.to_string(),
            key: key.to_string(),
            comment: comment.map(|v| v.to_string()),
        })
    }
}

impl ToString for KeyEntry {
    fn to_string(&self) -> String {
        match (self.options.as_ref(), self.comment.as_ref()) {
            (Some(a), Some(b)) => format!("{} {} {} {}", a, self.key_type, self.key, b),
            (None, Some(b)) => format!("{} {} {}", self.key_type, self.key, b),
            (Some(a), None) => format!("{} {} {}", a, self.key_type, self.key),
            (None, None) => format!("{} {}", self.key_type, self.key),
        }
    }
}

#[cfg(test)]
mod string_tests {
    use super::*;

    #[test]
    fn test_key_long_comment() {
        let key = "options ssh-dss abcdefg comment and other text".parse::<KeyEntry>().unwrap();
        assert_eq!(key.options.as_deref(), Some("options"));
        assert_eq!(key.key_type, "ssh-dss");
        assert_eq!(key.key, "abcdefg");
        assert_eq!(key.comment.as_deref(), Some("comment and other text"));
    }

    #[test]
    fn test_key_leading_fields() {
        assert_eq!(
            "options word ssh-dss abcdefg".parse::<KeyEntry>().unwrap_err(),
            ParseKeyError::InvalidKeyType
        );
    }

    #[test]
    fn test_key_not_enough_fields() {
        assert_eq!(
            "options ssh-rsa".parse::<KeyEntry>().unwrap_err(),
            ParseKeyError::WrongNumberOfFields
        );
    }

    #[test]
    fn test_key_empty() {
        assert_eq!("".parse::<KeyEntry>().unwrap_err(), ParseKeyError::InvalidKey);
    }

    #[test]
    fn test_key_too_long() {
        let line = "a".repeat(8193);
        assert_eq!(line.parse::<KeyEntry>().unwrap_err(), ParseKeyError::KeyTooLong);
    }

    const VALID_ECDSA_KEY: &str = "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKR7FCcS2e4OfqHi8h3HAPZhu1fvZUXaXjSDEUr0NPV49jKJSgCptu7YQq1DlfKXXw3aPGJdZAyk1fixQvYli8A=";

    #[test]
    fn test_parse_valid_key_no_options_or_comment() {
        let line = format!("ecdsa-sha2-nistp256 {}", VALID_ECDSA_KEY);
        let key = line.parse::<KeyEntry>().expect("parse ok");
        assert_eq!(key.options, None);
        assert_eq!(key.key_type, "ecdsa-sha2-nistp256");
        assert_eq!(key.key, VALID_ECDSA_KEY);
        assert_eq!(key.comment, None);
        assert_eq!(line, key.to_string());
    }

    #[test]
    fn test_parse_valid_key_with_options() {
        let line = format!("options ecdsa-sha2-nistp256 {}", VALID_ECDSA_KEY);
        let key = line.parse::<KeyEntry>().expect("parse ok");
        assert_eq!(key.options.as_deref(), Some("options"));
        assert_eq!(key.key_type, "ecdsa-sha2-nistp256");
        assert_eq!(key.key, VALID_ECDSA_KEY);
        assert_eq!(key.comment, None);
        assert_eq!(line, key.to_string());
    }

    #[test]
    fn test_parse_valid_key_with_comment() {
        let line = format!("ecdsa-sha2-nistp256 {} comment", VALID_ECDSA_KEY);
        let key = line.parse::<KeyEntry>().expect("parse ok");
        assert_eq!(key.options, None);
        assert_eq!(key.key_type, "ecdsa-sha2-nistp256");
        assert_eq!(key.key, VALID_ECDSA_KEY);
        assert_eq!(key.comment.as_deref(), Some("comment"));
        assert_eq!(line, key.to_string());
    }

    #[test]
    fn test_parse_valid_key_with_comment_and_options() {
        let line = format!("options ecdsa-sha2-nistp256 {} comment", VALID_ECDSA_KEY);
        let key = line.parse::<KeyEntry>().expect("parse ok");
        assert_eq!(key.options.as_deref(), Some("options"));
        assert_eq!(key.key_type, "ecdsa-sha2-nistp256");
        assert_eq!(key.key, VALID_ECDSA_KEY);
        assert_eq!(key.comment.as_deref(), Some("comment"));
        assert_eq!(line, key.to_string());
    }

    #[test]
    fn test_parse_comment_line() {
        assert_eq!("# commented".parse::<KeyEntry>().unwrap_err(), ParseKeyError::InvalidKey);
    }
}

#[cfg(test)]
mod eq_tests {
    use super::*;

    #[test]
    fn test_eq_not_identical() {
        let a = KeyEntry {
            options: None,
            key_type: "ssh-rsa".to_owned(),
            key: "abc".to_owned(),
            comment: None,
        };
        let b = KeyEntry {
            options: None,
            key_type: "ssh-dss".to_owned(),
            key: "abc".to_owned(),
            comment: None,
        };

        assert_ne!(a, b);
    }

    #[test]
    fn test_eq_ignores_options_and_comment() {
        let a = KeyEntry {
            options: None,
            key_type: "ssh-rsa".to_owned(),
            key: "abc".to_owned(),
            comment: None,
        };
        let b = KeyEntry {
            options: Some("test".to_owned()),
            key_type: "ssh-rsa".to_owned(),
            key: "abc".to_owned(),
            comment: Some("test".to_owned()),
        };

        assert_eq!(a, b);
    }
}
