pijul_org / thrussh

Reboot

By blabla on April 29, 2018
This patch is not signed.
8uUvQV1Btavj9dcYV7PpwaZwKuyJP27boWPHknNU4tUo9E6KtCN8fP1V8Ly9hQd25DFxn1GHPgHEa5kHU6qtjupL
This patch is in the following branches:
master

1
2
3
4
5
6
7
8
"thrussh-libsodium:0.1.2" = { path = "thrussh-libsodium" }
[workspace]

members = [ "thrussh-keys", "thrussh", "thrussh-libsodium", "thrussh-agent" ]

[replace]

"thrussh-keys:0.9.5" = { path = "thrussh-keys" }
"thrussh-libsodium:0.1.3" = { path = "thrussh-libsodium" }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
[package]
name = "thrussh"
description = "A client and server SSH library."
keywords = ["ssh"]
version = "0.20.0"
authors = ["Pierre-Étienne Meunier <pe@pijul.org>"]
repository = "https://nest.pijul.com/pijul_org/thrussh"
homepage = "https://pijul.org/thrussh"
documentation = "https://docs.rs/thrussh"
license = "Apache-2.0"
include = [
        "Cargo.toml",
        "src/auth.rs",
        "src/kex.rs",
        "src/key.rs",
        "src/lib.rs",
        "src/msg.rs",
        "src/negotiation.rs",
        "src/pty.rs",
        "src/session.rs",
        "src/sshbuffer.rs",
        "src/ssh_read.rs",
        "src/tcp.rs",
        "src/bin/client.rs",
        "src/bin/server.rs",
        "src/cipher/chacha20poly1305.rs",
        "src/cipher/clear.rs",
        "src/cipher/mod.rs",
        "src/client/mod.rs",
        "src/client/encrypted.rs",
        "src/client/authenticate.rs",
        "src/client/channel_open.rs",
        "src/client/connection.rs",
        "src/client/data.rs",
        "src/client/kex.rs",
        "src/client/session.rs",
        "src/client/wait.rs",
        "src/server/mod.rs",
        "src/server/encrypted.rs",
        "src/server/connection.rs",
        "src/server/kex.rs",
        "src/server/session.rs",
        "src/sodium.rs",
        "src/read_exact_from.rs"
        ]

[dependencies]
byteorder = "1.1"
bitflags = "1.0"
log = "0.3"
thrussh-keys = "0.9.5"
openssl = "0.10"
thrussh-libsodium = "0.1"
cryptovec = "0.4.1"
tokio = "0.1"
tokio-io = "0.1"
futures = "0.1"
tokio-timer = "0.1"

[dev-dependencies]
env_logger = "0.5"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

use thrussh_keys::encoding;
use cryptovec::CryptoVec;
use thrussh_keys::key;
use std::sync::Arc;

bitflags! {
    /// Set of methods, represented by bit flags.
    pub struct MethodSet: u32 {
        /// The SSH `none` method (no authentication).
        const NONE = 1;
        /// The SSH `password` method (plaintext passwords).
        const PASSWORD = 2;
        /// The SSH `publickey` method (sign a challenge sent by the
        /// server).
        const PUBLICKEY = 4;
        /// The SSH `hostbased` method (certain hostnames are allowed
        /// by the server).
        const HOSTBASED = 8;
        /// The SSH `keyboard-interactive` method (answer to a
        /// challenge, where the "challenge" can be a password prompt,
        /// a bytestring to sign with a smartcard, or something else).
        const KEYBOARD_INTERACTIVE = 16;
    }
}

macro_rules! iter {
    ( $y:expr, $x:expr ) => {
        {
            if $y.contains($x) {
                $y.remove($x);
                return Some($x)
            }
        }
    };
}


impl Iterator for MethodSet {
    type Item = MethodSet;
    fn next(&mut self) -> Option<MethodSet> {
        iter!(self, MethodSet::NONE);
        iter!(self, MethodSet::PASSWORD);
        iter!(self, MethodSet::PUBLICKEY);
        iter!(self, MethodSet::HOSTBASED);
        iter!(self, MethodSet::KEYBOARD_INTERACTIVE);
        None
    }
}

pub enum Method {
    // None,
    Password { password: String },
    PublicKey { key: Arc<key::KeyPair> },
    FuturePublicKey { key: key::PublicKey },
    // Hostbased,
}

impl encoding::Bytes for MethodSet {
    fn bytes(&self) -> &'static [u8] {
        match *self {
            MethodSet::NONE => b"none",
            MethodSet::PASSWORD => b"password",
            MethodSet::PUBLICKEY => b"publickey",
            MethodSet::HOSTBASED => b"hostbased",
            MethodSet::KEYBOARD_INTERACTIVE => b"keyboard-interactive",
            _ => b"",
        }
    }
}

impl MethodSet {
    pub(crate) fn from_bytes(b: &[u8]) -> Option<MethodSet> {
        match b {
            b"none" => Some(MethodSet::NONE),
            b"password" => Some(MethodSet::PASSWORD),
            b"publickey" => Some(MethodSet::PUBLICKEY),
            b"hostbased" => Some(MethodSet::HOSTBASED),
            b"keyboard-interactive" => Some(MethodSet::KEYBOARD_INTERACTIVE),
            _ => None,
        }
    }
}

#[doc(hidden)]
#[derive(Debug)]
pub struct AuthRequest {
    pub methods: MethodSet,
    pub partial_success: bool,
    pub current: Option<CurrentRequest>,
    pub rejection_count: usize,
}

#[doc(hidden)]
#[derive(Debug)]
pub enum CurrentRequest {
    PublicKey {
        key: CryptoVec,
        algo: CryptoVec,
        sent_pk_ok: bool,
    },
    KeyboardInteractive { submethods: String },
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

// http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.chacha20poly1305?annotate=HEAD

use super::super::Error;
use sodium::Sodium;
use sodium::chacha20::{KEY_BYTES, NONCE_BYTES, Nonce, Key};
use byteorder::{ByteOrder, BigEndian};

pub struct OpeningKey { k1: Key, k2: Key, sodium: Sodium }
pub struct SealingKey { k1: Key, k2: Key, sodium: Sodium }

const TAG_LEN: usize = 16;

pub static CIPHER: super::Cipher = super::Cipher {
    name: NAME,
    key_len: 64,
    make_sealing_cipher,
    make_opening_cipher,
};

pub const NAME: super::Name = super::Name("chacha20-poly1305@openssh.com");

fn make_sealing_cipher(k: &[u8]) -> super::SealingCipher {
    let mut k1 = Key([0; KEY_BYTES]);
    let mut k2 = Key([0; KEY_BYTES]);
    k1.0.clone_from_slice(&k[KEY_BYTES..]);
    k2.0.clone_from_slice(&k[..KEY_BYTES]);
    super::SealingCipher::Chacha20Poly1305(SealingKey { k1, k2, sodium: Sodium::new() })
}

fn make_opening_cipher(k: &[u8]) -> super::OpeningCipher {
    let mut k1 = Key([0; KEY_BYTES]);
    let mut k2 = Key([0; KEY_BYTES]);
    k1.0.clone_from_slice(&k[KEY_BYTES..]);
    k2.0.clone_from_slice(&k[..KEY_BYTES]);
    super::OpeningCipher::Chacha20Poly1305(OpeningKey { k1, k2, sodium: Sodium::new() })
}

fn make_counter(sequence_number: u32) -> Nonce {
    let mut nonce = Nonce([0; NONCE_BYTES]);
    let i0 = NONCE_BYTES-4;
    BigEndian::write_u32(&mut nonce.0[i0..], sequence_number);
    nonce
}

impl super::OpeningKey for OpeningKey {

    fn decrypt_packet_length(
        &self,
        sequence_number: u32,
        mut encrypted_packet_length: [u8; 4],
    ) -> [u8; 4] {
        let nonce = make_counter(sequence_number);
        self.sodium.chacha20_xor(&mut encrypted_packet_length, &nonce, &self.k1);
        encrypted_packet_length
    }

    fn tag_len(&self) -> usize {
        TAG_LEN
    }

    fn open<'a>(
        &self,
        sequence_number: u32,
        ciphertext_in_plaintext_out: &'a mut [u8],
        tag: &[u8],
    ) -> Result<&'a [u8], Error> {

        let nonce = make_counter(sequence_number);
        {
            use sodium::poly1305::Key;
            let mut poly_key = Key([0; 32]);
            self.sodium.chacha20_xor(&mut poly_key.0, &nonce, &self.k2);
            // let mut tag_ = Tag([0; 16]);
            // tag_.0.clone_from_slice(tag);
            if !self.sodium.poly1305_verify(&tag, ciphertext_in_plaintext_out, &poly_key) {
                return Err(Error::PacketAuth)
            }
        }
        self.sodium.chacha20_xor_ic(&mut ciphertext_in_plaintext_out[4..], &nonce, 1, &self.k2);
        Ok(&ciphertext_in_plaintext_out[4..])
    }
}

impl super::SealingKey for SealingKey {

    fn padding_length(&self, payload: &[u8]) -> usize {
        let block_size = 8;
        let extra_len = super::PACKET_LENGTH_LEN + super::PADDING_LENGTH_LEN;
        let padding_len = if payload.len() + extra_len <= super::MINIMUM_PACKET_LEN {
            super::MINIMUM_PACKET_LEN - payload.len() - super::PADDING_LENGTH_LEN
        } else {
            (block_size - ((super::PADDING_LENGTH_LEN + payload.len()) % block_size))
        };
        if padding_len < super::PACKET_LENGTH_LEN {
            padding_len + block_size
        } else {
            padding_len
        }
    }

    // As explained in "SSH via CTR mode with stateful decryption" in
    // https://openvpn.net/papers/ssh-security.pdf, the padding doesn't need to
    // be random because we're doing stateful counter-mode encryption. Use
    // fixed padding to avoid PRNG overhead.
    fn fill_padding(&self, padding_out: &mut [u8]) {
        for padding_byte in padding_out {
            *padding_byte = 0;
        }
    }

    fn tag_len(&self) -> usize {
        TAG_LEN
    }

    /// Append an encrypted packet with contents `packet_content` at the end of `buffer`.
    fn seal(
        &self,
        sequence_number: u32,
        plaintext_in_ciphertext_out: &mut [u8],
        tag_out: &mut [u8],
    ) {
        let mut nonce = make_counter(sequence_number);
        {
            let (a, b) = plaintext_in_ciphertext_out.split_at_mut(4);
            self.sodium.chacha20_xor(a, &nonce, &self.k1);
            self.sodium.chacha20_xor_ic(b, &nonce, 1, &self.k2);
        }
        nonce.0[0] = 0;
        use sodium::poly1305::Key;
        let mut poly_key = Key([0; 32]);
        self.sodium.chacha20_xor(&mut poly_key.0, &nonce, &self.k2);
        let tag = self.sodium.poly1305_auth(plaintext_in_ciphertext_out, &poly_key);
        tag_out.clone_from_slice(&tag.0);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

use Error;

#[derive(Debug)]
pub struct Key;

impl super::OpeningKey for Key {
    fn decrypt_packet_length(&self, _seqn: u32, packet_length: [u8; 4]) -> [u8; 4] {
        packet_length
    }

    fn tag_len(&self) -> usize {
        0
    }

    fn open<'a>(
        &self,
        _seqn: u32,
        ciphertext_in_plaintext_out: &'a mut [u8],
        tag: &[u8],
    ) -> Result<&'a [u8], Error> {

        debug_assert_eq!(tag.len(), 0); // self.tag_len());
        Ok(&ciphertext_in_plaintext_out[4..])
    }
}

impl super::SealingKey for Key {
    // Cleartext packets (including lengths) must be multiple of 8 in
    // length.
    fn padding_length(&self, payload: &[u8]) -> usize {
        let block_size = 8;
        let padding_len = block_size - ((5 + payload.len()) % block_size);
        if padding_len < 4 {
            padding_len + block_size
        } else {
            padding_len
        }
    }

    fn fill_padding(&self, padding_out: &mut [u8]) {
        // Since the packet is unencrypted anyway, there's no advantage to
        // randomizing the padding, so avoid possibly leaking extra RNG state
        // by padding with zeros.
        for padding_byte in padding_out {
            *padding_byte = 0;
        }
    }

    fn tag_len(&self) -> usize {
        0
    }

    fn seal(&self, _seqn: u32, _plaintext_in_ciphertext_out: &mut [u8], tag_out: &mut [u8]) {
        debug_assert_eq!(tag_out.len(), self.tag_len());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//
use byteorder::{ByteOrder, BigEndian};
use Error;
use std;
use sshbuffer::SSHBuffer;
use std::num::Wrapping;
use tokio::io::AsyncRead;
use read_exact_from::*;
use futures::{Future, Async, Poll};
use std::sync::Arc;
pub mod chacha20poly1305;
pub mod clear;
use cryptovec::CryptoVec;


pub struct Cipher {
    pub name: Name,
    pub key_len: usize,
    pub make_opening_cipher: fn(key: &[u8]) -> OpeningCipher,
    pub make_sealing_cipher: fn(key: &[u8]) -> SealingCipher,
}

pub enum OpeningCipher {
    Clear(clear::Key),
    Chacha20Poly1305(chacha20poly1305::OpeningKey),
}

impl<'a> OpeningCipher {
    fn as_opening_key(&self) -> &OpeningKey {
        match *self {
            OpeningCipher::Clear(ref key) => key,
            OpeningCipher::Chacha20Poly1305(ref key) => key,
        }
    }
}

pub enum SealingCipher {
    Clear(clear::Key),
    Chacha20Poly1305(chacha20poly1305::SealingKey),
}

impl<'a> SealingCipher {
    fn as_sealing_key(&'a self) -> &'a SealingKey {
        match *self {
            SealingCipher::Clear(ref key) => key,
            SealingCipher::Chacha20Poly1305(ref key) => key,
        }
    }
}

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct Name(&'static str);
impl AsRef<str> for Name {
    fn as_ref(&self) -> &str {
        self.0
    }
}

pub struct CipherPair {
    pub local_to_remote: SealingCipher,
    pub remote_to_local: OpeningCipher,
}

impl std::fmt::Debug for CipherPair {
    fn fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        Ok(()) // TODO?
    }
}

pub const CLEAR_PAIR: CipherPair = CipherPair {
    local_to_remote: SealingCipher::Clear(clear::Key),
    remote_to_local: OpeningCipher::Clear(clear::Key),
};

pub trait OpeningKey {

    fn decrypt_packet_length(&self, seqn: u32, encrypted_packet_length: [u8; 4]) -> [u8; 4];

    fn tag_len(&self) -> usize;

    fn open<'a>(
        &self,
        seqn: u32,
        ciphertext_in_plaintext_out: &'a mut [u8],
        tag: &[u8],
    ) -> Result<&'a [u8], Error>;
}

pub trait SealingKey {

    fn padding_length(&self, plaintext: &[u8]) -> usize;

    fn fill_padding(&self, padding_out: &mut [u8]);

    fn tag_len(&self) -> usize;

    fn seal(&self, seqn: u32, plaintext_in_ciphertext_out: &mut [u8], tag_out: &mut [u8]);
}

enum CipherReadState<R: AsyncRead> {
    Len {
        len: ReadExact<R, [u8; 4]>,
        buffer: SSHBuffer,
        pair: Arc<CipherPair>,
    },
    Body {
        body: ReadExact<R, CryptoVec>,
        buffer: SSHBuffer,
        pair: Arc<CipherPair>,
    },
}

pub struct CipherRead<R: AsyncRead>(Option<CipherReadState<R>>);

impl<R: AsyncRead> CipherRead<R> {
    pub fn try_abort(&mut self) -> Option<(R, SSHBuffer)> {
        if let Some(CipherReadState::Len {
                        mut len,
                        buffer,
                        pair,
                    }) = self.0.take()
        {
            // Aborting, and abandoning the 4 bytes of buffer.
            if let Some((r, _)) = len.try_abort() {
                return Some((r, buffer));
            } else {
                self.0 = Some(CipherReadState::Len { len, buffer, pair })
            }
        }
        None
    }
}

impl<R: AsyncRead> Future for CipherRead<R> {
    type Item = (R, SSHBuffer, usize);
    type Error = Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            debug!("cipherread poll");
            match self.0.take() {
                None => panic!("future is over"),
                Some(CipherReadState::Len {
                         mut len,
                         mut buffer,
                         pair,
                     }) => {
                    if let Async::Ready((stream, len_)) = len.poll()? {
                        {
                            let key = pair.remote_to_local.as_opening_key();
                            let seqn = buffer.seqn.0;
                            buffer.buffer.clear();
                            buffer.buffer.extend(&len_);
                            let len = key.decrypt_packet_length(seqn, len_);
                            let len = BigEndian::read_u32(&len) as usize + key.tag_len();
                            buffer.buffer.resize(len + 4);
                        }
                        self.0 = Some(CipherReadState::Body {
                            body: read_exact_from(
                                stream,
                                std::mem::replace(&mut buffer.buffer, CryptoVec::new()),
                                4,
                            ),
                            buffer,
                            pair,
                        })
                    } else {
                        self.0 = Some(CipherReadState::Len { len, buffer, pair });
                        return Ok(Async::NotReady);
                    }
                }
                Some(CipherReadState::Body {
                         mut body,
                         mut buffer,
                         pair,
                     }) => {
                    if let Async::Ready((stream, body)) = body.poll()? {
                        let plaintext_end = {
                            buffer.buffer = body;
                            let key = pair.remote_to_local.as_opening_key();
                            let seqn = buffer.seqn.0;
                            let ciphertext_len = buffer.buffer.len() - key.tag_len();
                            let (ciphertext, tag) = buffer.buffer.split_at_mut(ciphertext_len);
                            let plaintext = key.open(seqn, ciphertext, tag)?;

                            let padding_length = plaintext[0] as usize;
                            let plaintext_end = plaintext.len().checked_sub(padding_length).ok_or(
                                Error::IndexOutOfBounds,
                            )?;

                            // Sequence numbers are on 32 bits and wrap.
                            // https://tools.ietf.org/html/rfc4253#section-6.4
                            buffer.seqn += Wrapping(1);
                            buffer.len = 0;

                            plaintext_end
                        };
                        return Ok(Async::Ready((stream, buffer, plaintext_end + 4)));
                    } else {
                        self.0 = Some(CipherReadState::Body { body, buffer, pair });
                        return Ok(Async::NotReady);
                    }
                }
            }
        }
    }
}

pub fn read<R: AsyncRead>(stream: R, buffer: SSHBuffer, pair: Arc<CipherPair>) -> CipherRead<R> {
    CipherRead(Some(CipherReadState::Len {
        len: read_exact_from(stream, [0; 4], 0),
        buffer,
        pair,
    }))
}

impl CipherPair {
    pub fn write(&self, payload: &[u8], buffer: &mut SSHBuffer) {
        // https://tools.ietf.org/html/rfc4253#section-6
        //
        // The variables `payload`, `packet_length` and `padding_length` refer
        // to the protocol fields of the same names.

        let key = self.local_to_remote.as_sealing_key();

        let padding_length = key.padding_length(payload);
        let packet_length = PADDING_LENGTH_LEN + payload.len() + padding_length;
        let offset = buffer.buffer.len();

        // Maximum packet length:
        // https://tools.ietf.org/html/rfc4253#section-6.1
        assert!(packet_length <= std::u32::MAX as usize);
        buffer.buffer.push_u32_be(packet_length as u32);

        assert!(padding_length <= std::u8::MAX as usize);
        buffer.buffer.push(padding_length as u8);
        buffer.buffer.extend(payload);
        key.fill_padding(buffer.buffer.resize_mut(padding_length));
        buffer.buffer.resize_mut(key.tag_len());

        let (plaintext, tag) =
            buffer.buffer[offset..].split_at_mut(PACKET_LENGTH_LEN + packet_length);

        key.seal(buffer.seqn.0, plaintext, tag);

        // Sequence numbers are on 32 bits and wrap.
        // https://tools.ietf.org/html/rfc4253#section-6.4
        buffer.seqn += Wrapping(1);
    }
}


pub const PACKET_LENGTH_LEN: usize = 4;

const MINIMUM_PACKET_LEN: usize = 16;

const PADDING_LENGTH_LEN: usize = 1;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use super::connection::Connection;
use tokio::io::{AsyncRead, AsyncWrite};
use super::Handler;
use {HandlerError, Status, AtomicPoll};
use futures::{Poll, Async, Future};
use thrussh_keys::key;
use std::sync::Arc;
use tcp::Tcp;
use auth;

impl<R: AsyncRead + AsyncWrite + Tcp, H: Handler> Connection<R, H> {

    /// Try to authenticate this client using a password.
    pub fn authenticate_password(mut self, user: &str, password: String) -> Authenticate<R, H> {
        let is_waiting = if let Some(ref mut s) = self.session {
            let meth = auth::Method::Password { password };
            s.write_auth_request_if_needed(user, meth)
        } else { false };
        if is_waiting {
            self.abort_read().unwrap_or(());
        }
        Authenticate(Some(self))
    }

    /// Try to authenticate this client using a key pair.
    pub fn authenticate_key(mut self, user: &str, key: Arc<key::KeyPair>) -> Authenticate<R, H> {
        let is_waiting = if let Some(ref mut s) = self.session {
            let meth = auth::Method::PublicKey { key };
            s.write_auth_request_if_needed(user, meth)
        } else { false };
        if is_waiting {
            self.abort_read().unwrap_or(());
        }
        Authenticate(Some(self))
    }

    /// Try to authenticate this client using a key pair.
    pub fn authenticate_key_future(
        mut self,
        user: &str,
        key: key::PublicKey,
    ) -> Authenticate<R, H>
    {
        let is_waiting = if let Some(ref mut s) = self.session {
            let meth = auth::Method::FuturePublicKey { key };
            s.write_auth_request_if_needed(user, meth)
        } else { false };
        if is_waiting {
            self.abort_read().unwrap_or(());
        }
        Authenticate(Some(self))
    }
}

/// An authenticating future, ultimately resolving into an authenticated connection.
pub struct Authenticate<R: AsyncRead + AsyncWrite + Tcp, H: Handler>(Option<Connection<R, H>>);

impl<R: AsyncRead + AsyncWrite + Tcp, H: Handler> Future for Authenticate<R, H> {
    type Item = Connection<R, H>;
    type Error = HandlerError<H::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            debug!("authenticated loop");
            let done = if let Some(ref c) = self.0 {
                c.is_reading() && {
                    if let Some(ref session) = c.session {
                        session.is_authenticated() || session.0.auth_method.is_none()
                    } else {
                        false
                    }
                }
            } else {
                false
            };
            if done {
                return Ok(Async::Ready(self.0.take().unwrap()))
            }
            let status = if let Some(ref mut c) = self.0 {
                debug!("atomic poll");
                try_ready!(c.atomic_poll())
            } else {
                unreachable!()
            };
            debug!("/atomic poll");

