Skip to content

Commit

Permalink
Merge pull request #6 from bluemax75/master
Browse files Browse the repository at this point in the history
Add PublicKey Authentication
  • Loading branch information
ba0f3 authored May 13, 2021
2 parents 6c3af2e + 88dd247 commit 4366e8c
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 4 deletions.
8 changes: 6 additions & 2 deletions src/ssh2.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncdispatch, asyncnet, strformat
from libssh2 import init, free, exit
import ssh2/private/[agent, channel, types, session]
export SSHException, AuthenticationException

export agent, channel, types, session

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

proc connect*(s: SSHClient, hostname: string, username: string, port = Port(22), password = "", useAgent = false) {.async.} =
proc connect*(s: SSHClient, hostname: string, username: string, port = Port(22), password = "", pkey = "", useAgent = false) {.async.} =
s.socket = newAsyncSocket()
await s.socket.connect(hostname, port)
s.session = initSession()
Expand All @@ -34,7 +35,10 @@ proc connect*(s: SSHClient, hostname: string, username: string, port = Port(22),
break
agent.close()
else:
discard s.session.authPassword(username, password)
if pkey.len != 0:
discard s.session.authPublicKey(username, pkey, password)
else:
discard s.session.authPassword(username, password)

proc execCommand*(s: SSHClient, command: string): Future[(string, string, int)] {.async.} =
var channel = initChannel(s)
Expand Down
16 changes: 14 additions & 2 deletions src/ssh2/private/session.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import libssh2, types, strformat, posix
import os, libssh2, types, strformat, posix

proc initSession*(): Session =
result = session_init()
Expand Down Expand Up @@ -26,6 +26,18 @@ proc authPassword*(session: Session, username, password: string): bool =
break
result = true

proc authPublicKey*(session: Session; username, pkey: string, passphrase = ""): bool =
let pkey = expandTilde(pkey)
while true:
let rc = session.userauth_publickey_from_file(username, nil, pkey, passphrase)
if rc == LIBSSH2_ERROR_EAGAIN:
discard
elif rc < 0:
raise newException(AuthenticationException, &"Authentication with privateKey {pkey} failed!")
else:
break
result = true

proc getLastError*(session: Session): (string, int) =
var
errmsg: cstring
Expand All @@ -40,4 +52,4 @@ proc getLastErrorMessage*(session: Session): string =
proc close*(session: Session) =
while session.session_disconnect("libssh2 wrapper for Nim, libssh2.nim/core") == LIBSSH2_ERROR_EAGAIN:
discard
discard session.session_free()
discard session.session_free()
9 changes: 9 additions & 0 deletions tests/test_exec_pkey.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import asyncdispatch, ssh2, ssh2/scp

proc main() {.async.} =
var client = newSSHClient()
defer: client.disconnect()
await client.connect("127.0.0.1", "nim", Port(22), pkey="~/.ssh/id_rsa", password="secret")
echo await client.execCommand("uptime")

waitFor main()

0 comments on commit 4366e8c

Please sign in to comment.