Index: build/tcl/ssh-agent.tcl ================================================================== --- build/tcl/ssh-agent.tcl +++ build/tcl/ssh-agent.tcl @@ -1,15 +1,21 @@ #! /usr/bin/env tclsh + +set dir [file dirname [info script]] if {[info exists ::env(SSH_AGENT_LIB_PATH)]} { lappend auto_path {*}$::env(SSH_AGENT_LIB_PATH) } + +if {![info exists ::env(SSH_AUTH_SOCK)]} { + error "Must set SSH_AUTH_SOCK" +} if {[info exists ::env(SSH_AGENT_PKCS11_MODULE)]} { set ::pkcs11ModuleFilename $::env(SSH_AGENT_PKCS11_MODULE) } else { - set ::pkcs11ModuleFilename /home/rkeene/tmp/cackey/build/tcl/softokn3-pkcs11.so + error "Must set SSH_AGENT_PKCS11_MODULE" } package require duktape 0.7 package require tuapi package require pki 0.6 @@ -26,10 +32,19 @@ "set ret(raw) $cert_seq; binary scan $ret(raw) H* ret(raw); ::asn::asnGetSequence cert_seq wholething" } $body] proc $procToUpdate [info args $procToUpdate] $body } }} + +proc pkcs11ModuleLogin {slot} { + set pin [exec cackey-askpass] + if {$pin eq ""} { + error "No PIN provided" + } + + ::pki::pkcs11::login $::pkcs11ModuleHandle $slot $pin +} proc pkcs11ModuleHandle {} { if {![info exists ::pkcs11ModuleHandle]} { set ::pkcs11ModuleHandle [::pki::pkcs11::loadmodule $::pkcs11ModuleFilename] } @@ -82,10 +97,16 @@ return $retval } ::duktape::tcl-function $jsHandle __crypto_subtle_digest bytearray {hash data} { switch -exact -- $hash { + "SHA-512" { + set data_b64 [binary encode base64 $data] + set checksum [exec base64 -d << $data_b64 | sha512sum] + set checksum [lindex [split $checksum] 0] + return [binary decode hex $checksum] + } "SHA-256" { package require sha256 return [::sha2::sha256 -- $data] } "SHA-1" { @@ -133,10 +154,11 @@ delete __parseCert; } } proc readFile {fileName} { + set fileName [file join $::dir $fileName] if {![info exists ::readFile($fileName)]} { catch { set fd [open $fileName] set ::readFile($fileName) [read $fd] } @@ -174,11 +196,11 @@ ::duktape::eval $jsHandle {var goog = {DEBUG: false};} ::duktape::eval $jsHandle [readFile chrome-emu.js] addRSAToJS $jsHandle ::duktape::eval $jsHandle [readFile ssh-agent-noasync.js] ::duktape::eval $jsHandle {cackeySSHAgentFeatures.enabled = true;} - ::duktape::eval $jsHandle {cackeySSHAgentFeatures.includeCerts = false;} + ::duktape::eval $jsHandle {cackeySSHAgentFeatures.includeCerts = true;} ::duktape::eval $jsHandle {cackeySSHAgentFeatures.legacy = false;} ::duktape::eval $jsHandle { function connection(callback) { this.sender = { id: "pnhechapfaindjhompbnflcldabbghjo" @@ -314,18 +336,25 @@ pkcs11ModuleUnload $handle return -code error "Unable to find certificate to sign with" } set slotId [dict get $certInfo pkcs11_slotid] - set data [::pki::sign $message $certInfo raw] + try { + set data [::pki::sign $message $certInfo raw] + } on error {} { + pkcs11ModuleLogin $slotId + + set data [::pki::sign $message $certInfo raw] + } return $data } - ::duktape::tcl-function $jsHandle cackeyListCertificatesBare {arraylist bytearray} {} { + ::duktape::tcl-function $jsHandle cackeyListCertificatesBare {array bytearray} {} { set handle [pkcs11ModuleHandle] - return [listCerts $handle] + set retval [listCerts $handle] + return $retval } return $jsHandle } @@ -335,10 +364,15 @@ set slots [::pki::pkcs11::listslots $handle] foreach slotInfo $slots { set slotId [lindex $slotInfo 0] set slotLabel [lindex $slotInfo 1] set slotFlags [lindex $slotInfo 2] + + # Skip missing tokens + if {"TOKEN_PRESENT" ni $slotFlags} { + continue + } set slotCerts [::pki::pkcs11::listcerts $handle $slotId] foreach keyList $slotCerts { set cert [dict get $keyList raw] set cert [binary decode hex $cert] @@ -348,11 +382,15 @@ lappend certs $cert } } if {$match ne ""} { - return [list] + set certs [list] + } + + if {[llength $certs] == 0} { + pkcs11ModuleUnload $handle } return $certs } @@ -382,8 +420,8 @@ puts stderr "ERROR: $::errorInfo" close $sock } } -::tuapi::syscall::socket_unix -server incomingConnection "./agent" +::tuapi::syscall::socket_unix -server incomingConnection $::env(SSH_AUTH_SOCK) vwait forever