            if let Status::Disconnect = status {
                debug!("disconnect");
                return Ok(Async::Ready(self.0.take().unwrap()));
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use super::*;
use tokio::io::{AsyncRead, AsyncWrite};
use tcp::Tcp;

impl<R: AsyncRead + AsyncWrite, H: Handler> Connection<R, H> {
    /// Ask the server to open a session channel.
    pub fn channel_open_session(mut self) -> ChannelOpen<R, H, SessionChannel> {
        let num = if let Some(ref mut s) = self.session {
            s.channel_open_session().unwrap()
        } else {
            unreachable!()
        };
        ChannelOpen {
            connection: Some(self),
            channel: num,
            channel_type: PhantomData,
            first_round: true,
        }
    }

    /// Ask the server to open an X11 forwarding channel.
    pub fn channel_open_x11(
        mut self,
        originator_address: &str,
        originator_port: u32,
    ) -> ChannelOpen<R, H, X11Channel> {
        let num = if let Some(ref mut s) = self.session {
            s.channel_open_x11(originator_address, originator_port)
                .unwrap()
        } else {
            unreachable!()
        };
        ChannelOpen {
            connection: Some(self),
            channel: num,
            channel_type: PhantomData,
            first_round: true,
        }
    }

    /// Ask the server to open a direct TCP/IP forwarding channel.
    pub fn channel_open_direct_tcpip(
        mut self,
        host_to_connect: &str,
        port_to_connect: u32,
        originator_address: &str,
        originator_port: u32,
    ) -> ChannelOpen<R, H, DirectTcpIpChannel> {
        let num = if let Some(ref mut s) = self.session {
            s.channel_open_direct_tcpip(
                host_to_connect,
                port_to_connect,
                originator_address,
                originator_port,
            ).unwrap()
        } else {
            unreachable!()
        };
        ChannelOpen {
            connection: Some(self),
            channel: num,
            channel_type: PhantomData,
            first_round: true,
        }
    }
}
use std::marker::PhantomData;

#[doc(hidden)]
pub enum X11Channel {}
#[doc(hidden)]
pub enum SessionChannel {}
#[doc(hidden)]
pub enum DirectTcpIpChannel {}

/// A future resolving into an open channel number of type
/// `ChannelType`, which can be either `SessionChannel`, `X11Channel`
/// or `DirectTcpIdChannel`.
pub struct ChannelOpen<R: AsyncRead + AsyncWrite, H: Handler, ChannelType> {
    connection: Option<Connection<R, H>>,
    channel: ChannelId,
    channel_type: PhantomData<ChannelType>,
    first_round: bool,
}

impl<R: AsyncRead + AsyncWrite + Tcp, H: Handler, ChannelType> Future
    for ChannelOpen<R, H, ChannelType> {
    type Item = (Connection<R, H>, ChannelId);
    type Error = HandlerError<H::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {

        if self.first_round {
            if let Some(ref mut c) = self.connection {
                c.abort_read()?;
            }
            self.first_round = false
        }
        loop {
            debug!("channelopen loop");
            let is_open = if let Some(ref c) = self.connection {
                if let Some(ref s) = c.session {
                    s.channel_is_open(self.channel) && c.is_reading()
                } else {
                    false
                }
            } else {
                false
            };
            if is_open {
                return Ok(Async::Ready(
                    (self.connection.take().unwrap(), self.channel),
                ));
            }

            let status = if let Some(ref mut c) = self.connection {
                try_ready!(c.atomic_poll())
            } else {
                unreachable!()
            };

            if let Status::Disconnect = status {
                return Err(HandlerError::Error(Error::Disconnect));
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
use super::*;
use cipher;
use msg;
use thrussh_keys::encoding::Reader;
use std::sync::Arc;
use tokio::io::{AsyncRead, AsyncWrite};
use ssh_read::SshRead;
use tcp::Tcp;
use tokio_io;
use tokio_timer::Sleep;

#[doc(hidden)]
pub enum ConnectionState<R: AsyncRead + AsyncWrite, H: Handler> {
    ReadSshId(SshRead<R>),
    WriteSshId(WriteAll<R, CryptoVec>),
    Read(cipher::CipherRead<SshRead<R>>),
    Write(WriteAll<SshRead<R>, CryptoVec>),
    Flush(Flush<SshRead<R>>),
    Pending {
        pending: PendingFuture<H>,
        stream: SshRead<R>,
    },
    Shutdown {
        read: tokio_io::io::Read<SshRead<R>, CryptoVec>,
        read_buffer: SSHBuffer,
    },
}

#[doc(hidden)]
pub enum PendingFuture<H: Handler> {
    ServerKeyCheck {
        check: H::FutureBool,
        kexdhdone: KexDhDone,
        buf_len: usize,
        session: Session,
    },
    AgentSign {
        sign: H::FutureSign,
        session: Session,
        request_index: usize,
        buffer_len: usize,
    },
    SessionUnit(H::SessionUnit),
    Done(H, Session),
}

/// Client connection. A connection implements `Future`, returning
/// `()` when it finishes (for instance if the client and server agree
/// to close the connection).
pub struct Connection<R: AsyncRead + AsyncWrite, H: Handler> {
    #[doc(hidden)]
    pub read_buffer: Option<SSHBuffer>,
    #[doc(hidden)]
    /// Session of this connection.
    pub session: Option<Session>,
    #[doc(hidden)]
    pub state: Option<ConnectionState<R, H>>,
    #[doc(hidden)]
    pub buffer: CryptoVec,
    #[doc(hidden)]
    /// Handler for this connection.
    pub handler: Option<H>,
    #[doc(hidden)]
    pub timeout: Option<Sleep>,
}

impl<R: AsyncRead + AsyncWrite, H: Handler> std::ops::Deref
    for Connection<R, H> {
    type Target = Session;
    fn deref(&self) -> &Self::Target {
        self.session.as_ref().unwrap()
    }
}

impl<R: AsyncRead + AsyncWrite, H: Handler> std::ops::DerefMut
    for Connection<R, H> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.session.as_mut().unwrap()
    }
}

impl<
    R: AsyncRead + AsyncWrite + Tcp,
    H: Handler,
> AtomicPoll<HandlerError<H::Error>> for Connection<R, H> {
    /// Process all packets available in the buffer, and returns
    /// whether the connection should continue.
    fn atomic_poll(&mut self) -> Poll<Status, HandlerError<H::Error>> {

        match self.state.take() {
            None => Ok(Async::Ready(Status::Disconnect)),
            Some(ConnectionState::WriteSshId(mut write)) => {
                if let Async::Ready((stream, mut buf)) = write.poll()? {
                    if let Some(ref mut session) = self.session {
                        buf.clear();
                        session.0.write_buffer.buffer = buf;
                    }
                    self.state = Some(ConnectionState::ReadSshId(SshRead::new(stream)));
                    Ok(Async::Ready(Status::Ok))
                } else {
                    Ok(Async::NotReady)
                }
            }
            Some(ConnectionState::ReadSshId(mut stream)) => {
                let is_ready = if let Async::Ready(sshid) = stream.read_ssh_id()? {
                    self.read_ssh_id(sshid)?;
                    true
                } else {
                    false
                };
                debug!("SSH- read {:?}", is_ready);
                if is_ready {
                    if let Some(ref mut session) = self.session {
                        session.flush()?;
                        self.state = Some(ConnectionState::Write(
                            session.0.write_buffer.write_all(stream),
                        ));
                    }
                    Ok(Async::Ready(Status::Ok))
                } else {
                    self.state = Some(ConnectionState::ReadSshId(stream));
                    Ok(Async::NotReady)
                }
            }
            Some(ConnectionState::Pending { pending, stream }) => {
                debug!("atomic pending");
                self.poll_pending(pending, stream)
            }
            Some(ConnectionState::Write(mut write)) => {
                debug!("atomic writing");
                if let Async::Ready((stream, mut buf)) = write.poll()? {
                    if let Some(ref mut session) = self.session {
                        buf.clear();
                        session.0.write_buffer.buffer = buf;

                        session.flush()?;
                        self.state = Some(ConnectionState::Flush(flush(stream)));
                        Ok(Async::Ready(Status::Ok))
                    } else {
                        unreachable!()
                    }
                } else {
                    self.state = Some(ConnectionState::Write(write));
                    Ok(Async::NotReady)
                }
            }
            Some(ConnectionState::Flush(mut flush)) => {
                debug!("atomic flushing");
                if let Async::Ready(mut stream) = flush.poll()? {

                    if let Some(ref mut session) = self.session {
                        if session.0.disconnected {
                            stream.tcp_shutdown()?;
                            let mut read_buffer = self.read_buffer.take().unwrap();
                            let buffer =
                                std::mem::replace(&mut read_buffer.buffer, CryptoVec::new());
                            self.state = Some(ConnectionState::Shutdown {
                                read: tokio_io::io::read(stream, buffer),
                                read_buffer,
                            });
                        } else {
                            let mut buf = self.read_buffer.take().unwrap();
                            buf.buffer.clear();
                            self.state = Some(ConnectionState::Read(
                                cipher::read(stream, buf, session.0.cipher.clone()),
                            ));
                        }
                    }
                    Ok(Async::Ready(Status::Ok))
                } else {
                    self.state = Some(ConnectionState::Flush(flush));
                    Ok(Async::NotReady)
                }
            }
            Some(ConnectionState::Read(mut read)) => {
                debug!("atomic reading");
                if let Async::Ready((stream, mut buf, end)) = read.poll()? {
                    debug!("buf: {:?}", buf.buffer.as_ref());
                    // Handle the transport layer.
                    if buf.buffer.len() < 5 || buf.buffer[5] == msg::DISCONNECT {
                        // Disconnect.
                        let buffer = std::mem::replace(&mut buf.buffer, CryptoVec::new());
                        self.state = Some(ConnectionState::Shutdown {
                            read: tokio_io::io::read(stream, buffer),
                            read_buffer: buf,
                        });
                        return Ok(Async::Ready(Status::Ok));
                    } else if buf.buffer[5] <= 4 {
                        let session = self.session.as_ref().unwrap();
                        buf.buffer.clear();
                        self.state = Some(ConnectionState::Read(
                            cipher::read(stream, buf, session.0.cipher.clone()),
                        ));
                        return Ok(Async::Ready(Status::Ok));
                    } else {
                        let result = self.read(&buf.buffer[5..end], stream);
                        self.read_buffer = Some(buf);
                        return result;
                    }
                } else {
                    debug!("atomic reading not ready");
                    self.state = Some(ConnectionState::Read(read));
                    Ok(Async::NotReady)
                }
            }
            Some(ConnectionState::Shutdown {
                     mut read,
                     mut read_buffer,
                 }) => {
                debug!("atomic shutdown");
                if let Async::Ready((stream, mut buf, n)) = read.poll()? {
                    if n == 0 {
                        read_buffer.buffer = buf;
                        self.read_buffer = Some(read_buffer);
                        Ok(Async::Ready(Status::Disconnect))
                    } else {
                        buf.clear();
                        self.state = Some(ConnectionState::Shutdown {
                            read: tokio_io::io::read(stream, buf),
                            read_buffer,
                        });
                        Ok(Async::Ready(Status::Ok))
                    }
                } else {
                    self.state = Some(ConnectionState::Shutdown { read, read_buffer });
                    Ok(Async::NotReady)
                }
            }
        }
    }
}


impl<R: AsyncRead + AsyncWrite, H: Handler> Connection<R, H> {
    fn poll_pending(
        &mut self,
        pending: PendingFuture<H>,
        stream: SshRead<R>,
    ) -> Poll<Status, HandlerError<H::Error>> {

        match pending {
            PendingFuture::SessionUnit(mut f) => {
                if let Async::Ready((h, mut session)) = f.poll().map_err(HandlerError::Handler)? {
                    self.handler = Some(h);
                    session.flush()?;
                    self.state = Some(ConnectionState::Write(
                        session.0.write_buffer.write_all(stream),
                    ));
                    self.session = Some(session);
                    Ok(Async::Ready(Status::Ok))
                } else {
                    self.state = Some(ConnectionState::Pending {
                        pending: PendingFuture::SessionUnit(f),
                        stream,
                    });
                    Ok(Async::NotReady)
                }
            }
            PendingFuture::Done(h, mut session) => {
                self.handler = Some(h);
                session.flush()?;
                self.state = Some(ConnectionState::Write(
                    session.0.write_buffer.write_all(stream),
                ));
                self.session = Some(session);
                Ok(Async::Ready(Status::Ok))
            }
            PendingFuture::ServerKeyCheck {
                mut check,
                kexdhdone,
                buf_len,
                mut session,
            } => {
                match check.poll().map_err(HandlerError::Handler)? {
                    Async::Ready((h, true)) => {
                        self.pending_server_key_check(
                            buf_len,
                            kexdhdone,
                            &mut session,
                        )?;
                        self.handler = Some(h);
                        session.flush()?;
                        self.state = Some(ConnectionState::Write(
                            session.0.write_buffer.write_all(stream),
                        ));
                        self.session = Some(session);
                        Ok(Async::Ready(Status::Ok))
                    }
                    Async::Ready((h, false)) => {
                        self.handler = Some(h);
                        session.flush()?;
                        self.state = Some(ConnectionState::Write(
                            session.0.write_buffer.write_all(stream),
                        ));
                        self.session = Some(session);
                        Err(HandlerError::Error(Error::UnknownKey))
                    }
                    Async::NotReady => {
                        self.state = Some(ConnectionState::Pending {
                            pending: PendingFuture::ServerKeyCheck {
                                check: check,
                                kexdhdone: kexdhdone,
                                buf_len: buf_len,
                                session,
                            },
                            stream,
                        });
                        Ok(Async::NotReady)
                    }
                }
            }
            PendingFuture::AgentSign { mut sign, mut session, request_index, buffer_len } => {
                if let Async::Ready((h, signature)) = sign.poll().map_err(HandlerError::Handler)? {

                    if signature.len() != buffer_len {
                        // The buffer was modified.
                        if let Some(ref mut enc) = session.0.encrypted {
                            push_packet!(enc.write, {
                                enc.write.extend(&signature[request_index..]);
                            })
                        }
                    } else {
                        session.0.auth_method = None;
                    }
                    session.0.buffer = Some(signature);
                    session.flush()?;
                    self.state = Some(ConnectionState::Write(
                        session.0.write_buffer.write_all(stream),
                    ));

                    self.handler = Some(h);
                    self.session = Some(session);
                    Ok(Async::Ready(Status::Ok))
                } else {
                    self.state = Some(ConnectionState::Pending {
                        pending: PendingFuture::AgentSign { sign, session, request_index, buffer_len },
                        stream,
                    });
                    Ok(Async::NotReady)
                }
            }
        }
    }

    fn read(
        &mut self,
        buf: &[u8],
        stream: SshRead<R>,
    ) -> Poll<Status, HandlerError<<H as Handler>::Error>> {

        let mut session = self.session.take().unwrap();
        // Handle key exchange/re-exchange.
        match session.0.kex.take() {
            Some(Kex::KexInit(kexinit)) => {
                if kexinit.algo.is_some() || buf[0] == msg::KEXINIT ||
                    session.0.encrypted.is_none()
                {
                    let kexdhdone = kexinit.client_parse(
                        session.0.config.as_ref(),
                        &session.0.cipher,
                        buf,
                        &mut session.0.write_buffer,
                    );
                    match kexdhdone {
                        Ok(kexdhdone) => {
                            session.0.kex = Some(Kex::KexDhDone(kexdhdone));
                            session.flush()?;
                            debug!("calling write_all");
                            self.state = Some(ConnectionState::Write(
                                session.0.write_buffer.write_all(stream),
                            ));
                            self.session = Some(session);
                            return Ok(Async::Ready(Status::Ok));
                        }
                        Err(e) => {
                            self.session = Some(session);
                            return Err(HandlerError::Error(e));
                        }
                    }
                } else {
                    unreachable!()
                }
            }
            Some(Kex::KexDhDone(mut kexdhdone)) => {
                if kexdhdone.names.ignore_guessed {
                    kexdhdone.names.ignore_guessed = false;
                    session.0.kex = Some(Kex::KexDhDone(kexdhdone));
                    session.flush()?;
                    debug!("calling write_all");
                    self.state = Some(ConnectionState::Write(
                        session.0.write_buffer.write_all(stream),
                    ));
                    self.session = Some(session);
                    return Ok(Async::Ready(Status::Ok));
                } else {
                    // We've sent ECDH_INIT, waiting for ECDH_REPLY
                    if buf[0] == msg::KEX_ECDH_REPLY {
                        let mut reader = buf.reader(1);
                        let pubkey = reader.read_string()?; // server public key.
                        let pubkey = parse_public_key(pubkey)?;
                        self.state = Some(ConnectionState::Pending {
                            pending: PendingFuture::ServerKeyCheck {
                                check: self.handler.take().unwrap().check_server_key(&pubkey),
                                kexdhdone: kexdhdone,
                                buf_len: buf.len(),
                                session: session,
                            },
                            stream,
                        });
                        return Ok(Async::Ready(Status::Ok));
                    } else {
                        self.state = Some(ConnectionState::Write(
                            session.0.write_buffer.write_all(stream),
                        ));
                        self.session = Some(session);
                        return Err(HandlerError::Error(Error::Inconsistent));
                    }
                }
            }
            Some(Kex::NewKeys(newkeys)) => {
                if buf[0] != msg::NEWKEYS {
                    return Err(HandlerError::Error(Error::Kex));
                }
                session.0.encrypted(
                    EncryptedState::WaitingServiceRequest,
                    newkeys,
                );
                // Ok, NEWKEYS received, now encrypted.
                let p = b"\x05\0\0\0\x0Cssh-userauth";
                session.0.cipher.write(p, &mut session.0.write_buffer);
                session.flush()?;
                self.state = Some(ConnectionState::Write(
                    session.0.write_buffer.write_all(stream),
                ));
                self.session = Some(session);
                return Ok(Async::Ready(Status::Ok));
            }
            Some(kex) => {
                session.0.kex = Some(kex);
                self.state = Some(ConnectionState::Write(
                    session.0.write_buffer.write_all(stream),
                ));
                self.session = Some(session);
                return Ok(Async::Ready(Status::Ok));
            }
            None => {}
        }
        debug!("atomic poll: take 2");
        self.state = Some(ConnectionState::Pending {
            pending: session.client_read_encrypted(
                self.handler.take().unwrap(),
                &buf
            )?,
            stream,
        });
        Ok(Async::Ready(Status::Ok))
    }
}

impl<R: AsyncRead + AsyncWrite, H: Handler> Connection<R, H> {
    #[doc(hidden)]
    pub fn is_reading(&self) -> bool {
        match self.state {
            Some(ConnectionState::Read(_)) => true,
            _ => false,
        }
    }

    #[doc(hidden)]
    pub fn abort_read(&mut self) -> Result<(), Error> {
        match self.state.take() {
            Some(ConnectionState::Read(mut read)) => {
                if let Some((stream, read_buffer)) = read.try_abort() {
                    self.read_buffer = Some(read_buffer);
                    if let Some(ref mut session) = self.session {
                        session.flush()?;
                    }
                    self.state = Some(ConnectionState::Write(
                        self.session.as_mut().unwrap().0.write_buffer.write_all(
                            stream,
                        ),
                    ))
                } else {
                    self.state = Some(ConnectionState::Read(read))
                }
            }
            st => self.state = st,
        }
        Ok(())
    }

    fn poll_timeout(&mut self) -> Poll<(), HandlerError<H::Error>> {
        if let Some(ref mut timeout) = self.timeout {
            if let Async::Ready(()) = timeout.poll()? {
                debug!("Timeout, shutdown");
                if let Some(ref mut s) = self.session {
                    s.0.disconnected = true;
                }
                return Err(HandlerError::Error(Error::ConnectionTimeout))
            }
        }
        Ok(Async::Ready(()))
    }

    fn pending_server_key_check(
        &mut self,
        buf_len: usize,
        mut kexdhdone: KexDhDone,
        session: &mut Session,
    ) -> Result<(), HandlerError<H::Error>> {

        let hash = {
            let buf = &self.read_buffer.as_ref().unwrap().buffer[5..5 + buf_len];
            let mut reader = buf.reader(1);
            let pubkey = reader.read_string()?; // server public key.
            let pubkey = parse_public_key(pubkey)?;
            debug!("server_public_Key: {:?}", pubkey);
            let server_ephemeral = reader.read_string()?;
            kexdhdone.exchange.server_ephemeral.extend(server_ephemeral);
            let signature = reader.read_string()?;

            kexdhdone.kex.compute_shared_secret(
                &kexdhdone.exchange.server_ephemeral,
            )?;

            let hash = kexdhdone.kex.compute_exchange_hash(
                &pubkey,
                &kexdhdone.exchange,
                &mut self.buffer,
            )?;
            debug!("exchange hash: {:?}", hash);
            let signature = {
                let mut sig_reader = signature.reader(0);
                let sig_type = sig_reader.read_string()?;
                debug!("sig_type: {:?}", sig_type);
                sig_reader.read_string()?
            };
            use thrussh_keys::key::Verify;
            debug!("signature: {:?}", signature);
            assert!(pubkey.verify_server_auth(hash.as_ref(), signature));
            hash
        };
        if let Some(ref mut buffer) = session.0.buffer {
            let mut newkeys = kexdhdone.compute_keys(
                hash,
                &mut self.buffer,
                buffer,
                false,
            )?;
            session.0.cipher.write(
                &[msg::NEWKEYS],
                &mut session.0.write_buffer,
            );
            session.0.kex = Some(Kex::NewKeys(newkeys));
            newkeys.sent = true;
        }
        Ok(())
    }


    /// Ask the server to close a channel, finishing any pending write and read.
    pub fn channel_close(&mut self, channel: ChannelId) {
        if let Some(ref mut s) = self.session {
            s.0.byte(channel, msg::CHANNEL_CLOSE);
        }
    }

    /// Gets a borrow to the connection's handler.
    pub fn handler(&self) -> &H {
        self.handler.as_ref().unwrap()
    }

    /// Gets a mutable borrow to the connection's handler.
    pub fn handler_mut(&mut self) -> &mut H {
        self.handler.as_mut().unwrap()
    }


    /// Tests whether a channel is open.
    pub fn is_channel_open(&self, channel: ChannelId) -> bool {
        if let Some(ref session) = self.session {
            if let Some(ref enc) = session.0.encrypted {
                return enc.channels.contains_key(&channel);
            }
        }
        false
    }


    /// Create a new client connection.
    pub fn new(
        config: Arc<Config>,
        stream: R,
        handler: H,
        timeout: Option<Sleep>,
    ) -> Result<Self, Error> {
        let mut write_buffer = SSHBuffer::new();
        write_buffer.send_ssh_id(config.as_ref().client_id.as_bytes());
        let write = write_buffer.write_all(stream);
        let mut connection = Connection {
            read_buffer: Some(SSHBuffer::new()),
            timeout: timeout,
            session: Some(Session(CommonSession {
                write_buffer: write_buffer,
                kex: None,
                auth_user: String::new(),
                auth_method: None, // Client only.
                cipher: Arc::new(cipher::CLEAR_PAIR),
                encrypted: None,
                config: config,
                wants_reply: false,
                disconnected: false,
                buffer: Some(CryptoVec::new()),
            })),
            state: Some(ConnectionState::WriteSshId(write)),
            handler: Some(handler),
            buffer: CryptoVec::new(),
        };
        if let Some(ref mut s) = connection.session {
            try!(s.flush())
        }
        Ok(connection)
    }

    #[doc(hidden)]
    fn read_ssh_id(&mut self, sshid: &[u8]) -> Result<(), Error> {
        // self.read_buffer.bytes += sshid.bytes_read + 2;
        let mut exchange = Exchange::new();
        exchange.server_id.extend(sshid);
        // Preparing the response
        if let Some(ref mut s) = self.session {
            exchange.client_id.extend(
                s.0.config.as_ref().client_id.as_bytes(),
            );
            let mut kexinit = KexInit {
                exchange: exchange,
                algo: None,
                sent: false,
                session_id: None,
            };
            kexinit.client_write(
                s.0.config.as_ref(),
                &mut s.0.cipher,
                &mut s.0.write_buffer,
            )?;
            s.0.kex = Some(Kex::KexInit(kexinit));
        }
        Ok(())
    }
}




impl<R: AsyncRead + AsyncWrite + Tcp, H: Handler> Future for Connection<R, H> {
    type Item = ();
    type Error = HandlerError<H::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // If timeout, shutdown the socket.
        try_ready!(self.poll_timeout()); // returns an error if there's a timeout.
        debug!("no timeout");
        if self.is_reading() {
            // the write buffer is in the connection, we can flush.
            self.flush()?;
            let needs_write = if let Some(ref mut session) = self.session {
                !session.0.write_buffer.buffer.is_empty()
            } else {
                false
            };
            if needs_write {
                self.abort_read()?
            }
        }
        loop {
            debug!("client polling");
            if let Status::Disconnect = try_ready!(self.atomic_poll()) {
                return Ok(Async::Ready(()));
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use super::connection::{Connection, ConnectionState};
use tokio::io::{AsyncRead, AsyncWrite};
use super::Handler;
use {ChannelId, HandlerError, Error, Status, AtomicPoll};
use futures::{Poll, Async, Future};
use tcp::Tcp;

impl<R: AsyncRead + AsyncWrite, H: Handler> Connection<R, H> {
    /// Send data to a channel. On session channels, `extended` can be
    /// used to encode standard error by passing `Some(1)`, and stdout
    /// by passing `None`.
    pub fn data<T: AsRef<[u8]>>(
        self,
        channel: ChannelId,
        extended: Option<u32>,
        data: T,
    ) -> Data<R, H, T> {

        debug!("data: {:?}", data.as_ref().len());
        Data {
            connection: Some(self),
            channel: channel,
            extended: extended,
            data: Some(data),
            position: 0,
            first_round: true,
        }
    }
}

/// Future for sending data.
pub struct Data<R: AsyncRead + AsyncWrite, H: Handler, T: AsRef<[u8]>> {
    connection: Option<Connection<R, H>>,
    data: Option<T>,
    extended: Option<u32>,
    channel: ChannelId,
    position: usize,
    first_round: bool,
}

// We are careful here, to leave the connection in the Read state (the
// only cancellable one) before returning Async::Ready.
impl<R: AsyncRead + AsyncWrite + Tcp, H: Handler, T: AsRef<[u8]>> Future for Data<R, H, T> {
    type Item = (Connection<R, H>, T);
    type Error = HandlerError<H::Error>;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {

        let mut connection = self.connection.take().unwrap();
        if self.first_round {
            connection.abort_read()?;
            self.first_round = false
        }
        let data = self.data.take().unwrap();

        loop {
            debug!("Data loop");
            // Do everything we can do.
            let status = connection.atomic_poll()?;
            let mut not_ready = false;
            match status {
                Async::Ready(Status::Disconnect) => return Err(From::from(Error::Disconnect)),
                Async::Ready(Status::Ok) if connection.is_reading() => {}
                Async::Ready(Status::Ok) => continue,
                Async::NotReady if connection.is_reading() => not_ready = true,
                Async::NotReady => {
                    self.connection = Some(connection);
                    self.data = Some(data);
                    return Ok(Async::NotReady);
                }
            }

            let mut session = connection.session.take().unwrap();
            {
                let data_ = data.as_ref();
                let enc = session.0.encrypted.as_mut().unwrap();
                self.position += enc.data(self.channel, self.extended, &data_[self.position..]);
            }
            session.flush()?;
            if !session.0.write_buffer.buffer.is_empty() {
                if let Some(ConnectionState::Read(mut read)) = connection.state {
                    if let Some((stream, read_buffer)) = read.try_abort() {
                        connection.read_buffer = Some(read_buffer);
                        connection.state = Some(ConnectionState::Write(
                            session.0.write_buffer.write_all(stream),
                        ));
                        connection.session = Some(session);
                    } else {
                        connection.state = Some(ConnectionState::Read(read));
                        connection.session = Some(session);
                    }
                } else {
                    connection.session = Some(session);
                }
            } else if self.position < data.as_ref().len() {
                connection.session = Some(session);
                if not_ready {
                    self.connection = Some(connection);
                    self.data = Some(data);
                    return Ok(Async::NotReady);
                }
            } else {
                connection.session = Some(session);
                return Ok(Async::Ready((connection, data)));
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//
use cryptovec::CryptoVec;
use {Sig, Error, HandlerError, ChannelOpenFailure, ChannelId};
use std;
use auth;
use session::*;
use msg;
use thrussh_keys::encoding::{Encoding, Reader};
use negotiation::Named;
use key::PubKey;
use negotiation;
use negotiation::Select;
use super::connection::PendingFuture;
const SSH_CONNECTION: &'static [u8] = b"ssh-connection";

enum ReadEncrypted {
    Authenticated,
    AgentSign(usize),
    None
}

impl super::session::Session {
    #[doc(hidden)]
    pub fn client_read_encrypted<C: super::Handler>(
        mut self,
        client: C,
        buf: &[u8],
    ) -> Result<PendingFuture<C>, HandlerError<C::Error>> {
        debug!("client_read_encrypted");
        // Either this packet is a KEXINIT, in which case we start a key re-exchange.
        if buf[0] == msg::KEXINIT {
            // Now, if we're encrypted:
            if let Some(ref mut enc) = self.0.encrypted {

                // If we're not currently rekeying, but buf is a rekey request
                if let Some(exchange) = std::mem::replace(&mut enc.exchange, None) {
                    let kexinit = KexInit::received_rekey(
                        exchange,
                        negotiation::Client::read_kex(
                            buf,
                            &self.0.config.as_ref().preferred,
                        )?,
                        &enc.session_id,
                    );
                    self.0.kex = Some(Kex::KexDhDone(kexinit.client_parse(
                        self.0.config.as_ref(),
                        &mut self.0.cipher,
                        buf,
                        &mut self.0.write_buffer,
                    )?));
                }
            } else {
                unreachable!()
            }
            return Ok(PendingFuture::Done(client, self));
        }
        // If we've successfully read a packet.
        debug!("buf = {:?}", buf);
        let mut state = ReadEncrypted::None;
        if let Some(ref mut enc) = self.0.encrypted {

            match enc.state.take() {
                 Some(EncryptedState::WaitingServiceRequest) => {
                    debug!(
                        "waiting service request, {:?} {:?}",
                        buf[0],
                        msg::SERVICE_ACCEPT
                    );
                    if buf[0] == msg::SERVICE_ACCEPT {
                        let mut r = buf.reader(1);
                        if r.read_string()? == b"ssh-userauth" {
                            if let Some(ref meth) = self.0.auth_method {
                                let auth_request = auth::AuthRequest {
                                    methods: auth::MethodSet::all(),
                                    partial_success: false,
                                    current: None,
                                    rejection_count: 0,
                                };
                                let len = enc.write.len();
                                if enc.write_auth_request(&self.0.auth_user, meth) {
                                    debug!("enc: {:?}", &enc.write[len..]);
                                    enc.state =
                                        Some(EncryptedState::WaitingAuthRequest(auth_request));
                                }
                            } else {
                                return Err(HandlerError::Error(Error::NoAuthMethod));
                            }
                        } else {
                            enc.state = Some(EncryptedState::WaitingServiceRequest)
                        }
                    } else {
                        debug!("unknown message: {:?}", buf);
                        return Err(HandlerError::Error(Error::Inconsistent));
                    }
                }
                Some(EncryptedState::WaitingAuthRequest(mut auth_request)) => {
                    if buf[0] == msg::USERAUTH_SUCCESS {

                        debug!("userauth_success");
                        enc.state = Some(EncryptedState::Authenticated);

                    } else if buf[0] == msg::USERAUTH_FAILURE {

                        debug!("userauth_failure");

                        let mut r = buf.reader(1);
                        let remaining_methods = r.read_string()?;
                        debug!("remaining methods {:?}", std::str::from_utf8(remaining_methods));
                        auth_request.methods = auth::MethodSet::empty();
                        for method in remaining_methods.split(|&c| c == b',') {
                            if let Some(m) = auth::MethodSet::from_bytes(method) {
                                auth_request.methods |= m
                            }
                        }
                        let no_more_methods = auth_request.methods.is_empty();
                        self.0.auth_method = None;
                        enc.state = Some(EncryptedState::WaitingAuthRequest(auth_request));

                        // If no other authentication method is allowed by the server, give up.
                        if no_more_methods {
                            return Err(HandlerError::Error(Error::NoAuthMethod));
                        }
                    } else if buf[0] == msg::USERAUTH_PK_OK {
                        debug!("userauth_pk_ok");
                        if let Some(auth::CurrentRequest::PublicKey {
                                        ref mut sent_pk_ok, ..
                                    }) = auth_request.current
                        {
                            *sent_pk_ok = true;
                        }

                        if let Some(ref mut buffer) = self.0.buffer {
                            match self.0.auth_method {
                                Some(ref auth_method @ auth::Method::PublicKey { .. }) =>
                                    enc.client_send_signature(
                                        &self.0.auth_user,
                                        auth_method,
                                        buffer,
                                    )?,
                                Some(auth::Method::FuturePublicKey { ref key }) =>
                                    state = ReadEncrypted::AgentSign(
                                        enc.client_make_to_sign(
                                            &self.0.auth_user,
                                            key,
                                            buffer
                                        )
                                    ),
                                _ => {}
                            }
                        }
                        enc.state = Some(EncryptedState::WaitingAuthRequest(auth_request));
                    } else {
                        debug!("unknown message: {:?}", buf);
                        return Err(HandlerError::Error(Error::Inconsistent));
                    }
                }
                Some(EncryptedState::Authenticated) => {
                    enc.state = Some(EncryptedState::Authenticated);
                    state = ReadEncrypted::Authenticated
                }
                None => unreachable!(),
            }
        }
        match state {
            ReadEncrypted::Authenticated => {
                self.client_read_authenticated(client, buf)
            },
            ReadEncrypted::AgentSign(request_index) => {
                let (sign, buffer_len) = match self.0.auth_method {
                    Some(auth::Method::FuturePublicKey { ref key }) => {
                        let buf = self.0.buffer.take().unwrap();
                        let len = buf.len();
                        (client.auth_publickey_sign(key, buf), len)
                    },
                    _ => unreachable!()
                };
                Ok(PendingFuture::AgentSign { sign, session: self, request_index, buffer_len })
            }
            ReadEncrypted::None => Ok(PendingFuture::Done(client, self))
        }
    }

    fn client_read_authenticated<C: super::Handler>(
        mut self,
        client: C,
        buf: &[u8],
    ) -> Result<PendingFuture<C>, HandlerError<C::Error>> {

        match buf[0] {
            msg::CHANNEL_OPEN_CONFIRMATION => {
                debug!("channel_open_confirmation");
                let mut reader = buf.reader(1);
                let id_send = ChannelId(try!(reader.read_u32()));
                let id_recv = try!(reader.read_u32());
                let window = try!(reader.read_u32());
                let max_packet = try!(reader.read_u32());

                if let Some(ref mut enc) = self.0.encrypted {

                    if let Some(parameters) = enc.channels.get_mut(&id_send) {

                        parameters.recipient_channel = id_recv;
                        parameters.recipient_window_size = window;
                        parameters.recipient_maximum_packet_size = max_packet;
                        parameters.confirmed = true;

                    } else {
                        // We've not requested this channel, close connection.
                        return Err(HandlerError::Error(Error::Inconsistent));
                    }
                }
                Ok(PendingFuture::SessionUnit(
                    client.channel_open_confirmation(id_send, self),
                ))
            }
            msg::CHANNEL_CLOSE => {
                debug!("channel_close");
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                if let Some(ref mut enc) = self.0.encrypted {
                    enc.channels.remove(&channel_num);
                }
                Ok(PendingFuture::SessionUnit(
                    client.channel_close(channel_num, self),
                ))
            }
            msg::CHANNEL_EOF => {
                debug!("channel_close");
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                Ok(PendingFuture::SessionUnit(
                    client.channel_eof(channel_num, self),
                ))
            }
            msg::CHANNEL_OPEN_FAILURE => {
                debug!("channel_open_failure");
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                let reason_code = ChannelOpenFailure::from_u32(try!(r.read_u32())).unwrap();
                let descr = try!(std::str::from_utf8(try!(r.read_string())));
                let language = try!(std::str::from_utf8(try!(r.read_string())));
                if let Some(ref mut enc) = self.0.encrypted {
                    enc.channels.remove(&channel_num);
                }
                Ok(PendingFuture::SessionUnit(client.channel_open_failure(
                    channel_num,
                    reason_code,
                    descr,
                    language,
                    self,
                )))
            }
            msg::CHANNEL_DATA => {
                debug!("channel_data");
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                let data = try!(r.read_string());
                let target = self.0.config.window_size;
                if let Some(ref mut enc) = self.0.encrypted {
                    enc.adjust_window_size(channel_num, data, target);
                }
                let unit = client.data(channel_num, None, &data, self);
                Ok(PendingFuture::SessionUnit(unit))
            }
            msg::CHANNEL_EXTENDED_DATA => {
                debug!("channel_extended_data");
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                let extended_code = try!(r.read_u32());
                let data = try!(r.read_string());
                let target = self.0.config.window_size;
                if let Some(ref mut enc) = self.0.encrypted {
                    enc.adjust_window_size(channel_num, data, target);
                }
                let unit = client.data(channel_num, Some(extended_code), &data, self);
                Ok(PendingFuture::SessionUnit(unit))
            }
            msg::CHANNEL_REQUEST => {
                debug!("channel_request");
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                let req = try!(r.read_string());
                match req {
                    b"forwarded_tcpip" => {
                        let a = try!(std::str::from_utf8(try!(r.read_string())));
                        let b = try!(r.read_u32());
                        let c = try!(std::str::from_utf8(try!(r.read_string())));
                        let d = try!(r.read_u32());
                        Ok(PendingFuture::SessionUnit(
                            client.channel_open_forwarded_tcpip(
                                channel_num,
                                a,
                                b,
                                c,
                                d,
                                self,
                            ),
                        ))
                    }
                    b"xon-xoff" => {
                        try!(r.read_byte()); // should be 0.
                        let client_can_do = try!(r.read_byte());
                        Ok(PendingFuture::SessionUnit(
                            client.xon_xoff(channel_num, client_can_do != 0, self),
                        ))
                    }
                    b"exit-status" => {
                        try!(r.read_byte()); // should be 0.
                        let exit_status = try!(r.read_u32());
                        Ok(PendingFuture::SessionUnit(
                            client.exit_status(channel_num, exit_status, self),
                        ))
                    }
                    b"exit-signal" => {
                        try!(r.read_byte()); // should be 0.
                        let signal_name = try!(Sig::from_name(try!(r.read_string())));
                        let core_dumped = try!(r.read_byte());
                        let error_message = try!(std::str::from_utf8(try!(r.read_string())));
                        let lang_tag = try!(std::str::from_utf8(try!(r.read_string())));
                        Ok(PendingFuture::SessionUnit(client.exit_signal(
                            channel_num,
                            signal_name,
                            core_dumped != 0,
                            error_message,
                            lang_tag,
                            self,
                        )))
                    }
                    _ => {
                        info!("Unknown channel request {:?}", std::str::from_utf8(req));
                        Ok(PendingFuture::Done(client, self))
                    }
                }
            }
            msg::CHANNEL_WINDOW_ADJUST => {
                debug!("channel_window_adjust");
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                let amount = try!(r.read_u32());
                let mut new_value = 0;
                debug!("amount: {:?}", amount);
                if let Some(ref mut enc) = self.0.encrypted {
                    if let Some(ref mut channel) = enc.channels.get_mut(&channel_num) {
                        channel.recipient_window_size += amount;
                        new_value = channel.recipient_window_size;
                    } else {
                        return Err(HandlerError::Error(Error::WrongChannel));
                    }
                }
                Ok(PendingFuture::SessionUnit(client.window_adjusted(
                    channel_num,
                    new_value as usize,
                    self,
                )))
            }
            msg::GLOBAL_REQUEST => {
                let mut r = buf.reader(1);
                let req = try!(r.read_string());
                info!("Unhandled global request: {:?}", std::str::from_utf8(req));
                Ok(PendingFuture::Done(client, self))
            }
            _ => {
                info!("Unhandled packet: {:?}", buf);
                Ok(PendingFuture::Done(client, self))
            }
        }
    }

    pub(crate) fn write_auth_request_if_needed(&mut self, user: &str, meth: auth::Method) -> bool {
        let mut is_waiting = false;
        if let Some(ref mut enc) = self.0.encrypted {
            is_waiting = match enc.state {
                Some(EncryptedState::WaitingAuthRequest(_)) => true,
                _ => false
            };
            debug!("write_auth_request_if_needed: is_waiting = {:?}", is_waiting);
            if is_waiting {
                enc.write_auth_request(user, &meth);
            }
        }
        self.0.auth_user.clear();
        self.0.auth_user.push_str(user);
        self.0.auth_method = Some(meth);
        is_waiting
    }
}

impl Encrypted {
    fn write_auth_request(
        &mut self,
        user: &str,
        auth_method: &auth::Method,
    ) -> bool {
        // The server is waiting for our USERAUTH_REQUEST.
        push_packet!(self.write, {
            self.write.push(msg::USERAUTH_REQUEST);

            match *auth_method {
                auth::Method::Password { ref password } => {
                    self.write.extend_ssh_string(user.as_bytes());
                    self.write.extend_ssh_string(SSH_CONNECTION);
                    self.write.extend_ssh_string(b"password");
                    self.write.push(1);
                    self.write.extend_ssh_string(password.as_bytes());
                    true
                }
                auth::Method::PublicKey { ref key } => {

                    self.write.extend_ssh_string(user.as_bytes());
                    self.write.extend_ssh_string(SSH_CONNECTION);
                    self.write.extend_ssh_string(b"publickey");
                    self.write.push(0); // This is a probe

                    debug!("write_auth_request: {:?}", key.name());
                    self.write.extend_ssh_string(key.name().as_bytes());
                    key.push_to(&mut self.write);
                    true
                }
                auth::Method::FuturePublicKey { ref key, .. } => {
                    self.write.extend_ssh_string(user.as_bytes());
                    self.write.extend_ssh_string(SSH_CONNECTION);
                    self.write.extend_ssh_string(b"publickey");
                    self.write.push(0); // This is a probe

                    self.write.extend_ssh_string(key.name().as_bytes());
                    key.push_to(&mut self.write);
                    true
                }
            }
        })
    }

    fn client_make_to_sign<Key: Named + PubKey>(
        &mut self,
        user: &str,
        key: &Key,
        buffer: &mut CryptoVec,
    ) -> usize {
        buffer.clear();
        buffer.extend_ssh_string(self.session_id.as_ref());

        let i0 = buffer.len();
        buffer.push(msg::USERAUTH_REQUEST);
        buffer.extend_ssh_string(user.as_bytes());
        buffer.extend_ssh_string(SSH_CONNECTION);
        buffer.extend_ssh_string(b"publickey");
        buffer.push(1);
        buffer.extend_ssh_string(key.name().as_bytes());
        key.push_to(buffer);
        i0
    }

    fn client_send_signature(
        &mut self,
        user: &str,
        method: &auth::Method,
        buffer: &mut CryptoVec,
    ) -> Result<(), Error> {

        match method {
            &auth::Method::PublicKey { ref key } => {
                let i0 = self.client_make_to_sign(user, key.as_ref(), buffer);
                // Extend with self-signature.
                key.add_self_signature(buffer)?;
                push_packet!(self.write, {
                    self.write.extend(&buffer[i0..]);
                })
            }
            _ => {}
        }
        Ok(())
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use super::*;
use negotiation::Select;
use cipher::CipherPair;
use negotiation;

use kex;

impl KexInit {
    pub fn client_parse(
        mut self,
        config: &Config,
        cipher: &CipherPair,
        buf: &[u8],
        write_buffer: &mut SSHBuffer,
    ) -> Result<KexDhDone, Error> {
        debug!("client parse");
        let algo = if self.algo.is_none() {
            // read algorithms from packet.
            self.exchange.server_kex_init.extend(buf);
            super::negotiation::Client::read_kex(buf, &config.preferred)?
        } else {
            return Err(Error::Kex);
        };
        if !self.sent {
            self.client_write(config, cipher, write_buffer)?
        }

        // This function is called from the public API.
        //
        // In order to simplify the public API, we reuse the
        // self.exchange.client_kex buffer to send an extra packet,
        // then truncate that buffer. Without that, we would need an
        // extra buffer.
        let i0 = self.exchange.client_kex_init.len();
        let kex = kex::Algorithm::client_dh(
            algo.kex,
            &mut self.exchange.client_ephemeral,
            &mut self.exchange.client_kex_init,
        )?;

        cipher.write(&self.exchange.client_kex_init[i0..], write_buffer);
        self.exchange.client_kex_init.resize(i0);

        debug!("moving to kexdhdone");
        Ok(KexDhDone {
            exchange: self.exchange,
            names: algo,
            kex: kex,
            key: 0,
            session_id: self.session_id,
        })
    }

    pub fn client_write(
        &mut self,
        config: &Config,
        cipher: &CipherPair,
        write_buffer: &mut SSHBuffer,
    ) -> Result<(), Error> {
        self.exchange.client_kex_init.clear();
        negotiation::write_kex(
            &config.preferred,
            &mut self.exchange.client_kex_init,
        )?;
        self.sent = true;
        cipher.write(&self.exchange.client_kex_init, write_buffer);
        Ok(())
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

use std::sync::Arc;
use std;
use futures::{Poll, Async};
use futures::future::Future;
use tokio_timer::Sleep;
use tokio::net::TcpStream;
use tokio::io::{WriteAll, Flush, flush};
use tokio;
use std::net::ToSocketAddrs;
use {Disconnect, Error, Limits, Sig, ChannelOpenFailure, ChannelId,
     FromFinished, HandlerError, Status, AtomicPoll};
use thrussh_keys::key::parse_public_key;
use thrussh_keys::key;
use auth;
use negotiation;
use cryptovec::CryptoVec;
use session::*;
use sshbuffer::*;
use pty::Pty;

mod encrypted;

mod session;
pub use self::session::*;
mod connection;
pub use self::connection::*;
mod data;
mod authenticate;
mod kex;
mod channel_open;
mod wait;

pub use self::data::*;
pub use self::authenticate::*;
pub use self::kex::*;
pub use self::channel_open::*;
pub use self::wait::*;

/// The configuration of clients.
#[derive(Debug)]
pub struct Config {
    /// The client ID string sent at the beginning of the protocol.
    pub client_id: String,
    /// The bytes and time limits before key re-exchange.
    pub limits: Limits,
    /// The initial size of a channel (used for flow control).
    pub window_size: u32,
    /// The maximal size of a single packet.
    pub maximum_packet_size: u32,
    /// Lists of preferred algorithms.
    pub preferred: negotiation::Preferred,
    /// Time after which the connection is garbage-collected.
    pub connection_timeout: Option<std::time::Duration>,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            client_id: format!(
                "SSH-2.0-{}_{}",
                env!("CARGO_PKG_NAME"),
                env!("CARGO_PKG_VERSION")
            ),
            limits: Limits::default(),
            window_size: 200000,
            maximum_packet_size: 200000,
            preferred: Default::default(),
            connection_timeout: None,
        }
    }
}


/// A client handler. Note that messages can be received from the
/// server at any time during a session.
pub trait Handler: Sized {
    /// Error type returned by the futures.
    type Error: std::fmt::Debug;

    /// A future ultimately resolving into a boolean, which can be
    /// returned by some parts of this handler.
    type FutureBool: Future<Item = (Self, bool), Error = Self::Error> + FromFinished<(Self, bool), Self::Error>;

    /// A future ultimately resolving into a boolean, which can be
    /// returned by some parts of this handler.
    type FutureUnit: Future<Item = Self, Error = Self::Error> + FromFinished<Self, Self::Error>;

    /// A future that computes the signature of a `CryptoVec`, appends
    /// that signature to that `CryptoVec`, and resolves to the
    /// `CryptoVec`. Useful for instance to implement SSH agent
    /// clients.
    type FutureSign: Future<Item = (Self, CryptoVec), Error = Self::Error> + FromFinished<(Self, CryptoVec), Self::Error>;

    /// A future ultimately resolving into unit, which can be returned
    /// by some parts of this handler.
    type SessionUnit: Future<Item = (Self, Session), Error = Self::Error> + FromFinished<(Self, Session), Self::Error>;


    /// Called when the server sends us an authentication banner. This
    /// is usually meant to be shown to the user, see
    /// [RFC4252](https://tools.ietf.org/html/rfc4252#section-5.4) for
    /// more details.
    #[allow(unused_variables)]
    fn auth_banner(self, banner: &str) -> Self::FutureUnit {
        Self::FutureUnit::finished(self)
    }

    /// Called when using the `FuturePublicKey` method, used for
    /// instance to implement SSH agent. This can be used for instance
    /// to implement an interface to SSH agents. The default
    /// implementation returns the supplied `CryptoVec` without
    /// touching it.
    #[allow(unused_variables)]
    fn auth_publickey_sign(self, key: &key::PublicKey, to_sign: CryptoVec) -> Self::FutureSign {
        Self::FutureSign::finished((self, to_sign))
    }

    /// Called to check the server's public key. This is a very important
    /// step to help prevent man-in-the-middle attacks. The default
    /// implementation rejects all keys.
    #[allow(unused_variables)]
    fn check_server_key(self, server_public_key: &key::PublicKey) -> Self::FutureBool {
        Self::FutureBool::finished((self, false))
    }

    /// Called when the server confirmed our request to open a
    /// channel. A channel can only be written to after receiving this
    /// message (this library panics otherwise).
    #[allow(unused_variables)]
    fn channel_open_confirmation(self, channel: ChannelId, session: Session) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }

    /// Called when the server closes a channel.
    #[allow(unused_variables)]
    fn channel_close(self, channel: ChannelId, session: Session) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }

    /// Called when the server sends EOF to a channel.
    #[allow(unused_variables)]
    fn channel_eof(self, channel: ChannelId, session: Session) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }

    /// Called when the server rejected our request to open a channel.
    #[allow(unused_variables)]
    fn channel_open_failure(
        self,
        channel: ChannelId,
        reason: ChannelOpenFailure,
        description: &str,
        language: &str,
        session: Session,
    ) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }

    /// Called when a new channel is created.
    #[allow(unused_variables)]
    fn channel_open_forwarded_tcpip(
        self,
        channel: ChannelId,
        connected_address: &str,
        connected_port: u32,
        originator_address: &str,
        originator_port: u32,
        session: Session,
    ) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }

    /// Called when the server sends us data. The `extended_code`
    /// parameter is a stream identifier, `None` is usually the
    /// standard output, and `Some(1)` is the standard error. See
    /// [RFC4254](https://tools.ietf.org/html/rfc4254#section-5.2).
    #[allow(unused_variables)]
    fn data(
        self,
        channel: ChannelId,
        extended_code: Option<u32>,
        data: &[u8],
        session: Session,
    ) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }

    /// The server informs this client of whether the client may
    /// perform control-S/control-Q flow control. See
    /// [RFC4254](https://tools.ietf.org/html/rfc4254#section-6.8).
    #[allow(unused_variables)]
    fn xon_xoff(
        self,
        channel: ChannelId,
        client_can_do: bool,
        session: Session,
    ) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }

    /// The remote process has exited, with the given exit status.
    #[allow(unused_variables)]
    fn exit_status(
        self,
        channel: ChannelId,
        exit_status: u32,
        session: Session,
    ) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }

    /// The remote process exited upon receiving a signal.
    #[allow(unused_variables)]
    fn exit_signal(
        self,
        channel: ChannelId,
        signal_name: Sig,
        core_dumped: bool,
        error_message: &str,
        lang_tag: &str,
        session: Session,
    ) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }

    /// Called when the network window is adjusted, meaning that we
    /// can send more bytes. This is useful if this client wants to
    /// send huge amounts of data, for instance if we have called
    /// `Session::data` before, and it returned less than the
    /// full amount of data.
    #[allow(unused_variables)]
    fn window_adjusted(
        self,
        channel: ChannelId,
        new_window_size: usize,
        session: Session,
    ) -> Self::SessionUnit {
        Self::SessionUnit::finished((self, session))
    }
}

/*
use tokio::reactor::Reactor;
/// Create a new client connection to the given address.
pub fn connect<
    Addr: ToSocketAddrs,
    H: Handler,
    I,
    E,
    X: Future<Item = I, Error = E>,
    F: FnOnce(Connection<TcpStream, H>) -> X,
>(
    addr: Addr,
    config: Arc<Config>,
    timeout: Option<Sleep>,
    handler: H,
    f: F,
) -> Result<I, HandlerError<E>> {

    let mut l = Reactor::new()?;
    let cur = tokio::executor::current_thread::CurrentThread::new();
    cur.block_on(connect_future(addr, config, timeout, handler, f)?)
}
*/

/// Create a new client connection to the given address.
pub fn connect_future<
    Addr: ToSocketAddrs,
    H: Handler,
    I,
    E,
    X: Future<Item = I, Error = E>,
    F: FnOnce(Connection<TcpStream, H>) -> X,
    >(
    addr: Addr,
    config: Arc<Config>,
    timeout: Option<Sleep>,
    handler: H,
    f: F,
) -> Result<ConnectFuture<H, I, E, X, F>, Error> {

    Ok(ConnectFuture {
        state: Some(ConnectFutureState::TcpConnect(
            TcpStream::connect(&addr.to_socket_addrs()?.next().unwrap())
        )),
        handler: Some(handler),
        config,
        timeout,
        f: Some(f),
    })
}

/// Future returned by `connect_future`.
pub struct ConnectFuture<H: Handler, I, E, X: Future<Item = I, Error = E>, F: FnOnce(Connection<TcpStream, H>) -> X> {
    handler: Option<H>,
    config: Arc<Config>,
    state: Option<ConnectFutureState<X>>,
    timeout: Option<Sleep>,
    f: Option<F>
}

enum ConnectFutureState<X> {
    TcpConnect(tokio::net::ConnectFuture),
    Connect(X)
}

impl<H: Handler, I, E, X: Future<Item = I, Error = E>, F: FnOnce(Connection<TcpStream, H>) -> X> Future for ConnectFuture<H, I, E, X, F> {
    type Item = I;
    type Error = HandlerError<E>;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            match self.state.take() {
                Some(ConnectFutureState::TcpConnect(mut connect)) => {
                    if let Async::Ready(socket) = connect.poll()? {

                        self.state = Some(ConnectFutureState::Connect(
                            (self.f.take().unwrap())(Connection::new(
                                self.config.clone(),
                                socket,
                                self.handler.take().unwrap(),
                                self.timeout.take(),
                            )?)
                        ))

                    } else {
                        self.state = Some(ConnectFutureState::TcpConnect(connect));
                        return Ok(Async::NotReady)
                    }
                }
                Some(ConnectFutureState::Connect(mut connect)) => {
                    match connect.poll() {
                        Ok(Async::Ready(f)) => return Ok(Async::Ready(f)),
                        Ok(Async::NotReady) => {
                            self.state = Some(ConnectFutureState::Connect(connect));
                            return Ok(Async::NotReady)
                        }
                        Err(e) => return Err(HandlerError::Handler(e))
                    }
                }
                None => panic!("Future polled after completion")
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
use super::*;
use msg;
use thrussh_keys::encoding::Encoding;
use std::sync::Arc;

/// The type of a client session.
pub struct Session(pub(crate) CommonSession<Arc<Config>>);

impl Session {
    /// Flush the temporary cleartext buffer into the encryption
    /// buffer. This does *not* flush to the socket.
    pub fn flush(&mut self) -> Result<(), Error> {
        if let Some(ref mut enc) = self.0.encrypted {
            if enc.flush(
                &self.0.config.as_ref().limits,
                &mut self.0.cipher,
                &mut self.0.write_buffer,
            )
            {
                if let Some(exchange) = std::mem::replace(&mut enc.exchange, None) {
                    let mut kexinit = KexInit::initiate_rekey(exchange, &enc.session_id);
                    kexinit.client_write(
                        &self.0.config.as_ref(),
                        &mut self.0.cipher,
                        &mut self.0.write_buffer,
                    )?;
                    enc.rekey = Some(Kex::KexInit(kexinit))
                }
            }
        }
        Ok(())
    }

    /// Retrieves the configuration of this session.
    pub fn config(&self) -> &Config {
        &self.0.config
    }

    /// Retrieves the current user.
    pub fn auth_user(&self) -> &str {
        &self.0.auth_user
    }

    /// Sends a disconnect message.
    pub fn disconnect(&mut self, reason: Disconnect, description: &str, language_tag: &str) {
        self.0.disconnect(reason, description, language_tag);
    }

    /// Whether the client is authenticated.
    pub fn is_authenticated(&self) -> bool {
        if let Some(ref enc) = self.0.encrypted {
            if let Some(EncryptedState::Authenticated) = enc.state {
                return true;
            }
        }
        false
    }

    /// Whether the client is disconnected.
    pub fn is_disconnected(&self) -> bool {
        self.0.disconnected
    }

    /// Check whether a channel has been confirmed.
    pub fn channel_is_open(&self, channel: ChannelId) -> bool {
        if let Some(ref enc) = self.0.encrypted {
            if let Some(ref channel) = enc.channels.get(&channel) {
                return channel.confirmed;
            }
        }
        false
    }

    /// Tests whether we need an authentication method (for instance
    /// if the last attempt failed).
    pub fn has_auth_method(&self) -> bool {
        self.0.auth_method.is_some()
    }

    /// Returns the set of authentication methods that can continue, or None if this is not valid.
    pub fn valid_auth_methods(&self) -> Option<auth::MethodSet> {
        if let Some(ref enc) = self.0.encrypted {
            match enc.state {
                Some(EncryptedState::WaitingAuthRequest(ref auth_request)) => {
                    Some(auth_request.methods)
                }
                _ => None,
            }
        } else {
            None
        }
    }


    /// Request a session channel (the most basic type of
    /// channel). This function returns `Some(..)` immediately if the
    /// connection is authenticated, but the channel only becomes
    /// usable when it's confirmed by the server, as indicated by the
    /// `confirmed` field of the corresponding `Channel`.
    pub fn channel_open_session(&mut self) -> Result<ChannelId, Error> {
        let result = if let Some(ref mut enc) = self.0.encrypted {
            match enc.state {
                Some(EncryptedState::Authenticated) => {
                    debug!("sending open request");

                    let sender_channel = enc.new_channel(
                        self.0.config.window_size,
                        self.0.config.maximum_packet_size,
                    );
                    push_packet!(enc.write, {
                        enc.write.push(msg::CHANNEL_OPEN);
                        enc.write.extend_ssh_string(b"session");

                        // sender channel id.
                        enc.write.push_u32_be(sender_channel.0);

                        // window.
                        enc.write.push_u32_be(self.0.config.as_ref().window_size);

                        // max packet size.
                        enc.write.push_u32_be(
                            self.0.config.as_ref().maximum_packet_size,
                        );
                    });
                    sender_channel
                }
                _ => return Err(Error::Inconsistent),
            }
        } else {
            return Err(Error::Inconsistent);
        };
        Ok(result)
    }


    /// Request an X11 channel, on which the X11 protocol may be tunneled.
    pub fn channel_open_x11(
        &mut self,
        originator_address: &str,
        originator_port: u32,
    ) -> Result<ChannelId, Error> {
        let result = if let Some(ref mut enc) = self.0.encrypted {
            match enc.state {
                Some(EncryptedState::Authenticated) => {

                    let sender_channel = enc.new_channel(
                        self.0.config.window_size,
                        self.0.config.maximum_packet_size,
                    );
                    push_packet!(enc.write, {
                        enc.write.push(msg::CHANNEL_OPEN);
                        enc.write.extend_ssh_string(b"x11");

                        // sender channel id.
                        enc.write.push_u32_be(sender_channel.0);

                        // window.
                        enc.write.push_u32_be(self.0.config.as_ref().window_size);

                        // max packet size.
                        enc.write.push_u32_be(
                            self.0.config.as_ref().maximum_packet_size,
                        );

                        enc.write.extend_ssh_string(originator_address.as_bytes());
                        enc.write.push_u32_be(originator_port); // sender channel id.
                    });
                    sender_channel
                }
                _ => return Err(Error::Inconsistent),
            }
        } else {
            return Err(Error::Inconsistent);
        };
        Ok(result)
    }

    /// Open a TCP/IP forwarding channel. This is usually done when a
    /// connection comes to a locally forwarded TCP/IP port. See
    /// [RFC4254](https://tools.ietf.org/html/rfc4254#section-7). The
    /// TCP/IP packets can then be tunneled through the channel using
    /// `.data()`.
    pub fn channel_open_direct_tcpip(
        &mut self,
        host_to_connect: &str,
        port_to_connect: u32,
        originator_address: &str,
        originator_port: u32,
    ) -> Result<ChannelId, Error> {
        let result = if let Some(ref mut enc) = self.0.encrypted {
            match enc.state {
                Some(EncryptedState::Authenticated) => {

                    let sender_channel = enc.new_channel(
                        self.0.config.window_size,
                        self.0.config.maximum_packet_size,
                    );
                    push_packet!(enc.write, {
                        enc.write.push(msg::CHANNEL_OPEN);
                        enc.write.extend_ssh_string(b"direct-tcpip");

                        // sender channel id.
                        enc.write.push_u32_be(sender_channel.0);

                        // window.
                        enc.write.push_u32_be(self.0.config.as_ref().window_size);

                        // max packet size.
                        enc.write.push_u32_be(
                            self.0.config.as_ref().maximum_packet_size,
                        );

                        enc.write.extend_ssh_string(host_to_connect.as_bytes());
                        enc.write.push_u32_be(port_to_connect); // sender channel id.
                        enc.write.extend_ssh_string(originator_address.as_bytes());
                        enc.write.push_u32_be(originator_port); // sender channel id.
                    });
                    sender_channel
                }
                _ => return Err(Error::Inconsistent),
            }
        } else {
            return Err(Error::Inconsistent);
        };
        Ok(result)
    }

    /// Send EOF to a channel
    pub fn channel_eof(&mut self, channel: ChannelId) {
        self.0.byte(channel, msg::CHANNEL_EOF);
    }

    /// Request a pseudo-terminal with the given characteristics.
    pub fn request_pty(
        &mut self,
        channel: ChannelId,
        want_reply: bool,
        term: &str,
        col_width: u32,
        row_height: u32,
        pix_width: u32,
        pix_height: u32,
        terminal_modes: &[(Pty, u32)],
    ) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"pty-req");
                    enc.write.push(if want_reply { 1 } else { 0 });

                    enc.write.extend_ssh_string(term.as_bytes());
                    enc.write.push_u32_be(col_width);
                    enc.write.push_u32_be(row_height);
                    enc.write.push_u32_be(pix_width);
                    enc.write.push_u32_be(pix_height);

                    enc.write.push_u32_be(
                        (5 * (1 + terminal_modes.len())) as u32,
                    );
                    for &(code, value) in terminal_modes {
                        enc.write.push(code as u8);
                        enc.write.push_u32_be(value)
                    }
                    // 0 code (to terminate the list)
                    enc.write.push(0);
                    enc.write.push_u32_be(0);
                });
            }
        }
    }

    /// Request X11 forwarding through an already opened X11
    /// channel. See
    /// [RFC4254](https://tools.ietf.org/html/rfc4254#section-6.3.1)
    /// for security issues related to cookies.
    pub fn request_x11(
        &mut self,
        channel: ChannelId,
        want_reply: bool,
        single_connection: bool,
        x11_authentication_protocol: &str,
        x11_authentication_cookie: &str,
        x11_screen_number: u32,
    ) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"x11-req");
                    enc.write.push(if want_reply { 1 } else { 0 });
                    enc.write.push(if single_connection { 1 } else { 0 });
                    enc.write.extend_ssh_string(
                        x11_authentication_protocol.as_bytes(),
                    );
                    enc.write.extend_ssh_string(
                        x11_authentication_cookie.as_bytes(),
                    );
                    enc.write.push_u32_be(x11_screen_number);
                });
            }
        }
    }

    /// Set a remote environment variable.
    pub fn set_env(
        &mut self,
        channel: ChannelId,
        want_reply: bool,
        variable_name: &str,
        variable_value: &str,
    ) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"env");
                    enc.write.push(if want_reply { 1 } else { 0 });
                    enc.write.extend_ssh_string(variable_name.as_bytes());
                    enc.write.extend_ssh_string(variable_value.as_bytes());
                });
            }
        }
    }


    /// Request a remote shell.
    pub fn request_shell(&mut self, want_reply: bool, channel: ChannelId) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"shell");
                    enc.write.push(if want_reply { 1 } else { 0 });
                });
            }
        }
    }

    /// Execute a remote program (will be passed to a shell). This can
    /// be used to implement scp (by calling a remote scp and
    /// tunneling to its standard input).
    pub fn exec(&mut self, channel: ChannelId, want_reply: bool, command: &str) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"exec");
                    enc.write.push(if want_reply { 1 } else { 0 });
                    enc.write.extend_ssh_string(command.as_bytes());
                });
            }
        }
    }

    /// Signal a remote process.
    pub fn signal(&mut self, channel: ChannelId, signal: Sig) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"signal");
                    enc.write.push(0);
                    enc.write.extend_ssh_string(signal.name().as_bytes());
                });
            }
        }
    }

    /// Request the start of a subsystem with the given name.
    pub fn request_subsystem(&mut self, want_reply: bool, channel: ChannelId, name: &str) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"subsystem");
                    enc.write.push(if want_reply { 1 } else { 0 });
                    enc.write.extend_ssh_string(name.as_bytes());
                });
            }
        }
    }

    /// Inform the server that our window size has changed.
    pub fn window_change(
        &mut self,
        channel: ChannelId,
        col_width: u32,
        row_height: u32,
        pix_width: u32,
        pix_height: u32,
    ) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"window-change");
                    enc.write.push(0); // this packet never wants reply
                    enc.write.push_u32_be(col_width);
                    enc.write.push_u32_be(row_height);
                    enc.write.push_u32_be(pix_width);
                    enc.write.push_u32_be(pix_height);
                });
            }
        }
    }

    /// Request the forwarding of a remote port to the client. The
    /// server will then open forwarding channels (which cause the
    /// client to call `.channel_open_forwarded_tcpip()`).
    pub fn tcpip_forward(&mut self, want_reply: bool, address: &str, port: u32) {
        if let Some(ref mut enc) = self.0.encrypted {
            push_packet!(enc.write, {
                enc.write.push(msg::GLOBAL_REQUEST);
                enc.write.extend_ssh_string(b"tcpip-forward");
                enc.write.push(if want_reply { 1 } else { 0 });
                enc.write.extend_ssh_string(address.as_bytes());
                enc.write.push_u32_be(port);
            });
        }
    }

    /// Cancel a previous forwarding request.
    pub fn cancel_tcpip_forward(&mut self, want_reply: bool, address: &str, port: u32) {
        if let Some(ref mut enc) = self.0.encrypted {
            push_packet!(enc.write, {
                enc.write.push(msg::GLOBAL_REQUEST);
                enc.write.extend_ssh_string(b"cancel-tcpip-forward");
                enc.write.push(if want_reply { 1 } else { 0 });
                enc.write.extend_ssh_string(address.as_bytes());
                enc.write.push_u32_be(port);
            });
        }
    }

    /// Send data to a channel. The number of bytes added to the
    /// "sending pipeline" (to be processed by the event loop) is
    /// returned.
    pub fn data(&mut self, channel: ChannelId, extended: Option<u32>, data: &[u8]) -> usize {
        if let Some(ref mut enc) = self.0.encrypted {
            enc.data(channel, extended, data)
        } else {
            unreachable!()
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use super::*;
use tokio::io::{AsyncRead, AsyncWrite};
use tcp::Tcp;

impl<R: AsyncRead + AsyncWrite, H: Handler> Connection<R, H> {
    /// Wait until a condition is met on the connection.
    pub fn wait<F: Fn(&Connection<R, H>) -> bool>(self, f: F) -> Wait<R, H, F> {
        Wait {
            connection: Some(self),
            condition: f,
            first_round: true,
        }
    }

    /// Flush the session, sending any pending message.
    pub fn wait_flush(self) -> WaitFlush<R, H> {
        WaitFlush {
            connection: Some(self),
            first_round: true,
        }
    }
}

/// A future waiting for a channel to be closed.
pub struct Wait<R: AsyncRead + AsyncWrite, H: Handler, F> {
    connection: Option<Connection<R, H>>,
    condition: F,
    first_round: bool,
}

impl<R: AsyncRead + AsyncWrite + Tcp, H: Handler, F: Fn(&Connection<R, H>) -> bool> Future
    for Wait<R, H, F> {
    type Item = Connection<R, H>;
    type Error = HandlerError<H::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.first_round {
            if let Some(ref mut c) = self.connection {
                c.abort_read()?
            }
            self.first_round = false
        }

        loop {
            debug!("wait loop");
            if let Some(mut connection) = self.connection.take() {
                if connection.handler.is_some() && (self.condition)(&connection) &&
                    connection.is_reading()
                {
                    return Ok(Async::Ready(connection));
                } else {
                    match try!(connection.atomic_poll()) {
                        Async::Ready(Status::Ok) => {
                            self.connection = Some(connection);
                        }
                        Async::Ready(Status::Disconnect) => return Ok(Async::Ready(connection)),
                        Async::NotReady => {
                            self.connection = Some(connection);
                            return Ok(Async::NotReady);
                        }
                    }
                }
            }
        }
    }
}


/// A future waiting for a flush request to complete.
pub struct WaitFlush<R: AsyncRead + AsyncWrite, H: Handler> {
    connection: Option<Connection<R, H>>,
    first_round: bool,
}


impl<R: AsyncRead + AsyncWrite + Tcp, H: Handler> Future for WaitFlush<R, H> {
    type Item = Connection<R, H>;
    type Error = HandlerError<H::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if self.first_round {
            if let Some(ref mut c) = self.connection {
                c.abort_read()?
            }
            self.first_round = false
        }
        loop {
            debug!("WaitFlush loop");
            if let Some(mut c) = self.connection.take() {
                match try!(c.atomic_poll()) {
                    Async::Ready(Status::Disconnect) => return Ok(Async::Ready(c)),
                    Async::NotReady => {
                        self.connection = Some(c);
                        return Ok(Async::NotReady);
                    }
                    Async::Ready(Status::Ok) => {
                        match c.state {
                            Some(ConnectionState::Read(_)) => return Ok(Async::Ready(c)),
                            _ => self.connection = Some(c),
                        }
                    }
                }
            } else {
                unreachable!()
            }
        }
    }
}
1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

use byteorder::{ByteOrder, BigEndian};
use Error;
use cryptovec::CryptoVec;

#[doc(hidden)]
pub trait Bytes {
    fn bytes(&self) -> &[u8];
}

impl<A: AsRef<str>> Bytes for A {
    fn bytes(&self) -> &[u8] {
        self.as_ref().as_bytes()
    }
}

/// Encode in the SSH format.
pub trait Encoding {
    /// Push an SSH-encoded string to `self`.
    fn extend_ssh_string(&mut self, s: &[u8]);
    /// Push an SSH-encoded blank string of length `s` to `self`.
    fn extend_ssh_string_blank(&mut self, s: usize) -> &mut [u8];
    /// Push an SSH-encoded multiple-precision integer.
    fn extend_ssh_mpint(&mut self, s: &[u8]);
    /// Push an SSH-encoded list.
    fn extend_list<A: Bytes, I: Iterator<Item = A>>(&mut self, list: I);
    /// Push an SSH-encoded empty list.
    fn write_empty_list(&mut self);
}

/// Encoding length of the given mpint.
pub fn mpint_len(s: &[u8]) -> usize {
    let mut i = 0;
    while i < s.len() && s[i] == 0 {
        i += 1
    }
    (if s[i] & 0x80 != 0 { 5 } else { 4 }) + s.len() - i
}


impl Encoding for CryptoVec {
    fn extend_ssh_string(&mut self, s: &[u8]) {
        self.push_u32_be(s.len() as u32);
        self.extend(s);
    }
    fn extend_ssh_string_blank(&mut self, len: usize) -> &mut [u8] {
        self.push_u32_be(len as u32);
        let current = self.len();
        self.resize(current + len);
        &mut self[current..]
    }
    fn extend_ssh_mpint(&mut self, s: &[u8]) {
        // Skip initial 0s.
        let mut i = 0;
        while i < s.len() && s[i] == 0 {
            i += 1
        }
        // If the first non-zero is >= 128, write its length (u32, BE), followed by 0.
        if s[i] & 0x80 != 0 {

            self.push_u32_be((s.len() - i + 1) as u32);
            self.push(0)

        } else {

            self.push_u32_be((s.len() - i) as u32);

        }
        self.extend(&s[i..]);
    }


    fn extend_list<A: Bytes, I: Iterator<Item = A>>(&mut self, list: I) {
        let len0 = self.len();
        self.extend(&[0, 0, 0, 0]);
        let mut first = true;
        for i in list {
            if !first {
                self.push(b',')
            } else {
                first = false;
            }
            self.extend(i.bytes())
        }
        let len = (self.len() - len0 - 4) as u32;

        BigEndian::write_u32(&mut self[len0..], len);
    }

    fn write_empty_list(&mut self) {
        self.extend(&[0, 0, 0, 0]);
    }
}

/// A cursor-like trait to read SSH-encoded things.
pub trait Reader {
    /// Create an SSH reader for `self`.
    fn reader<'a>(&'a self, starting_at: usize) -> Position<'a>;
}

impl Reader for CryptoVec {
    fn reader<'a>(&'a self, starting_at: usize) -> Position<'a> {
        Position {
            s: &self,
            position: starting_at,
        }
    }
}

impl Reader for [u8] {
    fn reader<'a>(&'a self, starting_at: usize) -> Position<'a> {
        Position {
            s: self,
            position: starting_at,
        }
    }
}

/// A cursor-like type to read SSH-encoded values.
#[derive(Debug)]
pub struct Position<'a> {
    s: &'a [u8],
    #[doc(hidden)]
    pub position: usize,
}
impl<'a> Position<'a> {
    /// Read one string from this reader.
    pub fn read_string(&mut self) -> Result<&'a [u8], Error> {
        let len = self.read_u32()? as usize;
        if self.position + len <= self.s.len() {
            let result = &self.s[self.position..(self.position + len)];
            self.position += len;
            Ok(result)
        } else {
            Err(Error::IndexOutOfBounds)
        }
    }
    /// Read a `u32` from this reader.
    pub fn read_u32(&mut self) -> Result<u32, Error> {
        if self.position + 4 <= self.s.len() {
            let u = BigEndian::read_u32(&self.s[self.position..]);
            self.position += 4;
            Ok(u)
        } else {
            Err(Error::IndexOutOfBounds)
        }
    }
    /// Read one byte from this reader.
    pub fn read_byte(&mut self) -> Result<u8, Error> {
        if self.position + 1 <= self.s.len() {
            let u = self.s[self.position];
            self.position += 1;
            Ok(u)
        } else {
            Err(Error::IndexOutOfBounds)
        }
    }

    /// Read one byte from this reader.
    pub fn read_mpint(&mut self) -> Result<&'a [u8], Error> {
        let len = self.read_u32()? as usize;
        if self.position + len <= self.s.len() {
            let result = &self.s[self.position..(self.position + len)];
            self.position += len;
            Ok(result)
        } else {
            Err(Error::IndexOutOfBounds)
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//
use byteorder::{ByteOrder, BigEndian};
use std;
use Error;
use msg;

use cryptovec::CryptoVec;
use session::Exchange;
use key;
use cipher;
use thrussh_keys::encoding::Encoding;
use openssl;
use sodium;

#[doc(hidden)]
pub struct Algorithm {
    local_secret: Option<sodium::scalarmult::Scalar>,
    shared_secret: Option<sodium::scalarmult::GroupElement>,
}

impl std::fmt::Debug for Algorithm {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "Algorithm {{ local_secret: [hidden], shared_secret: [hidden] }}",
        )
    }
}

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct Name(&'static str);
impl AsRef<str> for Name {
    fn as_ref(&self) -> &str {
        self.0
    }
}
pub const CURVE25519: Name = Name("curve25519-sha256@libssh.org");

// We used to support curve "NIST P-256" here, but the security of
// that curve is controversial, see
// http://safecurves.cr.yp.to/rigid.html

impl Algorithm {
    #[doc(hidden)]
    pub fn server_dh(
        _name: Name,
        exchange: &mut Exchange,
        payload: &[u8],
    ) -> Result<Algorithm, Error> {
        debug!("server_dh");

        assert_eq!(payload[0], msg::KEX_ECDH_INIT);
        let mut client_pubkey = GroupElement([0; 32]);
        {
            let pubkey_len = BigEndian::read_u32(&payload[1..]) as usize;
            client_pubkey.0.clone_from_slice(
                &payload[5..(5 + pubkey_len)],
            )
        };
        debug!("client_pubkey: {:?}", client_pubkey);
        use sodium::scalarmult::*;
        use openssl::rand::*;
        let mut server_secret = Scalar([0; 32]);
        rand_bytes(&mut server_secret.0)?;
        let sodium = sodium::Sodium::new();
        let server_pubkey = sodium.scalarmult_base(&server_secret);

        // fill exchange.
        exchange.server_ephemeral.clear();
        exchange.server_ephemeral.extend(&server_pubkey.0);
        let shared = sodium.scalarmult(&server_secret, &client_pubkey);
        Ok(Algorithm {
            local_secret: None,
            shared_secret: Some(shared),
        })
    }

    #[doc(hidden)]
    pub fn client_dh(
        _name: Name,
        client_ephemeral: &mut CryptoVec,
        buf: &mut CryptoVec,
    ) -> Result<Algorithm, Error> {

        use sodium::scalarmult::*;
        use openssl::rand::*;
        let mut client_secret = Scalar([0; 32]);
        rand_bytes(&mut client_secret.0)?;
        let sodium = sodium::Sodium::new();
        let client_pubkey = sodium.scalarmult_base(&client_secret);

        // fill exchange.
        client_ephemeral.clear();
        client_ephemeral.extend(&client_pubkey.0);

        buf.push(msg::KEX_ECDH_INIT);
        buf.extend_ssh_string(&client_pubkey.0);


        Ok(Algorithm {
            local_secret: Some(client_secret),
            shared_secret: None,
        })
    }

    pub fn compute_shared_secret(&mut self, remote_pubkey_: &[u8]) -> Result<(), Error> {
        let local_secret = std::mem::replace(&mut self.local_secret, None).unwrap();

        use sodium::scalarmult::*;
        let mut remote_pubkey = GroupElement([0; 32]);
        remote_pubkey.0.clone_from_slice(remote_pubkey_);
        let sodium = sodium::Sodium::new();
        let shared = sodium.scalarmult(&local_secret, &remote_pubkey);
        self.shared_secret = Some(shared);
        Ok(())
    }

    pub fn compute_exchange_hash<K: key::PubKey>(
        &self,
        key: &K,
        exchange: &Exchange,
        buffer: &mut CryptoVec,
    ) -> Result<openssl::hash::DigestBytes, Error> {
        // Computing the exchange hash, see page 7 of RFC 5656.
        buffer.clear();
        buffer.extend_ssh_string(&exchange.client_id);
        buffer.extend_ssh_string(&exchange.server_id);
        buffer.extend_ssh_string(&exchange.client_kex_init);
        buffer.extend_ssh_string(&exchange.server_kex_init);


        key.push_to(buffer);
        buffer.extend_ssh_string(&exchange.client_ephemeral);
        buffer.extend_ssh_string(&exchange.server_ephemeral);

        if let Some(ref shared) = self.shared_secret {
            buffer.extend_ssh_mpint(&shared.0);
        }
        use openssl::hash::*;
        let hash = {
            let mut hasher = Hasher::new(MessageDigest::sha256())?;
            hasher.update(&buffer)?;
            hasher.finish()?
        };
        Ok(hash)
    }


    pub fn compute_keys(
        &self,
        session_id: &openssl::hash::DigestBytes,
        exchange_hash: &openssl::hash::DigestBytes,
        buffer: &mut CryptoVec,
        key: &mut CryptoVec,
        cipher: cipher::Name,
        is_server: bool,
    ) -> Result<super::cipher::CipherPair, Error> {
        let cipher = match cipher {
            super::cipher::chacha20poly1305::NAME => &super::cipher::chacha20poly1305::CIPHER,
            _ => unreachable!(),
        };

        // https://tools.ietf.org/html/rfc4253#section-7.2
        let mut compute_key = |c, key: &mut CryptoVec, len| -> Result<(), Error> {
            buffer.clear();
            key.clear();

            if let Some(ref shared) = self.shared_secret {
                buffer.extend_ssh_mpint(&shared.0);
            }

            buffer.extend(exchange_hash.as_ref());
            buffer.push(c);
            buffer.extend(session_id.as_ref());
            use openssl::hash::*;
            let hash = {
                let mut hasher = Hasher::new(MessageDigest::sha256())?;
                hasher.update(&buffer)?;
                hasher.finish()?
            };
            key.extend(hash.as_ref());

            while key.len() < len {
                // extend.
                buffer.clear();
                if let Some(ref shared) = self.shared_secret {
                    buffer.extend_ssh_mpint(&shared.0);
                }
                buffer.extend(exchange_hash.as_ref());
                buffer.extend(key);
                let hash = {
                    let mut hasher = Hasher::new(MessageDigest::sha256())?;
                    hasher.update(&buffer)?;
                    hasher.finish()?
                };
                key.extend(&hash.as_ref());
            }
            Ok(())
        };

        let (local_to_remote, remote_to_local) = if is_server {
            (b'D', b'C')
        } else {
            (b'C', b'D')
        };

        compute_key(local_to_remote, key, cipher.key_len)?;
        let local_to_remote = (cipher.make_sealing_cipher)(key);

        compute_key(remote_to_local, key, cipher.key_len)?;
        let remote_to_local = (cipher.make_opening_cipher)(key);

        Ok(super::cipher::CipherPair {
            local_to_remote: local_to_remote,
            remote_to_local: remote_to_local,
        })
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//
use thrussh_keys::encoding::*;
use thrussh_keys::key::*;
use cryptovec::CryptoVec;

#[doc(hidden)]
pub trait PubKey {
    fn push_to(&self, buffer: &mut CryptoVec);
}

impl PubKey for PublicKey {
    fn push_to(&self, buffer: &mut CryptoVec) {
        match self {
            &PublicKey::Ed25519(ref public) => {

                buffer.push_u32_be((ED25519.0.len() + public.key.len() + 8) as u32);
                buffer.extend_ssh_string(ED25519.0.as_bytes());
                buffer.extend_ssh_string(&public.key);
            }
            &PublicKey::RSA { ref key, .. } => {
                let rsa = key.0.rsa().unwrap();
                let e = rsa.e().to_vec();
                let n = rsa.n().to_vec();
                buffer.push_u32_be(
                    (4 + SSH_RSA.len() + mpint_len(&n) + mpint_len(&e)) as u32,
                );
                buffer.extend_ssh_string(SSH_RSA.as_bytes());
                buffer.extend_ssh_mpint(&e);
                buffer.extend_ssh_mpint(&n);
            }
        }
    }
}

impl PubKey for KeyPair {
    fn push_to(&self, buffer: &mut CryptoVec) {
        match self {
            &KeyPair::Ed25519(ref key) => {
                let public = &key.key[32..];
                buffer.push_u32_be((ED25519.0.len() + public.len() + 8) as u32);
                buffer.extend_ssh_string(ED25519.0.as_bytes());
                buffer.extend_ssh_string(public);
            }
            &KeyPair::RSA { ref key, ..} => {
                let e = key.e().to_vec();
                let n = key.n().to_vec();
                buffer.push_u32_be(
                    (4 + SSH_RSA.len() + mpint_len(&n) + mpint_len(&e)) as u32,
                );
                buffer.extend_ssh_string(SSH_RSA.as_bytes());
                buffer.extend_ssh_mpint(&e);
                buffer.extend_ssh_mpint(&n);
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

#![deny(missing_docs,
        trivial_casts,
        unstable_features,
        unused_import_braces)]

//! Server and client SSH library, based on *ring* for its crypto, and
//! tokio/futures for its network management. More information at
//! [pijul.org/thrussh](https://pijul.org/thrussh).
//!
//! Here is an example client and server:
//!
//! ```
//!extern crate thrussh;
//!extern crate thrussh_keys;
//!extern crate futures;
//!extern crate tokio;
//!extern crate env_logger;
//!use std::sync::Arc;
//!use thrussh::*;
//!use thrussh::server::{Auth, Session};
//!use thrussh_keys::*;
//!
//!#[derive(Clone)]
//!struct Server {
//!  client_pubkey: Arc<thrussh_keys::key::PublicKey>
//!}
//!
//!impl server::Server for Server {
//!    type Handler = Self;
//!    fn new(&self) -> Self {
//!        self.clone()
//!    }
//!}
//!
//!impl server::Handler for Server {
//!    type Error = std::io::Error;
//!    type FutureAuth = futures::Finished<(Self, server::Auth), Self::Error>;
//!    type FutureUnit = futures::Finished<(Self, server::Session), Self::Error>;
//!    type FutureBool = futures::Finished<(Self, server::Session, bool), Self::Error>;
//!
//!    fn finished_auth(self, auth: Auth) -> Self::FutureAuth {
//!        futures::finished((self, auth))
//!    }
//!    fn finished_bool(self, session: Session, b: bool) -> Self::FutureBool {
//!        futures::finished((self, session, b))
//!    }
//!    fn finished(self, session: Session) -> Self::FutureUnit {
//!        futures::finished((self, session))
//!    }
//!
//!    fn auth_publickey(self, _: &str, _: &key::PublicKey) -> Self::FutureAuth {
//!        futures::finished((self, server::Auth::Accept))
//!    }
//!    fn data(self, channel: ChannelId, data: &[u8], mut session: server::Session) -> Self::FutureUnit {
//!        println!("data on channel {:?}: {:?}", channel, std::str::from_utf8(data));
//!        session.data(channel, None, data);
//!        futures::finished((self, session))
//!    }
//!}
//!
//!
//!use futures::Future;
//!use std::io::Read;
//!
//!
//!struct Client {
//!  key: Arc<thrussh_keys::key::KeyPair>
//!}
//!
//!impl client::Handler for Client {
//!    type Error = ();
//!    type FutureBool = futures::Finished<(Self, bool), Self::Error>;
//!    type FutureUnit = futures::Finished<Self, Self::Error>;
//!    type FutureSign = futures::Finished<(Self, thrussh::CryptoVec), Self::Error>;
//!    type SessionUnit = futures::Finished<(Self, client::Session), Self::Error>;
//!    fn check_server_key(self, server_public_key: &key::PublicKey) -> Self::FutureBool {
//!        println!("check_server_key: {:?}", server_public_key);
//!        futures::finished((self, true))
//!    }
//!    fn channel_open_confirmation(self, channel: ChannelId, session: client::Session) -> Self::SessionUnit {
//!        println!("channel_open_confirmation: {:?}", channel);
//!        futures::finished((self, session))
//!    }
//!    fn data(self, channel: ChannelId, ext: Option<u32>, data: &[u8], session: client::Session) -> Self::SessionUnit {
//!        println!("data on channel {:?} {:?}: {:?}", ext, channel, std::str::from_utf8(data));
//!        futures::finished((self, session))
//!    }
//!}
//!
//!impl Client {
//!
//!  fn run(self, config: Arc<client::Config>, _: &str) {
//!     let key = self.key.clone();
//!     tokio::run(
//!
//!       client::connect_future(
//!         "127.0.0.1:2222", config, None, self,
//!         |connection| {
//!           connection.authenticate_key("pe", key)
//!             .and_then(|session| {
//!               session.channel_open_session().and_then(|(session, channelid)| {
//!                 session.data(channelid, None, "Hello, world!").and_then(|(mut session, _)| {
//!                   session.disconnect(Disconnect::ByApplication, "Ciao", "");
//!                   session
//!                 })
//!               })
//!         })
//!       }).unwrap().map_err(|_| ())
//!     )
//!  }
//!}
//!
//!fn main() {
//!    env_logger::init().unwrap();
//!    // Starting the server thread.
//!    let client_key = thrussh_keys::key::KeyPair::generate(thrussh_keys::key::ED25519).unwrap();
//!    let client_pubkey = Arc::new(client_key.clone_public_key());
//!    let t = std::thread::spawn(|| {
//!        let mut config = thrussh::server::Config::default();
//!        config.connection_timeout = Some(std::time::Duration::from_secs(600));
//!        config.auth_rejection_time = std::time::Duration::from_secs(3);
//!        config.keys.push(thrussh_keys::key::KeyPair::generate(thrussh_keys::key::ED25519).unwrap());
//!        let config = Arc::new(config);
//!        let sh = Server{ client_pubkey };
//!        thrussh::server::run(config, "0.0.0.0:2222", sh);
//!    });
//!
//!    std::thread::sleep(std::time::Duration::from_secs(1));
//!    let mut config = thrussh::client::Config::default();
//!    config.connection_timeout = Some(std::time::Duration::from_secs(600));
//!    let config = Arc::new(config);
//!    let sh = Client { key: Arc::new(client_key) };
//!    sh.run(config, "127.0.0.1:2222");
//!
//!    // Kill the server thread after the client has ended.
//!    std::mem::forget(t)
//!}
//! ```

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate log;
extern crate byteorder;

extern crate cryptovec;

extern crate tokio;
extern crate tokio_io;
#[macro_use]
extern crate futures;
extern crate openssl;
extern crate thrussh_libsodium as sodium;
extern crate thrussh_keys;
extern crate tokio_timer;

mod read_exact_from;

pub use cryptovec::CryptoVec;
mod sshbuffer;
mod ssh_read;
mod tcp;
mod key;

pub use tcp::Tcp;

macro_rules! push_packet {
    ( $buffer:expr, $x:expr ) => {
        {
            use byteorder::{BigEndian, ByteOrder};
            let i0 = $buffer.len();
            $buffer.extend(b"\0\0\0\0");
            let x = $x;
            let i1 = $buffer.len();
            use std::ops::DerefMut;
            let buf = $buffer.deref_mut();
            BigEndian::write_u32(&mut buf[i0..], (i1-i0-4) as u32);
            x
        }
    };
}

mod session;



#[derive(Clone, Copy)]
enum Status {
    Ok,
    Disconnect,
}

/// Run one step of the protocol. This trait is currently not used,
/// but both the client and the server implement it. It was meant to
/// factor out code in common between client::Data and a former
/// server::Data.
///
/// The reason the server cannot have a useful `Data` future is that
/// the main interactions between the server and the library user are
/// through callbacks (whereas the client is mostly used by
/// manipulating `Connection`s directly).
trait AtomicPoll<E> {
    fn atomic_poll(&mut self) -> futures::Poll<Status, E>;
}

/// Since handlers are large, their associated future types must implement this trait to provide reasonable default implementations (basically, rejecting all requests).
pub trait FromFinished<T, E>: futures::Future<Item = T, Error = E> {
    /// Turns type `T` into `Self`, a future yielding `T`.
    fn finished(t: T) -> Self;
}

impl<T, E> FromFinished<T, E> for futures::Finished<T, E> {
    fn finished(t: T) -> Self {
        futures::finished(t)
    }
}

impl<T: 'static, E: 'static> FromFinished<T, E> for Box<futures::Future<Item = T, Error = E>> {
    fn finished(t: T) -> Self {
        Box::new(futures::finished(t))
    }
}


#[derive(Debug)]
/// Errors.
pub enum Error {
    /// The key file could not be parsed.
    CouldNotReadKey,

    /// Unspecified problem with the beginning of key exchange.
    KexInit,

    /// No common key exchange algorithm.
    NoCommonKexAlgo,

    /// No common signature algorithm.
    NoCommonKeyAlgo,

    /// No common cipher.
    NoCommonCipher,

    /// Invalid SSH version string.
    Version,

    /// Error during key exchange.
    Kex,

    /// Invalid packet authentication code.
    PacketAuth,

    /// The protocol is in an inconsistent state.
    Inconsistent,

    /// Index out of bounds.
    IndexOutOfBounds,

    /// UTF-8 decoding error (most probably ASCII error).
    Utf8(std::str::Utf8Error),

    /// Unknown server key.
    UnknownKey,

    /// Message received/sent on unopened channel.
    WrongChannel,

    /// I/O error.
    IO(std::io::Error),

    /// Disconnected
    Disconnect,

    /// No home directory found when trying to learn new host key.
    NoHomeDir,

    /// Remote key changed, this could mean a man-in-the-middle attack
    /// is being performed on the connection.
    KeyChanged(usize),

    /// Connection closed by the remote side.
    HUP,

    /// Error from the cryptography layer.
    OpenSSL(openssl::error::Error),

    /// Error from the cryptography layer.
    OpenSSLStack(openssl::error::ErrorStack),

    /// Unit error (sodiumoxide might return that).
    Unit,

    /// Connection timeout.
    ConnectionTimeout,

    /// Missing authentication method.
    NoAuthMethod,

    /// Keys error
    Keys(thrussh_keys::Error),

    /// Timer error
    Timer(tokio_timer::TimerError),
}

/// Errors including those coming from handler. These are not included
/// in this crate's "main" error type to allow for a simpler API (the
/// "handler error" type cannot be inferred by the compiler in some
/// functions).
#[derive(Debug)]
pub enum HandlerError<E> {
    /// Standard errors
    Error(Error),
    /// From handler
    Handler(E),
}

use std::error::Error as StdError;
impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.description())
    }
}
impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Utf8(ref e) => e.description(),
            Error::IO(ref e) => e.description(),
            Error::CouldNotReadKey => "Could not read key",
            Error::KexInit => "KexInit problem",
            Error::NoCommonKexAlgo => "No common key exchange algorithms were found",
            Error::NoCommonKeyAlgo => "No common signature algorithms were found",
            Error::NoCommonCipher => "No common ciphers were found",
            Error::Kex => "Received invalid key exchange packet",
            Error::Version => "Invalid version string from the remote side",
            Error::PacketAuth => "Incorrect packet authentication code",
            Error::Inconsistent => "Unexpected packet",
            Error::IndexOutOfBounds => "Index out of bounds in a packet",
            Error::UnknownKey => "Unknown host key",
            Error::WrongChannel => "Inexistent channel",
            Error::Disconnect => "Disconnected",
            Error::NoHomeDir => "Home directory not found",
            Error::KeyChanged(_) => "Server key changed",
            Error::HUP => "Connection closed by the remote side",
            Error::ConnectionTimeout => "Connection timout",
            Error::NoAuthMethod => "No more authentication methods available",
            Error::OpenSSL(ref e) => e.description(),
            Error::OpenSSLStack(ref e) => e.description(),
            Error::Unit => "Unknown (unit) error",
            Error::Keys(ref e) => e.description(),
            Error::Timer(ref e) => e.description(),
        }
    }
    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Utf8(ref e) => Some(e),
            Error::IO(ref e) => Some(e),
            _ => None,
        }
    }
}

