Skip to content

Instantly share code, notes, and snippets.

@bartojs
Last active December 3, 2015 00:30
Show Gist options
  • Save bartojs/bc6b503a0847e46359a4 to your computer and use it in GitHub Desktop.
Save bartojs/bc6b503a0847e46359a4 to your computer and use it in GitHub Desktop.
sftp with publickey using apache-sshd
;; 1) download this build.boot file
;; 2) download & install http://boot-clj.com
;; 3) cp ~/.ssh/id_rsa.pub authorized_keys
;; 4) boot run
;; -- this will run the server for a minute on port 2222
;; 5) test with scp -v -i ~/.ssh/id_rsa -P 2222 mytestfile-original.txt localhost:mytestfile-transferred.txt
;; 6) check scp output for which keys are sent - remember to check if ssh-agent is running (which will cache keys)
(set-env! :dependencies '[[org.apache.sshd/sshd-core "0.9.0"]
[org.apache.sshd/sshd-sftp "0.9.0"]])
(require '[clojure.java.io :as io])
(import org.apache.sshd.SshServer
org.apache.sshd.sftp.subsystem.SftpSubsystem$Factory
org.apache.sshd.server.command.ScpCommandFactory
org.apache.sshd.server.auth.UserAuthPublicKey$Factory
org.apache.sshd.server.PublickeyAuthenticator
org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider
org.apache.mina.util.Base64
java.nio.ByteBuffer
[java.security KeyFactory PublicKey]
[java.security.interfaces RSAPublicKey DSAPublicKey]
[java.security.spec DSAPublicKeySpec RSAPublicKeySpec])
(defn readbytes [buf]
(let [bytearray (byte-array (.getInt buf))]
(.get buf bytearray)
bytearray))
(defn readbigint [buf]
(-> buf (readbytes) (BigInteger.)))
(defn linebuf [line]
(let [buf (-> line (.split " ") (first) (.getBytes) (Base64/decodeBase64) (ByteBuffer/wrap))]
(readbytes buf)
buf))
(defn parse-rsa [line]
(let [buf (linebuf line)
exp (readbigint buf)
mod (readbigint buf)]
(.generatePublic (KeyFactory/getInstance "RSA") (RSAPublicKeySpec. mod exp))))
(defn parse-dsa [line]
(let [buf (linebuf line)
p (readbigint buf)
q (readbigint buf)
g (readbigint buf)
y (readbigint buf)]
(.generatePublic (KeyFactory/getInstance "DSA") (DSAPublicKeySpec. y p q g))))
(defn parse-key [line]
(let [l (.trim line)]
(println "authorized key " l)
(cond (.startsWith l "ssh-rsa ") (parse-rsa (subs l 8))
(.startsWith l "ssh-dsa ") (parse-dsa (subs l 8))
(.startsWith l "ssh-dss ") (parse-dsa (subs l 8))
:else nil)))
(defn samekey? [k1 k2]
(or (and
(instance? RSAPublicKey k1)
(instance? RSAPublicKey k2)
(= (.getModulus k1) (.getModulus k2))
(= (.getPublicExponent k1) (.getPublicExponent k2)))
(and
(instance? DSAPublicKey k1)
(instance? DSAPublicKey k2)
(= (.getY k1) (.getY k2))
(= (.getP (.getParams k1)) (.getP (.getParams k2)))
(= (.getQ (.getParams k1)) (.getQ (.getParams k2)))
(= (.getG (.getParams k1)) (.getG (.getParams k2))))))
(defn auth [user pk]
(let [ks (keep parse-key (line-seq (io/reader "authorized_keys")))]
(some (partial samekey? pk) ks)))
(def sshd (doto (SshServer/setUpDefaultServer)
(.setPort 2222)
(.setKeyPairProvider (SimpleGeneratorHostKeyProvider. "sshd.ser"))
(.setSubsystemFactories [(SftpSubsystem$Factory.)])
(.setCommandFactory (ScpCommandFactory.))
(.setUserAuthFactories [(UserAuthPublicKey$Factory.)])
(.setPublickeyAuthenticator (reify PublickeyAuthenticator (authenticate [this user publickey session] (auth user publickey))))))
(deftask run []
(.start sshd)
(Thread/sleep 60000))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment