#![doc(html_root_url = "https://docs.rs/ssh2")]
#![allow(trivial_numeric_casts)]
#![deny(missing_docs, unused_results)]
#![cfg_attr(test, deny(warnings))]
extern crate libc;
extern crate libssh2_sys as raw;
#[macro_use]
extern crate bitflags;
extern crate parking_lot;
use std::ffi::CStr;
pub use agent::{Agent, PublicKey};
pub use channel::{Channel, ExitSignal, ReadWindow, Stream, WriteWindow};
pub use error::{Error, ErrorCode};
pub use knownhosts::{Host, KnownHosts};
pub use listener::Listener;
use session::SessionInner;
pub use session::{BlockDirections, KeyboardInteractivePrompt, Prompt, ScpFileStat, Session, TraceFlags};
pub use sftp::{File, FileStat, FileType, OpenType};
pub use sftp::{OpenFlags, RenameFlags, Sftp};
pub use DisconnectCode::{AuthCancelledByUser, TooManyConnections};
pub use DisconnectCode::{ByApplication, ConnectionLost, HostKeyNotVerifiable};
pub use DisconnectCode::{CompressionError, KeyExchangeFailed, MacError, Reserved};
pub use DisconnectCode::{HostNotAllowedToConnect, ProtocolError};
pub use DisconnectCode::{IllegalUserName, NoMoreAuthMethodsAvailable};
pub use DisconnectCode::{ProtocolVersionNotSupported, ServiceNotAvailable};
mod agent;
mod channel;
mod error;
mod knownhosts;
mod listener;
mod session;
mod sftp;
mod util;
pub fn init() {
raw::init();
}
unsafe fn opt_bytes<'a, T>(_: &'a T, c: *const libc::c_char) -> Option<&'a [u8]> {
if c.is_null() {
None
} else {
Some(CStr::from_ptr(c).to_bytes())
}
}
#[allow(missing_docs)]
#[derive(Copy, Clone)]
pub enum DisconnectCode {
HostNotAllowedToConnect = raw::SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT as isize,
ProtocolError = raw::SSH_DISCONNECT_PROTOCOL_ERROR as isize,
KeyExchangeFailed = raw::SSH_DISCONNECT_KEY_EXCHANGE_FAILED as isize,
Reserved = raw::SSH_DISCONNECT_RESERVED as isize,
MacError = raw::SSH_DISCONNECT_MAC_ERROR as isize,
CompressionError = raw::SSH_DISCONNECT_COMPRESSION_ERROR as isize,
ServiceNotAvailable = raw::SSH_DISCONNECT_SERVICE_NOT_AVAILABLE as isize,
ProtocolVersionNotSupported = raw::SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED as isize,
HostKeyNotVerifiable = raw::SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE as isize,
ConnectionLost = raw::SSH_DISCONNECT_CONNECTION_LOST as isize,
ByApplication = raw::SSH_DISCONNECT_BY_APPLICATION as isize,
TooManyConnections = raw::SSH_DISCONNECT_TOO_MANY_CONNECTIONS as isize,
AuthCancelledByUser = raw::SSH_DISCONNECT_AUTH_CANCELLED_BY_USER as isize,
NoMoreAuthMethodsAvailable = raw::SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE as isize,
IllegalUserName = raw::SSH_DISCONNECT_ILLEGAL_USER_NAME as isize,
}
#[allow(missing_docs)]
#[derive(Copy, Clone, Debug)]
pub enum HostKeyType {
Unknown = raw::LIBSSH2_HOSTKEY_TYPE_UNKNOWN as isize,
Rsa = raw::LIBSSH2_HOSTKEY_TYPE_RSA as isize,
Dss = raw::LIBSSH2_HOSTKEY_TYPE_DSS as isize,
Ecdsa256 = raw::LIBSSH2_HOSTKEY_TYPE_ECDSA_256 as isize,
Ecdsa384 = raw::LIBSSH2_HOSTKEY_TYPE_ECDSA_384 as isize,
Ecdsa521 = raw::LIBSSH2_HOSTKEY_TYPE_ECDSA_521 as isize,
Ed255219 = raw::LIBSSH2_HOSTKEY_TYPE_ED25519 as isize,
}
#[allow(missing_docs)]
#[derive(Copy, Clone)]
pub enum MethodType {
Kex = raw::LIBSSH2_METHOD_KEX as isize,
HostKey = raw::LIBSSH2_METHOD_HOSTKEY as isize,
CryptCs = raw::LIBSSH2_METHOD_CRYPT_CS as isize,
CryptSc = raw::LIBSSH2_METHOD_CRYPT_SC as isize,
MacCs = raw::LIBSSH2_METHOD_MAC_CS as isize,
MacSc = raw::LIBSSH2_METHOD_MAC_SC as isize,
CompCs = raw::LIBSSH2_METHOD_COMP_CS as isize,
CompSc = raw::LIBSSH2_METHOD_COMP_SC as isize,
LangCs = raw::LIBSSH2_METHOD_LANG_CS as isize,
LangSc = raw::LIBSSH2_METHOD_LANG_SC as isize,
SignAlgo = raw::LIBSSH2_METHOD_SIGN_ALGO as isize,
}
pub static FLUSH_EXTENDED_DATA: i32 = -1;
pub static FLUSH_ALL: i32 = -2;
pub static EXTENDED_DATA_STDERR: i32 = 1;
#[allow(missing_docs)]
#[derive(Copy, Clone, Debug)]
pub enum HashType {
Md5 = raw::LIBSSH2_HOSTKEY_HASH_MD5 as isize,
Sha1 = raw::LIBSSH2_HOSTKEY_HASH_SHA1 as isize,
Sha256 = raw::LIBSSH2_HOSTKEY_HASH_SHA256 as isize,
}
#[allow(missing_docs)]
#[derive(Copy, Clone, Debug)]
pub enum KnownHostFileKind {
OpenSSH = raw::LIBSSH2_KNOWNHOST_FILE_OPENSSH as isize,
}
#[derive(Copy, Clone, Debug)]
pub enum CheckResult {
Match = raw::LIBSSH2_KNOWNHOST_CHECK_MATCH as isize,
Mismatch = raw::LIBSSH2_KNOWNHOST_CHECK_MISMATCH as isize,
NotFound = raw::LIBSSH2_KNOWNHOST_CHECK_NOTFOUND as isize,
Failure = raw::LIBSSH2_KNOWNHOST_CHECK_FAILURE as isize,
}
#[allow(missing_docs)]
#[derive(Copy, Clone, Debug)]
pub enum KnownHostKeyFormat {
Unknown = raw::LIBSSH2_KNOWNHOST_KEY_UNKNOWN as isize,
Rsa1 = raw::LIBSSH2_KNOWNHOST_KEY_RSA1 as isize,
SshRsa = raw::LIBSSH2_KNOWNHOST_KEY_SSHRSA as isize,
SshDss = raw::LIBSSH2_KNOWNHOST_KEY_SSHDSS as isize,
Ecdsa256 = raw::LIBSSH2_KNOWNHOST_KEY_ECDSA_256 as isize,
Ecdsa384 = raw::LIBSSH2_KNOWNHOST_KEY_ECDSA_384 as isize,
Ecdsa521 = raw::LIBSSH2_KNOWNHOST_KEY_ECDSA_521 as isize,
Ed255219 = raw::LIBSSH2_KNOWNHOST_KEY_ED25519 as isize,
}
impl From<HostKeyType> for KnownHostKeyFormat {
fn from(host_type: HostKeyType) -> KnownHostKeyFormat {
match host_type {
HostKeyType::Unknown => KnownHostKeyFormat::Unknown,
HostKeyType::Rsa => KnownHostKeyFormat::SshRsa,
HostKeyType::Dss => KnownHostKeyFormat::SshDss,
HostKeyType::Ecdsa256 => KnownHostKeyFormat::Ecdsa256,
HostKeyType::Ecdsa384 => KnownHostKeyFormat::Ecdsa384,
HostKeyType::Ecdsa521 => KnownHostKeyFormat::Ecdsa521,
HostKeyType::Ed255219 => KnownHostKeyFormat::Ed255219,
}
}
}
#[derive(Copy, Clone, Debug)]
pub enum ExtendedData {
Normal = raw::LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL as isize,
Merge = raw::LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE as isize,
Ignore = raw::LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE as isize,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum PtyModeOpcode {
TTY_OP_END = 0,
VINTR = 1,
VQUIT = 2,
VERASE = 3,
VKILL = 4,
VEOF = 5,
VEOL = 6,
VEOL2 = 7,
VSTART = 8,
VSTOP = 9,
VSUSP = 10,
VDSUSP = 11,
VREPRINT = 12,
VWERASE = 13,
VLNEXT = 14,
VFLUSH = 15,
VSWTCH = 16,
VSTATUS = 17,
VDISCARD = 18,
IGNPAR = 30,
PARMRK = 31,
INPCK = 32,
ISTRIP = 33,
INLCR = 34,
IGNCR = 35,
ICRNL = 36,
IUCLC = 37,
IXON = 38,
IXANY = 39,
IXOFF = 49,
IMAXBEL = 41,
ISIG = 50,
ICANON = 51,
XCASE = 52,
ECHO = 53,
ECHOE = 54,
ECHOK = 55,
ECHONL = 56,
NOFLSH = 57,
TOSTOP = 58,
IEXTEN = 59,
ECHOCTL = 60,
ECHOKE = 61,
PENDIN = 62,
OPOST = 70,
OLCUC = 71,
ONLCR = 72,
OCRNL = 73,
ONOCR = 74,
ONLRET = 75,
CS7 = 90,
CS8 = 91,
PARENB = 92,
PARODD = 93,
TTY_OP_ISPEED = 128,
TTY_OP_OSPEED = 129,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ExtensiblePtyModeOpcode {
Mode(PtyModeOpcode),
Extended(u8),
}
impl From<PtyModeOpcode> for ExtensiblePtyModeOpcode {
fn from(op: PtyModeOpcode) -> ExtensiblePtyModeOpcode {
ExtensiblePtyModeOpcode::Mode(op)
}
}
impl From<u8> for ExtensiblePtyModeOpcode {
fn from(op: u8) -> ExtensiblePtyModeOpcode {
ExtensiblePtyModeOpcode::Extended(op)
}
}
impl ExtensiblePtyModeOpcode {
fn as_opcode(&self) -> u8 {
match self {
ExtensiblePtyModeOpcode::Mode(m) => *m as u8,
ExtensiblePtyModeOpcode::Extended(op) => *op,
}
}
}
#[derive(Debug, Clone)]
pub struct PtyModes {
data: Vec<u8>,
}
impl PtyModes {
pub fn new() -> Self {
Self { data: vec![] }
}
pub fn set_u32<O: Into<ExtensiblePtyModeOpcode>>(&mut self, option: O, value: u32) {
let data = [
option.into().as_opcode(),
((value >> 24) & 0xff) as u8,
((value >> 16) & 0xff) as u8,
((value >> 8) & 0xff) as u8,
(value & 0xff) as u8,
];
self.data.extend_from_slice(&data);
}
pub fn set_boolean<O: Into<ExtensiblePtyModeOpcode>>(&mut self, option: O, value: bool) {
self.set_u32(option, if value { 1 } else { 0 })
}
pub fn set_character<O: Into<ExtensiblePtyModeOpcode>>(&mut self, option: O, c: Option<char>) {
self.set_u32(option, c.map(|c| c as u32).unwrap_or(255))
}
pub fn finish(mut self) -> Vec<u8> {
self.data.push(PtyModeOpcode::TTY_OP_END as u8);
self.data
}
}