impl<E:std::error::Error> std::fmt::Display for HandlerError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.description())
    }
}
impl<E:std::error::Error> std::error::Error for HandlerError<E> {
    fn description(&self) -> &str {
        match *self {
            HandlerError::Error(ref e) => e.description(),
            HandlerError::Handler(ref e) => e.description(),
        }
    }
    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            HandlerError::Error(ref e) => e.cause(),
            HandlerError::Handler(ref e) => e.cause(),
        }
    }
}



impl From<std::io::Error> for Error {
    fn from(e: std::io::Error) -> Error {
        Error::IO(e)
    }
}

impl From<thrussh_keys::Error> for Error {
    fn from(e: thrussh_keys::Error) -> Error {
        Error::Keys(e)
    }
}

impl From<std::str::Utf8Error> for Error {
    fn from(e: std::str::Utf8Error) -> Error {
        Error::Utf8(e)
    }
}

impl From<openssl::error::ErrorStack> for Error {
    fn from(e: openssl::error::ErrorStack) -> Error {
        Error::OpenSSLStack(e)
    }
}
/*
impl From<tokio_timer::TimerError> for Error {
    fn from(e: tokio_timer::TimerError) -> Error {
        Error::Timer(e)
    }
}
*/
impl From<()> for Error {
    fn from(_: ()) -> Error {
        Error::Unit
    }
}

impl<E> From<Error> for HandlerError<E> {
    fn from(e: Error) -> HandlerError<E> {
        HandlerError::Error(e)
    }
}
impl<E> From<std::io::Error> for HandlerError<E> {
    fn from(e: std::io::Error) -> HandlerError<E> {
        HandlerError::Error(Error::IO(e))
    }
}

impl<E> From<std::str::Utf8Error> for HandlerError<E> {
    fn from(e: std::str::Utf8Error) -> HandlerError<E> {
        HandlerError::Error(Error::Utf8(e))
    }
}
impl<E> From<thrussh_keys::Error> for HandlerError<E> {
    fn from(e: thrussh_keys::Error) -> HandlerError<E> {
        HandlerError::Error(Error::Keys(e))
    }
}

impl<E> From<tokio_timer::TimerError> for HandlerError<E> {
    fn from(e: tokio_timer::TimerError) -> HandlerError<E> {
        HandlerError::Error(Error::Timer(e))
    }
}


mod negotiation;
pub use negotiation::{Named, Preferred};
mod pty;
pub use pty::Pty;
mod msg;
mod kex;
mod cipher;

// mod mac;
// use mac::*;
// mod compression;

mod auth;

/// The number of bytes read/written, and the number of seconds before a key re-exchange is requested.
#[derive(Debug, Clone)]
pub struct Limits {
    rekey_write_limit: usize,
    rekey_read_limit: usize,
    rekey_time_limit: std::time::Duration,
}

impl Limits {
    /// Create a new `Limits`, checking that the given bounds cannot lead to nonce reuse.
    pub fn new(write_limit: usize, read_limit: usize, time_limit: std::time::Duration) -> Limits {
        assert!(write_limit <= 1 << 30 && read_limit <= 1 << 30);
        Limits {
            rekey_write_limit: write_limit,
            rekey_read_limit: read_limit,
            rekey_time_limit: time_limit,
        }
    }
}

impl Default for Limits {
    fn default() -> Self {
        // Following the recommendations of
        // https://tools.ietf.org/html/rfc4253#section-9
        Limits {
            rekey_write_limit: 1 << 30, // 1 Gb
            rekey_read_limit: 1 << 30, // 1 Gb
            rekey_time_limit: std::time::Duration::from_secs(3600),
        }
    }
}

pub use auth::MethodSet;

/// Server side of this library.
pub mod server;

/// Client side of this library.
pub mod client;

/// A reason for disconnection.
#[allow(missing_docs)] // This should be relatively self-explanatory.
pub enum Disconnect {
    HostNotAllowedToConnect = 1,
    ProtocolError = 2,
    KeyExchangeFailed = 3,
    #[doc(hidden)]
    Reserved = 4,
    MACError = 5,
    CompressionError = 6,
    ServiceNotAvailable = 7,
    ProtocolVersionNotSupported = 8,
    HostKeyNotVerifiable = 9,
    ConnectionLost = 10,
    ByApplication = 11,
    TooManyConnections = 12,
    AuthCancelledByUser = 13,
    NoMoreAuthMethodsAvailable = 14,
    IllegalUserName = 15,
}

/// The type of signals that can be sent to a remote process. If you
/// plan to use custom signals, read [the
/// RFC](https://tools.ietf.org/html/rfc4254#section-6.10) to
/// understand the encoding.
#[allow(missing_docs)]
// This should be relatively self-explanatory.
#[derive(Debug, Clone, Copy)]
pub enum Sig<'a> {
    ABRT,
    ALRM,
    FPE,
    HUP,
    ILL,
    INT,
    KILL,
    PIPE,
    QUIT,
    SEGV,
    TERM,
    USR1,
    Custom(&'a str),
}

impl<'a> Sig<'a> {
    fn name(&self) -> &'a str {
        match *self {
            Sig::ABRT => "ABRT",
            Sig::ALRM => "ALRM",
            Sig::FPE => "FPE",
            Sig::HUP => "HUP",
            Sig::ILL => "ILL",
            Sig::INT => "INT",
            Sig::KILL => "KILL",
            Sig::PIPE => "PIPE",
            Sig::QUIT => "QUIT",
            Sig::SEGV => "SEGV",
            Sig::TERM => "TERM",
            Sig::USR1 => "USR1",
            Sig::Custom(c) => c,
        }
    }
    fn from_name(name: &'a [u8]) -> Result<Sig, Error> {
        match name {
            b"ABRT" => Ok(Sig::ABRT),
            b"ALRM" => Ok(Sig::ALRM),
            b"FPE" => Ok(Sig::FPE),
            b"HUP" => Ok(Sig::HUP),
            b"ILL" => Ok(Sig::ILL),
            b"INT" => Ok(Sig::INT),
            b"KILL" => Ok(Sig::KILL),
            b"PIPE" => Ok(Sig::PIPE),
            b"QUIT" => Ok(Sig::QUIT),
            b"SEGV" => Ok(Sig::SEGV),
            b"TERM" => Ok(Sig::TERM),
            b"USR1" => Ok(Sig::USR1),
            x => Ok(Sig::Custom(try!(std::str::from_utf8(x)))),
        }
    }
}


/// Reason for not being able to open a channel.
#[derive(Debug, Copy, Clone, PartialEq)]
#[allow(missing_docs)]
pub enum ChannelOpenFailure {
    AdministrativelyProhibited = 1,
    ConnectFailed = 2,
    UnknownChannelType = 3,
    ResourceShortage = 4,
}

impl ChannelOpenFailure {
    fn from_u32(x: u32) -> Option<ChannelOpenFailure> {
        match x {
            1 => Some(ChannelOpenFailure::AdministrativelyProhibited),
            2 => Some(ChannelOpenFailure::ConnectFailed),
            3 => Some(ChannelOpenFailure::UnknownChannelType),
            4 => Some(ChannelOpenFailure::ResourceShortage),
            _ => None,
        }
    }
}


#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
/// The identifier of a channel.
pub struct ChannelId(u32);

/// The parameters of a channel.
#[derive(Debug)]
pub(crate) struct Channel {
    recipient_channel: u32,
    sender_channel: ChannelId,
    recipient_window_size: u32,
    sender_window_size: u32,
    recipient_maximum_packet_size: u32,
    sender_maximum_packet_size: u32,
    /// Has the other side confirmed the channel?
    pub confirmed: bool,
    wants_reply: bool,
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//
// https://tools.ietf.org/html/rfc4253#section-12
pub const DISCONNECT: u8 = 1;
#[allow(dead_code)]
pub const IGNORE: u8 = 2;
#[allow(dead_code)]
pub const UNIMPLEMENTED: u8 = 3;
#[allow(dead_code)]
pub const DEBUG: u8 = 4;

pub const SERVICE_REQUEST: u8 = 5;
pub const SERVICE_ACCEPT: u8 = 6;
pub const KEXINIT: u8 = 20;
pub const NEWKEYS: u8 = 21;


// http://tools.ietf.org/html/rfc5656#section-7.1
pub const KEX_ECDH_INIT: u8 = 30;
pub const KEX_ECDH_REPLY: u8 = 31;

// https://tools.ietf.org/html/rfc4250#section-4.1.2
pub const USERAUTH_REQUEST: u8 = 50;
pub const USERAUTH_FAILURE: u8 = 51;
pub const USERAUTH_SUCCESS: u8 = 52;
pub const USERAUTH_BANNER: u8 = 53;
pub const USERAUTH_PK_OK: u8 = 60;

// https://tools.ietf.org/html/rfc4256#section-5
pub const USERAUTH_INFO_REQUEST: u8 = 60;
pub const USERAUTH_INFO_RESPONSE: u8 = 61;


// https://tools.ietf.org/html/rfc4254#section-9
pub const GLOBAL_REQUEST: u8 = 80;
pub const REQUEST_SUCCESS: u8 = 81;
pub const REQUEST_FAILURE: u8 = 82;

pub const CHANNEL_OPEN: u8 = 90;
pub const CHANNEL_OPEN_CONFIRMATION: u8 = 91;
pub const CHANNEL_OPEN_FAILURE: u8 = 92;
pub const CHANNEL_WINDOW_ADJUST: u8 = 93;
pub const CHANNEL_DATA: u8 = 94;
pub const CHANNEL_EXTENDED_DATA: u8 = 95;
pub const CHANNEL_EOF: u8 = 96;
pub const CHANNEL_CLOSE: u8 = 97;
pub const CHANNEL_REQUEST: u8 = 98;
pub const CHANNEL_SUCCESS: u8 = 99;
pub const CHANNEL_FAILURE: u8 = 100;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//
use Error;
use thrussh_keys::key;
use kex;
use cipher;
use msg;
use std::str::from_utf8;
// use super::mac; // unimplemented
// use super::compression; // unimplemented
use cryptovec::CryptoVec;
use thrussh_keys::encoding::{Encoding, Reader};
use thrussh_keys::key::{PublicKey, KeyPair};
use openssl::rand;

#[derive(Debug)]
pub struct Names {
    pub kex: kex::Name,
    pub key: key::Name,
    pub cipher: cipher::Name,
    pub mac: Option<&'static str>,
    pub ignore_guessed: bool,
}

/// Lists of preferred algorithms. This is normally hard-coded into implementations.
#[derive(Debug)]
pub struct Preferred {
    /// Preferred key exchange algorithms.
    pub kex: &'static [kex::Name],
    /// Preferred public key algorithms.
    pub key: &'static [key::Name],
    /// Preferred symmetric ciphers.
    pub cipher: &'static [cipher::Name],
    /// Preferred MAC algorithms.
    pub mac: &'static [&'static str],
    /// Preferred compression algorithms.
    pub compression: &'static [&'static str],
}

pub const DEFAULT: Preferred = Preferred {
    kex: &[kex::CURVE25519],
    key: &[key::ED25519, key::RSA_SHA2_256, key::RSA_SHA2_512],
    cipher: &[cipher::chacha20poly1305::NAME],
    mac: &["none"],
    compression: &["none"],
};

impl Default for Preferred {
    fn default() -> Preferred {
        DEFAULT
    }
}

/// Named algorithms.
pub trait Named {
    /// The name of this algorithm.
    fn name(&self) -> &'static str;
}

impl Named for () {
    fn name(&self) -> &'static str {
        ""
    }
}

use thrussh_keys::key::{ED25519, SSH_RSA};

impl Named for PublicKey {
    fn name(&self) -> &'static str {
        match self {
            &PublicKey::Ed25519(_) => ED25519.0,
            &PublicKey::RSA { .. } => SSH_RSA,
        }
    }
}

impl Named for KeyPair {
    fn name(&self) -> &'static str {
        match self {
            &KeyPair::Ed25519 { .. } => ED25519.0,
            &KeyPair::RSA { ref hash, .. } => hash.name().0,
        }
    }
}

pub trait Select {
    fn select<S: AsRef<str> + Copy>(a: &[S], b: &[u8]) -> Option<(bool, S)>;

    fn read_kex(buffer: &[u8], pref: &Preferred) -> Result<Names, Error> {
        let mut r = buffer.reader(17);
        let kex_string = try!(r.read_string());
        let (kex_both_first, kex_algorithm) = if let Some(x) = Self::select(pref.kex, kex_string) {
            x
        } else {
            debug!(
                "Could not find common kex algorithm, other side only supports {:?}, we only support {:?}",
                from_utf8(kex_string),
                pref.kex
            );
            return Err(Error::NoCommonKexAlgo);
        };

        let key_string = try!(r.read_string());
        let (key_both_first, key_algorithm) = if let Some(x) = Self::select(pref.key, key_string) {
            x
        } else {
            debug!(
                "Could not find common key algorithm, other side only supports {:?}, we only support {:?}",
                from_utf8(key_string),
                pref.key
            );
            return Err(Error::NoCommonKeyAlgo);
        };

        let cipher_string = try!(r.read_string());
        let cipher = Self::select(pref.cipher, cipher_string);
        if cipher.is_none() {
            debug!(
                "Could not find common cipher, other side only supports {:?}, we only support {:?}",
                from_utf8(cipher_string),
                pref.cipher
            );
            return Err(Error::NoCommonCipher);
        }
        try!(r.read_string()); // SERVER_TO_CLIENT
        let mac = Self::select(pref.mac, try!(r.read_string()));
        let mac = mac.and_then(|(_, x)| Some(x));
        try!(r.read_string()); // SERVER_TO_CLIENT
        try!(r.read_string()); //
        try!(r.read_string()); //
        try!(r.read_string()); //

        let follows = try!(r.read_byte()) != 0;
        match (cipher, mac, follows) {
            (Some((_, cip)), mac, fol) => {
                Ok(Names {
                    kex: kex_algorithm,
                    key: key_algorithm,
                    cipher: cip,
                    mac: mac,
                    // Ignore the next packet if (1) it follows and (2) it's not the correct guess.
                    ignore_guessed: fol && !(kex_both_first && key_both_first),
                })
            }
            _ => Err(Error::KexInit),
        }
    }
}

pub struct Server;
pub struct Client;

impl Select for Server {
    fn select<S: AsRef<str> + Copy>(server_list: &[S], client_list: &[u8]) -> Option<(bool, S)> {
        let mut both_first_choice = true;
        for c in client_list.split(|&x| x == b',') {
            for &s in server_list {
                if c == s.as_ref().as_bytes() {
                    return Some((both_first_choice, s));
                }
                both_first_choice = false
            }
        }
        None
    }
}

impl Select for Client {
    fn select<S: AsRef<str> + Copy>(client_list: &[S], server_list: &[u8]) -> Option<(bool, S)> {
        let mut both_first_choice = true;
        for &c in client_list {
            for s in server_list.split(|&x| x == b',') {
                if s == c.as_ref().as_bytes() {
                    return Some((both_first_choice, c));
                }
                both_first_choice = false
            }
        }
        None
    }
}


