Skip to content

Commit 4366e8c

Browse files
authored
Merge pull request #6 from bluemax75/master
Add PublicKey Authentication
2 parents 6c3af2e + 88dd247 commit 4366e8c

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

src/ssh2.nim

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import asyncdispatch, asyncnet, strformat
22
from libssh2 import init, free, exit
33
import ssh2/private/[agent, channel, types, session]
4+
export SSHException, AuthenticationException
45

56
export agent, channel, types, session
67

@@ -17,7 +18,7 @@ proc disconnect*(ssh: SSHClient) =
1718
ssh.socket.close()
1819
libssh2.exit()
1920

20-
proc connect*(s: SSHClient, hostname: string, username: string, port = Port(22), password = "", useAgent = false) {.async.} =
21+
proc connect*(s: SSHClient, hostname: string, username: string, port = Port(22), password = "", pkey = "", useAgent = false) {.async.} =
2122
s.socket = newAsyncSocket()
2223
await s.socket.connect(hostname, port)
2324
s.session = initSession()
@@ -34,7 +35,10 @@ proc connect*(s: SSHClient, hostname: string, username: string, port = Port(22),
3435
break
3536
agent.close()
3637
else:
37-
discard s.session.authPassword(username, password)
38+
if pkey.len != 0:
39+
discard s.session.authPublicKey(username, pkey, password)
40+
else:
41+
discard s.session.authPassword(username, password)
3842

3943
proc execCommand*(s: SSHClient, command: string): Future[(string, string, int)] {.async.} =
4044
var channel = initChannel(s)

src/ssh2/private/session.nim

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import libssh2, types, strformat, posix
1+
import os, libssh2, types, strformat, posix
22

33
proc initSession*(): Session =
44
result = session_init()
@@ -26,6 +26,18 @@ proc authPassword*(session: Session, username, password: string): bool =
2626
break
2727
result = true
2828

29+
proc authPublicKey*(session: Session; username, pkey: string, passphrase = ""): bool =
30+
let pkey = expandTilde(pkey)
31+
while true:
32+
let rc = session.userauth_publickey_from_file(username, nil, pkey, passphrase)
33+
if rc == LIBSSH2_ERROR_EAGAIN:
34+
discard
35+
elif rc < 0:
36+
raise newException(AuthenticationException, &"Authentication with privateKey {pkey} failed!")
37+
else:
38+
break
39+
result = true
40+
2941
proc getLastError*(session: Session): (string, int) =
3042
var
3143
errmsg: cstring
@@ -40,4 +52,4 @@ proc getLastErrorMessage*(session: Session): string =
4052
proc close*(session: Session) =
4153
while session.session_disconnect("libssh2 wrapper for Nim, libssh2.nim/core") == LIBSSH2_ERROR_EAGAIN:
4254
discard
43-
discard session.session_free()
55+
discard session.session_free()

tests/test_exec_pkey.nim

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import asyncdispatch, ssh2, ssh2/scp
2+
3+
proc main() {.async.} =
4+
var client = newSSHClient()
5+
defer: client.disconnect()
6+
await client.connect("127.0.0.1", "nim", Port(22), pkey="~/.ssh/id_rsa", password="secret")
7+
echo await client.execCommand("uptime")
8+
9+
waitFor main()

0 commit comments

Comments
 (0)