pub fn write_kex(prefs: &Preferred, buf: &mut CryptoVec) -> Result<(), Error> {

    // buf.clear();
    buf.push(msg::KEXINIT);

    let mut cookie = [0; 16];
    rand::rand_bytes(&mut cookie)?;

    buf.extend(&cookie); // cookie
    buf.extend_list(prefs.kex.iter()); // kex algo

    buf.extend_list(prefs.key.iter());

    buf.extend_list(prefs.cipher.iter()); // cipher client to server
    buf.extend_list(prefs.cipher.iter()); // cipher server to client

    buf.extend_list(prefs.mac.iter()); // mac client to server
    buf.extend_list(prefs.mac.iter()); // mac server to client
    buf.extend_list(prefs.compression.iter()); // compress client to server
    buf.extend_list(prefs.compression.iter()); // compress server to client

    buf.write_empty_list(); // languages client to server
    buf.write_empty_list(); // languagesserver to client

    buf.push(0); // doesn't follow
    buf.extend(&[0, 0, 0, 0]); // reserved
    Ok(())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#[allow(non_camel_case_types, missing_docs)]
#[derive(Debug, Copy, Clone, PartialEq)]
/// Standard pseudo-terminal codes.
pub enum Pty {
    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 = 40,
    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,
}

impl Pty {
    #[doc(hidden)]
    pub fn from_u8(x: u8) -> Option<Pty> {
        match x {
            0 => None,
            1 => Some(Pty::VINTR),
            2 => Some(Pty::VQUIT),
            3 => Some(Pty::VERASE),
            4 => Some(Pty::VKILL),
            5 => Some(Pty::VEOF),
            6 => Some(Pty::VEOL),
            7 => Some(Pty::VEOL2),
            8 => Some(Pty::VSTART),
            9 => Some(Pty::VSTOP),
            10 => Some(Pty::VSUSP),
            11 => Some(Pty::VDSUSP),

            12 => Some(Pty::VREPRINT),
            13 => Some(Pty::VWERASE),
            14 => Some(Pty::VLNEXT),
            15 => Some(Pty::VFLUSH),
            16 => Some(Pty::VSWTCH),
            17 => Some(Pty::VSTATUS),
            18 => Some(Pty::VDISCARD),
            30 => Some(Pty::IGNPAR),
            31 => Some(Pty::PARMRK),
            32 => Some(Pty::INPCK),
            33 => Some(Pty::ISTRIP),
            34 => Some(Pty::INLCR),
            35 => Some(Pty::IGNCR),
            36 => Some(Pty::ICRNL),
            37 => Some(Pty::IUCLC),
            38 => Some(Pty::IXON),
            39 => Some(Pty::IXANY),
            40 => Some(Pty::IXOFF),
            41 => Some(Pty::IMAXBEL),
            50 => Some(Pty::ISIG),
            51 => Some(Pty::ICANON),
            52 => Some(Pty::XCASE),
            53 => Some(Pty::ECHO),
            54 => Some(Pty::ECHOE),
            55 => Some(Pty::ECHOK),
            56 => Some(Pty::ECHONL),
            57 => Some(Pty::NOFLSH),
            58 => Some(Pty::TOSTOP),
            59 => Some(Pty::IEXTEN),
            60 => Some(Pty::ECHOCTL),
            61 => Some(Pty::ECHOKE),
            62 => Some(Pty::PENDIN),
            70 => Some(Pty::OPOST),
            71 => Some(Pty::OLCUC),
            72 => Some(Pty::ONLCR),
            73 => Some(Pty::OCRNL),
            74 => Some(Pty::ONOCR),
            75 => Some(Pty::ONLRET),

            90 => Some(Pty::CS7),
            91 => Some(Pty::CS8),
            92 => Some(Pty::PARENB),
            93 => Some(Pty::PARODD),

            128 => Some(Pty::TTY_OP_ISPEED),
            129 => Some(Pty::TTY_OP_OSPEED),
            _ => None,
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use tokio::io::AsyncRead;
use futures::{Future, Poll, Async};
use std::io;
use std::mem;
use std::io::ErrorKind;

#[derive(Debug)]
pub struct ReadExact<A, T> {
    state: State<A, T>,
}

#[derive(Debug)]
enum State<A, T> {
    Reading {
        a: A,
        buf: T,
        pos: usize,
        initial_pos: usize,
    },
    Empty,
}

pub fn read_exact_from<A, T>(a: A, buf: T, pos: usize) -> ReadExact<A, T>
where
    A: AsyncRead,
    T: AsMut<[u8]>,
{
    ReadExact {
        state: State::Reading {
            a,
            buf,
            pos,
            initial_pos: pos,
        },
    }
}

fn eof() -> io::Error {
    io::Error::new(io::ErrorKind::UnexpectedEof, "early eof")
}

impl<A, T> Future for ReadExact<A, T>
where
    A: AsyncRead,
    T: AsMut<[u8]>,
{
    type Item = (A, T);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(A, T), io::Error> {
        match self.state {
            State::Reading {
                ref mut a,
                ref mut buf,
                ref mut pos,
                ..
            } => {
                let buf = buf.as_mut();
                while *pos < buf.len() {
                    let n = match a.read(&mut buf[*pos..]) {
                        Ok(n) => n,
                        Err(ref e) if e.kind() == ErrorKind::WouldBlock => return Ok(Async::NotReady),
                        Err(e) => return Err(e)
                    };
                    *pos += n;
                    if n == 0 {
                        return Err(eof());
                    }
                }
            }
            State::Empty => panic!("poll a ReadExact after it's done"),
        }

        match mem::replace(&mut self.state, State::Empty) {
            State::Reading { a, buf, .. } => Ok((a, buf).into()),
            State::Empty => panic!(),
        }
    }
}

impl<A, T> ReadExact<A, T> {
    pub fn try_abort(&mut self) -> Option<(A, T)> {
        if let State::Reading {
            a,
            buf,
            pos,
            initial_pos,
        } = mem::replace(&mut self.state, State::Empty)
        {
            if pos == initial_pos {
                Some((a, buf))
            } else {
                None
            }
        } else {
            None
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
use super::*;
use cipher;
use negotiation::Select;
use msg;
use negotiation;
use std::sync::Arc;
use tcp::Tcp;
use ssh_read::SshRead;
use tokio_timer::{Timer, Sleep};

#[doc(hidden)]
pub enum ConnectionState<R: AsyncRead + AsyncWrite + Tcp, H: Handler> {
    ReadSshId(SshRead<R>),
    WriteSshId(WriteAll<R, CryptoVec>),
    Read(cipher::CipherRead<SshRead<R>>),
    Write(WriteAll<SshRead<R>, CryptoVec>),
    Flush(Flush<SshRead<R>>),
    Pending {
        pending: PendingFuture<H>,
        stream: SshRead<R>,
    },
    Shutdown {
        read: tokio_io::io::Read<SshRead<R>, CryptoVec>,
        read_buffer: SSHBuffer,
    },
}

#[doc(hidden)]
pub enum PendingFuture<H: Handler> {
    Ok { handler: H, session: Session },
    RejectTimeout {
        handler: H,
        session: Session,
        timeout: Sleep,
    },
    ReadAuthRequest {
        session: Session,
        auth_request: encrypted::ReadAuthRequest<H>,
    },
    Authenticated(encrypted::Authenticated<H>),
}

#[doc(hidden)]
pub struct Connection<R: AsyncRead + AsyncWrite + Tcp, H: Handler> {
    pub read_buffer: Option<SSHBuffer>,
    pub session: Option<Session>,
    pub state: Option<ConnectionState<R, H>>,
    pub buffer: CryptoVec,
    pub buffer2: CryptoVec,
    pub handler: Option<H>,
    pub timeout: Option<Sleep>,
}

impl<R: AsyncRead + AsyncWrite + Tcp, H: Handler> Future for Connection<R, H> {
    type Item = ();
    type Error = HandlerError<H::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            // If timeout, shutdown the socket.
            if let Some(ref mut timeout) = self.timeout {
                match try!(timeout.poll()) {
                    Async::Ready(()) => {
                        // try_nb!(self.stream.get_mut().shutdown(std::net::Shutdown::Both));
                        debug!("Disconnected, shutdown");
                        return Ok(Async::Ready(()));
                    }
                    Async::NotReady => {}
                }
            }
            debug!("polling");
            if let Status::Disconnect = try_ready!(self.atomic_poll()) {
                debug!("disconnect, {}", line!());
                return Ok(Async::Ready(()));
            }
        }
    }
}

impl<R: AsyncRead + AsyncWrite + Tcp, H: Handler> AtomicPoll<HandlerError<H::Error>>
    for Connection<R, H> {
    fn atomic_poll(&mut self) -> Poll<Status, HandlerError<H::Error>> {

        match self.state.take() {
            None => {
                debug!("no state");
                Ok(Async::Ready(Status::Disconnect))
            },
            Some(ConnectionState::WriteSshId(mut write)) => {
                if let Async::Ready((stream, mut buf)) = write.poll()? {
                    // Here we're recycling the buffer used for the
                    // SSH-identification as the write buffer.
                    if let Some(ref mut session) = self.session {
                        buf.clear();
                        session.0.write_buffer.buffer = buf;
                    }
                    self.state = Some(ConnectionState::ReadSshId(SshRead::new(stream)));
                    Ok(Async::Ready(Status::Ok))
                } else {
                    Ok(Async::NotReady)
                }
            }
            Some(ConnectionState::ReadSshId(mut read)) => {
                let is_ready = if let Async::Ready(sshid) = read.read_ssh_id()? {
                    self.read_ssh_id(sshid)?;
                    true
                } else {
                    false
                };
                debug!("SSH- read: {:?}", is_ready);
                if is_ready {
                    if let Some(ref mut session) = self.session {
                        session.flush()?;
                        self.state = Some(ConnectionState::Write(
                            session.0.write_buffer.write_all(read),
                        ));
                    }
                    Ok(Async::Ready(Status::Ok))
                } else {
                    self.state = Some(ConnectionState::ReadSshId(read));
                    return Ok(Async::NotReady);
                }
            }
            Some(ConnectionState::Pending { pending, stream }) => {
                debug!("atomic pending");
                self.poll_pending(pending, stream)
            }
            Some(ConnectionState::Write(mut write)) => {
                debug!("atomic writing");
                if let Async::Ready((stream, mut buf)) = write.poll()? {
                    if let Some(ref mut session) = self.session {
                        buf.clear();
                        session.0.write_buffer.buffer = buf;
                        self.state = Some(ConnectionState::Flush(flush(stream)));
                        Ok(Async::Ready(Status::Ok))
                    } else {
                        unreachable!()
                    }
                } else {
                    self.state = Some(ConnectionState::Write(write));
                    Ok(Async::NotReady)
                }
            }
            Some(ConnectionState::Flush(mut flush)) => {
                debug!("atomic flushing");
                if let Async::Ready(mut stream) = flush.poll()? {

                    if let Some(ref mut session) = self.session {
                        if session.0.disconnected {
                            stream.tcp_shutdown()?;
                            let mut read_buffer = self.read_buffer.take().unwrap();
                            let buffer =
                                std::mem::replace(&mut read_buffer.buffer, CryptoVec::new());
                            self.state = Some(ConnectionState::Shutdown {
                                read: tokio_io::io::read(stream, buffer),
                                read_buffer,
                            });
                        } else {
                            let mut buf = self.read_buffer.take().unwrap();
                            buf.buffer.clear();
                            self.state = Some(ConnectionState::Read(
                                cipher::read(stream, buf, session.0.cipher.clone()),
                            ));
                        }
                    }
                    Ok(Async::Ready(Status::Ok))
                } else {
                    self.state = Some(ConnectionState::Flush(flush));
                    Ok(Async::NotReady)
                }
            }
            Some(ConnectionState::Read(mut read)) => {
                debug!("atomic reading");
                if let Async::Ready((stream, mut buf, end)) = read.poll()? {
                    debug!("buf: {:?}", buf.buffer.as_ref());
                    // Handle the transport layer.
                    if buf.buffer.len() < 5 || buf.buffer[5] == msg::DISCONNECT {
                        // transport
                        let buffer = std::mem::replace(&mut buf.buffer, CryptoVec::new());
                        debug!("disconnect {}", line!());
                        self.state = Some(ConnectionState::Shutdown {
                            read: tokio_io::io::read(stream, buffer),
                            read_buffer: buf,
                        });
                        return Ok(Async::Ready(Status::Ok));
                    } else if buf.buffer[5] <= 4 {
                        let session = self.session.as_ref().unwrap();
                        self.state = Some(ConnectionState::Read(
                            cipher::read(stream, buf, session.0.cipher.clone()),
                        ));
                        return Ok(Async::Ready(Status::Ok));
                    } else {
                        let result = self.read(&buf.buffer[5..end], stream);
                        self.read_buffer = Some(buf);
                        return result;
                    }
                } else {
                    debug!("atomic reading not ready");
                    self.state = Some(ConnectionState::Read(read));
                    Ok(Async::NotReady)
                }
            }
            Some(ConnectionState::Shutdown {
                     mut read,
                     mut read_buffer,
                 }) => {
                debug!("atomic shutdown");
                if let Async::Ready((stream, mut buf, n)) = read.poll()? {
                    if n == 0 {
                        read_buffer.buffer = buf;
                        self.read_buffer = Some(read_buffer);
                        Ok(Async::Ready(Status::Disconnect))
                    } else {
                        buf.clear();
                        self.state = Some(ConnectionState::Shutdown {
                            read: tokio_io::io::read(stream, buf),
                            read_buffer,
                        });
                        Ok(Async::Ready(Status::Ok))
                    }
                } else {
                    self.state = Some(ConnectionState::Shutdown { read, read_buffer });
                    Ok(Async::NotReady)
                }
            }
        }
    }
}


impl<H: Handler, R: AsyncRead + AsyncWrite + Tcp> Connection<R, H> {
    #[doc(hidden)]
    pub fn new(config: Arc<Config>, stream: R, handler: H) -> Result<Self, Error> {
        let mut write_buffer = SSHBuffer::new();
        write_buffer.send_ssh_id(config.as_ref().server_id.as_bytes());
        let timeout = if let Some(t) = config.connection_timeout {
            let timer = Timer::default();
            Some(timer.sleep(t))
        } else {
            None
        };
        let write = write_buffer.write_all(stream);
        let session = Session(CommonSession {
            write_buffer: SSHBuffer::new(),
            kex: None,
            auth_user: String::new(),
            auth_method: None, // Client only.
            cipher: Arc::new(cipher::CLEAR_PAIR),
            encrypted: None,
            config: config,
            wants_reply: false,
            disconnected: false,
            buffer: Some(CryptoVec::new()),
        });
        let connection = Connection {
            read_buffer: Some(SSHBuffer::new()),
            timeout: timeout,
            session: Some(session),
            state: Some(ConnectionState::WriteSshId(write)),
            handler: Some(handler),
            buffer: CryptoVec::new(),
            buffer2: CryptoVec::new(),
        };
        Ok(connection)
    }

    #[doc(hidden)]
    pub fn read_ssh_id(&mut self, sshid: &[u8]) -> Result<(), Error> {
        let mut exchange = Exchange::new();
        exchange.client_id.extend(sshid);
        // Preparing the response
        if let Some(ref mut session) = self.session {
            exchange.server_id.extend(
                session
                    .0
                    .config
                    .as_ref()
                    .server_id
                    .as_bytes(),
            );
            let mut kexinit = KexInit {
                exchange: exchange,
                algo: None,
                sent: false,
                session_id: None,
            };
            kexinit.server_write(
                session.0.config.as_ref(),
                session.0.cipher.as_ref(),
                &mut session.0.write_buffer,
            )?;
            session.0.kex = Some(Kex::KexInit(kexinit));
        }
        Ok(())
    }

    fn poll_pending(
        &mut self,
        pending: PendingFuture<H>,
        stream: SshRead<R>,
    ) -> Poll<Status, HandlerError<H::Error>> {
        debug!("Running encrypted future");
        let (handler, mut session) = match pending {
            PendingFuture::Ok { handler, session } => (handler, session),
            PendingFuture::RejectTimeout {
                handler,
                mut timeout,
                session,
            } => {
                debug!("future: rejectTimeout");
                match try!(timeout.poll()) {
                    Async::Ready(()) => (handler, session),
                    Async::NotReady => {
                        self.state = Some(ConnectionState::Pending {
                            pending: PendingFuture::RejectTimeout {
                                session,
                                timeout,
                                handler,
                            },
                            stream,
                        });
                        return Ok(Async::NotReady);
                    }
                }
            }
            PendingFuture::ReadAuthRequest {
                mut session,
                mut auth_request,
            } => {
                debug!("future: read_auth_request");
                let pre_auth = std::time::Instant::now();

                let auth = {
                    let enc = session.0.encrypted.as_mut().unwrap();
                    auth_request.poll(
                        enc,
                        &mut session.0.auth_user,
                        &mut self.buffer,
                    )?
                };

                match auth {
                    Async::Ready((handler, Auth::Reject)) => {
                        debug!("reject");
                        let rejection_time = session.0.config.auth_rejection_time;
                        let timer = Timer::default();
                        let now = std::time::Instant::now();
                        self.state = Some(ConnectionState::Pending {
                            pending: PendingFuture::RejectTimeout {
                                session,
                                handler,
                                timeout: timer.sleep(pre_auth - now + rejection_time)
                            },
                            stream,
                        });
                        return Ok(Async::Ready(Status::Ok));
                    }
                    Async::Ready((handler, _)) => (handler, session),
                    Async::NotReady => {
                        self.state = Some(ConnectionState::Pending {
                            pending: PendingFuture::ReadAuthRequest {
                                session,
                                auth_request,
                            },
                            stream,
                        });
                        return Ok(Async::NotReady);
                    }
                }
            }
            PendingFuture::Authenticated(mut r) => {
                debug!("future: authenticated");
                if let Async::Ready((handler, session)) = try!(r.poll()) {
                    (handler, session)
                } else {
                    self.state = Some(ConnectionState::Pending {
                        pending: PendingFuture::Authenticated(r),
                        stream,
                    });
                    return Ok(Async::NotReady);
                }
            }
        };


        self.handler = Some(handler);
        session.flush()?;
        self.state = Some(ConnectionState::Write(
            session.0.write_buffer.write_all(stream),
        ));
        self.session = Some(session);
        Ok(Async::Ready(Status::Ok))
    }


    fn read(
        &mut self,
        buf: &[u8],
        stream: SshRead<R>,
    ) -> Poll<Status, HandlerError<<H as Handler>::Error>> {

        let mut session = self.session.take().unwrap();

        // Handle key exchange/re-exchange.
        match session.0.kex.take() {
            Some(Kex::KexInit(kexinit)) => {
                if kexinit.algo.is_some() || buf[0] == msg::KEXINIT ||
                    session.0.encrypted.is_none()
                {
                    let next_kex = kexinit.server_parse(
                        session.0.config.as_ref(),
                        &session.0.cipher,
                        &buf,
                        &mut session.0.write_buffer,
                    );
                    match next_kex {
                        Ok(next_kex) => {
                            session.0.kex = Some(next_kex);
                            session.flush()?;
                            self.state = Some(ConnectionState::Write(
                                session.0.write_buffer.write_all(stream),
                            ));
                            self.session = Some(session);
                            return Ok(Async::Ready(Status::Ok));
                        }
                        Err(e) => {
                            session.flush()?;
                            self.state = Some(ConnectionState::Write(
                                session.0.write_buffer.write_all(stream),
                            ));
                            self.session = Some(session);
                            return Err(HandlerError::Error(e));
                        }
                    }
                }
                // Else, i.e. if the other side has not started
                // the key exchange, process its packets by simple
                // not returning.
            }
            Some(Kex::KexDh(kexdh)) => {
                let next_kex = kexdh.parse(
                    session.0.config.as_ref(),
                    &mut self.buffer,
                    &mut self.buffer2,
                    &session.0.cipher,
                    &buf,
                    &mut session.0.write_buffer,
                );
                match next_kex {
                    Ok(next_kex) => {
                        session.0.kex = Some(next_kex);
                        session.flush()?;
                        self.state = Some(ConnectionState::Write(
                            session.0.write_buffer.write_all(stream),
                        ));
                        self.session = Some(session);
                        return Ok(Async::Ready(Status::Ok));
                    }
                    Err(e) => {
                        session.flush()?;
                        self.state = Some(ConnectionState::Write(
                            session.0.write_buffer.write_all(stream),
                        ));
                        self.session = Some(session);
                        return Err(HandlerError::Error(e));
                    }
                }
            }
            Some(Kex::NewKeys(newkeys)) => {
                if buf[0] != msg::NEWKEYS {
                    session.flush()?;
                    self.state = Some(ConnectionState::Write(
                        session.0.write_buffer.write_all(stream),
                    ));
                    self.session = Some(session);
                    return Err(HandlerError::Error(Error::Kex));
                }
                // Ok, NEWKEYS received, now encrypted.
                session.0.encrypted(
                    EncryptedState::WaitingServiceRequest,
                    newkeys,
                );
                session.flush()?;
                self.state = Some(ConnectionState::Write(
                    session.0.write_buffer.write_all(stream),
                ));
                self.session = Some(session);
                return Ok(Async::Ready(Status::Ok));
            }
            Some(kex) => {
                session.0.kex = Some(kex);
                session.flush()?;
                self.state = Some(ConnectionState::Write(
                    session.0.write_buffer.write_all(stream),
                ));
                self.session = Some(session);
                return Ok(Async::Ready(Status::Ok));
            }
            None => {}
        }

        // Start a key re-exchange, if the client is asking for it.
        if buf[0] == msg::KEXINIT {
            // Now, if we're encrypted:
            if let Some(ref mut enc) = session.0.encrypted {

                // If we're not currently rekeying, but buf is a rekey request
                if let Some(exchange) = enc.exchange.take() {
                    let pref = &session.0.config.as_ref().preferred;
                    let kexinit = KexInit::received_rekey(
                        exchange,
                        negotiation::Server::read_kex(buf, pref)?,
                        &enc.session_id,
                    );
                    session.0.kex = Some(kexinit.server_parse(
                        session.0.config.as_ref(),
                        &mut session.0.cipher,
                        buf,
                        &mut session.0.write_buffer,
                    )?);
                }
            }
            session.flush()?;
            self.state = Some(ConnectionState::Write(
                session.0.write_buffer.write_all(stream),
            ));
            self.session = Some(session);
            return Ok(Async::Ready(Status::Ok));
        }

        // No kex going on, and the version id is done.
        self.state = Some(ConnectionState::Pending {
            pending: session.server_read_encrypted(
                self.handler.take().unwrap(),
                &buf,
            )?,
            stream,
        });
        Ok(Async::Ready(Status::Ok))
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//
use std;
use byteorder::{ByteOrder, BigEndian};
use super::super::*;
use super::*;
use msg;
use thrussh_keys::encoding::{Encoding, Reader};
use thrussh_keys::key;
use auth::*;
use thrussh_keys::key::Verify;
use negotiation;
use negotiation::Select;
use futures::{Async, Future};
use futures;
use futures::Poll;

impl Session {
    #[doc(hidden)]
    /// Returns false iff a request was rejected.
    pub fn server_read_encrypted<H: Handler>(
        mut self,
        handler: H,
        buf: &[u8],
    ) -> Result<PendingFuture<H>, HandlerError<H::Error>> {

        debug!("read_encrypted");
        // Either this packet is a KEXINIT, in which case we start a key re-exchange.

        let mut enc = self.0.encrypted.take().unwrap();
        if buf[0] == msg::KEXINIT {
            // If we're not currently rekeying, but buf is a rekey request
            if let Some(exchange) = enc.exchange.take() {
                let kexinit = KexInit::received_rekey(
                    exchange,
                    try!(negotiation::Server::read_kex(
                        buf,
                        &self.0.config.as_ref().preferred,
                    )),
                    &enc.session_id,
                );
                self.0.kex = Some(kexinit.server_parse(
                    self.0.config.as_ref(),
                    &mut self.0.cipher,
                    buf,
                    &mut self.0.write_buffer,
                )?);
            }
            self.0.encrypted = Some(enc);
            return Ok(PendingFuture::Ok {
                handler: handler,
                session: self,
            });
        }
        // If we've successfully read a packet.
        // debug!("state = {:?}, buf = {:?}", self.0.state, buf);
        let mut is_authenticated = false;
        let state = enc.state.take();
        debug!(
            "state = {:?} {:?} {:?}",
            state,
            buf[0],
            msg::SERVICE_REQUEST
        );
        match state {
            Some(EncryptedState::WaitingServiceRequest) if buf[0] == msg::SERVICE_REQUEST => {

                let mut r = buf.reader(1);
                let request = try!(r.read_string());
                debug!("request: {:?}", std::str::from_utf8(request));
                if request == b"ssh-userauth" {

                    let auth_request = server_accept_service(
                        self.0.config.as_ref().auth_banner,
                        self.0.config.as_ref().methods,
                        &mut enc.write,
                    );
                    enc.state = Some(EncryptedState::WaitingAuthRequest(auth_request));

                } else {

                    enc.state = Some(EncryptedState::WaitingServiceRequest)
                }
            }
            Some(EncryptedState::WaitingAuthRequest(auth_request)) => {
                if buf[0] == msg::USERAUTH_REQUEST {
                    let auth_request = enc.server_read_auth_request(
                        handler,
                        buf,
                        &mut self.0.auth_user,
                        auth_request,
                    )?;
                    self.0.encrypted = Some(enc);
                    return Ok(PendingFuture::ReadAuthRequest {
                        session: self,
                        auth_request: auth_request,
                    });
                } else if buf[0] == msg::USERAUTH_INFO_RESPONSE {
                    let auth_request = try!(enc.read_userauth_info_response(
                        handler,
                        &mut self.0.auth_user,
                        auth_request,
                        buf,
                    ));
                    self.0.encrypted = Some(enc);
                    return Ok(PendingFuture::ReadAuthRequest {
                        session: self,
                        auth_request: auth_request,
                    });
                } else {
                    // Wrong request
                    enc.state = Some(EncryptedState::WaitingAuthRequest(auth_request));
                }
            }
            Some(EncryptedState::Authenticated) => {
                is_authenticated = true;
                enc.state = Some(EncryptedState::Authenticated)
            }
            state => {
                enc.state = state;
            }
        }
        self.0.encrypted = Some(enc);
        if is_authenticated {
            let auth = self.server_read_authenticated(handler, buf).unwrap();
            Ok(PendingFuture::Authenticated(auth))
        } else {
            Ok(PendingFuture::Ok {
                handler: handler,
                session: self,
            })
        }
    }

    fn server_read_authenticated<H: Handler>(
        mut self,
        handler: H,
        buf: &[u8],
    ) -> Result<Authenticated<H>, HandlerError<H::Error>> {
        debug!(
            "authenticated buf = {:?}",
            &buf[..std::cmp::min(buf.len(), 100)]
        );
        match buf[0] {
            msg::CHANNEL_OPEN => {
                Ok(Authenticated::FutureUnit(
                    try!(self.server_handle_channel_open(handler, buf)),
                ))
            }
            msg::CHANNEL_CLOSE => {
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                if let Some(ref mut enc) = self.0.encrypted {
                    enc.channels.remove(&channel_num);
                }
                debug!("handler.channel_close {:?}", channel_num);
                Ok(Authenticated::future_unit(
                    handler.channel_close(channel_num, self),
                ))
            }
            msg::CHANNEL_EOF => {
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                debug!("handler.channel_eof {:?}", channel_num);
                Ok(Authenticated::future_unit(
                    handler.channel_eof(channel_num, self),
                ))
            }
            msg::CHANNEL_EXTENDED_DATA |
            msg::CHANNEL_DATA => {
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));

                let ext = if buf[0] == msg::CHANNEL_DATA {
                    None
                } else {
                    Some(try!(r.read_u32()))
                };
                debug!("handler.data {:?} {:?}", ext, channel_num);
                let data = try!(r.read_string());
                let target = self.0.config.window_size;
                if let Some(ref mut enc) = self.0.encrypted {
                    enc.adjust_window_size(channel_num, data, target);
                }
                self.flush()?;
                if let Some(ext) = ext {
                    Ok(Authenticated::future_unit(
                        handler.extended_data(channel_num, ext, &data, self),
                    ))
                } else {
                    Ok(Authenticated::future_unit(
                        handler.data(channel_num, &data, self),
                    ))
                }
            }

            msg::CHANNEL_WINDOW_ADJUST => {
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                let amount = try!(r.read_u32());
                let mut new_value = 0;
                if let Some(ref mut enc) = self.0.encrypted {
                    if let Some(channel) = enc.channels.get_mut(&channel_num) {
                        channel.recipient_window_size += amount;
                        new_value = channel.recipient_window_size;
                    } else {
                        return Err(HandlerError::Error(Error::WrongChannel));
                    }
                }
                debug!("handler.window_adjusted {:?}", channel_num);
                Ok(Authenticated::future_unit(handler.window_adjusted(
                    channel_num,
                    new_value as usize,
                    self,
                )))
            }

            msg::CHANNEL_REQUEST => {
                let mut r = buf.reader(1);
                let channel_num = ChannelId(try!(r.read_u32()));
                let req_type = try!(r.read_string());
                let wants_reply = try!(r.read_byte());
                if let Some(ref mut enc) = self.0.encrypted {
                    if let Some(channel) = enc.channels.get_mut(&channel_num) {
                        channel.wants_reply = wants_reply != 0;
                    }
                }
                match req_type {
                    b"pty-req" => {
                        let term = try!(std::str::from_utf8(try!(r.read_string())));
                        let col_width = try!(r.read_u32());
                        let row_height = try!(r.read_u32());
                        let pix_width = try!(r.read_u32());
                        let pix_height = try!(r.read_u32());
                        let mut modes = [(Pty::TTY_OP_END, 0); 130];
                        let mut i = 0;
                        {
                            let mode_string = try!(r.read_string());
                            while 5 * i < mode_string.len() {
                                let code = mode_string[5 * i];
                                if code == 0 {
                                    break;
                                }
                                let num = BigEndian::read_u32(&mode_string[5 * i + 1..]);
                                debug!("code = {:?}", code);
                                if let Some(code) = Pty::from_u8(code) {
                                    modes[i] = (code, num);
                                } else {
                                    info!("pty-req: unknown pty code {:?}", code);
                                }
                                i += 1
                            }
                        }
                        debug!("handler.pty_request {:?}", channel_num);
                        Ok(Authenticated::future_unit(handler.pty_request(
                            channel_num,
                            term,
                            col_width,
                            row_height,
                            pix_width,
                            pix_height,
                            &modes[0..i],
                            self,
                        )))
                    }
                    b"x11-req" => {
                        let single_connection = try!(r.read_byte()) != 0;
                        let x11_auth_protocol = try!(std::str::from_utf8(try!(r.read_string())));
                        let x11_auth_cookie = try!(std::str::from_utf8(try!(r.read_string())));
                        let x11_screen_number = try!(r.read_u32());
                        debug!("handler.x11_request {:?}", channel_num);
                        Ok(Authenticated::future_unit(handler.x11_request(
                            channel_num,
                            single_connection,
                            x11_auth_protocol,
                            x11_auth_cookie,
                            x11_screen_number,
                            self,
                        )))
                    }
                    b"env" => {
                        let env_variable = try!(std::str::from_utf8(try!(r.read_string())));
                        let env_value = try!(std::str::from_utf8(try!(r.read_string())));
                        debug!("handler.env_request {:?}", channel_num);
                        Ok(Authenticated::future_unit(handler.env_request(
                            channel_num,
                            env_variable,
                            env_value,
                            self,
                        )))
                    }
                    b"shell" => {
                        debug!("handler.shell_request {:?}", channel_num);
                        Ok(Authenticated::future_unit(
                            handler.shell_request(channel_num, self),
                        ))
                    }
                    b"exec" => {
                        let req = try!(r.read_string());
                        debug!("handler.exec_request {:?}", channel_num);
                        Ok(Authenticated::future_unit(
                            handler.exec_request(channel_num, req, self),
                        ))
                    }
                    b"subsystem" => {
                        let name = try!(std::str::from_utf8(try!(r.read_string())));
                        debug!("handler.subsystem_request {:?}", channel_num);
                        Ok(Authenticated::future_unit(
                            handler.subsystem_request(channel_num, name, self),
                        ))
                    }
                    b"window_change" => {
                        let col_width = try!(r.read_u32());
                        let row_height = try!(r.read_u32());
                        let pix_width = try!(r.read_u32());
                        let pix_height = try!(r.read_u32());
                        debug!("handler.window_change {:?}", channel_num);
                        Ok(Authenticated::future_unit(handler.window_change_request(
                            channel_num,
                            col_width,
                            row_height,
                            pix_width,
                            pix_height,
                            self,
                        )))
                    }
                    b"signal" => {
                        try!(r.read_byte()); // should be 0.
                        let signal_name = try!(Sig::from_name(try!(r.read_string())));
                        debug!("handler.signal {:?} {:?}", channel_num, signal_name);
                        Ok(Authenticated::future_unit(
                            handler.signal(channel_num, signal_name, self),
                        ))
                    }
                    x => {
                        debug!(
                            "{:?}, line {:?} req_type = {:?}",
                            file!(),
                            line!(),
                            std::str::from_utf8(x)
                        );
                        if let Some(ref mut enc) = self.0.encrypted {
                            push_packet!(enc.write, {
                                enc.write.push(msg::CHANNEL_FAILURE);
                            });
                        }
                        Ok(Authenticated::FutureUnit(
                            FutureUnit::Done(futures::done(Ok((handler, self)))),
                        ))
                    }
                }
            }
            msg::GLOBAL_REQUEST => {
                let mut r = buf.reader(1);
                let req_type = try!(r.read_string());
                self.0.wants_reply = try!(r.read_byte()) != 0;
                match req_type {
                    b"tcpip-forward" => {
                        let address = try!(std::str::from_utf8(try!(r.read_string())));
                        let port = try!(r.read_u32());
                        debug!("handler.tcpip_forward {:?} {:?}", address, port);
                        Ok(Authenticated::Forward(Forward {
                            forward: handler.tcpip_forward(address, port, self),
                        }))
                    }
                    b"cancel-tcpip-forward" => {
                        let address = try!(std::str::from_utf8(try!(r.read_string())));
                        let port = try!(r.read_u32());
                        debug!("handler.cancel_tcpip_forward {:?} {:?}", address, port);
                        Ok(Authenticated::Forward(Forward {
                            forward: handler.cancel_tcpip_forward(address, port, self),
                        }))
                    }
                    _ => {
                        if let Some(ref mut enc) = self.0.encrypted {
                            push_packet!(enc.write, {
                                enc.write.push(msg::REQUEST_FAILURE);
                            });
                        }
                        Ok(Authenticated::FutureUnit(
                            FutureUnit::Done(futures::done(Ok((handler, self)))),
                        ))
                    }
                }
            }
            m => {
                debug!("unknown message received: {:?}", m);
                Ok(Authenticated::FutureUnit(
                    FutureUnit::Done(futures::done(Ok((handler, self)))),
                ))
            }
        }
    }

    fn server_handle_channel_open<H: Handler>(
        mut self,
        handler: H,
        buf: &[u8],
    ) -> Result<FutureUnit<H>, HandlerError<H::Error>> {

        // https://tools.ietf.org/html/rfc4254#section-5.1
        let mut r = buf.reader(1);
        let typ = try!(r.read_string());
        let sender = try!(r.read_u32());
        let window = try!(r.read_u32());
        let maxpacket = try!(r.read_u32());

        let sender_channel = if let Some(ref mut enc) = self.0.encrypted {
            enc.new_channel_id()
        } else {
            unreachable!()
        };
        let channel = Channel {
            recipient_channel: sender,

            // "sender" is the local end, i.e. we're the sender, the remote is the recipient.
            sender_channel: sender_channel,

            recipient_window_size: window,
            sender_window_size: self.0.config.window_size,
            recipient_maximum_packet_size: maxpacket,
            sender_maximum_packet_size: self.0.config.maximum_packet_size,
            confirmed: true,
            wants_reply: false,
        };
        Ok(match typ {
            b"session" => {
                self.confirm_channel_open(channel);
                FutureUnit::H(handler.channel_open_session(sender_channel, self))
            }
            b"x11" => {
                self.confirm_channel_open(channel);
                let a = try!(std::str::from_utf8(try!(r.read_string())));
                let b = try!(r.read_u32());
                FutureUnit::H(handler.channel_open_x11(sender_channel, a, b, self))
            }
            b"direct-tcpip" => {
                self.confirm_channel_open(channel);
                let a = try!(std::str::from_utf8(try!(r.read_string())));
                let b = try!(r.read_u32());
                let c = try!(std::str::from_utf8(try!(r.read_string())));
                let d = try!(r.read_u32());
                FutureUnit::H(handler.channel_open_direct_tcpip(
                    sender_channel,
                    a,
                    b,
                    c,
                    d,
                    self,
                ))
            }
            t => {
                debug!("unknown channel type: {:?}", t);
                if let Some(ref mut enc) = self.0.encrypted {
                    push_packet!(enc.write, {
                        enc.write.push(msg::CHANNEL_OPEN_FAILURE);
                        enc.write.push_u32_be(sender);
                        enc.write.push_u32_be(3); // SSH_OPEN_UNKNOWN_CHANNEL_TYPE
                        enc.write.extend_ssh_string(b"Unknown channel type");
                        enc.write.extend_ssh_string(b"en");
                    });
                }
                FutureUnit::Done(futures::done(Ok((handler, self))))
            }
        })
    }
    fn confirm_channel_open(&mut self, channel: Channel) {
        if let Some(ref mut enc) = self.0.encrypted {
            server_confirm_channel_open(&mut enc.write, &channel, self.0.config.as_ref());
            enc.channels.insert(channel.sender_channel, channel);
            enc.state = Some(EncryptedState::Authenticated);
        }
    }
}

pub enum Authenticated<H: Handler> {
    FutureUnit(FutureUnit<H>),
    Forward(Forward<H>),
}

impl<H: Handler> Authenticated<H> {
    pub fn poll(&mut self) -> Poll<(H, Session), HandlerError<H::Error>> {
        match *self {
            Authenticated::FutureUnit(ref mut a) => a.poll(),
            Authenticated::Forward(ref mut a) => a.poll(),
        }
    }
}

impl<H: Handler> Authenticated<H> {
    fn future_unit(h: H::FutureUnit) -> Self {
        Authenticated::FutureUnit(FutureUnit::H(h))
    }
}

pub enum FutureUnit<H: Handler> {
    H(H::FutureUnit),
    Done(futures::Done<(H, Session), HandlerError<H::Error>>),
}
impl<H: Handler> Future for FutureUnit<H> {
    type Item = (H, Session);
    type Error = HandlerError<H::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match *self {
            FutureUnit::H(ref mut a) => a.poll().map_err(HandlerError::Handler),
            FutureUnit::Done(ref mut a) => a.poll(),
        }
    }
}

pub struct Forward<H: Handler> {
    forward: H::FutureBool,
}

impl<H: Handler> Forward<H> {
    pub fn poll(&mut self) -> Poll<(H, Session), HandlerError<H::Error>> {
        let (handler, mut session, result) =
            try_ready!(self.forward.poll().map_err(HandlerError::Handler));
        if let Some(ref mut enc) = session.0.encrypted {
            if result {
                push_packet!(enc.write, enc.write.push(msg::REQUEST_SUCCESS))
            } else {
                push_packet!(enc.write, enc.write.push(msg::REQUEST_FAILURE))
            }
        }
        Ok(Async::Ready((handler, session)))
    }
}

pub enum ReadAuthRequest<H: Handler> {
    Req {
        future: FutureAuth<H>,
        auth_request: Option<AuthRequest>,
    },
    Reject(Option<H>),
    Accept(Option<H>),
    UnsupportedMethod(Option<H>),
}

pub enum FutureAuth<H: Handler> {
    Password(H::FutureAuth),
    Pubkey {
        validate: ValidatePubkey<H>,
        sig: Vec<u8>,
        init: Vec<u8>,
        key: key::PublicKey,
    },
    PubkeyProbe {
        probe: H::FutureAuth,
        pubkey_algo: Vec<u8>,
        pubkey_key: Vec<u8>,
        key: key::PublicKey,
    },
    KeyboardInteractive { ki: H::FutureAuth },
}

pub enum ValidatePubkey<H: Handler> {
    Valid(Option<H>),
    Future(H::FutureAuth),
    Invalid(Option<H>),
}

impl<H: Handler> ReadAuthRequest<H> {
    pub(crate) fn poll(
        &mut self,
        enc: &mut Encrypted,
        auth_user: &mut String,
        buffer: &mut CryptoVec,
    ) -> Poll<(H, Auth), HandlerError<H::Error>> {
        match *self {
            ReadAuthRequest::Req {
                ref mut future,
                ref mut auth_request,
            } => {
                match *future {
                    FutureAuth::Password(ref mut fut) => {
                        debug!("ReadAuthRequest.poll(): Password");
                        let (handler, auth) = try_ready!(fut.poll().map_err(HandlerError::Handler));
                        if let Auth::Accept = auth {
                            server_auth_request_success(&mut enc.write);
                            enc.state = Some(EncryptedState::Authenticated);
                            Ok(Async::Ready((handler, Auth::Accept)))
                        } else {
                            auth_user.clear();
                            let mut auth_request = auth_request.take().unwrap();
                            auth_request.methods = auth_request.methods - MethodSet::PASSWORD;
                            auth_request.partial_success = false;
                            enc.reject_auth_request(auth_request);
                            Ok(Async::Ready((handler, Auth::Reject)))
                        }
                    }
                    FutureAuth::Pubkey {
                        ref mut validate,
                        ref sig,
                        ref init,
                        ref key,
                    } => {
                        debug!("ReadAuthRequest.poll(): Pubkey");
                        let (handler, is_valid) = match *validate {
                            ValidatePubkey::Valid(ref mut h) => (h.take().unwrap(), true),
                            ValidatePubkey::Future(ref mut h) => {
                                let (handler, auth) =
                                    try_ready!(h.poll().map_err(HandlerError::Handler));
                                (handler, auth == Auth::Accept)
                            }
                            ValidatePubkey::Invalid(ref mut h) => (h.take().unwrap(), false),
                        };
                        if is_valid {
                            buffer.clear();
                            buffer.extend_ssh_string(enc.session_id.as_ref());
                            buffer.extend(init);
                            // Verify signature.
                            if key.verify_client_auth(buffer, sig) {
                                debug!("signature verified");
                                server_auth_request_success(&mut enc.write);
                                enc.state = Some(EncryptedState::Authenticated);
                                return Ok(Async::Ready((handler, Auth::Accept)));
                            } else {
                                debug!("signature wrong");
                            }
                        }
                        Ok(Async::Ready((handler, Auth::Reject)))
                    }
                    FutureAuth::PubkeyProbe {
                        ref mut probe,
                        ref pubkey_algo,
                        ref pubkey_key,
                        ..
                    } => {
                        debug!("ReadAuthRequest.poll(): PubkeyProbe");
                        let (handler, auth) =
                            try_ready!(probe.poll().map_err(HandlerError::Handler));
                        if let Auth::Accept = auth {

                            let mut public_key = CryptoVec::new();
                            public_key.extend(pubkey_key);

                            let mut algo = CryptoVec::new();
                            algo.extend(pubkey_algo);
                            debug!("pubkey_key: {:?}", pubkey_key);
                            push_packet!(enc.write, {
                                enc.write.push(msg::USERAUTH_PK_OK);
                                enc.write.extend_ssh_string(&pubkey_algo);
                                enc.write.extend_ssh_string(&pubkey_key);
                            });

                            let mut auth_request = auth_request.take().unwrap();
                            auth_request.current = Some(CurrentRequest::PublicKey {
                                key: public_key,
                                algo: algo,
                                sent_pk_ok: true,
                            });

                            enc.state = Some(EncryptedState::WaitingAuthRequest(auth_request));
                            Ok(Async::Ready((handler, Auth::Accept)))
                        } else {
                            let mut auth_request = auth_request.take().unwrap();
                            // auth_request.methods -= MethodSet::PUBLICKEY;
                            auth_request.partial_success = false;
                            auth_user.clear();
                            enc.reject_auth_request(auth_request);
                            Ok(Async::Ready((handler, Auth::Reject)))
                        }
                    }
                    FutureAuth::KeyboardInteractive { ref mut ki } => {

                        match try_ready!(ki.poll().map_err(HandlerError::Handler)) {
                            (handler, Auth::Accept) => {
                                server_auth_request_success(&mut enc.write);
                                enc.state = Some(EncryptedState::Authenticated);
                                Ok(Async::Ready((handler, Auth::Accept)))
                            }
                            (_, Auth::UnsupportedMethod) => unreachable!(),
                            (handler, Auth::Reject) => {
                                let mut auth_request = auth_request.take().unwrap();
                                // auth_request.methods -= KEYBOARD_INTERACTIVE;
                                auth_request.partial_success = false;
                                auth_user.clear();
                                enc.reject_auth_request(auth_request);
                                Ok(Async::Ready((handler, Auth::Reject)))
                            }
                            (handler,
                             Auth::Partial {
                                 name,
                                 instructions,
                                 prompts,
                             }) => {

                                push_packet!(enc.write, {
                                    enc.write.push(msg::USERAUTH_INFO_REQUEST);
                                    enc.write.extend_ssh_string(name.as_bytes());
                                    enc.write.extend_ssh_string(instructions.as_bytes());
                                    enc.write.extend_ssh_string(b""); // lang, should be empty
                                    enc.write.push_u32_be(prompts.len() as u32);
                                    for &(ref a, b) in prompts.iter() {
                                        enc.write.extend_ssh_string(a.as_bytes());
                                        enc.write.push(if b { 1 } else { 0 });
                                    }
                                });
                                let auth_request = auth_request.take().unwrap();
                                enc.state = Some(EncryptedState::WaitingAuthRequest(auth_request));
                                Ok(Async::Ready((
                                    handler,
                                    Auth::Partial {
                                        name: name,
                                        instructions: instructions,
                                        prompts: prompts,
                                    },
                                )))
                            }
                        }

                    }
                }

            }
            ReadAuthRequest::Reject(ref mut h) => {
                Ok(Async::Ready((h.take().unwrap(), Auth::Reject)))
            }
            ReadAuthRequest::UnsupportedMethod(ref mut h) => {
                Ok(Async::Ready((h.take().unwrap(), Auth::UnsupportedMethod)))
            }
            ReadAuthRequest::Accept(ref mut h) => {
                Ok(Async::Ready((h.take().unwrap(), Auth::Accept)))
            }
        }
    }
}

impl Encrypted {
    /// Returns false iff the request was rejected.
    fn server_read_auth_request<H: Handler>(
        &mut self,
        handler: H,
        buf: &[u8],
        auth_user: &mut String,
        mut auth_request: AuthRequest,
    ) -> Result<ReadAuthRequest<H>, HandlerError<H::Error>> {

        // https://tools.ietf.org/html/rfc4252#section-5
        let mut r = buf.reader(1);
        let user = try!(r.read_string());
        let user = try!(std::str::from_utf8(user));
        let service_name = try!(r.read_string());
        let method = try!(r.read_string());
        debug!(
            "name: {:?} {:?} {:?}",
            user,
            std::str::from_utf8(service_name),
            std::str::from_utf8(method)
        );

        if service_name == b"ssh-connection" {

            if method == b"password" {

                auth_user.clear();
                auth_user.push_str(user);

                try!(r.read_byte());
                let password = try!(r.read_string());
                let password = try!(std::str::from_utf8(password));

                Ok(ReadAuthRequest::Req {
                    future: FutureAuth::Password(handler.auth_password(user, password)),
                    auth_request: Some(auth_request),
                })

            } else if method == b"publickey" {

                let is_real = try!(r.read_byte());
                let pubkey_algo = try!(r.read_string());
                let pubkey_key = try!(r.read_string());
                debug!("algo: {:?}, key: {:?}", pubkey_algo, pubkey_key);
                match key::PublicKey::parse(pubkey_algo, pubkey_key) {
                    Ok(pubkey) => {
                        debug!("is_real = {:?}", is_real);

                        if is_real != 0 {

                            let pos0 = r.position;
                            let sent_pk_ok = if let Some(CurrentRequest::PublicKey {
                                                             sent_pk_ok, ..
                                                         }) = auth_request.current
                            {
                                sent_pk_ok
                            } else {
                                false
                            };

                            let signature = try!(r.read_string());
                            let mut s = signature.reader(0);
                            let algo_ = try!(s.read_string());
                            debug!("algo_: {:?}", algo_);
                            let sig = try!(s.read_string());
                            let init = &buf[0..pos0];

                            let validate = if sent_pk_ok && user == auth_user {
                                ValidatePubkey::Valid(Some(handler))
                            } else if auth_user.len() == 0 {
                                auth_user.clear();
                                auth_user.push_str(user);
                                ValidatePubkey::Future(handler.auth_publickey(user, &pubkey))
                            } else {
                                ValidatePubkey::Invalid(Some(handler))
                            };

                            Ok(ReadAuthRequest::Req {
                                future: FutureAuth::Pubkey {
                                    validate: validate,
                                    sig: sig.to_vec(),
                                    init: init.to_vec(),
                                    key: pubkey,
                                },
                                auth_request: Some(auth_request),
                            })

                        } else {
                            auth_user.clear();
                            auth_user.push_str(user);

                            Ok(ReadAuthRequest::Req {
                                future: FutureAuth::PubkeyProbe {
                                    probe: handler.auth_publickey(user, &pubkey),
                                    pubkey_algo: pubkey_algo.to_vec(),
                                    pubkey_key: pubkey_key.to_vec(),
                                    key: pubkey,
                                },
                                auth_request: Some(auth_request),
                            })
                        }
                    }
                    Err(e) => {
                        if let &thrussh_keys::ErrorKind::CouldNotReadKey = e.kind() {
                            self.reject_auth_request(auth_request);
                            Ok(ReadAuthRequest::Reject(Some(handler)))
                        } else {
                            return Err(HandlerError::Error(Error::from(e)))
                        }
                    }
                }
            // Other methods of the base specification are insecure or optional.
            } else if method == b"keyboard-interactive" {

                auth_user.clear();
                auth_user.push_str(user);
                let _ = try!(r.read_string()); // language_tag, deprecated.
                let submethods = try!(std::str::from_utf8(try!(r.read_string())));
                debug!("{:?}", submethods);
                auth_request.current = Some(CurrentRequest::KeyboardInteractive {
                    submethods: submethods.to_string(),
                });
                Ok(ReadAuthRequest::Req {
                    future: FutureAuth::KeyboardInteractive {
                        ki: handler.auth_keyboard_interactive(user, submethods, None),
                    },
                    auth_request: Some(auth_request),
                })

            } else {
                self.reject_auth_request(auth_request);
                Ok(ReadAuthRequest::UnsupportedMethod(Some(handler)))
            }
        } else {
            // Unknown service
            Err(HandlerError::Error(Error::Inconsistent))
        }
    }

    fn read_userauth_info_response<H: Handler>(
        &mut self,
        handler: H,
        user: &mut String,
        auth_request: AuthRequest,
        b: &[u8],
    ) -> Result<ReadAuthRequest<H>, HandlerError<H::Error>> {

        let ki = if let Some(CurrentRequest::KeyboardInteractive { ref submethods }) =
            auth_request.current
        {
            let mut r = b.reader(1);
            let n = try!(r.read_u32());
            let response = Response { pos: r, n: n };
            handler.auth_keyboard_interactive(user, submethods, Some(response))
        } else {
            return Ok(ReadAuthRequest::Reject(Some(handler)));
        };

        Ok(ReadAuthRequest::Req {
            future: FutureAuth::KeyboardInteractive { ki: ki },
            auth_request: Some(auth_request),
        })
    }

    fn reject_auth_request(&mut self, mut auth_request: AuthRequest) {
        debug!("rejecting {:?}", auth_request);
        push_packet!(self.write, {
            self.write.push(msg::USERAUTH_FAILURE);
            self.write.extend_list(auth_request.methods);
            self.write.push(
                if auth_request.partial_success { 1 } else { 0 },
            );
        });
        auth_request.current = None;
        auth_request.rejection_count += 1;
        debug!("packet pushed");
        self.state = Some(EncryptedState::WaitingAuthRequest(auth_request));
    }
}





fn server_accept_service(
    banner: Option<&str>,
    methods: MethodSet,
    buffer: &mut CryptoVec,
) -> AuthRequest {

    push_packet!(buffer, {
        buffer.push(msg::SERVICE_ACCEPT);
        buffer.extend_ssh_string(b"ssh-userauth");
    });

    if let Some(ref banner) = banner {
        push_packet!(buffer, {
            buffer.push(msg::USERAUTH_BANNER);
            buffer.extend_ssh_string(banner.as_bytes());
            buffer.extend_ssh_string(b"");
        })
    }

    AuthRequest {
        methods: methods,
        partial_success: false, // not used immediately anway.
        current: None,
        rejection_count: 0,
    }
}


fn server_auth_request_success(buffer: &mut CryptoVec) {

    push_packet!(buffer, {
        buffer.push(msg::USERAUTH_SUCCESS);
    })
}

fn server_confirm_channel_open(buffer: &mut CryptoVec, channel: &Channel, config: &Config) {

    push_packet!(buffer, {
        buffer.push(msg::CHANNEL_OPEN_CONFIRMATION);
        buffer.push_u32_be(channel.recipient_channel); // remote channel number.
        buffer.push_u32_be(channel.sender_channel.0); // our channel number.
        buffer.push_u32_be(config.window_size);
        buffer.push_u32_be(config.maximum_packet_size);
    });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use super::*;
use negotiation::Select;
use msg;
use cipher::CipherPair;
use negotiation;
use key::PubKey;
use thrussh_keys::encoding::{Encoding, Reader};

use kex;

impl KexInit {
    pub fn server_parse(
        mut self,
        config: &Config,
        cipher: &CipherPair,
        buf: &[u8],
        write_buffer: &mut SSHBuffer,
    ) -> Result<Kex, Error> {

        if buf[0] == msg::KEXINIT {
            debug!("server parse");
            let algo = if self.algo.is_none() {
                // read algorithms from packet.
                self.exchange.client_kex_init.extend(buf);
                super::negotiation::Server::read_kex(buf, &config.preferred)?
            } else {
                return Err(Error::Kex);
            };
            if !self.sent {
                self.server_write(config, cipher, write_buffer)?
            }
            let mut key = 0;
            debug!("config {:?} algo {:?}", config.keys, algo.key);
            while key < config.keys.len() && config.keys[key].name() != algo.key.as_ref() {
                key += 1
            }
            let next_kex = if key < config.keys.len() {
                Kex::KexDh(KexDh {
                    exchange: self.exchange,
                    key: key,
                    names: algo,
                    session_id: self.session_id,
                })
            } else {
                return Err(Error::UnknownKey);
            };

            Ok(next_kex)
        } else {
            Ok(Kex::KexInit(self))
        }
    }

    pub fn server_write(
        &mut self,
        config: &Config,
        cipher: &CipherPair,
        write_buffer: &mut SSHBuffer,
    ) -> Result<(), Error> {
        self.exchange.server_kex_init.clear();
        negotiation::write_kex(&config.preferred, &mut self.exchange.server_kex_init)?;
        self.sent = true;
        cipher.write(&self.exchange.server_kex_init, write_buffer);
        Ok(())
    }
}

impl KexDh {
    pub fn parse(
        mut self,
        config: &Config,
        buffer: &mut CryptoVec,
        buffer2: &mut CryptoVec,
        cipher: &CipherPair,
        buf: &[u8],
        write_buffer: &mut SSHBuffer,
    ) -> Result<Kex, Error> {
        debug!("KexDh: parse {:?}", self.names.ignore_guessed);
        if self.names.ignore_guessed {
            // If we need to ignore this packet.
            self.names.ignore_guessed = false;
            Ok(Kex::KexDh(self))
        } else {
            // Else, process it.
            debug!("buf = {:?}", buf);
            assert!(buf[0] == msg::KEX_ECDH_INIT);
            let mut r = buf.reader(1);
            self.exchange.client_ephemeral.extend(r.read_string()?);
            let kex = try!(kex::Algorithm::server_dh(
                self.names.kex,
                &mut self.exchange,
                buf,
            ));
            // Then, we fill the write buffer right away, so that we
            // can output it immediately when the time comes.
            let kexdhdone = KexDhDone {
                exchange: self.exchange,
                kex: kex,
                key: self.key,
                names: self.names,
                session_id: self.session_id,
            };

            let hash = try!(kexdhdone.kex.compute_exchange_hash(
                &config.keys[kexdhdone.key],
                &kexdhdone.exchange,
                buffer,
            ));
            debug!("exchange hash: {:?}", hash);
            buffer.clear();
            buffer.push(msg::KEX_ECDH_REPLY);
            config.keys[kexdhdone.key].push_to(buffer);
            // Server ephemeral
            buffer.extend_ssh_string(&kexdhdone.exchange.server_ephemeral);
            // Hash signature
            debug!(" >>>>>>>>>>>>>>> signing with key {:?}", kexdhdone.key);
            debug!("hash: {:?}", hash);
            debug!("key: {:?}", config.keys[kexdhdone.key]);
            config.keys[kexdhdone.key].add_signature(buffer, &hash)?;
            cipher.write(&buffer, write_buffer);

            cipher.write(&[msg::NEWKEYS], write_buffer);

            Ok(Kex::NewKeys(
                try!(kexdhdone.compute_keys(hash, buffer, buffer2, true)),
            ))
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

use std;
use std::net::ToSocketAddrs;
use std::sync::Arc;

use futures::stream::Stream;
use futures::{Poll, Async};
use futures::future::Future;
use tokio::net::TcpListener;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::io::{flush, Flush, WriteAll};
use thrussh_keys::key;

use super::*;
use sshbuffer::*;
use negotiation;

use session::*;
use auth;

mod encrypted;
mod connection;
mod kex;
mod session;
pub use self::connection::*;
pub use self::kex::*;
pub use self::session::*;

#[derive(Debug)]
/// Configuration of a server.
pub struct Config {
    /// The server ID string sent at the beginning of the protocol.
    pub server_id: String,
    /// Authentication methods proposed to the client.
    pub methods: auth::MethodSet,
    /// The authentication banner, usually a warning message shown to the client.
    pub auth_banner: Option<&'static str>,
    /// Authentication rejections must happen in constant time for
    /// security reasons. Thrussh does not handle this by default.
    pub auth_rejection_time: std::time::Duration,
    /// The server's keys. The first key pair in the client's preference order will be chosen.
    pub keys: Vec<key::KeyPair>,
    /// The bytes and time limits before key re-exchange.
    pub limits: Limits,
    /// The initial size of a channel (used for flow control).
    pub window_size: u32,
    /// The maximal size of a single packet.
    pub maximum_packet_size: u32,
    /// Lists of preferred algorithms.
    pub preferred: Preferred,
    /// Maximal number of allowed authentication attempts.
    pub max_auth_attempts: usize,
    /// Time after which the connection is garbage-collected.
    pub connection_timeout: Option<std::time::Duration>,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            server_id: format!(
                "SSH-2.0-{}_{}",
                env!("CARGO_PKG_NAME"),
                env!("CARGO_PKG_VERSION")
            ),
            methods: auth::MethodSet::all(),
            auth_banner: None,
            auth_rejection_time: std::time::Duration::from_secs(1),
            keys: Vec::new(),
            window_size: 200000,
            maximum_packet_size: 200000,
            limits: Limits::default(),
            preferred: Default::default(),
            max_auth_attempts: 10,
            connection_timeout: Some(std::time::Duration::from_secs(600)),
        }
    }
}

/// A client's response in a challenge-response authentication.
#[derive(Debug)]
pub struct Response<'a> {
    pos: thrussh_keys::encoding::Position<'a>,
    n: u32,
}

impl<'a> Iterator for Response<'a> {
    type Item = &'a [u8];
    fn next(&mut self) -> Option<Self::Item> {
        if self.n == 0 {
            None
        } else {
            self.n -= 1;
            self.pos.read_string().ok()
        }
    }
}

use std::borrow::Cow;
/// An authentication result, in a challenge-response authentication.
#[derive(Debug, PartialEq, Eq)]
pub enum Auth {
    /// Reject the authentication request.
    Reject,
    /// Accept the authentication request.
    Accept,

    /// Method was not accepted, but no other check was performed.
    UnsupportedMethod,

    /// Partially accept the challenge-response authentication
    /// request, providing more instructions for the client to follow.
    Partial {
        /// Name of this challenge.
        name: Cow<'static, str>,
        /// Instructions for this challenge.
        instructions: Cow<'static, str>,
        /// A number of prompts to the user. Each prompt has a `bool`
        /// indicating whether the terminal must echo the characters
        /// typed by the user.
        prompts: Cow<'static, [(Cow<'static, str>, bool)]>,
    },
}

/// Server handler. Each client will have their own handler.
pub trait Handler: Sized {
    /// The type of errors returned by the futures.
    type Error: std::error::Error + Send + Sync;

    /// The type of authentications, which can be a future ultimately
    /// resolving to
    type FutureAuth: Future<Item = (Self, Auth), Error = Self::Error> + Send;

    /// The type of units returned by some parts of this handler.
    type FutureUnit: Future<Item = (Self, Session), Error = Self::Error> + Send;

    /// The type of future bools returned by some parts of this handler.
    type FutureBool: Future<Item = (Self, Session, bool), Error = Self::Error> + Send;

    /// Convert an `Auth` to `Self::FutureAuth`. This is used to
    /// produce the default handlers.
    fn finished_auth(self, auth: Auth) -> Self::FutureAuth;

    /// Convert a `bool` to `Self::FutureBool`. This is used to
    /// produce the default handlers.
    fn finished_bool(self, session: Session, b: bool) -> Self::FutureBool;

    /// Produce a `Self::FutureUnit`. This is used to produce the
    /// default handlers.
    fn finished(self, session: Session) -> Self::FutureUnit;

    /// Check authentication using the "none" method. Thrussh makes
    /// sure rejection happens in time `config.auth_rejection_time`,
    /// except if this method takes more than that.
    #[allow(unused_variables)]
    fn auth_none(self, user: &str) -> Self::FutureAuth {
        self.finished_auth(Auth::Reject)
    }

    /// Check authentication using the "password" method. Thrussh
    /// makes sure rejection happens in time
    /// `config.auth_rejection_time`, except if this method takes more
    /// than that.
    #[allow(unused_variables)]
    fn auth_password(self, user: &str, password: &str) -> Self::FutureAuth {
        self.finished_auth(Auth::Reject)
    }

    /// Check authentication using the "publickey" method. This method
    /// should just check whether the public key matches the
    /// authorized ones. Thrussh then checks the signature. If the key
    /// is unknown, or the signature is invalid, Thrussh guarantees
    /// that rejection happens in constant time
    /// `config.auth_rejection_time`, except if this method takes more
    /// time than that.
    #[allow(unused_variables)]
    fn auth_publickey(self, user: &str, public_key: &key::PublicKey) -> Self::FutureAuth {
        self.finished_auth(Auth::Reject)
    }

    /// Check authentication using the "keyboard-interactive"
    /// method. Thrussh makes sure rejection happens in time
    /// `config.auth_rejection_time`, except if this method takes more
    /// than that.
    #[allow(unused_variables)]
    fn auth_keyboard_interactive(
        self,
        user: &str,
        submethods: &str,
        response: Option<Response>,
    ) -> Self::FutureAuth {
        self.finished_auth(Auth::Reject)
    }

    /// Called when the client closes a channel.
    #[allow(unused_variables)]
    fn channel_close(self, channel: ChannelId, session: Session) -> Self::FutureUnit {
        self.finished(session)
    }

    /// Called when the client sends EOF to a channel.
    #[allow(unused_variables)]
    fn channel_eof(self, channel: ChannelId, session: Session) -> Self::FutureUnit {
        self.finished(session)
    }

    /// Called when a new session channel is created.
    #[allow(unused_variables)]
    fn channel_open_session(self, channel: ChannelId, session: Session) -> Self::FutureUnit {
        self.finished(session)
    }

    /// Called when a new X11 channel is created.
    #[allow(unused_variables)]
    fn channel_open_x11(
        self,
        channel: ChannelId,
        originator_address: &str,
        originator_port: u32,
        session: Session,
    ) -> Self::FutureUnit {
        self.finished(session)
    }

    /// Called when a new channel is created.
    #[allow(unused_variables)]
    fn channel_open_direct_tcpip(
        self,
        channel: ChannelId,
        host_to_connect: &str,
        port_to_connect: u32,
        originator_address: &str,
        originator_port: u32,
        session: Session,
    ) -> Self::FutureUnit {
        self.finished(session)
    }

    /// Called when a data packet is received. A response can be
    /// written to the `response` argument.
    #[allow(unused_variables)]
    fn data(self, channel: ChannelId, data: &[u8], session: Session) -> Self::FutureUnit {
        self.finished(session)
    }

    /// Called when an extended data packet is received. Code 1 means
    /// that this packet comes from stderr, other codes are not
    /// defined (see
    /// [RFC4254](https://tools.ietf.org/html/rfc4254#section-5.2)).
    #[allow(unused_variables)]
    fn extended_data(
        self,
        channel: ChannelId,
        code: u32,
        data: &[u8],
        session: Session,
    ) -> Self::FutureUnit {
        self.finished(session)
    }

    /// Called when the network window is adjusted, meaning that we
    /// can send more bytes.
    #[allow(unused_variables)]
    fn window_adjusted(
        self,
        channel: ChannelId,
        new_window_size: usize,
        session: Session,
    ) -> Self::FutureUnit {
        self.finished(session)
    }

    /// The client requests a pseudo-terminal with the given
    /// specifications.
    #[allow(unused_variables)]
    fn pty_request(
        self,
        channel: ChannelId,
        term: &str,
        col_width: u32,
        row_height: u32,
        pix_width: u32,
        pix_height: u32,
        modes: &[(Pty, u32)],
        session: Session,
    ) -> Self::FutureUnit {
        self.finished(session)
    }

    /// The client requests an X11 connection.
    #[allow(unused_variables)]
    fn x11_request(
        self,
        channel: ChannelId,
        single_connection: bool,
        x11_auth_protocol: &str,
        x11_auth_cookie: &str,
        x11_screen_number: u32,
        session: Session,
    ) -> Self::FutureUnit {
        self.finished(session)
    }

    /// The client wants to set the given environment variable. Check
    /// these carefully, as it is dangerous to allow any variable
    /// environment to be set.
    #[allow(unused_variables)]
    fn env_request(
        self,
        channel: ChannelId,
        variable_name: &str,
        variable_value: &str,
        session: Session,
    ) -> Self::FutureUnit {
        self.finished(session)
    }

    /// The client requests a shell.
    #[allow(unused_variables)]
    fn shell_request(self, channel: ChannelId, session: Session) -> Self::FutureUnit {
        self.finished(session)
    }

    /// The client sends a command to execute, to be passed to a
    /// shell. Make sure to check the command before doing so.
    #[allow(unused_variables)]
    fn exec_request(self, channel: ChannelId, data: &[u8], session: Session) -> Self::FutureUnit {
        self.finished(session)
    }

    /// The client asks to start the subsystem with the given name
    /// (such as sftp).
    #[allow(unused_variables)]
    fn subsystem_request(
        self,
        channel: ChannelId,
        name: &str,
        session: Session,
    ) -> Self::FutureUnit {
        self.finished(session)
    }

    /// The client's pseudo-terminal window size has changed.
    #[allow(unused_variables)]
    fn window_change_request(
        self,
        channel: ChannelId,
        col_width: u32,
        row_height: u32,
        pix_width: u32,
        pix_height: u32,
        session: Session,
    ) -> Self::FutureUnit {
        self.finished(session)
    }

    /// The client is sending a signal (usually to pass to the
    /// currently running process).
    #[allow(unused_variables)]
    fn signal(self, channel: ChannelId, signal_name: Sig, session: Session) -> Self::FutureUnit {
        self.finished(session)
    }

    /// Used for reverse-forwarding ports, see
    /// [RFC4254](https://tools.ietf.org/html/rfc4254#section-7).
    #[allow(unused_variables)]
    fn tcpip_forward(self, address: &str, port: u32, session: Session) -> Self::FutureBool {
        self.finished_bool(session, false)
    }
    /// Used to stop the reverse-forwarding of a port, see
    /// [RFC4254](https://tools.ietf.org/html/rfc4254#section-7).
    #[allow(unused_variables)]
    fn cancel_tcpip_forward(self, address: &str, port: u32, session: Session) -> Self::FutureBool {
        self.finished_bool(session, false)
    }
}

/// Trait used to create new handlers when clients connect.
pub trait Server {
    /// The type of handlers.
    type Handler: Handler+Send;
    /// Called when a new client connects.
    fn new(&self) -> Self::Handler;
}

/// Run this server.
pub fn run<H: Server + Send + 'static>(config: Arc<Config>, addr: &str, server: H) {

    let addr = addr.to_socket_addrs().unwrap().next().unwrap();
    let socket = TcpListener::bind(&addr).unwrap();

    let done = socket.incoming().for_each(move |socket| {
        let handler = server.new();
        let connection = Connection::new(config.clone(), socket, handler).unwrap();
        use tokio::executor::Executor;
        tokio::executor::DefaultExecutor::current().spawn(Box::new(connection.map_err(|err|  println!("err {:?}", err)))).unwrap();
        Ok(())
    }).map_err(|_| ());
    tokio::run(done);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
use super::*;
use msg;
use thrussh_keys::encoding::Encoding;
use std::sync::Arc;

/// A connected server session. This type is unique to a client.
pub struct Session(pub(crate) CommonSession<Arc<Config>>);


impl Session {
    /// Flush the session, i.e. encrypt the pending buffer.
    pub fn flush(&mut self) -> Result<(), Error> {
        if let Some(ref mut enc) = self.0.encrypted {
            if enc.flush(
                &self.0.config.as_ref().limits,
                &self.0.cipher,
                &mut self.0.write_buffer,
            )
            {
                if let Some(exchange) = enc.exchange.take() {
                    let mut kexinit = KexInit::initiate_rekey(exchange, &enc.session_id);
                    kexinit.server_write(
                        &self.0.config.as_ref(),
                        &mut self.0.cipher,
                        &mut self.0.write_buffer,
                    )?;
                    enc.rekey = Some(Kex::KexInit(kexinit))
                }
            }
        }
        Ok(())
    }

    /// Retrieves the configuration of this session.
    pub fn config(&self) -> &Config {
        &self.0.config
    }

    /// Sends a disconnect message.
    pub fn disconnect(&mut self, reason: Disconnect, description: &str, language_tag: &str) {
        self.0.disconnect(reason, description, language_tag);
    }

    /// Send a "success" reply to a /global/ request (requests without
    /// a channel number, such as TCP/IP forwarding or
    /// cancelling). Always call this function if the request was
    /// successful (it checks whether the client expects an answer).
    pub fn request_success(&mut self) {
        if self.0.wants_reply {
            if let Some(ref mut enc) = self.0.encrypted {
                self.0.wants_reply = false;
                push_packet!(enc.write, enc.write.push(msg::REQUEST_SUCCESS))
            }
        }
    }

    /// Send a "failure" reply to a global request.
    pub fn request_failure(&mut self) {
        if let Some(ref mut enc) = self.0.encrypted {
            self.0.wants_reply = false;
            push_packet!(enc.write, enc.write.push(msg::REQUEST_FAILURE))
        }
    }

    /// Send a "success" reply to a channel request. Always call this
    /// function if the request was successful (it checks whether the
    /// client expects an answer).
    pub fn channel_success(&mut self, channel: ChannelId) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get_mut(&channel) {
                assert!(channel.confirmed);
                if channel.wants_reply {
                    channel.wants_reply = false;
                    push_packet!(enc.write, {
                        enc.write.push(msg::CHANNEL_SUCCESS);
                        enc.write.push_u32_be(channel.recipient_channel);
                    })
                }
            }
        }
    }

    /// Send a "failure" reply to a global request.
    pub fn channel_failure(&mut self, channel: ChannelId) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get_mut(&channel) {
                assert!(channel.confirmed);
                if channel.wants_reply {
                    channel.wants_reply = false;
                    push_packet!(enc.write, {
                        enc.write.push(msg::CHANNEL_FAILURE);
                        enc.write.push_u32_be(channel.recipient_channel);
                    })
                }
            }
        }
    }

    /// Send a "failure" reply to a request to open a channel open.
    pub fn channel_open_failure(
        &mut self,
        channel: ChannelId,
        reason: ChannelOpenFailure,
        description: &str,
        language: &str,
    ) {
        if let Some(ref mut enc) = self.0.encrypted {
            push_packet!(enc.write, {
                enc.write.push(msg::CHANNEL_OPEN_FAILURE);
                enc.write.push_u32_be(channel.0);
                enc.write.push_u32_be(reason as u32);
                enc.write.extend_ssh_string(description.as_bytes());
                enc.write.extend_ssh_string(language.as_bytes());
            })
        }
    }


    /// Close a channel.
    pub fn close(&mut self, channel: ChannelId) {
        self.0.byte(channel, msg::CHANNEL_CLOSE);
    }

    /// Send EOF to a channel
    pub fn eof(&mut self, channel: ChannelId) {
        self.0.byte(channel, msg::CHANNEL_EOF);
    }

    /// Send data to a channel. On session channels, `extended` can be
    /// used to encode standard error by passing `Some(1)`, and stdout
    /// by passing `None`.
    ///

    /// The number of bytes added to the "sending pipeline" (to be
    /// processed by the event loop) is returned.
    pub fn data(&mut self, channel: ChannelId, extended: Option<u32>, data: &[u8]) -> usize {
        if let Some(ref mut enc) = self.0.encrypted {
            enc.data(channel, extended, data)
        } else {
            unreachable!()
        }
    }

    /// Inform the client of whether they may perform
    /// control-S/control-Q flow control. See
    /// [RFC4254](https://tools.ietf.org/html/rfc4254#section-6.8).
    pub fn xon_xoff_request(&mut self, channel: ChannelId, client_can_do: bool) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                assert!(channel.confirmed);
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"xon-xoff");
                    enc.write.push(0);
                    enc.write.push(if client_can_do { 1 } else { 0 });
                })
            }
        }
    }

    /// Send the exit status of a program.
    pub fn exit_status_request(&mut self, channel: ChannelId, exit_status: u32) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                assert!(channel.confirmed);
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"exit-status");
                    enc.write.push(0);
                    enc.write.push_u32_be(exit_status)
                })
            }
        }
    }

    /// If the program was killed by a signal, send the details about the signal to the client.
    pub fn exit_signal_request(
        &mut self,
        channel: ChannelId,
        signal: Sig,
        core_dumped: bool,
        error_message: &str,
        language_tag: &str,
    ) {
        if let Some(ref mut enc) = self.0.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                assert!(channel.confirmed);
                push_packet!(enc.write, {
                    enc.write.push(msg::CHANNEL_REQUEST);

                    enc.write.push_u32_be(channel.recipient_channel);
                    enc.write.extend_ssh_string(b"exit-signal");
                    enc.write.push(0);
                    enc.write.extend_ssh_string(signal.name().as_bytes());
                    enc.write.push(if core_dumped { 1 } else { 0 });
                    enc.write.extend_ssh_string(error_message.as_bytes());
                    enc.write.extend_ssh_string(language_tag.as_bytes());
                })
            }
        }
    }

    /// Open a TCP/IP forwarding channel, when a connection comes to a
    /// local port for which forwarding has been requested. See
    /// [RFC4254](https://tools.ietf.org/html/rfc4254#section-7). The
    /// TCP/IP packets can then be tunneled through the channel using
    /// `.data()`.
    pub fn channel_open_forwarded_tcpip(
        &mut self,
        connected_address: &str,
        connected_port: u32,
        originator_address: &str,
        originator_port: u32,
    ) -> Result<ChannelId, Error> {
        let result = if let Some(ref mut enc) = self.0.encrypted {
            match enc.state {
                Some(EncryptedState::Authenticated) => {
                    debug!("sending open request");

                    let sender_channel = enc.new_channel(
                        self.0.config.window_size,
                        self.0.config.maximum_packet_size,
                    );
                    push_packet!(enc.write, {
                        enc.write.push(msg::CHANNEL_OPEN);
                        enc.write.extend_ssh_string(b"forwarded-tcpip");

                        // sender channel id.
                        enc.write.push_u32_be(sender_channel.0);

                        // window.
                        enc.write.push_u32_be(self.0.config.as_ref().window_size);

                        // max packet size.
                        enc.write.push_u32_be(
                            self.0.config.as_ref().maximum_packet_size,
                        );

                        enc.write.extend_ssh_string(connected_address.as_bytes());
                        enc.write.push_u32_be(connected_port); // sender channel id.
                        enc.write.extend_ssh_string(originator_address.as_bytes());
                        enc.write.push_u32_be(originator_port); // sender channel id.
                    });
                    sender_channel
                }
                _ => return Err(Error::Inconsistent),
            }
        } else {
            return Err(Error::Inconsistent);
        };
        Ok(result)
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

use std;
use auth;
use negotiation;
use kex;
use cipher;
use msg;
use {Error, ChannelId, Channel, Disconnect};
use cryptovec::CryptoVec;
use std::collections::HashMap;
use Limits;
use sshbuffer::SSHBuffer;
use byteorder::{BigEndian, ByteOrder};
use openssl::hash;
use thrussh_keys::encoding::Encoding;
use std::num::Wrapping;
use std::sync::Arc;

#[derive(Debug)]
pub(crate) struct Encrypted {
    pub state: Option<EncryptedState>,

    // It's always Some, except when we std::mem::replace it temporarily.
    pub exchange: Option<Exchange>,
    pub kex: kex::Algorithm,
    pub key: usize,
    pub mac: Option<&'static str>,
    pub session_id: hash::DigestBytes,
    pub rekey: Option<Kex>,
    pub channels: HashMap<ChannelId, Channel>,
    pub last_channel_id: Wrapping<u32>,
    pub wants_reply: bool,
    pub write: CryptoVec,
    pub write_cursor: usize,
    pub last_rekey: std::time::Instant,
}

pub(crate) struct CommonSession<Config> {
    pub auth_user: String,
    pub config: Config,
    pub encrypted: Option<Encrypted>,
    pub auth_method: Option<auth::Method>,
    pub write_buffer: SSHBuffer,
    pub kex: Option<Kex>,
    pub cipher: Arc<cipher::CipherPair>,
    pub wants_reply: bool,
    pub disconnected: bool,
    pub buffer: Option<CryptoVec>,
}

impl<C> CommonSession<C> {
    pub fn encrypted(&mut self, state: EncryptedState, newkeys: NewKeys) {
        if let Some(ref mut enc) = self.encrypted {
            enc.exchange = Some(newkeys.exchange);
            enc.kex = newkeys.kex;
            enc.key = newkeys.key;
            enc.mac = newkeys.names.mac;
            self.cipher = Arc::new(newkeys.cipher);
        } else {
            self.encrypted = Some(Encrypted {
                exchange: Some(newkeys.exchange),
                kex: newkeys.kex,
                key: newkeys.key,
                mac: newkeys.names.mac,
                session_id: newkeys.session_id,
                state: Some(state),
                rekey: None,
                channels: HashMap::new(),
                last_channel_id: Wrapping(1),
                wants_reply: false,
                write: CryptoVec::new(),
                write_cursor: 0,
                last_rekey: std::time::Instant::now(),
            });
            self.cipher = Arc::new(newkeys.cipher);
        }
    }

    /// Send a disconnect message.
    pub fn disconnect(&mut self, reason: Disconnect, description: &str, language_tag: &str) {
        let disconnect = |buf: &mut CryptoVec| {
            push_packet!(buf, {
                buf.push(msg::DISCONNECT);
                buf.push_u32_be(reason as u32);
                buf.extend_ssh_string(description.as_bytes());
                buf.extend_ssh_string(language_tag.as_bytes());
            });
        };
        if !self.disconnected {
            self.disconnected = true;
            if let Some(ref mut enc) = self.encrypted {
                disconnect(&mut enc.write)
            } else {
                disconnect(&mut self.write_buffer.buffer)
            }
        }
    }

    /// Send a single byte message onto the channel.
    pub fn byte(&mut self, channel: ChannelId, msg: u8) {
        if let Some(ref mut enc) = self.encrypted {
            if let Some(channel) = enc.channels.get(&channel) {
                push_packet!(enc.write, {
                    enc.write.push(msg);
                    enc.write.push_u32_be(channel.recipient_channel);
                });
            }
        }
    }
}

impl Encrypted {
    pub fn adjust_window_size(&mut self, channel: ChannelId, data: &[u8], target: u32) {
        debug!("adjust_window_size");
        if let Some(ref mut channel) = self.channels.get_mut(&channel) {
            debug!("channel {:?}", channel);
            // Ignore extra data.
            // https://tools.ietf.org/html/rfc4254#section-5.2
            if data.len() as u32 <= channel.sender_window_size {
                channel.sender_window_size -= data.len() as u32;
            }
            if channel.sender_window_size < target / 2 {
                debug!(
                    "sender_window_size {:?}, target {:?}",
                    channel.sender_window_size,
                    target
                );
                push_packet!(self.write, {
                    self.write.push(msg::CHANNEL_WINDOW_ADJUST);
                    self.write.push_u32_be(channel.recipient_channel);
                    self.write.push_u32_be(target - channel.sender_window_size);
                });
                channel.sender_window_size = target;
            }
        }
    }

    pub fn data(&mut self, channel: ChannelId, extended: Option<u32>, buf: &[u8]) -> usize {
        use std::ops::Deref;
        if let Some(channel) = self.channels.get_mut(&channel) {
            assert!(channel.confirmed);
            debug!(
                "output {:?} {:?} {:?}",
                channel,
                buf.len(),
                &buf[..std::cmp::min(buf.len(), 100)]
            );
            debug!("output {:?}", self.write.deref());
            let mut buf = if buf.len() as u32 > channel.recipient_window_size {
                &buf[0..channel.recipient_window_size as usize]
            } else {
                buf
            };
            let buf_len = buf.len();

            while buf.len() > 0 {
                // Compute the length we're allowed to send.
                let off = std::cmp::min(buf.len(), channel.recipient_maximum_packet_size as usize);
                let off = std::cmp::min(off, channel.recipient_window_size as usize);
                push_packet!(self.write, {
                    if let Some(ext) = extended {
                        self.write.push(msg::CHANNEL_EXTENDED_DATA);
                        self.write.push_u32_be(channel.recipient_channel);
                        self.write.push_u32_be(ext);
                    } else {
                        self.write.push(msg::CHANNEL_DATA);
                        self.write.push_u32_be(channel.recipient_channel);
                    }
                    self.write.extend_ssh_string(&buf[..off]);
                });
                debug!("buffer: {:?}", self.write.deref().len());
                channel.recipient_window_size -= off as u32;
                buf = &buf[off..]
            }
            debug!("buf.len() = {:?}, buf_len = {:?}", buf.len(), buf_len);
            buf_len
        } else {
            0
        }
    }

    pub fn flush(
        &mut self,
        limits: &Limits,
        cipher: &cipher::CipherPair,
        write_buffer: &mut SSHBuffer,
    ) -> bool {
        // If there are pending packets (and we've not started to rekey), flush them.
        {
            while self.write_cursor < self.write.len() {

                let now = std::time::Instant::now();
                let dur = now.duration_since(self.last_rekey);

                if write_buffer.bytes >= limits.rekey_write_limit ||
                    dur >= limits.rekey_time_limit
                {

                    // Resetting those now is not strictly correct
                    // (since we're resetting before the rekeying),
                    // but since the bytes sent during rekeying will
                    // be counted, the limits are still an upper bound
                    // on the size that can be sent.
                    write_buffer.bytes = 0;
                    self.last_rekey = now;
                    return true;

                } else {
                    // Read a single packet, selfrypt and send it.
                    let len = BigEndian::read_u32(&self.write[self.write_cursor..]) as usize;
                    debug!("flushing len {:?}", len);
                    let packet = &self.write[(self.write_cursor + 4)..
                                             (self.write_cursor + 4 + len)];
                    cipher.write(packet, write_buffer);
                    self.write_cursor += 4 + len
                }
            }
        }
        if self.write_cursor >= self.write.len() {
            // If all packets have been written, clear.
            self.write_cursor = 0;
            self.write.clear();
        }
        false
    }
    pub fn new_channel_id(&mut self) -> ChannelId {
        self.last_channel_id += Wrapping(1);
        while self.channels.contains_key(
            &ChannelId(self.last_channel_id.0),
        )
        {
            self.last_channel_id += Wrapping(1)
        }
        ChannelId(self.last_channel_id.0)
    }
    pub fn new_channel(&mut self, window_size: u32, maxpacket: u32) -> ChannelId {
        loop {
            self.last_channel_id += Wrapping(1);
            if let std::collections::hash_map::Entry::Vacant(vacant_entry) =
                self.channels.entry(ChannelId(self.last_channel_id.0))
            {
                vacant_entry.insert(Channel {
                    recipient_channel: 0,
                    sender_channel: ChannelId(self.last_channel_id.0),
                    sender_window_size: window_size,
                    recipient_window_size: 0,
                    sender_maximum_packet_size: maxpacket,
                    recipient_maximum_packet_size: 0,
                    confirmed: false,
                    wants_reply: false,
                });
                return ChannelId(self.last_channel_id.0);
            }
        }
    }
}




#[derive(Debug)]
pub enum EncryptedState {
    WaitingServiceRequest,
    WaitingAuthRequest(auth::AuthRequest),
    Authenticated,
}


#[derive(Debug)]
pub struct Exchange {
    pub client_id: CryptoVec,
    pub server_id: CryptoVec,
    pub client_kex_init: CryptoVec,
    pub server_kex_init: CryptoVec,
    pub client_ephemeral: CryptoVec,
    pub server_ephemeral: CryptoVec,
}

impl Exchange {
    pub fn new() -> Self {
        Exchange {
            client_id: CryptoVec::new(),
            server_id: CryptoVec::new(),
            client_kex_init: CryptoVec::new(),
            server_kex_init: CryptoVec::new(),
            client_ephemeral: CryptoVec::new(),
            server_ephemeral: CryptoVec::new(),
        }
    }
}

#[derive(Debug)]
pub enum Kex {
    /// Version number sent. `algo` and `sent` tell wether kexinit has
    /// been received, and sent, respectively.
    KexInit(KexInit),

    /// Algorithms have been determined, the DH algorithm should run.
    KexDh(KexDh),

    /// The kex has run.
    KexDhDone(KexDhDone),

    /// The DH is over, we've sent the NEWKEYS packet, and are waiting
    /// the NEWKEYS from the other side.
    NewKeys(NewKeys),
}


#[derive(Debug)]
pub struct KexInit {
    pub algo: Option<negotiation::Names>,
    pub exchange: Exchange,
    pub session_id: Option<hash::DigestBytes>,
    pub sent: bool,
}


impl KexInit {
    pub fn received_rekey(
        ex: Exchange,
        algo: negotiation::Names,
        session_id: &hash::DigestBytes,
    ) -> Self {
        let mut kexinit = KexInit {
            exchange: ex,
            algo: Some(algo),
            sent: false,
            session_id: Some(session_id.clone()),
        };
        kexinit.exchange.client_kex_init.clear();
        kexinit.exchange.server_kex_init.clear();
        kexinit.exchange.client_ephemeral.clear();
        kexinit.exchange.server_ephemeral.clear();
        kexinit
    }

    pub fn initiate_rekey(ex: Exchange, session_id: &hash::DigestBytes) -> Self {
        let mut kexinit = KexInit {
            exchange: ex,
            algo: None,
            sent: true,
            session_id: Some(session_id.clone()),
        };
        kexinit.exchange.client_kex_init.clear();
        kexinit.exchange.server_kex_init.clear();
        kexinit.exchange.client_ephemeral.clear();
        kexinit.exchange.server_ephemeral.clear();
        kexinit
    }
}

#[derive(Debug)]
pub struct KexDh {
    pub exchange: Exchange,
    pub names: negotiation::Names,
    pub key: usize,
    pub session_id: Option<hash::DigestBytes>,
}

#[derive(Debug)]
pub struct KexDhDone {
    pub exchange: Exchange,
    pub kex: kex::Algorithm,
    pub key: usize,
    pub session_id: Option<hash::DigestBytes>,
    pub names: negotiation::Names,
}

impl KexDhDone {
    pub fn compute_keys(
        self,
        hash: hash::DigestBytes,
        buffer: &mut CryptoVec,
        buffer2: &mut CryptoVec,
        is_server: bool,
    ) -> Result<NewKeys, Error> {
        let session_id = if let Some(session_id) = self.session_id {
            session_id
        } else {
            hash.clone()
        };
        // Now computing keys.
        let c = self.kex.compute_keys(
            &session_id,
            &hash,
            buffer,
            buffer2,
            self.names.cipher,
            is_server,
        )?;
        Ok(NewKeys {
            exchange: self.exchange,
            names: self.names,
            kex: self.kex,
            key: self.key,
            cipher: c,
            session_id: session_id,
            received: false,
            sent: false,
        })
    }
}

#[derive(Debug)]
pub struct NewKeys {
    pub exchange: Exchange,
    pub names: negotiation::Names,
    pub kex: kex::Algorithm,
    pub key: usize,
    pub cipher: cipher::CipherPair,
    pub session_id: hash::DigestBytes,
    pub received: bool,
    pub sent: bool,
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
use std;
use Error;
use cryptovec::CryptoVec;
use futures::{Async, Poll};
use tokio::io::{AsyncRead, AsyncWrite};
use tcp::Tcp;
use std::io::ErrorKind;

/// The buffer to read the identification string (first line in the
/// protocol).
struct ReadSshIdBuffer {
    pub buf: CryptoVec,
    pub total: usize,
    pub bytes_read: usize,
    pub sshid_len: usize,
}

impl ReadSshIdBuffer {
    pub fn id(&self) -> &[u8] {
        &self.buf[..self.sshid_len]
    }

    pub fn new() -> ReadSshIdBuffer {
        let mut buf = CryptoVec::new();
        buf.resize(256);
        ReadSshIdBuffer {
            buf: buf,
            sshid_len: 0,
            bytes_read: 0,
            total: 0,
        }
    }
}

impl std::fmt::Debug for ReadSshIdBuffer {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(fmt, "ReadSshId {:?}", self.id())
    }
}

/// SshRead<R> is the same as R, plus a small buffer in the beginning to
/// read the identification string. After the first line in the
/// connection, the `id` parameter is never used again.
pub struct SshRead<R> {
    id: Option<ReadSshIdBuffer>,
    r: R,
}

impl<R: std::io::Read> std::io::Read for SshRead<R> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
        if let Some(mut id) = self.id.take() {
            debug!("id {:?} {:?}", id.total, id.bytes_read);
            if id.total > id.bytes_read {
                let result = {
                    let mut readable = &id.buf[id.bytes_read..id.total];
                    readable.read(buf).unwrap()
                };
                debug!("read {:?} bytes from id.buf", result);
                id.bytes_read += result;
                self.id = Some(id);
                return Ok(result);
            }
        }
        self.r.read(buf)
    }
}

impl<R: AsyncRead> AsyncRead for SshRead<R> {}

impl<R: std::io::Write> std::io::Write for SshRead<R> {
    fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
        self.r.write(buf)
    }
    fn flush(&mut self) -> Result<(), std::io::Error> {
        self.r.flush()
    }
}

impl<R: AsyncWrite> AsyncWrite for SshRead<R> {
    fn shutdown(&mut self) -> Poll<(), std::io::Error> {
        self.r.shutdown()
    }
}


impl<R: Tcp> Tcp for SshRead<R> {
    fn tcp_shutdown(&mut self) -> Result<(), std::io::Error> {
        self.r.tcp_shutdown()
    }
}



impl<R: std::io::Read> SshRead<R> {
    pub fn new(r: R) -> Self {
        SshRead {
            id: Some(ReadSshIdBuffer::new()),
            r: r,
        }
    }

    pub fn read_ssh_id(&mut self) -> Poll<&[u8], Error> {
        let ssh_id = self.id.as_mut().unwrap();
        loop {
            let mut i = 0;
            debug!("read_ssh_id: reading");
            let n = match self.r.read(&mut ssh_id.buf[ssh_id.total..]) {
                Ok(n) => n,
                Err(ref e) if e.kind() == ErrorKind::WouldBlock => return Ok(Async::NotReady),
                Err(e) => return Err(e.into())
            };
            debug!("read {:?}", n);

            // let buf = try_nb!(stream.fill_buf());
            ssh_id.total += n;
            debug!("{:?}", std::str::from_utf8(&ssh_id.buf[..ssh_id.total]));
            if n == 0 {
                return Err(Error::Disconnect);
            }
            loop {
                if i >= ssh_id.total - 1 {
                    break;
                }
                if ssh_id.buf[i] == b'\r' && ssh_id.buf[i + 1] == b'\n' {
                    ssh_id.bytes_read = i + 2;
                    break;
                } else if ssh_id.buf[i + 1] == b'\n' {
                    // This is really wrong, but OpenSSH 7.4 uses
                    // it.
                    ssh_id.bytes_read = i + 2;
                    i += 1;
                    break;
                } else {
                    i += 1;
                }
            }

            if ssh_id.bytes_read > 0 {
                // If we have a full line, handle it.
                if i >= 8 {
                    if &ssh_id.buf[0..8] == b"SSH-2.0-" {
                        // Either the line starts with "SSH-2.0-"
                        ssh_id.sshid_len = i;
                        return Ok(Async::Ready(&ssh_id.buf[..ssh_id.sshid_len]));
                    }
                }
                // Else, it is a "preliminary" (see
                // https://tools.ietf.org/html/rfc4253#section-4.2),
                // and we can discard it and read the next one.
                ssh_id.total = 0;
                ssh_id.bytes_read = 0;
            }
            debug!("bytes_read: {:?}", ssh_id.bytes_read);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

use super::*;
use std::num::Wrapping;
use tokio::io::{WriteAll, write_all};
use tokio::io::AsyncWrite;

#[derive(Debug)]
pub struct SSHBuffer {
    pub buffer: CryptoVec,
    pub len: usize, // next packet length.
    pub bytes: usize,

    // Sequence numbers are on 32 bits and wrap.
    // https://tools.ietf.org/html/rfc4253#section-6.4
    pub seqn: Wrapping<u32>,
}

impl SSHBuffer {
    pub fn new() -> Self {
        SSHBuffer {
            buffer: CryptoVec::new(),
            len: 0,
            bytes: 0,
            seqn: Wrapping(0),
        }
    }

    pub fn len(&self) -> usize {
        self.buffer.len() - self.len
    }

    pub fn send_ssh_id(&mut self, id: &[u8]) {
        self.buffer.extend(id);
        self.buffer.push(b'\r');
        self.buffer.push(b'\n');
    }

    pub fn write_all<W: AsyncWrite>(&mut self, stream: W) -> WriteAll<W, CryptoVec> {
        debug!("write_all: {:?}", self.buffer.as_ref());
        write_all(
            stream,
            std::mem::replace(&mut self.buffer, CryptoVec::new()),
        )
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
use std;
use tokio::net::TcpStream;

/// Types that have a "TCP shutdown" operation.
pub trait Tcp {
    /// Shutdown the TCP connection cleanly.
    fn tcp_shutdown(&mut self) -> Result<(), std::io::Error> {
        Ok(())
    }
}

impl Tcp for TcpStream {
    fn tcp_shutdown(&mut self) -> Result<(), std::io::Error> {
        debug!("tcp shutdown for tcpstream");
        self.shutdown(std::net::Shutdown::Both)
    }
}

impl<T: ?Sized + Tcp> Tcp for Box<T> {
    fn tcp_shutdown(&mut self) -> Result<(), std::io::Error> {
        self.as_mut().tcp_shutdown()
    }
}
impl<'a, T: ?Sized + Tcp> Tcp for &'a mut T {
    fn tcp_shutdown(&mut self) -> Result<(), std::io::Error> {
        (*self).tcp_shutdown()
    }
}
impl<'a> Tcp for std::io::Cursor<&'a mut [u8]> {}
impl Tcp for std::io::Cursor<Vec<u8>> {}
impl Tcp for std::io::Cursor<Box<[u8]>> {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[package]
name = "thrussh-agent"
version = "0.1.0"
authors = ["pe@pijul.org <pe@pijul.org>"]
license = "Apache-2.0/MIT"
description = "An SSH agent, including a server (thrussh-agent) and a client (thrussh-add)."
repository = "https://nest.pijul.com/pijul_org/thrussh"
include = [ "Cargo.toml", "src/thrussh-agent.rs", "src/thrussh-add.rs" ]

[dependencies]
thrussh-keys = "0.8.1"
futures = "0.1"
tokio-uds = "0.1"
tokio-core = "0.1"
clap = "2.28"
rand = "0.3"
libc = "0.2"
termion = "1.5"

[[bin]]
name = "thrussh-agent"
path = "src/thrussh-agent.rs"

[[bin]]
name = "thrussh-add"
path = "src/thrussh-add.rs"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
extern crate thrussh_keys;
extern crate futures;
extern crate tokio_uds;
extern crate tokio_core;
extern crate clap;
extern crate termion;

use futures::{Future, Stream};
use futures::future::Either;
use thrussh_keys::agent;
use std::path::Path;
use std::io::Read;
use std::fs::File;

fn main() {
    let matches = clap::App::new("Thrussh-add")
        .version("0.1")
        .author("Pierre-Étienne Meunier <pe@pijul.org>")
        .arg(clap::Arg::with_name("address")
             .short("a")
             .takes_value(true)
             .help("Bind the agent to that address"))
        .arg(clap::Arg::with_name("file")
             .takes_value(true)
             .multiple(true)
             .help("Secret key files to add"))
        .get_matches();

    let agent_path = {
        if let Some(addr) = matches.value_of("address") {
            std::path::Path::new(addr).to_path_buf()
        } else if let Ok(tmp) = std::env::var("SSH_AUTH_SOCK") {
            Path::new(&tmp).to_path_buf()
        } else {
            eprintln!("No $TMPDIR, and no address was given");
            std::process::exit(1)
        }
    };

    if let Some(files) = matches.values_of("file") {
        let mut core = tokio_core::reactor::Core::new().unwrap();
        let h = core.handle();
        let stream = tokio_uds::UnixStream::connect(&agent_path, &h).unwrap();
        let client = agent::client::AgentClient::connect(stream);

        core.run(
            futures::stream::iter_ok::<_, thrussh_keys::Error>(files)
                .fold(client, |client, s| {
                    let mut f = File::open(s).unwrap();
                    let mut key = String::new();
                    f.read_to_string(&mut key).unwrap();
                    let key = match thrussh_keys::decode_secret_key(&key, None) {
                        Ok(key) => Ok(key),
                        Err(_) => {
                            let password = password().unwrap();
                            thrussh_keys::decode_secret_key(&key, Some(password.as_bytes()))
                        }
                    };
                    match key {
                        Ok(key) => Either::A(client.add_identity(&key, &[]).map(move |(client, success)| {
                            if !success {
                                eprintln!("failed to add {:?}", s);
                            }
                            client
                        })),
                        Err(e) => {
                            eprintln!("Could not open key file: {:?}", e);
                            Either::B(futures::finished(client))
                        }
                    }
                })
        ).unwrap();
    }
}

fn password() -> Result<String, std::io::Error> {
    print!("Password: ");
    use std::io::{stdin, stdout};
    use termion::input::TermRead;
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let stdin = stdin();
    let mut stdin = stdin.lock();
    if let Some(pass) = stdin.read_passwd(&mut stdout)? {
        return Ok(pass)
    } else {
        return Ok(String::new())
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
extern crate thrussh_keys;
extern crate futures;
extern crate tokio_uds;
extern crate tokio_core;
extern crate rand;
extern crate clap;
extern crate libc;

use thrussh_keys::agent;
use std::path::Path;
use rand::Rng;

fn main() {
    let matches = clap::App::new("Thrussh-agent")
        .version("0.1")
        .author("Pierre-Étienne Meunier <pe@pijul.org>")
        .arg(clap::Arg::with_name("address")
             .short("a")
             .takes_value(true)
             .help("Bind the agent to that address"))
        .arg(clap::Arg::with_name("foreground")
             .short("D")
             .help("Foreground mode"))
        .get_matches();

    let mut rng = rand::thread_rng();
    let agent_path = {
        if let Some(addr) = matches.value_of("address") {
            std::path::Path::new(addr).to_path_buf()
        } else if let Ok(tmp) = std::env::var("TMPDIR") {
            let file: String = "thrussh-".chars().chain(rng.gen_ascii_chars().take(10)).collect();
            let mut path = Path::new(&tmp).join(&file);
            path.push("agent.ppid");
            path
        } else {
            eprintln!("No $TMPDIR, and no address was given");
            std::process::exit(1)
        }
    };

    if let Some(parent) = agent_path.parent() {
        std::fs::create_dir_all(parent).unwrap()
    }

    let foreground = matches.is_present("foreground");

    let pid = if foreground {
        unsafe { libc::getpid() }
    } else {
        unsafe { libc::fork() }
    };

    if pid > 0 || foreground {

        println!("SSH_AUTH_SOCK={:?}; export SSH_AUTH_SOCK;\nSSH_AGENT_ID={}; export SSH_AGENT_ID; echo Agent pid {}", agent_path, pid, pid);

    }

    if pid == 0 || foreground {
        let mut core = tokio_core::reactor::Core::new().unwrap();
        let h = core.handle();
        let listener = tokio_uds::UnixListener::bind(&agent_path, &h).unwrap().incoming();
        core.run(agent::server::AgentServer::new(listener, h, ())).unwrap();
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
[package]
name = "thrussh-keys"
version = "0.9.5"
authors = ["Pierre-Étienne Meunier <pe@pijul.org>"]
description = "Deal with SSH keys: load them, decrypt them, call an SSH agent."
keywords = ["ssh"]
repository = "https://nest.pijul.com/pijul_org/thrussh"
homepage = "https://pijul.org/thrussh"
documentation = "https://docs.rs/thrussh-keys"
license = "Apache-2.0"
include = [
        "Cargo.toml",
        "src/lib.rs",
        "src/pem.rs",
        "src/agent/mod.rs",
        "src/agent/msg.rs",
        "src/agent/server.rs",
        "src/agent/client.rs",
        "src/bcrypt_pbkdf.rs",
        "src/blowfish.rs",
        "src/encoding.rs",
        "src/format/mod.rs",
        "src/format/openssh.rs",
        "src/format/pkcs5.rs",
        "src/format/pkcs8.rs",
        "src/key.rs",
        "src/signature.rs"
        ]

[dependencies]
base64 = "0.8"
byteorder = "1.2"
tokio-core = "0.1"
tokio-io = "0.1"
futures = "0.1"
cryptovec = "0.4"
error-chain = "0.11"
hex = "0.3"
yasna = "0.1"
num-bigint = { version = "0.1", default-features = false }
num-integer = { version = "0.1", default-features = false }
openssl = "0.10"
bit-vec = "0.4"
thrussh-libsodium = "0.1"
serde_derive = "1.0"
serde = "1.0"

[dev-dependencies]
env_logger = "0.3"
tempdir="0.3"
tokio-uds = "0.1"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
use {Error, ErrorKind};
use tokio_io::io::{Flush, WriteAll, ReadExact};
use tokio_io::{AsyncRead, AsyncWrite};
use cryptovec::CryptoVec;
use futures::{Async, Poll, Future};
use encoding::Reader;
use byteorder::{BigEndian, ByteOrder};
use tokio_io;
use key::{PublicKey, SignatureHash};
use encoding::Encoding;
use key;

use super::msg;
use super::Constraint;

/// SSH agent client.
pub struct AgentClient<S: AsyncRead+AsyncWrite> {
    stream: S,
    buf: CryptoVec
}

enum State<S: AsyncRead+AsyncWrite> {
    ReadLen(ReadExact<S, CryptoVec>),
    Read(ReadExact<S, CryptoVec>),
    Write(WriteAll<S, CryptoVec>),
    Flush { flush: Flush<S>, buf: CryptoVec }
}

/// Future resolving to a response from the agent.
pub struct ReadResponse<S: AsyncRead+AsyncWrite>(Option<State<S>>);

impl<S: AsyncRead+AsyncWrite> Future for ReadResponse<S> {
    type Item = (AgentClient<S>, bool);
    type Error = Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            match self.0.take() {
                Some(State::Write(mut w)) => {
                    if let Async::Ready((stream, buf)) = w.poll()? {
                        self.0 = Some(State::Flush {
                            buf,
                            flush: tokio_io::io::flush(stream)
                        })
                    } else {
                        self.0 = Some(State::Write(w));
                        return Ok(Async::NotReady)
                    }
                }
                Some(State::Flush { mut flush, mut buf }) => {
                    if let Async::Ready(stream) = flush.poll()? {
                        buf.clear();
                        buf.resize(4);
                        self.0 = Some(State::ReadLen(tokio_io::io::read_exact(stream, buf)))
                    } else {
                        self.0 = Some(State::Flush { flush, buf });
                        return Ok(Async::NotReady)
                    }
                }
                Some(State::ReadLen(mut read)) => {
                    if let Async::Ready((stream, mut buf)) = read.poll()? {
                        let len = BigEndian::read_u32(&buf) as usize;
                        buf.clear();
                        buf.resize(len);
                        self.0 = Some(State::Read(tokio_io::io::read_exact(stream, buf)))
                    } else {
                        self.0 = Some(State::ReadLen(read));
                        return Ok(Async::NotReady)
                    }
                }
                Some(State::Read(mut read)) => {
                    if let Async::Ready((stream, buf)) = read.poll()? {
                        let success = !buf.is_empty() && buf[0] == msg::SUCCESS;
                        return Ok(Async::Ready((AgentClient { stream, buf }, success)))
                    } else {
                        self.0 = Some(State::ReadLen(read));
                        return Ok(Async::NotReady)
                    }
                }
                _ => panic!("future called after yielded")
            }
        }
    }
}

/// Future resolving to a response from the agent.
pub struct RequestIdentities<S: AsyncRead+AsyncWrite>(ReadResponse<S>);

impl<S: AsyncRead+AsyncWrite> Future for RequestIdentities<S> {
    type Item = (AgentClient<S>, Option<Vec<PublicKey>>);
    type Error = Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Async::Ready((agent, _)) = self.0.poll()? {
            let mut keys = Vec::new();
            if agent.buf[0] == msg::IDENTITIES_ANSWER {
                let mut r = agent.buf.reader(1);
                let n = r.read_u32()?;
                for _ in 0..n {
                    let key = r.read_string()?;
                    let mut r = key.reader(0);
                    let t = r.read_string()?;
                    match t {
                        b"ssh-rsa" => {
                            let e = r.read_mpint()?;
                            let n = r.read_mpint()?;
                            use openssl::rsa::Rsa;
                            use openssl::bn::BigNum;
                            use openssl::pkey::PKey;
                            keys.push(PublicKey::RSA {
                                key: key::OpenSSLPKey(PKey::from_rsa(Rsa::from_public_components(
                                    BigNum::from_slice(n)?,
                                    BigNum::from_slice(e)?,
                                )?)?),
                                hash: SignatureHash::SHA2_512
                            })
                        }
                        b"ssh-ed25519" => {
                            let mut p = key::ed25519::PublicKey::new_zeroed();
                            p.key.clone_from_slice(r.read_string()?);
                            keys.push(PublicKey::Ed25519(p))
                        }
                        t => return Err(ErrorKind::UnsupportedKeyType(t.to_vec()).into())
                    }
                }
            }
            return Ok(Async::Ready((agent, Some(keys))))
        } else {
            return Ok(Async::NotReady)
        }
    }
}

/// Future resolving to a response from the agent.
pub struct SignRequest<S: AsyncRead+AsyncWrite>(ReadResponse<S>);

impl<S: AsyncRead+AsyncWrite> Future for SignRequest<S> {
    type Item = (AgentClient<S>, Option<CryptoVec>);
    type Error = Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Async::Ready((agent, _)) = self.0.poll()? {
            if agent.buf.is_empty() {
                return Ok(Async::Ready((agent, None)))
            } else if agent.buf[0] == msg::SIGN_RESPONSE {
                let sig = {
                    let mut r = agent.buf.reader(1);
                    CryptoVec::from_slice(r.read_string()?)
                };
                return Ok(Async::Ready((agent, Some(sig))))
            } else {
                return Ok(Async::Ready((agent, None)))
            }
        } else {
            return Ok(Async::NotReady)
        }
    }
}

/// Future resolving to a response from the agent.
pub struct QueryExtension<S: AsyncRead+AsyncWrite>(ReadResponse<S>, Option<CryptoVec>);

impl<S: AsyncRead+AsyncWrite> Future for QueryExtension<S> {
    type Item = (AgentClient<S>, CryptoVec, bool);
    type Error = Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Async::Ready((agent, _)) = self.0.poll()? {
            let mut buf = self.1.take().unwrap();
            if agent.buf[0] == msg::SUCCESS {
                {
                    let mut r = agent.buf.reader(1);
                    buf.extend(r.read_string()?)
                }
                return Ok(Async::Ready((agent, buf, true)))
            } else {
                return Ok(Async::Ready((agent, buf, false)))
            }
        } else {
            return Ok(Async::NotReady)
        }
    }
}

// https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-4.1

impl<S: AsyncRead+AsyncWrite> AgentClient<S> {

    /// Build a future that connects to an SSH agent via the provided
    /// stream (on Unix, usually a Unix-domain socket).
    pub fn connect(stream: S) -> AgentClient<S> {
        AgentClient { stream, buf: CryptoVec::new() }
    }

    /// Send a key to the agent, with a (possibly empty) slice of
    /// constraints to apply when using the key to sign.
    pub fn add_identity(mut self, key: &key::KeyPair, constraints: &[Constraint]) -> ReadResponse<S> {
        use encoding::Encoding;
        self.buf.clear();
        self.buf.resize(4);
        if constraints.is_empty() {
            self.buf.push(msg::ADD_IDENTITY)
        } else {
            self.buf.push(msg::ADD_ID_CONSTRAINED)
        }
        match *key {
            key::KeyPair::Ed25519(ref secret) => {
                self.buf.extend_ssh_string(b"ssh-ed25519");
                let public = &secret.key[32..];
                self.buf.extend_ssh_string(public);
                self.buf.push_u32_be(64);
                self.buf.extend(&secret.key);
                self.buf.extend_ssh_string(b"");
            }
            key::KeyPair::RSA { ref key, .. } => {
                self.buf.extend_ssh_string(b"ssh-rsa");
                self.buf.extend_ssh_mpint(&key.n().to_vec());
                self.buf.extend_ssh_mpint(&key.e().to_vec());
                self.buf.extend_ssh_mpint(&key.d().to_vec());
                self.buf.extend_ssh_mpint(&key.iqmp().unwrap().to_vec());
                self.buf.extend_ssh_mpint(&key.p().unwrap().to_vec());
                self.buf.extend_ssh_mpint(&key.q().unwrap().to_vec());
                self.buf.extend_ssh_string(b"");
            }
        }
        if !constraints.is_empty() {
            self.buf.push_u32_be(constraints.len() as u32);
            for cons in constraints {
                match *cons {
                    Constraint::KeyLifetime { seconds } => {
                        self.buf.push(msg::CONSTRAIN_LIFETIME);
                        self.buf.push_u32_be(seconds)
                    }
                    Constraint::Confirm => self.buf.push(msg::CONSTRAIN_CONFIRM),
                    Constraint::Extensions { ref name, ref details } => {
                        self.buf.push(msg::CONSTRAIN_EXTENSION);
                        self.buf.extend_ssh_string(name);
                        self.buf.extend_ssh_string(details);
                    },
                }
            }
        }
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[..], len as u32);
        ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf))))
    }

    /// Add a smart card to the agent, with a (possibly empty) set of
    /// constraints to apply when signing.
    pub fn add_smartcard_key(mut self, id: &str, pin: &[u8], constraints: &[Constraint]) -> ReadResponse<S> {
        use encoding::Encoding;
        self.buf.clear();
        self.buf.resize(4);
        if constraints.is_empty() {
            self.buf.push(msg::ADD_SMARTCARD_KEY)
        } else {
            self.buf.push(msg::ADD_SMARTCARD_KEY_CONSTRAINED)
        }
        self.buf.extend_ssh_string(id.as_bytes());
        self.buf.extend_ssh_string(pin);
        if !constraints.is_empty() {
            self.buf.push_u32_be(constraints.len() as u32);
            for cons in constraints {
                match *cons {
                    Constraint::KeyLifetime { seconds } => {
                        self.buf.push(msg::CONSTRAIN_LIFETIME);
                        self.buf.push_u32_be(seconds)
                    }
                    Constraint::Confirm => self.buf.push(msg::CONSTRAIN_CONFIRM),
                    Constraint::Extensions { ref name, ref details } => {
                        self.buf.push(msg::CONSTRAIN_EXTENSION);
                        self.buf.extend_ssh_string(name);
                        self.buf.extend_ssh_string(details);
                    },
                }
            }
        }
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[0..], len as u32);
        ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf))))
    }

    /// Lock the agent, making it refuse to sign until unlocked.
    pub fn lock(mut self, passphrase: &[u8]) -> ReadResponse<S> {
        use encoding::Encoding;
        self.buf.clear();
        self.buf.resize(4);
        self.buf.push(msg::LOCK);
        self.buf.extend_ssh_string(passphrase);
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[0..], len as u32);
        ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf))))
    }

    /// Unlock the agent, allowing it to sign again.
    pub fn unlock(mut self, passphrase: &[u8]) -> ReadResponse<S> {
        use encoding::Encoding;
        self.buf.clear();
        self.buf.resize(4);
        self.buf.push(msg::UNLOCK);
        self.buf.extend_ssh_string(passphrase);
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[0..], len as u32);
        ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf))))
    }

    /// Ask the agent for a list of the currently registered secret
    /// keys.
    pub fn request_identities(mut self) -> RequestIdentities<S> {
        self.buf.clear();
        self.buf.resize(4);
        self.buf.push(msg::REQUEST_IDENTITIES);
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[0..], len as u32);
        RequestIdentities(ReadResponse(Some(State::Write(
            tokio_io::io::write_all(self.stream, self.buf)
        ))))
    }

    /// Ask the agent to sign the supplied piece of data.
    pub fn sign_request(mut self, public: &key::PublicKey, data: &[u8]) -> SignRequest<S> {
        self.buf.clear();
        self.buf.resize(4);
        self.buf.push(msg::SIGN_REQUEST);
        key_blob(public, &mut self.buf);
        self.buf.extend_ssh_string(data);
        match *public {
            PublicKey::RSA { hash, .. } =>
                self.buf.push_u32_be(match hash {
                    SignatureHash::SHA2_256 => 2,
                    SignatureHash::SHA2_512 => 4,
                }),
            _ => self.buf.push_u32_be(0),
        }
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[0..], len as u32);
        SignRequest(ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf)))))
    }

    /// Ask the agent to remove a key from its memory.
    pub fn remove_identity(mut self, public: &key::PublicKey) -> ReadResponse<S> {
        self.buf.clear();
        self.buf.resize(4);
        self.buf.push(msg::REMOVE_IDENTITY);
        key_blob(public, &mut self.buf);
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[0..], len as u32);
        ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf))))
    }

    /// Ask the agent to remove a smartcard from its memory.
    pub fn remove_smartcard_key(mut self, id: &str, pin: &[u8]) -> ReadResponse<S> {
        self.buf.clear();
        self.buf.resize(4);
        self.buf.push(msg::REMOVE_SMARTCARD_KEY);
        self.buf.extend_ssh_string(id.as_bytes());
        self.buf.extend_ssh_string(pin);
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[0..], len as u32);
        ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf))))
    }

    /// Ask the agent to forget all known keys.
    pub fn remove_all_identities(mut self) -> ReadResponse<S> {
        self.buf.clear();
        self.buf.resize(4);
        self.buf.push(msg::REMOVE_ALL_IDENTITIES);
        BigEndian::write_u32(&mut self.buf[0..], 5);
        ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf))))
    }

    /// Send a custom message to the agent.
    pub fn extension(mut self, typ: &[u8], ext: &[u8]) -> ReadResponse<S> {
        self.buf.clear();
        self.buf.resize(4);
        self.buf.push(msg::EXTENSION);
        self.buf.extend_ssh_string(typ);
        self.buf.extend_ssh_string(ext);
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[0..], len as u32);
        ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf))))
    }

    /// Ask the agent what extensions about supported extensions.
    pub fn query_extension(mut self, typ: &[u8], ext: CryptoVec) -> QueryExtension<S> {
        self.buf.clear();
        self.buf.resize(4);
        self.buf.push(msg::EXTENSION);
        self.buf.extend_ssh_string(typ);
        let len = self.buf.len() - 4;
        BigEndian::write_u32(&mut self.buf[0..], len as u32);
        QueryExtension(
            ReadResponse(Some(State::Write(tokio_io::io::write_all(self.stream, self.buf)))),
            Some(ext)
        )
    }

}

fn key_blob(public: &key::PublicKey, buf: &mut CryptoVec) {
    match *public {
        PublicKey::RSA{ ref key, .. } => {
            buf.extend(&[0, 0, 0, 0]);
            let len0 = buf.len();
            buf.extend_ssh_string(b"ssh-rsa");
            let rsa = key.0.rsa().unwrap();
            buf.extend_ssh_mpint(&rsa.e().to_vec());
            buf.extend_ssh_mpint(&rsa.n().to_vec());
            let len1 = buf.len();
            BigEndian::write_u32(&mut buf[5..], (len1 - len0) as u32);
        }
        PublicKey::Ed25519(ref p) => {
            buf.extend(&[0, 0, 0, 0]);
            let len0 = buf.len();
            buf.extend_ssh_string(b"ssh-ed25519");
            buf.extend_ssh_string(&p.key[0..]);
            let len1 = buf.len();
            BigEndian::write_u32(&mut buf[5..], (len1 - len0) as u32);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mod msg;
/// Write clients for SSH agents.
pub mod client;
/// Write servers for SSH agents.
pub mod server;

/// Constraints on how keys can be used
#[derive(Debug)]
pub enum Constraint {
    /// The key shall disappear from the agent's memory after that many seconds.
    KeyLifetime { seconds: u32 },
    /// Signatures need to be confirmed by the agent (for instance using a dialog).
    Confirm,
    /// Custom constraints
    Extensions { name: Vec<u8>, details: Vec<u8> }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
pub const FAILURE: u8 = 5;
pub const SUCCESS: u8 = 6;
pub const IDENTITIES_ANSWER: u8 = 12;
pub const SIGN_RESPONSE: u8 = 14;
pub const EXTENSION_FAILURE: u8 = 28;

pub const REQUEST_IDENTITIES:u8 = 11;
pub const SIGN_REQUEST:u8 = 13;
pub const ADD_IDENTITY:u8 = 17;
pub const REMOVE_IDENTITY:u8 = 18;
pub const REMOVE_ALL_IDENTITIES:u8 = 19;
pub const ADD_ID_CONSTRAINED:u8 = 25;
pub const ADD_SMARTCARD_KEY:u8 = 20;
pub const REMOVE_SMARTCARD_KEY:u8 = 21;
pub const LOCK:u8 = 22;
pub const UNLOCK:u8 = 23;
pub const ADD_SMARTCARD_KEY_CONSTRAINED:u8 = 26;
pub const EXTENSION:u8 = 27;

pub const CONSTRAIN_LIFETIME:u8 = 1;
pub const CONSTRAIN_CONFIRM:u8 = 2;
pub const CONSTRAIN_EXTENSION:u8 = 3;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use cryptovec::CryptoVec;
use futures::{Future, Stream, Poll, Async};
use futures::future::FutureResult;
use futures::future::ok;
use tokio_core::reactor::Handle;
use tokio_io::io::{read_exact, ReadExact, flush, Flush, write_all, WriteAll};
use tokio_io::{AsyncRead, AsyncWrite};
use byteorder::{BigEndian, ByteOrder};
use std::time::Duration;
use tokio_core::reactor::Timeout;
use std::time::SystemTime;
use key::SignatureHash;
use encoding::{Position, Reader, Encoding};
use key;

use {Error, ErrorKind};
use super::msg;
use super::Constraint;

#[derive(Clone)]
struct KeyStore(Arc<RwLock<HashMap<Vec<u8>, (key::KeyPair, SystemTime, Vec<Constraint>)>>>);

#[derive(Clone)]
struct Lock(Arc<RwLock<CryptoVec>>);

#[allow(missing_docs)]
#[derive(Debug)]
pub enum ServerError<E> {
    E(E),
    Error(Error)
}

pub trait Agent: Clone {
    type F: Future<Item = bool, Error = Error> + From<bool>;
    /// Called when data is about to be signed, and a confirmation is needed.
    #[allow(unused_variables)]
    fn confirm(&self, pk: &key::KeyPair) -> Self::F {
        From::from(false)
    }
}

/// Simple agent that either confirms or refuses all signing requests.
#[derive(Clone)]
pub struct SimpleAgent {
    confirm_all: bool,
}

impl SimpleAgent {
    pub fn new(confirm_all: bool) -> Self {
        SimpleAgent { confirm_all }
    }
}

pub struct SimpleAgentFuture(FutureResult<bool, Error>);

impl From<bool> for SimpleAgentFuture {
    fn from(b: bool) -> Self {
        SimpleAgentFuture(ok(b))
    }
}

impl Future for SimpleAgentFuture {
    type Item = bool;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

impl Agent for SimpleAgent {
    type F = SimpleAgentFuture;

    fn confirm(&self, _pk: &key::KeyPair) -> Self::F {
        From::from(self.confirm_all)
    }
}

/// The agent
pub struct AgentServer<S: AsyncRead+AsyncWrite, Addr, E, L: Stream<Item = (S, Addr), Error = E>, A: Agent> {
    listener: L,
    lock: Lock,
    keys: KeyStore,
    handle: Handle,
    agent: A,
}

impl<S: AsyncRead+AsyncWrite, Addr, E, L: Stream<Item = (S, Addr), Error = E>, A: Agent> AgentServer<S, Addr, E, L, A> {

    /// Create a new agent.
    pub fn new(listener: L, handle: Handle, agent: A) -> Self {
        AgentServer {
            listener,
            handle,
            agent,
            lock: Lock(Arc::new(RwLock::new(CryptoVec::new()))),
            keys: KeyStore(Arc::new(RwLock::new(HashMap::new()))),
        }
    }
}

impl<S: AsyncRead+AsyncWrite+'static, Addr, E, L: Stream<Item = (S, Addr), Error = E>, A: Agent+'static> Future for AgentServer<S, Addr, E, L, A> {
    type Item = ();
    type Error = ServerError<E>;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            match self.listener.poll() {
                Ok(Async::Ready(Some((stream, _)))) => {
                    let mut buf = CryptoVec::new();
                    buf.resize(4);
                    self.handle.spawn(Connection {
                        lock: self.lock.clone(),
                        keys: self.keys.clone(),
                        state: Some(State::ReadLen(read_exact(stream, buf), CryptoVec::new())),
                        handle: self.handle.clone(),
                        agent: self.agent.clone(),
                    }.map_err(|e| eprintln!("{:?}", e)))
                }
                Ok(Async::Ready(None)) => return Ok(Async::Ready(())),
                Ok(Async::NotReady) => return Ok(Async::NotReady),
                Err(e) => return Err(ServerError::E(e))
            }
        }
    }
}

struct Connection<S: AsyncRead+AsyncWrite, A: Agent> {
    lock: Lock,
    keys: KeyStore,
    state: Option<State<S, A>>,
    handle: Handle,
    agent: A,
}

enum State<S: AsyncRead+AsyncWrite, A: Agent> {
    ReadLen(ReadExact<S, CryptoVec>, CryptoVec),
    Read(ReadExact<S, CryptoVec>, CryptoVec),
    Write(WriteAll<S, CryptoVec>, CryptoVec),
    Respond { futures: Vec<A::F>, i: usize, stream: S, writebuf: CryptoVec, buf: CryptoVec },
    Flush(Flush<S>, CryptoVec, CryptoVec)
}

impl<S: AsyncRead+AsyncWrite, A: Agent> Future for Connection<S, A> {
    type Item = ();
    type Error = Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            match self.state.take() {
                Some(State::ReadLen(mut r, writebuf)) => {
                    if let Async::Ready((stream, mut buf)) = r.poll()? {
                        let len = BigEndian::read_u32(&buf) as usize;
                        buf.clear();
                        buf.resize(len);
                        self.state = Some(State::Read(read_exact(stream, buf), writebuf))
                    } else {
                        self.state = Some(State::ReadLen(r, writebuf));
                        return Ok(Async::NotReady)
                    }
                }
                Some(State::Read(mut r, mut writebuf)) => {
                    if let Async::Ready((stream, buf)) = r.poll()? {
                        writebuf.clear();
                        if let Some(v) = self.respond(&buf, &mut writebuf) {
                            self.state = Some(State::Respond { futures: v, i: 0, stream, writebuf, buf })
                        } else {
                            self.state = Some(State::Write(write_all(stream, writebuf), buf))
                        }
                    } else {
                        self.state = Some(State::Read(r, writebuf));
                        return Ok(Async::NotReady)
                    }
                }
                Some(State::Respond { mut futures, i, stream, mut writebuf, buf }) => {
                    // Validate constraints and sign.
                    if i >= futures.len() {
                        // All constraints passed!
                        {
                            let mut r = buf.reader(0);
                            r.read_byte()?;
                            self.really_sign(r, &mut writebuf)?;
                        }
                        self.state = Some(State::Write(write_all(stream, writebuf), buf))
                    } else {
                        match futures[i].poll()? {
                            Async::Ready(true) =>
                                self.state = Some(State::Respond {
                                    futures,
                                    i: i + 1,
                                    stream,
                                    writebuf,
                                    buf
                                }),
                            Async::Ready(false) => {
                                // failure
                                writebuf.resize(4);
                                writebuf.push(msg::FAILURE);
                                self.state = Some(State::Write(write_all(stream, writebuf), buf))
                            }
                            Async::NotReady => return Ok(Async::NotReady),
                        }
                    }
                }
                Some(State::Write(mut w, readbuf)) => {
                    if let Async::Ready((stream, buf)) = w.poll()? {
                        self.state = Some(State::Flush(flush(stream), readbuf, buf))
                    } else {
                        self.state = Some(State::Write(w, readbuf));
                        return Ok(Async::NotReady)
                    }
                }
                Some(State::Flush(mut w, mut readbuf, writebuf)) => {
                    if let Async::Ready(stream) = w.poll()? {
                        readbuf.clear();
                        readbuf.resize(4);
                        self.state = Some(State::ReadLen(read_exact(stream, readbuf), writebuf))
                    } else {
                        self.state = Some(State::Flush(w, readbuf, writebuf));
                        return Ok(Async::NotReady)
                    }
                }
                None => {
                    panic!("future polled after completion")
                }
            }
        }
    }
}

impl<S: AsyncRead+AsyncWrite, A: Agent> Connection<S, A> {

    fn respond(&self, buf: &CryptoVec, w: &mut CryptoVec) -> Option<Vec<A::F>> {
        let is_locked = {
            if let Ok(password) = self.lock.0.read() {
                !password.is_empty()
            } else {
                true
            }
        };
        w.extend(&[0, 0, 0, 0]);
        let mut r = buf.reader(0);
        match r.read_byte() {
            Ok(11) if !is_locked => {
                // request identities
                if let Ok(keys) = self.keys.0.read() {
                    w.push(msg::IDENTITIES_ANSWER);
                    w.push_u32_be(keys.len() as u32);
                    for (k, _) in keys.iter() {
                        w.extend_ssh_string(k);
                        w.extend_ssh_string(b"");
                    }
                } else {
                    w.push(msg::FAILURE)
                }
            }
            Ok(13) if !is_locked => {
                // sign request
                if let Ok(v) = self.try_sign(r) {
                    return Some(v)
                } else {
                    w.resize(4);
                    w.push(msg::FAILURE)
                }
            }
            Ok(17) if !is_locked => {
                // add identity
                if let Ok(true) = self.add_key(buf, w, r, false) {
                } else {
                    w.push(msg::FAILURE)
                }
            }
            Ok(18) if !is_locked => {
                // remove identity
                if let Ok(true) = self.remove_identity(r) {
                    w.push(msg::SUCCESS)
                } else {
                    w.push(msg::FAILURE)
                }
            }
            Ok(19) if !is_locked => {
                // remove all identities
                if let Ok(mut keys) = self.keys.0.write() {
                    keys.clear();
                    w.push(msg::SUCCESS)
                } else {
                    w.push(msg::FAILURE)
                }
            }
            Ok(22) if !is_locked => {
                // lock
                if let Ok(()) = self.lock(r) {
                    w.push(msg::SUCCESS)
                } else {
                    w.push(msg::FAILURE)
                }
            }
            Ok(23) if is_locked => {
                // unlock
                if let Ok(true) = self.unlock(r) {
                    w.push(msg::SUCCESS)
                } else {
                    w.push(msg::FAILURE)
                }
            }
            Ok(25) if !is_locked => {
                // add identity constrained
                if let Ok(true) = self.add_key(buf, w, r, true) {
                } else {
                    w.push(msg::FAILURE)
                }
            }
            _ => {
                // Message not understood
                w.push(msg::FAILURE)
            }
        }
        let len = w.len() - 4;
        BigEndian::write_u32(&mut w[0..], len as u32);
        None
    }

    fn lock(&self, mut r: Position) -> Result<(), Error> {
        let password = r.read_string()?;
        let mut lock = self.lock.0.write().map_err(|_| ErrorKind::Poison)?;
        lock.extend(password);
        Ok(())
    }

    fn unlock(&self, mut r: Position) -> Result<bool, Error> {
        let password = r.read_string()?;
        let mut lock = self.lock.0.write().map_err(|_| ErrorKind::Poison)?;
        if &lock[0..] == password {
            lock.clear();
            Ok(true)
        } else {
            Ok(false)
        }
    }

    fn remove_identity(&self, mut r: Position) -> Result<bool, Error> {
        if let Ok(mut keys) = self.keys.0.write() {
            if keys.remove(r.read_string()?).is_some() {
                Ok(true)
            } else {
                Ok(false)
            }
        } else {
            Ok(false)
        }

    }

    fn add_key(&self, buf: &CryptoVec, w: &mut CryptoVec, mut r: Position, constrained: bool) -> Result<bool, Error> {
        let pos0 = r.position;
        let t = r.read_string()?;
        let (blob, key) = match t {
            b"ssh-ed25519" => {
                let public_ = r.read_string()?;
                let pos1 = r.position;
                let concat = r.read_string()?;
                let _comment = r.read_string()?;
                if &concat[32..64] != public_ {
                    return Ok(false)
                }
                use key::ed25519::*;
                let mut public = PublicKey::new_zeroed();
                let mut secret = SecretKey::new_zeroed();
                public.key.clone_from_slice(&public_[..32]);
                secret.key.clone_from_slice(&concat[..]);
                w.push(msg::SUCCESS);
                (buf[pos0..pos1].to_vec(),
                 key::KeyPair::Ed25519(secret))
            }
            b"ssh-rsa" => {
                use openssl::bn::{BigNum, BigNumContext};
                use openssl::rsa::Rsa;
                let n = r.read_mpint()?;
                let e = r.read_mpint()?;
                let d = BigNum::from_slice(r.read_mpint()?)?;
                let q_inv = r.read_mpint()?;
                let p = BigNum::from_slice(r.read_mpint()?)?;
                let q = BigNum::from_slice(r.read_mpint()?)?;
                let (dp, dq) = {
                    let one = BigNum::from_u32(1)?;
                    let p1 = p.as_ref() - one.as_ref();
                    let q1 = q.as_ref() - one.as_ref();
                    let mut context = BigNumContext::new()?;
                    let mut dp = BigNum::new()?;
                    let mut dq = BigNum::new()?;
                    dp.checked_rem(&d, &p1, &mut context)?;
                    dq.checked_rem(&d, &q1, &mut context)?;
                    (dp, dq)
                };
                let _comment = r.read_string()?;
                let key = Rsa::from_private_components (
                    BigNum::from_slice(n)?,
                    BigNum::from_slice(e)?,
                    d,
                    p,
                    q,
                    dp,
                    dq,
                    BigNum::from_slice(&q_inv)?,
                )?;

                let len0 = w.len();
                w.extend_ssh_string(b"ssh-rsa");
                w.extend_ssh_mpint(&e);
                w.extend_ssh_mpint(&n);
                let blob = w[len0..].to_vec();
                w.resize(len0);
                w.push(msg::SUCCESS);
                (blob, key::KeyPair::RSA { key, hash: SignatureHash::SHA2_256 })
            }
            _ => return Ok(false)
        };
        let mut w = self.keys.0.write().unwrap();
        let now = SystemTime::now();
        if constrained {
            let n = r.read_u32()?;
            let mut c = Vec::new();
            for _ in 0..n {
                let t = r.read_byte()?;
                if t == msg::CONSTRAIN_LIFETIME {
                    let seconds = r.read_u32()?;
                    c.push(Constraint::KeyLifetime { seconds });
                    let blob = blob.clone();
                    let keys = self.keys.clone();
                    self.handle.spawn(
                        Timeout::new(Duration::from_secs(seconds as u64), &self.handle).unwrap()
                            .map(move |_| {
                                let mut keys = keys.0.write().unwrap();
                                let delete = if let Some(&(_, time, _)) = keys.get(&blob) {
                                    time == now
                                } else {
                                    false
                                };
                                if delete {
                                    keys.remove(&blob);
                                }
                            })
                            .map_err(|_| ())
                    )
                } else if t == msg::CONSTRAIN_CONFIRM {
                    c.push(Constraint::Confirm)
                } else {
                    return Ok(false)
                }
            }
            w.insert(blob, (key, now, Vec::new()));
        } else {
            w.insert(blob, (key, now, Vec::new()));
        }
        Ok(true)
    }

    fn try_sign(&self, mut r: Position) -> Result<Vec<A::F>, Error> {
        let blob = r.read_string()?;
        let k = self.keys.0.read().unwrap();
        if let Some(&(ref key, _, ref constraints)) = k.get(blob) {
            let mut v = Vec::new();
            for cons in constraints {
                match *cons {
                    Constraint::KeyLifetime { .. } | Constraint::Extensions { .. } => {}
                    Constraint::Confirm => v.push(self.agent.confirm(key))
                }
            }
            Ok(v)
        } else {
            Ok(vec![A::F::from(false)])
        }
    }

    fn really_sign(&self, mut r: Position, w: &mut CryptoVec) -> Result<(), Error> {
        let blob = r.read_string()?;
        let data = r.read_string()?;
        let k = self.keys.0.read().unwrap();
        if let Some(&(ref key, _, _)) = k.get(blob) {
            w.push(msg::SIGN_RESPONSE);
            key.add_signature(w, data)?;
            let len = w.len();
            BigEndian::write_u32(&mut w[0..], (len-4) as u32);
        }
        Ok(())
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// From the rust-crypto project.

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use byteorder::{BigEndian, LittleEndian, ByteOrder};
use openssl::sha::Sha512;
use blowfish::*;

fn bcrypt_hash(hpass: &[u8], hsalt: &[u8], output: &mut [u8; 32]) {
    let mut bf = Blowfish::init_state();
    bf.salted_expand_key(hsalt, hpass);

    for _ in 0..64 {
        bf.expand_key(hsalt);
        bf.expand_key(hpass);
    }

    // b"OxychromaticBlowfishSwatDynamite"
    let mut buf:[u32; 8] = [1333295459, 1752330093, 1635019107, 1114402679, 1718186856, 1400332660, 1148808801, 1835627621];
    let mut i = 0;
    while i < 8 {
        for _ in 0..64 {
            let (l, r) = bf.encrypt(buf[i], buf[i+1]);
            buf[i] = l;
            buf[i+1] = r;
        }
        i += 2
    }

    for i in 0..8 {
        LittleEndian::write_u32(&mut output[i*4..(i+1)*4], buf[i]);
    }
}

pub fn bcrypt_pbkdf(password: &[u8], salt: &[u8], rounds: u32, output: &mut [u8]) {

    assert!(password.len() > 0);
    assert!(salt.len() > 0);
    assert!(rounds > 0);
    assert!(output.len() > 0);
    assert!(output.len() <= 1024);

    let nblocks = (output.len() + 31) / 32;

    let hpass = {
        let mut hasher = Sha512::new();
        hasher.update(password);
        hasher.finish()
    };

    for block in 1..(nblocks+1) {
        let mut count = [0u8; 4];
        let mut out   = [0u8; 32];
        BigEndian::write_u32(&mut count, block as u32);

        let mut hasher = Sha512::new();
        hasher.update(salt);
        hasher.update(&count);
        let hsalt = hasher.finish();

        bcrypt_hash(hpass.as_ref(), hsalt.as_ref(), &mut out);
        let mut tmp = out;

        for _ in 1..rounds {

            let mut hasher = Sha512::new();
            hasher.update(&tmp);
            let hsalt = hasher.finish();

            bcrypt_hash(hpass.as_ref(), hsalt.as_ref(), &mut tmp);
            for i in 0..out.len() {
                out[i] ^= tmp[i];
            }

            for i in 0..out.len() {
                let idx = i * nblocks + (block-1);
                if idx < output.len() {
                    output[idx] = out[i];
                }
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
// From the rust-crypto project.

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[derive(Clone,Copy)]
pub struct Blowfish {
    s: [[u32; 256]; 4],
    p: [u32; 18]
}

fn next_u32_wrap(buf: &[u8], offset: &mut usize) -> u32 {
    let mut v = 0;
    for _ in 0..4 {
        if *offset >= buf.len() {
            *offset = 0;
        }
        v = (v << 8) | buf[*offset] as u32;
        *offset += 1;
    }
    v
}

impl Blowfish {

    // For bcrypt. Use Blowfish::new instead.
    pub fn init_state() -> Blowfish {
        Blowfish {
            p: [0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
                0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
                0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b],
            s: [[0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
                 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
                 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
                 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
                 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
                 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
                 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
                 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
                 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
                 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
                 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
                 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
                 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
                 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
                 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
                 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
                 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
                 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
                 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
                 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
                 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
                 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
                 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
                 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
                 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
                 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
                 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
                 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
                 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
                 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
                 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
                 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
                 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
                 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
                 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
                 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
                 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
                 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
                 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
                 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
                 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
                 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
                 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a],
                [0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
                 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
                 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
                 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
                 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
                 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
                 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
                 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
                 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
                 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
                 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
                 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
                 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
                 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
                 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
                 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
                 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
                 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
                 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
                 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
                 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
                 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
                 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
                 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
                 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
                 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
                 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
                 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
                 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
                 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
                 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
                 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
                 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
                 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
                 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
                 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
                 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
                 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
                 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
                 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
                 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
                 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
                 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7],
                [0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
                 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
                 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
                 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
                 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
                 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
                 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
                 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
                 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
                 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
                 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
                 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
                 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
                 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
                 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
                 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
                 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
                 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
                 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
                 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
                 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
                 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
                 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
                 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
                 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
                 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
                 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
                 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
                 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
                 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
                 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
                 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
                 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
                 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
                 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
                 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
                 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
                 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
                 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
                 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
                 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
                 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
                 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0],
                [0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
                 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
                 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
                 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
                 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
                 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
                 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
                 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
                 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
                 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
                 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
                 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
                 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
                 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
                 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
                 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
                 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
                 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
                 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
                 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
                 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
                 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
                 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
                 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
                 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
                 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
                 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
                 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
                 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
                 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
                 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
                 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
                 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
                 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
                 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
                 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
                 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
                 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
                 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
                 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
                 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
                 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
                 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6]]
        }
    }

    // For bcrypt. Use Blowfish::new instead.
    pub fn expand_key(&mut self, key: &[u8]) {
        let mut key_pos = 0;
        for i in 0..18 {
            self.p[i] ^= next_u32_wrap(key, &mut key_pos);
        }
        let mut l = 0u32;
        let mut r = 0u32;
        let mut i = 0;
        while i < 18 {
            let (new_l, new_r) = self.encrypt(l, r);
            l = new_l;
            r = new_r;
            self.p[i] = l;
            self.p[i+1] = r;
            i += 2
        }
        for i in 0..4 {
            let mut j = 0;
            while j < 256 {
                let (new_l, new_r) = self.encrypt(l, r);
                l = new_l;
                r = new_r;
                self.s[i][j] = l;
                self.s[i][j+1] = r;
                j += 2
            }
        }
    }

    // Bcrypt key schedule.
    pub fn salted_expand_key(&mut self, salt: &[u8], key: &[u8]) {
        let mut key_pos = 0;
        for i in 0..18 {
            self.p[i] ^= next_u32_wrap(key, &mut key_pos);
        }
        let mut l = 0u32;
        let mut r = 0u32;
        let mut salt_pos = 0;
        let mut i = 0;
        while i < 18 {
            let (new_l, new_r) = self.encrypt(l ^ next_u32_wrap(salt, &mut salt_pos), r ^ next_u32_wrap(salt, &mut salt_pos));
            l = new_l;
            r = new_r;
            self.p[i] = l;
            self.p[i+1] = r;
            i += 2
        }
        for i in 0..4 {
            let mut j = 0;
            while j < 256 {
                let (new_l, new_r) = self.encrypt(l ^ next_u32_wrap(salt, &mut salt_pos), r ^ next_u32_wrap(salt, &mut salt_pos));
                l = new_l;
                r = new_r;
                self.s[i][j] = l;
                self.s[i][j+1] = r;

                let (new_l, new_r) = self.encrypt(l ^ next_u32_wrap(salt, &mut salt_pos), r ^ next_u32_wrap(salt, &mut salt_pos));
                l = new_l;
                r = new_r;
                self.s[i][j+2] = l;
                self.s[i][j+3] = r;
                j += 4
            }
        }
    }

    fn round_function(&self, x: u32) -> u32 {
        ((self.s[0][(x >> 24) as usize].wrapping_add(self.s[1][((x >> 16) & 0xff) as usize])) ^ self.s[2][((x >> 8) & 0xff) as usize]).wrapping_add(self.s[3][(x & 0xff) as usize])
    }

    // Public for bcrypt.
    pub fn encrypt(&self, mut l: u32, mut r: u32) -> (u32, u32) {
        let mut i = 0;
        while i < 16 {
            l ^= self.p[i];
            r ^= self.round_function(l);
            r ^= self.p[i+1];
            l ^= self.round_function(r);
            i += 2
        }
        l ^= self.p[16];
        r ^= self.p[17];
        (r, l)
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// Copyright 2016 Pierre-Étienne Meunier
//
// 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.
//

use byteorder::{ByteOrder, BigEndian, WriteBytesExt};
use {ErrorKind, Error};
use cryptovec::CryptoVec;

#[doc(hidden)]
pub trait Bytes {
    fn bytes(&self) -> &[u8];
}

impl<A: AsRef<str>> Bytes for A {
    fn bytes(&self) -> &[u8] {
        self.as_ref().as_bytes()
    }
}

/// Encode in the SSH format.
pub trait Encoding {
    /// Push an SSH-encoded string to `self`.
    fn extend_ssh_string(&mut self, s: &[u8]);
    /// Push an SSH-encoded blank string of length `s` to `self`.
    fn extend_ssh_string_blank(&mut self, s: usize) -> &mut [u8];
    /// Push an SSH-encoded multiple-precision integer.
    fn extend_ssh_mpint(&mut self, s: &[u8]);
    /// Push an SSH-encoded list.
    fn extend_list<A: Bytes, I: Iterator<Item = A>>(&mut self, list: I);
    /// Push an SSH-encoded empty list.
    fn write_empty_list(&mut self);
}

/// Encoding length of the given mpint.
pub fn mpint_len(s: &[u8]) -> usize {
    let mut i = 0;
    while i < s.len() && s[i] == 0 {
        i += 1
    }
    (if s[i] & 0x80 != 0 { 5 } else { 4 }) + s.len() - i
}


impl Encoding for Vec<u8> {
    fn extend_ssh_string(&mut self, s: &[u8]) {
        self.write_u32::<BigEndian>(s.len() as u32).unwrap();
        self.extend(s);
    }
    fn extend_ssh_string_blank(&mut self, len: usize) -> &mut [u8] {
        self.write_u32::<BigEndian>(len as u32).unwrap();
        let current = self.len();
        self.resize(current + len, 0u8);
        &mut self[current..]
    }
    fn extend_ssh_mpint(&mut self, s: &[u8]) {
        // Skip initial 0s.
        let mut i = 0;
        while i < s.len() && s[i] == 0 {
            i += 1
        }
        // If the first non-zero is >= 128, write its length (u32, BE), followed by 0.
        if s[i] & 0x80 != 0 {

            self.write_u32::<BigEndian>((s.len() - i + 1) as u32).unwrap();
            self.push(0)

        } else {

            self.write_u32::<BigEndian>((s.len() - i) as u32).unwrap();

        }
        self.extend(&s[i..]);
    }


    fn extend_list<A: Bytes, I: Iterator<Item = A>>(&mut self, list: I) {
        let len0 = self.len();
        self.extend(&[0, 0, 0, 0]);
        let mut first = true;
        for i in list {
            if !first {
                self.push(b',')
            } else {
                first = false;
            }
            self.extend(i.bytes())
        }
        let len = (self.len() - len0 - 4) as u32;

        BigEndian::write_u32(&mut self[len0..], len);
    }

    fn write_empty_list(&mut self) {
        self.extend(&[0, 0, 0, 0]);
    }
}

impl Encoding for CryptoVec {
    fn extend_ssh_string(&mut self, s: &[u8]) {
        self.push_u32_be(s.len() as u32);
        self.extend(s);
    }
    fn extend_ssh_string_blank(&mut self, len: usize) -> &mut [u8] {
        self.push_u32_be(len as u32);
        let current = self.len();
        self.resize(current + len);
        &mut self[current..]
    }
    fn extend_ssh_mpint(&mut self, s: &[u8]) {
        // Skip initial 0s.
        let mut i = 0;
        while i < s.len() && s[i] == 0 {
            i += 1
        }
        // If the first non-zero is >= 128, write its length (u32, BE), followed by 0.
        if s[i] & 0x80 != 0 {

            self.push_u32_be((s.len() - i + 1) as u32);
            self.push(0)

        } else {

            self.push_u32_be((s.len() - i) as u32);

        }
        self.extend(&s[i..]);
    }


    fn extend_list<A: Bytes, I: Iterator<Item = A>>(&mut self, list: I) {
        let len0 = self.len();
        self.extend(&[0, 0, 0, 0]);
        let mut first = true;
        for i in list {
            if !first {
                self.push(b',')
            } else {
                first = false;
            }
            self.extend(i.bytes())
        }
        let len = (self.len() - len0 - 4) as u32;

        BigEndian::write_u32(&mut self[len0..], len);
    }

    fn write_empty_list(&mut self) {
        self.extend(&[0, 0, 0, 0]);
    }
}

/// A cursor-like trait to read SSH-encoded things.
pub trait Reader {
    /// Create an SSH reader for `self`.
    fn reader<'a>(&'a self, starting_at: usize) -> Position<'a>;
}

impl Reader for CryptoVec {
    fn reader<'a>(&'a self, starting_at: usize) -> Position<'a> {
        Position {
            s: &self,
            position: starting_at,
        }
    }
}

impl Reader for [u8] {
    fn reader<'a>(&'a self, starting_at: usize) -> Position<'a> {
        Position {
            s: self,
            position: starting_at,
        }
    }
}

/// A cursor-like type to read SSH-encoded values.
#[derive(Debug)]
pub struct Position<'a> {
    s: &'a [u8],
    #[doc(hidden)]
    pub position: usize,
}
impl<'a> Position<'a> {
    /// Read one string from this reader.
    pub fn read_string(&mut self) -> Result<&'a [u8], Error> {
        let len = self.read_u32()? as usize;
        if self.position + len <= self.s.len() {
            let result = &self.s[self.position..(self.position + len)];
            self.position += len;
            Ok(result)
        } else {
            Err(ErrorKind::IndexOutOfBounds.into())
        }
    }
    /// Read a `u32` from this reader.
    pub fn read_u32(&mut self) -> Result<u32, Error> {
        if self.position + 4 <= self.s.len() {
            let u = BigEndian::read_u32(&self.s[self.position..]);
            self.position += 4;
            Ok(u)
        } else {
            Err(ErrorKind::IndexOutOfBounds.into())
        }
    }
    /// Read one byte from this reader.
    pub fn read_byte(&mut self) -> Result<u8, Error> {
        if self.position + 1 <= self.s.len() {
            let u = self.s[self.position];
            self.position += 1;
            Ok(u)
        } else {
            Err(ErrorKind::IndexOutOfBounds.into())
        }
    }

    /// Read one byte from this reader.
    pub fn read_mpint(&mut self) -> Result<&'a [u8], Error> {
        let len = self.read_u32()? as usize;
        if self.position + len <= self.s.len() {
            let result = &self.s[self.position..(self.position + len)];
            self.position += len;
            Ok(result)
        } else {
            Err(ErrorKind::IndexOutOfBounds.into())
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use {Error, ErrorKind};
use key;
use super::is_base64_char;
use hex::FromHex;
use base64::{decode_config, encode_config, MIME};
use openssl::rsa::Rsa;
use std::io::Write;

mod openssh;
pub use self::openssh::*;

mod pkcs5;
pub use self::pkcs5::*;

mod pkcs8;

const AES_128_CBC: &'static str = "DEK-Info: AES-128-CBC,";

#[derive(Clone, Copy, Debug)]
/// AES encryption key.
pub enum Encryption {
    /// Key for AES128
    Aes128Cbc([u8; 16]),
    /// Key for AES256
    Aes256Cbc([u8; 16]),
}

#[derive(Clone, Debug)]
enum Format {
    Rsa,
    Openssh,
    Pkcs5Encrypted(Encryption),
    Pkcs8Encrypted,
    Pkcs8,
}

/// Decode a secret key, possibly deciphering it with the supplied
/// password.
pub fn decode_secret_key(
    secret: &str,
    password: Option<&[u8]>,
) -> Result<key::KeyPair, Error> {

    let mut format = None;
    let secret = {
        let mut started = false;
        let mut sec = String::new();
        for l in secret.lines() {
            if started == true {
                if l.chars().all(is_base64_char) {
                    sec.push_str(l)
                } else if l.starts_with(AES_128_CBC) {
                    let iv_: Vec<u8> = FromHex::from_hex(l.split_at(AES_128_CBC.len()).1)?;
                    if iv_.len() != 16 {
                        return Err(ErrorKind::CouldNotReadKey.into());
                    }
                    let mut iv = [0; 16];
                    iv.clone_from_slice(&iv_);
                    format = Some(Format::Pkcs5Encrypted(Encryption::Aes128Cbc(iv)))
                }
            }
            if l == "-----BEGIN OPENSSH PRIVATE KEY-----" {
                started = true;
                format = Some(Format::Openssh);
            } else if l == "-----BEGIN RSA PRIVATE KEY-----" {
                started = true;
                format = Some(Format::Rsa);
            } else if l == "-----BEGIN ENCRYPTED PRIVATE KEY-----" {
                started = true;
                format = Some(Format::Pkcs8Encrypted);
            } else if l == "-----BEGIN PRIVATE KEY-----" {
                started = true;
                format = Some(Format::Pkcs8);
            } else if l.starts_with("-----END ") {
                break;
            }
        }
        sec
    };

    // debug!("secret = {:?}", secret);
    let secret = decode_config(&secret, MIME)?;
    match format {
        Some(Format::Openssh) => decode_openssh(&secret, password),
        Some(Format::Rsa) => decode_rsa(&secret),
        Some(Format::Pkcs5Encrypted(enc)) => decode_pkcs5(&secret, password, enc),
        Some(Format::Pkcs8Encrypted) |
        Some(Format::Pkcs8) => self::pkcs8::decode_pkcs8(&secret, password),
        None => Err(ErrorKind::CouldNotReadKey.into()),
    }
}

pub fn encode_pkcs8_pem<W:Write>(key: &key::KeyPair, mut w: W) -> Result<(), Error> {
    let x = self::pkcs8::encode_pkcs8(key);
    w.write_all(b"-----BEGIN PRIVATE KEY-----\n")?;
    w.write_all(encode_config(&x, MIME).as_bytes())?;
    w.write_all(b"\n-----END PRIVATE KEY-----\n")?;
    Ok(())
}

pub fn encode_pkcs8_pem_encrypted<W:Write>(key: &key::KeyPair, pass: &[u8], rounds: u32, mut w: W) -> Result<(), Error> {
    let x = self::pkcs8::encode_pkcs8_encrypted(pass, rounds, key)?;
    w.write_all(b"-----BEGIN ENCRYPTED PRIVATE KEY-----\n")?;
    w.write_all(encode_config(&x, MIME).as_bytes())?;
    w.write_all(b"\n-----END ENCRYPTED PRIVATE KEY-----\n")?;
    Ok(())
}


fn decode_rsa(secret: &[u8]) -> Result<key::KeyPair, Error> {
    Ok(key::KeyPair::RSA {
        key: Rsa::private_key_from_der(secret)?,
        hash: key::SignatureHash::SHA2_256
    })
}

fn pkcs_unpad(dec: &mut Vec<u8>) {
    let len = dec.len();
    if len > 0 {
        let padding_len = dec[len-1];
        if dec[(len - padding_len as usize)..].iter().all(|&x| x == padding_len) {
            dec.truncate(len - padding_len as usize)
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use {Error, ErrorKind, KEYTYPE_ED25519};
use encoding::Reader;
use key;
use cryptovec::CryptoVec;
use openssl::symm::{Cipher, Mode, Crypter};
use bcrypt_pbkdf;

/// Decode a secret key given in the OpenSSH format, deciphering it if
/// needed using the supplied password.
pub fn decode_openssh(
    secret: &[u8],
    password: Option<&[u8]>,
) -> Result<key::KeyPair, Error> {
    if &secret[0..15] == b"openssh-key-v1\0" {
        let mut position = secret.reader(15);