Hex Artifact Content

Artifact 195a50ba5e9e2d254f1e3dbcce2700ae110499c3:


0000: 23 21 20 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20  #! /usr/bin/env 
0010: 74 63 6c 73 68 0a 0a 73 65 74 20 70 61 73 73 77  tclsh..set passw
0020: 6f 72 64 46 69 6c 65 20 5b 6c 69 6e 64 65 78 20  ordFile [lindex 
0030: 24 61 72 67 76 20 30 5d 0a 73 65 74 20 61 63 74  $argv 0].set act
0040: 69 6f 6e 20 5b 6c 69 6e 64 65 78 20 24 61 72 67  ion [lindex $arg
0050: 76 20 31 5d 0a 0a 73 65 74 20 76 61 6c 69 64 43  v 1]..set validC
0060: 6f 6d 6d 61 6e 64 73 20 5b 6c 69 73 74 20 22 6c  ommands [list "l
0070: 69 73 74 4c 6f 63 61 6c 4b 65 79 73 22 20 22 6c  istLocalKeys" "l
0080: 69 73 74 50 61 73 73 77 6f 72 64 73 22 20 22 6c  istPasswords" "l
0090: 69 73 74 41 76 61 69 6c 61 62 6c 65 50 61 73 73  istAvailablePass
00a0: 77 6f 72 64 73 22 20 22 6c 69 73 74 55 73 65 72  words" "listUser
00b0: 73 22 20 22 61 64 64 55 73 65 72 22 20 22 61 64  s" "addUser" "ad
00c0: 64 50 61 73 73 77 6f 72 64 22 20 22 61 75 74 68  dPassword" "auth
00d0: 6f 72 69 7a 65 55 73 65 72 22 20 22 61 75 74 68  orizeUser" "auth
00e0: 6f 72 69 7a 65 55 73 65 72 73 22 20 22 64 65 61  orizeUsers" "dea
00f0: 75 74 68 6f 72 69 7a 65 55 73 65 72 22 20 22 64  uthorizeUser" "d
0100: 65 61 75 74 68 6f 72 69 7a 65 55 73 65 72 73 22  eauthorizeUsers"
0110: 20 22 67 65 74 50 61 73 73 77 6f 72 64 22 20 22   "getPassword" "
0120: 75 70 64 61 74 65 50 61 73 73 77 6f 72 64 22 20  updatePassword" 
0130: 22 64 65 6c 65 74 65 50 61 73 73 77 6f 72 64 22  "deletePassword"
0140: 20 22 68 65 6c 70 22 5d 0a 0a 70 72 6f 63 20 5f   "help"]..proc _
0150: 61 72 67 44 65 73 63 72 69 70 74 69 6f 6e 20 7b  argDescription {
0160: 63 6f 6d 6d 61 6e 64 20 61 72 67 4e 61 6d 65 7d  command argName}
0170: 20 7b 0a 09 73 77 69 74 63 68 20 2d 2d 20 24 61   {..switch -- $a
0180: 72 67 4e 61 6d 65 20 7b 0a 09 09 22 70 61 73 73  rgName {..."pass
0190: 77 6f 72 64 4e 61 6d 65 22 20 7b 0a 09 09 09 72  wordName" {....r
01a0: 65 74 75 72 6e 20 22 24 61 72 67 4e 61 6d 65 20  eturn "$argName 
01b0: 2d 20 4e 61 6d 65 20 6f 66 20 74 68 65 20 70 61  - Name of the pa
01c0: 73 73 77 6f 72 64 20 65 6e 74 72 79 22 0a 09 09  ssword entry"...
01d0: 7d 0a 09 09 22 6b 65 79 22 20 7b 0a 09 09 09 72  }..."key" {....r
01e0: 65 74 75 72 6e 20 22 24 61 72 67 4e 61 6d 65 20  eturn "$argName 
01f0: 2d 20 50 75 62 6c 69 63 20 6b 65 79 20 6f 66 20  - Public key of 
0200: 74 68 65 20 75 73 65 72 22 0a 09 09 7d 0a 09 09  the user"...}...
0210: 22 70 61 73 73 77 6f 72 64 22 20 7b 0a 09 09 09  "password" {....
0220: 72 65 74 75 72 6e 20 22 24 61 72 67 4e 61 6d 65  return "$argName
0230: 20 2d 20 41 20 70 6c 61 69 6e 2d 74 65 78 74 20   - A plain-text 
0240: 70 61 73 73 77 6f 72 64 22 0a 09 09 7d 0a 09 09  password"...}...
0250: 22 75 73 65 72 4e 61 6d 65 22 20 7b 0a 09 09 09  "userName" {....
0260: 72 65 74 75 72 6e 20 22 24 61 72 67 4e 61 6d 65  return "$argName
0270: 20 2d 20 41 20 75 73 65 72 20 6e 61 6d 65 22 0a   - A user name".
0280: 09 09 7d 0a 09 09 22 61 63 74 69 6f 6e 22 20 7b  ..}..."action" {
0290: 0a 09 09 09 72 65 74 75 72 6e 20 22 24 61 72 67  ....return "$arg
02a0: 4e 61 6d 65 20 2d 20 41 6e 20 61 63 74 69 6f 6e  Name - An action
02b0: 20 6e 61 6d 65 20 66 6f 72 20 68 65 6c 70 20 77   name for help w
02c0: 69 74 68 22 0a 09 09 7d 0a 09 09 22 61 72 67 73  ith"...}..."args
02d0: 22 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 22 75  " {....return "u
02e0: 73 65 72 4c 69 73 74 20 2d 20 41 20 6c 69 73 74  serList - A list
02f0: 20 6f 66 20 75 73 65 72 6e 61 6d 65 73 22 0a 09   of usernames"..
0300: 09 7d 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 20 22  .}..}...return "
0310: 3c 55 4e 4b 4e 4f 57 4e 3e 22 0a 7d 0a 0a 70 72  <UNKNOWN>".}..pr
0320: 6f 63 20 5f 70 72 69 6e 74 48 65 6c 70 20 7b 63  oc _printHelp {c
0330: 68 61 6e 6e 65 6c 20 63 6f 6d 6d 61 6e 64 7d 20  hannel command} 
0340: 7b 0a 09 69 66 20 7b 24 63 6f 6d 6d 61 6e 64 20  {..if {$command 
0350: 3d 3d 20 22 22 7d 20 7b 0a 09 09 70 75 74 73 20  == ""} {...puts 
0360: 24 63 68 61 6e 6e 65 6c 20 22 55 73 61 67 65 3a  $channel "Usage:
0370: 20 68 75 6e 74 65 72 32 20 3c 70 61 73 73 77 6f   hunter2 <passwo
0380: 72 64 46 69 6c 65 3e 20 3c 61 63 74 69 6f 6e 3e  rdFile> <action>
0390: 20 5c 5b 3c 61 63 74 69 6f 6e 41 72 67 73 2e 2e   \[<actionArgs..
03a0: 2e 3e 5c 5d 22 0a 09 09 70 75 74 73 20 24 63 68  .>\]"...puts $ch
03b0: 61 6e 6e 65 6c 20 22 22 0a 09 09 70 75 74 73 20  annel ""...puts 
03c0: 24 63 68 61 6e 6e 65 6c 20 22 41 63 74 69 6f 6e  $channel "Action
03d0: 73 3a 22 0a 09 09 70 75 74 73 20 24 63 68 61 6e  s:"...puts $chan
03e0: 6e 65 6c 20 22 20 20 20 20 5b 6a 6f 69 6e 20 24  nel "    [join $
03f0: 3a 3a 76 61 6c 69 64 43 6f 6d 6d 61 6e 64 73 20  ::validCommands 
0400: 7b 2c 20 7d 5d 22 0a 09 09 70 75 74 73 20 24 63  {, }]"...puts $c
0410: 68 61 6e 6e 65 6c 20 22 22 0a 09 09 70 75 74 73  hannel ""...puts
0420: 20 24 63 68 61 6e 6e 65 6c 20 22 20 20 20 20 68   $channel "    h
0430: 75 6e 74 65 72 32 20 3c 66 69 6c 65 3e 20 68 65  unter2 <file> he
0440: 6c 70 20 3c 61 63 74 69 6f 6e 3e 20 20 20 20 66  lp <action>    f
0450: 6f 72 20 68 65 6c 70 20 77 69 74 68 20 61 6e 20  or help with an 
0460: 61 63 74 69 6f 6e 22 0a 09 7d 20 65 6c 73 65 20  action"..} else 
0470: 7b 0a 09 09 73 65 74 20 61 72 67 73 20 5b 69 6e  {...set args [in
0480: 66 6f 20 61 72 67 73 20 24 63 6f 6d 6d 61 6e 64  fo args $command
0490: 5d 0a 09 09 73 65 74 20 70 72 69 6e 74 41 72 67  ]...set printArg
04a0: 73 20 5b 6c 69 73 74 5d 0a 09 09 66 6f 72 65 61  s [list]...forea
04b0: 63 68 20 61 72 67 20 24 61 72 67 73 20 7b 0a 09  ch arg $args {..
04c0: 09 09 69 66 20 7b 24 61 72 67 20 3d 3d 20 22 61  ..if {$arg == "a
04d0: 72 67 73 22 7d 20 7b 0a 09 09 09 09 73 65 74 20  rgs"} {.....set 
04e0: 61 72 67 20 22 75 73 65 72 4c 69 73 74 22 0a 09  arg "userList"..
04f0: 09 09 7d 0a 09 09 09 6c 61 70 70 65 6e 64 20 70  ..}....lappend p
0500: 72 69 6e 74 41 72 67 73 20 22 3c 24 61 72 67 3e  rintArgs "<$arg>
0510: 22 0a 09 09 7d 0a 0a 09 09 70 75 74 73 20 24 63  "...}....puts $c
0520: 68 61 6e 6e 65 6c 20 22 55 73 61 67 65 3a 20 68  hannel "Usage: h
0530: 75 6e 74 65 72 32 20 3c 70 61 73 73 77 6f 72 64  unter2 <password
0540: 46 69 6c 65 3e 20 24 63 6f 6d 6d 61 6e 64 20 5b  File> $command [
0550: 6a 6f 69 6e 20 24 70 72 69 6e 74 41 72 67 73 5d  join $printArgs]
0560: 22 0a 0a 09 09 69 66 20 7b 5b 6c 6c 65 6e 67 74  "....if {[llengt
0570: 68 20 24 61 72 67 73 5d 20 3e 20 30 7d 20 7b 0a  h $args] > 0} {.
0580: 09 09 09 70 75 74 73 20 24 63 68 61 6e 6e 65 6c  ...puts $channel
0590: 20 22 22 0a 09 09 09 70 75 74 73 20 24 63 68 61   ""....puts $cha
05a0: 6e 6e 65 6c 20 22 41 72 67 75 6d 65 6e 74 73 3a  nnel "Arguments:
05b0: 22 0a 09 09 09 66 6f 72 65 61 63 68 20 61 72 67  "....foreach arg
05c0: 20 24 61 72 67 73 20 7b 0a 09 09 09 09 70 75 74   $args {.....put
05d0: 73 20 24 63 68 61 6e 6e 65 6c 20 22 20 20 20 20  s $channel "    
05e0: 5b 5f 61 72 67 44 65 73 63 72 69 70 74 69 6f 6e  [_argDescription
05f0: 20 24 63 6f 6d 6d 61 6e 64 20 24 61 72 67 5d 22   $command $arg]"
0600: 0a 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a 7d 0a 0a  ....}...}..}.}..
0610: 69 66 20 7b 5b 6c 6c 65 6e 67 74 68 20 24 61 72  if {[llength $ar
0620: 67 76 5d 20 3c 20 32 7d 20 7b 0a 09 5f 70 72 69  gv] < 2} {.._pri
0630: 6e 74 48 65 6c 70 20 73 74 64 65 72 72 20 22 22  ntHelp stderr ""
0640: 0a 0a 09 65 78 69 74 20 31 0a 7d 0a 0a 73 65 74  ...exit 1.}..set
0650: 20 61 72 67 76 20 5b 6c 72 61 6e 67 65 20 24 61   argv [lrange $a
0660: 72 67 76 20 32 20 65 6e 64 5d 0a 0a 70 61 63 6b  rgv 2 end]..pack
0670: 61 67 65 20 72 65 71 75 69 72 65 20 73 71 6c 69  age require sqli
0680: 74 65 33 0a 70 61 63 6b 61 67 65 20 72 65 71 75  te3.package requ
0690: 69 72 65 20 70 6c 61 74 66 6f 72 6d 0a 0a 6c 61  ire platform..la
06a0: 70 70 65 6e 64 20 3a 3a 61 75 74 6f 5f 70 61 74  ppend ::auto_pat
06b0: 68 20 5b 66 69 6c 65 20 6a 6f 69 6e 20 5b 66 69  h [file join [fi
06c0: 6c 65 20 64 69 72 6e 61 6d 65 20 5b 69 6e 66 6f  le dirname [info
06d0: 20 73 63 72 69 70 74 5d 5d 20 6c 69 62 20 5b 70   script]] lib [p
06e0: 6c 61 74 66 6f 72 6d 3a 3a 69 64 65 6e 74 69 66  latform::identif
06f0: 79 5d 5d 0a 6c 61 70 70 65 6e 64 20 3a 3a 61 75  y]].lappend ::au
0700: 74 6f 5f 70 61 74 68 20 5b 66 69 6c 65 20 6a 6f  to_path [file jo
0710: 69 6e 20 5b 66 69 6c 65 20 64 69 72 6e 61 6d 65  in [file dirname
0720: 20 5b 69 6e 66 6f 20 73 63 72 69 70 74 5d 5d 20   [info script]] 
0730: 6c 69 62 20 5b 70 6c 61 74 66 6f 72 6d 3a 3a 67  lib [platform::g
0740: 65 6e 65 72 69 63 5d 5d 0a 6c 61 70 70 65 6e 64  eneric]].lappend
0750: 20 3a 3a 61 75 74 6f 5f 70 61 74 68 20 5b 66 69   ::auto_path [fi
0760: 6c 65 20 6a 6f 69 6e 20 5b 66 69 6c 65 20 64 69  le join [file di
0770: 72 6e 61 6d 65 20 5b 69 6e 66 6f 20 73 63 72 69  rname [info scri
0780: 70 74 5d 5d 20 6c 69 62 5d 0a 0a 70 61 63 6b 61  pt]] lib]..packa
0790: 67 65 20 72 65 71 75 69 72 65 20 70 6b 69 0a 70  ge require pki.p
07a0: 61 63 6b 61 67 65 20 72 65 71 75 69 72 65 20 70  ackage require p
07b0: 6b 69 3a 3a 70 6b 63 73 31 31 0a 70 61 63 6b 61  ki::pkcs11.packa
07c0: 67 65 20 72 65 71 75 69 72 65 20 61 65 73 0a 0a  ge require aes..
07d0: 23 20 42 61 63 6b 70 6f 72 74 73 20 66 6f 72 20  # Backports for 
07e0: 6f 6c 64 65 72 20 76 65 72 73 69 6f 6e 73 20 6f  older versions o
07f0: 66 20 22 70 6b 69 22 0a 70 72 6f 63 20 3a 3a 70  f "pki".proc ::p
0800: 6b 69 3a 3a 70 6b 63 73 3a 3a 70 61 72 73 65 5f  ki::pkcs::parse_
0810: 70 75 62 6c 69 63 5f 6b 65 79 20 7b 6b 65 79 20  public_key {key 
0820: 7b 70 61 73 73 77 6f 72 64 20 22 22 7d 7d 20 7b  {password ""}} {
0830: 0a 20 20 20 20 20 20 20 20 61 72 72 61 79 20 73  .        array s
0840: 65 74 20 70 61 72 73 65 64 5f 6b 65 79 20 5b 3a  et parsed_key [:
0850: 3a 70 6b 69 3a 3a 5f 70 61 72 73 65 5f 70 65 6d  :pki::_parse_pem
0860: 20 24 6b 65 79 20 22 2d 2d 2d 2d 2d 42 45 47 49   $key "-----BEGI
0870: 4e 20 50 55 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d  N PUBLIC KEY----
0880: 2d 22 20 22 2d 2d 2d 2d 2d 45 4e 44 20 50 55 42  -" "-----END PUB
0890: 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d 22 20 24 70  LIC KEY-----" $p
08a0: 61 73 73 77 6f 72 64 5d 0a 0a 20 20 20 20 20 20  assword]..      
08b0: 20 20 73 65 74 20 6b 65 79 5f 73 65 71 20 24 70    set key_seq $p
08c0: 61 72 73 65 64 5f 6b 65 79 28 64 61 74 61 29 0a  arsed_key(data).
08d0: 0a 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a  .        ::asn::
08e0: 61 73 6e 47 65 74 53 65 71 75 65 6e 63 65 20 6b  asnGetSequence k
08f0: 65 79 5f 73 65 71 20 70 75 62 6b 65 79 69 6e 66  ey_seq pubkeyinf
0900: 6f 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  o.              
0910: 20 20 3a 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 53    ::asn::asnGetS
0920: 65 71 75 65 6e 63 65 20 70 75 62 6b 65 79 69 6e  equence pubkeyin
0930: 66 6f 20 70 75 62 6b 65 79 5f 61 6c 67 6f 69 64  fo pubkey_algoid
0940: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
0950: 20 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a           ::asn::
0960: 61 73 6e 47 65 74 4f 62 6a 65 63 74 49 64 65 6e  asnGetObjectIden
0970: 74 69 66 69 65 72 20 70 75 62 6b 65 79 5f 61 6c  tifier pubkey_al
0980: 67 6f 69 64 20 6f 69 64 0a 20 20 20 20 20 20 20  goid oid.       
0990: 20 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a           ::asn::
09a0: 61 73 6e 47 65 74 42 69 74 53 74 72 69 6e 67 20  asnGetBitString 
09b0: 70 75 62 6b 65 79 69 6e 66 6f 20 70 75 62 6b 65  pubkeyinfo pubke
09c0: 79 0a 20 20 20 20 20 20 20 20 73 65 74 20 72 65  y.        set re
09d0: 74 28 70 75 62 6b 65 79 5f 61 6c 67 6f 29 20 5b  t(pubkey_algo) [
09e0: 3a 3a 70 6b 69 3a 3a 5f 6f 69 64 5f 6e 75 6d 62  ::pki::_oid_numb
09f0: 65 72 5f 74 6f 5f 6e 61 6d 65 20 24 6f 69 64 5d  er_to_name $oid]
0a00: 0a 0a 20 20 20 20 20 20 20 20 73 77 69 74 63 68  ..        switch
0a10: 20 2d 2d 20 24 72 65 74 28 70 75 62 6b 65 79 5f   -- $ret(pubkey_
0a20: 61 6c 67 6f 29 20 7b 0a 20 20 20 20 20 20 20 20  algo) {.        
0a30: 20 20 20 20 20 20 20 20 22 72 73 61 45 6e 63 72          "rsaEncr
0a40: 79 70 74 69 6f 6e 22 20 7b 0a 20 20 20 20 20 20  yption" {.      
0a50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0a60: 20 20 73 65 74 20 70 75 62 6b 65 79 20 5b 62 69    set pubkey [bi
0a70: 6e 61 72 79 20 66 6f 72 6d 61 74 20 42 2a 20 24  nary format B* $
0a80: 70 75 62 6b 65 79 5d 0a 0a 20 20 20 20 20 20 20  pubkey]..       
0a90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0aa0: 20 3a 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 53 65   ::asn::asnGetSe
0ab0: 71 75 65 6e 63 65 20 70 75 62 6b 65 79 20 70 75  quence pubkey pu
0ac0: 62 6b 65 79 5f 70 61 72 74 73 0a 20 20 20 20 20  bkey_parts.     
0ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ae0: 20 20 20 20 20 20 20 20 20 20 20 3a 3a 61 73 6e             ::asn
0af0: 3a 3a 61 73 6e 47 65 74 42 69 67 49 6e 74 65 67  ::asnGetBigInteg
0b00: 65 72 20 70 75 62 6b 65 79 5f 70 61 72 74 73 20  er pubkey_parts 
0b10: 72 65 74 28 6e 29 0a 20 20 20 20 20 20 20 20 20  ret(n).         
0b20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0b30: 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61 73         ::asn::as
0b40: 6e 47 65 74 42 69 67 49 6e 74 65 67 65 72 20 70  nGetBigInteger p
0b50: 75 62 6b 65 79 5f 70 61 72 74 73 20 72 65 74 28  ubkey_parts ret(
0b60: 65 29 0a 0a 20 20 20 20 20 20 20 20 20 20 20 20  e)..            
0b70: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 74 20              set 
0b80: 72 65 74 28 6e 29 20 5b 3a 3a 6d 61 74 68 3a 3a  ret(n) [::math::
0b90: 62 69 67 6e 75 6d 3a 3a 74 6f 73 74 72 20 24 72  bignum::tostr $r
0ba0: 65 74 28 6e 29 5d 0a 20 20 20 20 20 20 20 20 20  et(n)].         
0bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
0bc0: 65 74 20 72 65 74 28 65 29 20 5b 3a 3a 6d 61 74  et ret(e) [::mat
0bd0: 68 3a 3a 62 69 67 6e 75 6d 3a 3a 74 6f 73 74 72  h::bignum::tostr
0be0: 20 24 72 65 74 28 65 29 5d 0a 20 20 20 20 20 20   $ret(e)].      
0bf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0c00: 20 20 73 65 74 20 72 65 74 28 6c 29 20 5b 65 78    set ret(l) [ex
0c10: 70 72 20 7b 69 6e 74 28 5b 3a 3a 70 6b 69 3a 3a  pr {int([::pki::
0c20: 5f 62 69 74 73 20 24 72 65 74 28 6e 29 5d 20 2f  _bits $ret(n)] /
0c30: 20 38 2e 30 30 30 30 20 2b 20 30 2e 35 29 20 2a   8.0000 + 0.5) *
0c40: 20 38 7d 5d 0a 20 20 20 20 20 20 20 20 20 20 20   8}].           
0c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65 74               set
0c60: 20 72 65 74 28 74 79 70 65 29 20 72 73 61 0a 20   ret(type) rsa. 
0c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7d                 }
0c80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
0c90: 20 64 65 66 61 75 6c 74 20 7b 0a 20 20 20 20 20   default {.     
0ca0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0cb0: 20 20 20 65 72 72 6f 72 20 22 55 6e 6b 6e 6f 77     error "Unknow
0cc0: 6e 20 61 6c 67 6f 72 69 74 68 6d 22 0a 20 20 20  n algorithm".   
0cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 7d 0a 20               }. 
0ce0: 20 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20         }..      
0cf0: 20 20 72 65 74 75 72 6e 20 5b 61 72 72 61 79 20    return [array 
0d00: 67 65 74 20 72 65 74 5d 0a 7d 0a 0a 70 72 6f 63  get ret].}..proc
0d10: 20 3a 3a 70 6b 69 3a 3a 72 73 61 3a 3a 73 65 72   ::pki::rsa::ser
0d20: 69 61 6c 69 7a 65 5f 70 75 62 6c 69 63 5f 6b 65  ialize_public_ke
0d30: 79 20 7b 6b 65 79 6c 69 73 74 7d 20 7b 0a 20 20  y {keylist} {.  
0d40: 20 20 20 20 20 20 61 72 72 61 79 20 73 65 74 20        array set 
0d50: 6b 65 79 20 24 6b 65 79 6c 69 73 74 0a 0a 20 20  key $keylist..  
0d60: 20 20 20 20 20 20 66 6f 72 65 61 63 68 20 65 6e        foreach en
0d70: 74 72 79 20 5b 6c 69 73 74 20 6e 20 65 5d 20 7b  try [list n e] {
0d80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
0d90: 20 69 66 20 7b 21 5b 69 6e 66 6f 20 65 78 69 73   if {![info exis
0da0: 74 73 20 6b 65 79 28 24 65 6e 74 72 79 29 5d 7d  ts key($entry)]}
0db0: 20 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   {.             
0dc0: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
0dd0: 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 4b  n -code error "K
0de0: 65 79 20 64 6f 65 73 20 6e 6f 74 20 63 6f 6e 74  ey does not cont
0df0: 61 69 6e 20 61 6e 20 65 6c 65 6d 65 6e 74 20 24  ain an element $
0e00: 65 6e 74 72 79 22 0a 20 20 20 20 20 20 20 20 20  entry".         
0e10: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20         }.       
0e20: 20 7d 0a 0a 20 20 20 20 20 20 20 20 73 65 74 20   }..        set 
0e30: 70 75 62 6b 65 79 20 5b 3a 3a 61 73 6e 3a 3a 61  pubkey [::asn::a
0e40: 73 6e 53 65 71 75 65 6e 63 65 20 5c 0a 20 20 20  snSequence \.   
0e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 5b 3a 3a               [::
0e60: 61 73 6e 3a 3a 61 73 6e 42 69 67 49 6e 74 65 67  asn::asnBigInteg
0e70: 65 72 20 5b 3a 3a 6d 61 74 68 3a 3a 62 69 67 6e  er [::math::bign
0e80: 75 6d 3a 3a 66 72 6f 6d 73 74 72 20 24 6b 65 79  um::fromstr $key
0e90: 28 6e 29 5d 5d 20 5c 0a 20 20 20 20 20 20 20 20  (n)]] \.        
0ea0: 20 20 20 20 20 20 20 20 5b 3a 3a 61 73 6e 3a 3a          [::asn::
0eb0: 61 73 6e 42 69 67 49 6e 74 65 67 65 72 20 5b 3a  asnBigInteger [:
0ec0: 3a 6d 61 74 68 3a 3a 62 69 67 6e 75 6d 3a 3a 66  :math::bignum::f
0ed0: 72 6f 6d 73 74 72 20 24 6b 65 79 28 65 29 5d 5d  romstr $key(e)]]
0ee0: 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   \.             
0ef0: 20 20 20 5d 20 20 0a 20 20 20 20 20 20 20 20 73     ]  .        s
0f00: 65 74 20 70 75 62 6b 65 79 5f 61 6c 67 6f 5f 70  et pubkey_algo_p
0f10: 61 72 61 6d 73 20 5b 3a 3a 61 73 6e 3a 3a 61 73  arams [::asn::as
0f20: 6e 4e 75 6c 6c 5d 0a 0a 20 20 20 20 20 20 20 20  nNull]..        
0f30: 62 69 6e 61 72 79 20 73 63 61 6e 20 24 70 75 62  binary scan $pub
0f40: 6b 65 79 20 42 2a 20 70 75 62 6b 65 79 5f 62 69  key B* pubkey_bi
0f50: 74 73 74 72 69 6e 67 0a 0a 20 20 20 20 20 20 20  tstring..       
0f60: 20 73 65 74 20 72 65 74 20 5b 3a 3a 61 73 6e 3a   set ret [::asn:
0f70: 3a 61 73 6e 53 65 71 75 65 6e 63 65 20 5c 0a 20  :asnSequence \. 
0f80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 5b                 [
0f90: 3a 3a 61 73 6e 3a 3a 61 73 6e 53 65 71 75 65 6e  ::asn::asnSequen
0fa0: 63 65 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20  ce \.           
0fb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0fc0: 20 20 20 20 20 5b 3a 3a 61 73 6e 3a 3a 61 73 6e       [::asn::asn
0fd0: 4f 62 6a 65 63 74 49 64 65 6e 74 69 66 69 65 72  ObjectIdentifier
0fe0: 20 5b 3a 3a 70 6b 69 3a 3a 5f 6f 69 64 5f 6e 61   [::pki::_oid_na
0ff0: 6d 65 5f 74 6f 5f 6e 75 6d 62 65 72 20 72 73 61  me_to_number rsa
1000: 45 6e 63 72 79 70 74 69 6f 6e 5d 5d 20 5c 0a 20  Encryption]] \. 
1010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1020: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 24                 $
1030: 70 75 62 6b 65 79 5f 61 6c 67 6f 5f 70 61 72 61  pubkey_algo_para
1040: 6d 73 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20  ms \.           
1050: 20 20 20 20 20 20 20 20 20 20 20 20 20 5d 20 5c               ] \
1060: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1070: 20 20 20 20 20 20 20 20 20 5b 3a 3a 61 73 6e 3a           [::asn:
1080: 3a 61 73 6e 42 69 74 53 74 72 69 6e 67 20 24 70  :asnBitString $p
1090: 75 62 6b 65 79 5f 62 69 74 73 74 72 69 6e 67 5d  ubkey_bitstring]
10a0: 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   \.             
10b0: 20 20 20 20 20 20 20 20 20 20 20 5d 0a 0a 20 20             ]..  
10c0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 6c 69        return [li
10d0: 73 74 20 64 61 74 61 20 24 72 65 74 20 62 65 67  st data $ret beg
10e0: 69 6e 20 22 2d 2d 2d 2d 2d 42 45 47 49 4e 20 50  in "-----BEGIN P
10f0: 55 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d 22 20  UBLIC KEY-----" 
1100: 65 6e 64 20 22 2d 2d 2d 2d 2d 45 4e 44 20 50 55  end "-----END PU
1110: 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d 22 5d 0a  BLIC KEY-----"].
1120: 7d 0a 23 20 45 6e 64 20 62 61 63 6b 70 6f 72 74  }.# End backport
1130: 73 0a 0a 23 20 53 74 61 72 74 20 69 6e 74 65 72  s..# Start inter
1140: 6e 61 6c 20 66 75 6e 63 74 69 6f 6e 73 0a 70 72  nal functions.pr
1150: 6f 63 20 5f 6c 69 73 74 43 65 72 74 69 66 69 63  oc _listCertific
1160: 61 74 65 73 20 7b 7d 20 7b 0a 09 69 66 20 7b 21  ates {} {..if {!
1170: 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 3a 3a 65  [info exists ::e
1180: 6e 76 28 50 4b 43 53 31 31 4d 4f 44 55 4c 45 29  nv(PKCS11MODULE)
1190: 5d 7d 20 7b 0a 09 09 72 65 74 75 72 6e 20 5b 6c  ]} {...return [l
11a0: 69 73 74 5d 0a 09 7d 0a 0a 09 73 65 74 20 3a 3a  ist]..}...set ::
11b0: 65 6e 76 28 43 41 43 4b 45 59 5f 4e 4f 5f 45 58  env(CACKEY_NO_EX
11c0: 54 52 41 5f 43 45 52 54 53 29 20 31 0a 0a 09 73  TRA_CERTS) 1...s
11d0: 65 74 20 68 61 6e 64 6c 65 20 5b 3a 3a 70 6b 69  et handle [::pki
11e0: 3a 3a 70 6b 63 73 31 31 3a 3a 6c 6f 61 64 6d 6f  ::pkcs11::loadmo
11f0: 64 75 6c 65 20 24 3a 3a 65 6e 76 28 50 4b 43 53  dule $::env(PKCS
1200: 31 31 4d 4f 44 55 4c 45 29 5d 0a 0a 09 73 65 74  11MODULE)]...set
1210: 20 73 6c 6f 74 49 6e 66 6f 20 5b 6c 69 73 74 5d   slotInfo [list]
1220: 0a 09 66 6f 72 65 61 63 68 20 73 6c 6f 74 20 5b  ..foreach slot [
1230: 3a 3a 70 6b 69 3a 3a 70 6b 63 73 31 31 3a 3a 6c  ::pki::pkcs11::l
1240: 69 73 74 73 6c 6f 74 73 20 24 68 61 6e 64 6c 65  istslots $handle
1250: 5d 20 7b 0a 09 09 73 65 74 20 73 6c 6f 74 49 44  ] {...set slotID
1260: 20 5b 6c 69 6e 64 65 78 20 24 73 6c 6f 74 20 30   [lindex $slot 0
1270: 5d 0a 09 09 73 65 74 20 73 6c 6f 74 4c 61 62 65  ]...set slotLabe
1280: 6c 20 5b 6c 69 6e 64 65 78 20 24 73 6c 6f 74 20  l [lindex $slot 
1290: 31 5d 0a 09 09 73 65 74 20 73 6c 6f 74 46 6c 61  1]...set slotFla
12a0: 67 73 20 5b 6c 69 6e 64 65 78 20 24 73 6c 6f 74  gs [lindex $slot
12b0: 20 32 5d 0a 0a 09 09 69 66 20 7b 22 54 4f 4b 45   2]....if {"TOKE
12c0: 4e 5f 50 52 45 53 45 4e 54 22 20 6e 69 20 24 73  N_PRESENT" ni $s
12d0: 6c 6f 74 46 6c 61 67 73 7d 20 7b 0a 09 09 09 63  lotFlags} {....c
12e0: 6f 6e 74 69 6e 75 65 0a 09 09 7d 0a 0a 09 09 69  ontinue...}....i
12f0: 66 20 7b 22 54 4f 4b 45 4e 5f 49 4e 49 54 49 41  f {"TOKEN_INITIA
1300: 4c 49 5a 45 44 22 20 6e 69 20 24 73 6c 6f 74 46  LIZED" ni $slotF
1310: 6c 61 67 73 7d 20 7b 0a 09 09 09 63 6f 6e 74 69  lags} {....conti
1320: 6e 75 65 0a 09 09 7d 0a 0a 09 09 73 65 74 20 73  nue...}....set s
1330: 6c 6f 74 50 72 6f 6d 70 74 46 6f 72 50 49 4e 20  lotPromptForPIN 
1340: 66 61 6c 73 65 0a 09 09 69 66 20 7b 22 50 52 4f  false...if {"PRO
1350: 54 45 43 54 45 44 5f 41 55 54 48 45 4e 54 49 43  TECTED_AUTHENTIC
1360: 41 54 49 4f 4e 5f 50 41 54 48 22 20 6e 69 20 24  ATION_PATH" ni $
1370: 73 6c 6f 74 46 6c 61 67 73 7d 20 7b 0a 09 09 09  slotFlags} {....
1380: 69 66 20 7b 22 4c 4f 47 49 4e 5f 52 45 51 55 49  if {"LOGIN_REQUI
1390: 52 45 44 22 20 69 6e 20 24 73 6c 6f 74 46 6c 61  RED" in $slotFla
13a0: 67 73 7d 20 7b 0a 09 09 09 09 73 65 74 20 73 6c  gs} {.....set sl
13b0: 6f 74 50 72 6f 6d 70 74 46 6f 72 50 49 4e 20 74  otPromptForPIN t
13c0: 72 75 65 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 09  rue....}...}....
13d0: 66 6f 72 65 61 63 68 20 63 65 72 74 20 5b 3a 3a  foreach cert [::
13e0: 70 6b 69 3a 3a 70 6b 63 73 31 31 3a 3a 6c 69 73  pki::pkcs11::lis
13f0: 74 63 65 72 74 73 20 24 68 61 6e 64 6c 65 20 24  tcerts $handle $
1400: 73 6c 6f 74 49 44 5d 20 7b 0a 09 09 09 73 65 74  slotID] {....set
1410: 20 70 75 62 6b 65 79 20 5b 62 69 6e 61 72 79 20   pubkey [binary 
1420: 65 6e 63 6f 64 65 20 62 61 73 65 36 34 20 5b 64  encode base64 [d
1430: 69 63 74 20 67 65 74 20 5b 3a 3a 70 6b 69 3a 3a  ict get [::pki::
1440: 72 73 61 3a 3a 73 65 72 69 61 6c 69 7a 65 5f 70  rsa::serialize_p
1450: 75 62 6c 69 63 5f 6b 65 79 20 24 63 65 72 74 5d  ublic_key $cert]
1460: 20 64 61 74 61 5d 5d 0a 0a 09 09 09 6c 61 70 70   data]].....lapp
1470: 65 6e 64 20 73 6c 6f 74 49 6e 66 6f 20 5b 6c 69  end slotInfo [li
1480: 73 74 20 68 61 6e 64 6c 65 20 24 68 61 6e 64 6c  st handle $handl
1490: 65 20 69 64 20 24 73 6c 6f 74 49 44 20 70 72 6f  e id $slotID pro
14a0: 6d 70 74 20 24 73 6c 6f 74 50 72 6f 6d 70 74 46  mpt $slotPromptF
14b0: 6f 72 50 49 4e 20 63 65 72 74 20 24 63 65 72 74  orPIN cert $cert
14c0: 20 70 75 62 6b 65 79 20 24 70 75 62 6b 65 79 5d   pubkey $pubkey]
14d0: 0a 09 09 7d 0a 09 7d 0a 0a 09 72 65 74 75 72 6e  ...}..}...return
14e0: 20 24 73 6c 6f 74 49 6e 66 6f 0a 7d 0a 0a 70 72   $slotInfo.}..pr
14f0: 6f 63 20 5f 61 64 64 50 61 73 73 77 6f 72 64 20  oc _addPassword 
1500: 7b 6e 61 6d 65 20 70 61 73 73 77 6f 72 64 20 70  {name password p
1510: 75 62 6c 69 63 4b 65 79 73 7d 20 7b 0a 09 73 65  ublicKeys} {..se
1520: 74 20 66 64 20 5b 6f 70 65 6e 20 22 2f 64 65 76  t fd [open "/dev
1530: 2f 75 72 61 6e 64 6f 6d 22 20 72 5d 0a 09 66 63  /urandom" r]..fc
1540: 6f 6e 66 69 67 75 72 65 20 24 66 64 20 2d 74 72  onfigure $fd -tr
1550: 61 6e 73 6c 61 74 69 6f 6e 20 62 69 6e 61 72 79  anslation binary
1560: 0a 0a 09 64 62 20 65 76 61 6c 20 7b 44 45 4c 45  ...db eval {DELE
1570: 54 45 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64  TE FROM password
1580: 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24  s WHERE name = $
1590: 6e 61 6d 65 3b 7d 0a 0a 09 66 6f 72 65 61 63 68  name;}...foreach
15a0: 20 70 75 62 6c 69 63 4b 65 79 20 24 70 75 62 6c   publicKey $publ
15b0: 69 63 4b 65 79 73 20 7b 0a 09 09 73 65 74 20 6b  icKeys {...set k
15c0: 65 79 20 5b 72 65 61 64 20 24 66 64 20 31 36 5d  ey [read $fd 16]
15d0: 0a 09 09 69 66 20 7b 5b 73 74 72 69 6e 67 20 6c  ...if {[string l
15e0: 65 6e 67 74 68 20 24 6b 65 79 5d 20 21 3d 20 31  ength $key] != 1
15f0: 36 7d 20 7b 0a 09 09 09 63 6c 6f 73 65 20 24 66  6} {....close $f
1600: 64 0a 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 6f  d.....return -co
1610: 64 65 20 65 72 72 6f 72 20 22 45 52 52 4f 52 3a  de error "ERROR:
1620: 20 53 68 6f 72 74 20 72 65 61 64 20 66 72 6f 6d   Short read from
1630: 20 72 61 6e 64 6f 6d 20 64 65 76 69 63 65 22 0a   random device".
1640: 09 09 7d 0a 0a 09 09 73 65 74 20 70 75 62 6c 69  ..}....set publi
1650: 63 4b 65 79 49 74 65 6d 20 5b 3a 3a 70 6b 69 3a  cKeyItem [::pki:
1660: 3a 70 6b 63 73 3a 3a 70 61 72 73 65 5f 70 75 62  :pkcs::parse_pub
1670: 6c 69 63 5f 6b 65 79 20 5b 62 69 6e 61 72 79 20  lic_key [binary 
1680: 64 65 63 6f 64 65 20 62 61 73 65 36 34 20 24 70  decode base64 $p
1690: 75 62 6c 69 63 4b 65 79 5d 5d 0a 0a 09 09 73 65  ublicKey]]....se
16a0: 74 20 65 6e 63 72 79 70 74 65 64 4b 65 79 20 5b  t encryptedKey [
16b0: 62 69 6e 61 72 79 20 65 6e 63 6f 64 65 20 62 61  binary encode ba
16c0: 73 65 36 34 20 5b 3a 3a 70 6b 69 3a 3a 65 6e 63  se64 [::pki::enc
16d0: 72 79 70 74 20 2d 70 75 62 20 2d 62 69 6e 61 72  rypt -pub -binar
16e0: 79 20 2d 2d 20 24 6b 65 79 20 24 70 75 62 6c 69  y -- $key $publi
16f0: 63 4b 65 79 49 74 65 6d 5d 5d 0a 0a 09 09 73 65  cKeyItem]]....se
1700: 74 20 65 6e 63 72 79 70 74 65 64 50 61 73 73 20  t encryptedPass 
1710: 5b 62 69 6e 61 72 79 20 65 6e 63 6f 64 65 20 62  [binary encode b
1720: 61 73 65 36 34 20 5b 3a 3a 61 65 73 3a 3a 61 65  ase64 [::aes::ae
1730: 73 20 2d 64 69 72 20 65 6e 63 72 79 70 74 20 2d  s -dir encrypt -
1740: 6b 65 79 20 24 6b 65 79 20 2d 2d 20 24 70 61 73  key $key -- $pas
1750: 73 77 6f 72 64 5d 5d 0a 0a 09 09 64 62 20 65 76  sword]]....db ev
1760: 61 6c 20 7b 49 4e 53 45 52 54 20 49 4e 54 4f 20  al {INSERT INTO 
1770: 70 61 73 73 77 6f 72 64 73 20 28 6e 61 6d 65 2c  passwords (name,
1780: 20 65 6e 63 72 79 70 74 65 64 50 61 73 73 2c 20   encryptedPass, 
1790: 65 6e 63 72 79 70 74 65 64 4b 65 79 2c 20 70 75  encryptedKey, pu
17a0: 62 6c 69 63 4b 65 79 29 20 56 41 4c 55 45 53 20  blicKey) VALUES 
17b0: 28 24 6e 61 6d 65 2c 20 40 65 6e 63 72 79 70 74  ($name, @encrypt
17c0: 65 64 50 61 73 73 2c 20 40 65 6e 63 72 79 70 74  edPass, @encrypt
17d0: 65 64 4b 65 79 2c 20 40 70 75 62 6c 69 63 4b 65  edKey, @publicKe
17e0: 79 29 3b 7d 0a 09 7d 0a 0a 09 63 6c 6f 73 65 20  y);}..}...close 
17f0: 24 66 64 0a 7d 0a 0a 70 72 6f 63 20 5f 70 72 6f  $fd.}..proc _pro
1800: 6d 70 74 20 7b 70 72 6f 6d 70 74 7d 20 7b 0a 09  mpt {prompt} {..
1810: 70 75 74 73 20 2d 6e 6f 6e 65 77 6c 69 6e 65 20  puts -nonewline 
1820: 24 70 72 6f 6d 70 74 0a 09 66 6c 75 73 68 20 73  $prompt..flush s
1830: 74 64 6f 75 74 0a 0a 09 70 75 74 73 20 2d 6e 6f  tdout...puts -no
1840: 6e 65 77 6c 69 6e 65 20 5b 65 78 65 63 20 73 74  newline [exec st
1850: 74 79 20 2d 65 63 68 6f 5d 0a 09 66 6c 75 73 68  ty -echo]..flush
1860: 20 73 74 64 6f 75 74 0a 0a 09 73 65 74 20 70 61   stdout...set pa
1870: 73 73 77 6f 72 64 20 5b 67 65 74 73 20 73 74 64  ssword [gets std
1880: 69 6e 5d 0a 0a 09 70 75 74 73 20 2d 6e 6f 6e 65  in]...puts -none
1890: 77 6c 69 6e 65 20 5b 65 78 65 63 20 73 74 74 79  wline [exec stty
18a0: 20 65 63 68 6f 5d 0a 09 70 75 74 73 20 22 22 0a   echo]..puts "".
18b0: 09 66 6c 75 73 68 20 73 74 64 6f 75 74 0a 0a 09  .flush stdout...
18c0: 72 65 74 75 72 6e 20 24 70 61 73 73 77 6f 72 64  return $password
18d0: 0a 7d 0a 0a 70 72 6f 63 20 5f 67 65 74 50 61 73  .}..proc _getPas
18e0: 73 77 6f 72 64 20 7b 6e 61 6d 65 7d 20 7b 0a 09  sword {name} {..
18f0: 66 6f 72 65 61 63 68 20 73 6c 6f 74 49 6e 66 6f  foreach slotInfo
1900: 44 69 63 74 20 5b 5f 6c 69 73 74 43 65 72 74 69  Dict [_listCerti
1910: 66 69 63 61 74 65 73 5d 20 7b 0a 09 09 75 6e 73  ficates] {...uns
1920: 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 73  et -nocomplain s
1930: 6c 6f 74 49 6e 66 6f 0a 09 09 61 72 72 61 79 20  lotInfo...array 
1940: 73 65 74 20 73 6c 6f 74 49 6e 66 6f 20 24 73 6c  set slotInfo $sl
1950: 6f 74 49 6e 66 6f 44 69 63 74 0a 0a 09 09 73 65  otInfoDict....se
1960: 74 20 70 75 62 6b 65 79 20 24 73 6c 6f 74 49 6e  t pubkey $slotIn
1970: 66 6f 28 70 75 62 6b 65 79 29 0a 09 09 73 65 74  fo(pubkey)...set
1980: 20 70 72 6f 6d 70 74 20 24 73 6c 6f 74 49 6e 66   prompt $slotInf
1990: 6f 28 70 72 6f 6d 70 74 29 0a 0a 09 09 69 66 20  o(prompt)....if 
19a0: 7b 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 70 72  {[info exists pr
19b0: 6f 6d 70 74 65 64 28 24 73 6c 6f 74 49 6e 66 6f  ompted($slotInfo
19c0: 28 69 64 29 29 5d 7d 20 7b 0a 09 09 09 73 65 74  (id))]} {....set
19d0: 20 70 72 6f 6d 70 74 20 66 61 6c 73 65 0a 09 09   prompt false...
19e0: 7d 0a 0a 09 09 69 66 20 7b 24 70 72 6f 6d 70 74  }....if {$prompt
19f0: 7d 20 7b 0a 09 09 09 73 65 74 20 50 49 4e 20 5b  } {....set PIN [
1a00: 5f 70 72 6f 6d 70 74 20 22 50 6c 65 61 73 65 20  _prompt "Please 
1a10: 65 6e 74 65 72 20 74 68 65 20 50 49 4e 20 66 6f  enter the PIN fo
1a20: 72 20 5b 64 69 63 74 20 67 65 74 20 24 73 6c 6f  r [dict get $slo
1a30: 74 49 6e 66 6f 28 63 65 72 74 29 20 73 75 62 6a  tInfo(cert) subj
1a40: 65 63 74 5d 3a 20 22 5d 0a 0a 09 09 09 69 66 20  ect]: "].....if 
1a50: 7b 21 5b 3a 3a 70 6b 69 3a 3a 70 6b 63 73 31 31  {![::pki::pkcs11
1a60: 3a 3a 6c 6f 67 69 6e 20 24 73 6c 6f 74 49 6e 66  ::login $slotInf
1a70: 6f 28 68 61 6e 64 6c 65 29 20 24 73 6c 6f 74 49  o(handle) $slotI
1a80: 6e 66 6f 28 69 64 29 20 24 50 49 4e 5d 7d 20 7b  nfo(id) $PIN]} {
1a90: 0a 09 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64  .....return -cod
1aa0: 65 20 65 72 72 6f 72 20 22 55 6e 61 62 6c 65 20  e error "Unable 
1ab0: 74 6f 20 61 75 74 68 65 6e 74 69 63 61 74 65 22  to authenticate"
1ac0: 0a 09 09 09 7d 0a 0a 09 09 09 73 65 74 20 70 72  ....}.....set pr
1ad0: 6f 6d 70 74 65 64 28 24 73 6c 6f 74 49 6e 66 6f  ompted($slotInfo
1ae0: 28 69 64 29 29 20 31 0a 09 09 7d 0a 0a 09 09 64  (id)) 1...}....d
1af0: 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 65  b eval {SELECT e
1b00: 6e 63 72 79 70 74 65 64 50 61 73 73 2c 20 65 6e  ncryptedPass, en
1b10: 63 72 79 70 74 65 64 4b 65 79 20 46 52 4f 4d 20  cryptedKey FROM 
1b20: 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45 20  passwords WHERE 
1b30: 6e 61 6d 65 20 3d 20 24 6e 61 6d 65 20 41 4e 44  name = $name AND
1b40: 20 70 75 62 6c 69 63 4b 65 79 20 3d 20 24 70 75   publicKey = $pu
1b50: 62 6b 65 79 3b 7d 20 72 6f 77 20 7b 0a 09 09 09  bkey;} row {....
1b60: 73 65 74 20 6b 65 79 20 5b 3a 3a 70 6b 69 3a 3a  set key [::pki::
1b70: 64 65 63 72 79 70 74 20 2d 62 69 6e 61 72 79 20  decrypt -binary 
1b80: 2d 70 72 69 76 20 2d 2d 20 5b 62 69 6e 61 72 79  -priv -- [binary
1b90: 20 64 65 63 6f 64 65 20 62 61 73 65 36 34 20 24   decode base64 $
1ba0: 72 6f 77 28 65 6e 63 72 79 70 74 65 64 4b 65 79  row(encryptedKey
1bb0: 29 5d 20 24 73 6c 6f 74 49 6e 66 6f 28 63 65 72  )] $slotInfo(cer
1bc0: 74 29 5d 0a 09 09 09 73 65 74 20 70 61 73 73 77  t)]....set passw
1bd0: 6f 72 64 20 5b 3a 3a 61 65 73 3a 3a 61 65 73 20  ord [::aes::aes 
1be0: 2d 64 69 72 20 64 65 63 72 79 70 74 20 2d 6b 65  -dir decrypt -ke
1bf0: 79 20 24 6b 65 79 20 2d 2d 20 5b 62 69 6e 61 72  y $key -- [binar
1c00: 79 20 64 65 63 6f 64 65 20 62 61 73 65 36 34 20  y decode base64 
1c10: 24 72 6f 77 28 65 6e 63 72 79 70 74 65 64 50 61  $row(encryptedPa
1c20: 73 73 29 5d 5d 0a 0a 09 09 09 72 65 74 75 72 6e  ss)]].....return
1c30: 20 24 70 61 73 73 77 6f 72 64 0a 09 09 7d 0a 09   $password...}..
1c40: 7d 0a 0a 09 72 65 74 75 72 6e 20 2d 63 6f 64 65  }...return -code
1c50: 20 65 72 72 6f 72 20 22 4e 6f 20 76 61 6c 69 64   error "No valid
1c60: 20 6b 65 79 73 22 0a 7d 0a 0a 70 72 6f 63 20 5f   keys".}..proc _
1c70: 6d 6f 64 69 66 79 50 75 62 6c 69 63 4b 65 79 73  modifyPublicKeys
1c80: 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 75   {passwordName u
1c90: 73 65 72 4e 61 6d 65 73 20 73 71 6c 7d 20 7b 0a  serNames sql} {.
1ca0: 09 73 65 74 20 70 75 62 6c 69 63 4b 65 79 73 20  .set publicKeys 
1cb0: 5b 6c 69 73 74 5d 0a 0a 09 64 62 20 65 76 61 6c  [list]...db eval
1cc0: 20 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b   {SELECT publicK
1cd0: 65 79 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64  ey FROM password
1ce0: 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24  s WHERE name = $
1cf0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 3b 7d 20 72  passwordName;} r
1d00: 6f 77 20 7b 0a 09 09 6c 61 70 70 65 6e 64 20 70  ow {...lappend p
1d10: 75 62 6c 69 63 4b 65 79 73 20 24 72 6f 77 28 70  ublicKeys $row(p
1d20: 75 62 6c 69 63 4b 65 79 29 0a 09 7d 0a 0a 09 73  ublicKey)..}...s
1d30: 65 74 20 63 68 61 6e 67 65 52 65 71 75 69 72 65  et changeRequire
1d40: 64 20 30 0a 09 66 6f 72 65 61 63 68 20 75 73 65  d 0..foreach use
1d50: 72 20 24 75 73 65 72 4e 61 6d 65 73 20 7b 0a 09  r $userNames {..
1d60: 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61  .unset -nocompla
1d70: 69 6e 20 72 6f 77 0a 09 09 64 62 20 65 76 61 6c  in row...db eval
1d80: 20 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b   {SELECT publicK
1d90: 65 79 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48  ey FROM users WH
1da0: 45 52 45 20 6e 61 6d 65 20 3d 20 24 75 73 65 72  ERE name = $user
1db0: 3b 7d 20 72 6f 77 20 24 73 71 6c 0a 09 7d 0a 0a  ;} row $sql..}..
1dc0: 09 69 66 20 7b 21 24 63 68 61 6e 67 65 52 65 71  .if {!$changeReq
1dd0: 75 69 72 65 64 7d 20 7b 0a 09 09 72 65 74 75 72  uired} {...retur
1de0: 6e 0a 09 7d 0a 0a 09 73 65 74 20 70 61 73 73 77  n..}...set passw
1df0: 6f 72 64 20 5b 5f 67 65 74 50 61 73 73 77 6f 72  ord [_getPasswor
1e00: 64 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5d  d $passwordName]
1e10: 0a 0a 09 5f 61 64 64 50 61 73 73 77 6f 72 64 20  ..._addPassword 
1e20: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 70  $passwordName $p
1e30: 61 73 73 77 6f 72 64 20 24 70 75 62 6c 69 63 4b  assword $publicK
1e40: 65 79 73 0a 7d 0a 0a 70 72 6f 63 20 5f 67 65 74  eys.}..proc _get
1e50: 55 73 65 72 73 46 6f 72 50 61 73 73 77 6f 72 64  UsersForPassword
1e60: 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 7d   {passwordNames}
1e70: 20 7b 0a 09 73 65 74 20 75 73 65 72 4e 61 6d 65   {..set userName
1e80: 73 20 5b 6c 69 73 74 5d 0a 0a 09 66 6f 72 65 61  s [list]...forea
1e90: 63 68 20 70 61 73 73 77 6f 72 64 4e 61 6d 65 20  ch passwordName 
1ea0: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 20 7b  $passwordNames {
1eb0: 0a 09 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45  ...db eval {SELE
1ec0: 43 54 20 70 75 62 6c 69 63 4b 65 79 20 46 52 4f  CT publicKey FRO
1ed0: 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52  M passwords WHER
1ee0: 45 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77 6f  E name = $passwo
1ef0: 72 64 4e 61 6d 65 3b 7d 20 70 61 73 73 77 6f 72  rdName;} passwor
1f00: 64 52 6f 77 20 7b 0a 09 09 09 64 62 20 65 76 61  dRow {....db eva
1f10: 6c 20 7b 53 45 4c 45 43 54 20 6e 61 6d 65 20 46  l {SELECT name F
1f20: 52 4f 4d 20 75 73 65 72 73 20 57 48 45 52 45 20  ROM users WHERE 
1f30: 70 75 62 6c 69 63 4b 65 79 20 3d 20 24 70 61 73  publicKey = $pas
1f40: 73 77 6f 72 64 52 6f 77 28 70 75 62 6c 69 63 4b  swordRow(publicK
1f50: 65 79 29 7d 20 75 73 65 72 52 6f 77 20 7b 0a 09  ey)} userRow {..
1f60: 09 09 09 69 66 20 7b 24 75 73 65 72 52 6f 77 28  ...if {$userRow(
1f70: 6e 61 6d 65 29 20 69 6e 20 24 75 73 65 72 4e 61  name) in $userNa
1f80: 6d 65 73 7d 20 7b 0a 09 09 09 09 09 63 6f 6e 74  mes} {......cont
1f90: 69 6e 75 65 0a 09 09 09 09 7d 0a 0a 09 09 09 09  inue.....}......
1fa0: 6c 61 70 70 65 6e 64 20 75 73 65 72 4e 61 6d 65  lappend userName
1fb0: 73 20 24 75 73 65 72 52 6f 77 28 6e 61 6d 65 29  s $userRow(name)
1fc0: 0a 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a 0a 09 72  ....}...}..}...r
1fd0: 65 74 75 72 6e 20 24 75 73 65 72 4e 61 6d 65 73  eturn $userNames
1fe0: 0a 7d 0a 0a 70 72 6f 63 20 5f 67 65 74 50 61 73  .}..proc _getPas
1ff0: 73 77 6f 72 64 73 46 6f 72 55 73 65 72 20 7b 75  swordsForUser {u
2000: 73 65 72 4e 61 6d 65 73 7d 20 7b 0a 09 73 65 74  serNames} {..set
2010: 20 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 20 5b   passwordNames [
2020: 6c 69 73 74 5d 0a 0a 09 66 6f 72 65 61 63 68 20  list]...foreach 
2030: 75 73 65 72 4e 61 6d 65 20 24 75 73 65 72 4e 61  userName $userNa
2040: 6d 65 73 20 7b 0a 09 09 64 62 20 65 76 61 6c 20  mes {...db eval 
2050: 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b 65  {SELECT publicKe
2060: 79 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48 45  y FROM users WHE
2070: 52 45 20 6e 61 6d 65 20 3d 20 24 75 73 65 72 4e  RE name = $userN
2080: 61 6d 65 3b 7d 20 75 73 65 72 52 6f 77 20 7b 0a  ame;} userRow {.
2090: 09 09 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45  ...db eval {SELE
20a0: 43 54 20 6e 61 6d 65 20 46 52 4f 4d 20 70 61 73  CT name FROM pas
20b0: 73 77 6f 72 64 73 20 57 48 45 52 45 20 70 75 62  swords WHERE pub
20c0: 6c 69 63 4b 65 79 20 3d 20 24 75 73 65 72 52 6f  licKey = $userRo
20d0: 77 28 70 75 62 6c 69 63 4b 65 79 29 7d 20 70 61  w(publicKey)} pa
20e0: 73 73 77 6f 72 64 52 6f 77 20 7b 0a 09 09 09 09  sswordRow {.....
20f0: 69 66 20 7b 24 70 61 73 73 77 6f 72 64 52 6f 77  if {$passwordRow
2100: 28 6e 61 6d 65 29 20 69 6e 20 24 70 61 73 73 77  (name) in $passw
2110: 6f 72 64 4e 61 6d 65 73 7d 20 7b 0a 09 09 09 09  ordNames} {.....
2120: 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 09 7d 0a  .continue.....}.
2130: 0a 09 09 09 09 6c 61 70 70 65 6e 64 20 70 61 73  .....lappend pas
2140: 73 77 6f 72 64 4e 61 6d 65 73 20 24 70 61 73 73  swordNames $pass
2150: 77 6f 72 64 52 6f 77 28 6e 61 6d 65 29 0a 09 09  wordRow(name)...
2160: 09 7d 0a 09 09 7d 0a 09 7d 0a 0a 09 72 65 74 75  .}...}..}...retu
2170: 72 6e 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65  rn $passwordName
2180: 73 0a 7d 0a 23 20 45 6e 64 20 69 6e 74 65 72 6e  s.}.# End intern
2190: 61 6c 20 66 75 6e 63 74 69 6f 6e 73 0a 0a 23 20  al functions..# 
21a0: 53 74 61 72 74 20 75 73 65 72 20 43 4c 49 20 66  Start user CLI f
21b0: 75 6e 63 74 69 6f 6e 73 0a 70 72 6f 63 20 6c 69  unctions.proc li
21c0: 73 74 4c 6f 63 61 6c 4b 65 79 73 20 7b 7d 20 7b  stLocalKeys {} {
21d0: 0a 09 66 6f 72 65 61 63 68 20 73 6c 6f 74 49 6e  ..foreach slotIn
21e0: 66 6f 44 69 63 74 20 5b 5f 6c 69 73 74 43 65 72  foDict [_listCer
21f0: 74 69 66 69 63 61 74 65 73 5d 20 7b 0a 09 09 75  tificates] {...u
2200: 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e  nset -nocomplain
2210: 20 73 6c 6f 74 49 6e 66 6f 0a 09 09 61 72 72 61   slotInfo...arra
2220: 79 20 73 65 74 20 73 6c 6f 74 49 6e 66 6f 20 24  y set slotInfo $
2230: 73 6c 6f 74 49 6e 66 6f 44 69 63 74 0a 0a 09 09  slotInfoDict....
2240: 73 65 74 20 73 75 62 6a 65 63 74 20 5b 64 69 63  set subject [dic
2250: 74 20 67 65 74 20 24 73 6c 6f 74 49 6e 66 6f 28  t get $slotInfo(
2260: 63 65 72 74 29 20 73 75 62 6a 65 63 74 5d 0a 09  cert) subject]..
2270: 09 73 65 74 20 70 75 62 6b 65 79 20 20 24 73 6c  .set pubkey  $sl
2280: 6f 74 49 6e 66 6f 28 70 75 62 6b 65 79 29 0a 0a  otInfo(pubkey)..
2290: 09 09 6c 61 70 70 65 6e 64 20 70 75 62 6c 69 63  ..lappend public
22a0: 4b 65 79 73 28 24 73 75 62 6a 65 63 74 29 20 24  Keys($subject) $
22b0: 70 75 62 6b 65 79 0a 09 7d 0a 0a 09 66 6f 72 65  pubkey..}...fore
22c0: 61 63 68 20 7b 73 75 62 6a 65 63 74 20 70 75 62  ach {subject pub
22d0: 6b 65 79 73 7d 20 5b 61 72 72 61 79 20 67 65 74  keys} [array get
22e0: 20 70 75 62 6c 69 63 4b 65 79 73 5d 20 7b 0a 09   publicKeys] {..
22f0: 09 70 75 74 73 20 22 24 73 75 62 6a 65 63 74 22  .puts "$subject"
2300: 0a 0a 09 09 66 6f 72 65 61 63 68 20 70 75 62 6b  ....foreach pubk
2310: 65 79 20 24 70 75 62 6b 65 79 73 20 7b 0a 09 09  ey $pubkeys {...
2320: 09 70 75 74 73 20 22 20 20 7c 2d 3e 20 24 70 75  .puts "  |-> $pu
2330: 62 6b 65 79 22 0a 09 09 7d 0a 09 7d 0a 7d 0a 0a  bkey"...}..}.}..
2340: 70 72 6f 63 20 6c 69 73 74 41 76 61 69 6c 61 62  proc listAvailab
2350: 6c 65 50 61 73 73 77 6f 72 64 73 20 7b 7d 20 7b  lePasswords {} {
2360: 0a 09 73 65 74 20 70 61 73 73 77 6f 72 64 4e 61  ..set passwordNa
2370: 6d 65 73 20 5b 6c 69 73 74 5d 0a 09 66 6f 72 65  mes [list]..fore
2380: 61 63 68 20 73 6c 6f 74 49 6e 66 6f 44 69 63 74  ach slotInfoDict
2390: 20 5b 5f 6c 69 73 74 43 65 72 74 69 66 69 63 61   [_listCertifica
23a0: 74 65 73 5d 20 7b 0a 09 09 75 6e 73 65 74 20 2d  tes] {...unset -
23b0: 6e 6f 63 6f 6d 70 6c 61 69 6e 20 73 6c 6f 74 49  nocomplain slotI
23c0: 6e 66 6f 0a 09 09 61 72 72 61 79 20 73 65 74 20  nfo...array set 
23d0: 73 6c 6f 74 49 6e 66 6f 20 24 73 6c 6f 74 49 6e  slotInfo $slotIn
23e0: 66 6f 44 69 63 74 0a 0a 09 09 73 65 74 20 70 75  foDict....set pu
23f0: 62 6b 65 79 20 24 73 6c 6f 74 49 6e 66 6f 28 70  bkey $slotInfo(p
2400: 75 62 6b 65 79 29 0a 0a 09 09 75 6e 73 65 74 20  ubkey)....unset 
2410: 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 72 6f 77 0a  -nocomplain row.
2420: 09 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43  ..db eval {SELEC
2430: 54 20 6e 61 6d 65 20 46 52 4f 4d 20 70 61 73 73  T name FROM pass
2440: 77 6f 72 64 73 20 57 48 45 52 45 20 70 75 62 6c  words WHERE publ
2450: 69 63 4b 65 79 20 3d 20 24 70 75 62 6b 65 79 3b  icKey = $pubkey;
2460: 7d 20 72 6f 77 20 7b 0a 09 09 09 69 66 20 7b 24  } row {....if {$
2470: 72 6f 77 28 6e 61 6d 65 29 20 69 6e 20 24 70 61  row(name) in $pa
2480: 73 73 77 6f 72 64 4e 61 6d 65 73 7d 20 7b 0a 09  sswordNames} {..
2490: 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 7d  ...continue....}
24a0: 0a 0a 09 09 09 6c 61 70 70 65 6e 64 20 70 61 73  .....lappend pas
24b0: 73 77 6f 72 64 4e 61 6d 65 73 20 24 72 6f 77 28  swordNames $row(
24c0: 6e 61 6d 65 29 0a 09 09 7d 0a 09 7d 0a 0a 0a 09  name)...}..}....
24d0: 66 6f 72 65 61 63 68 20 70 61 73 73 77 6f 72 64  foreach password
24e0: 4e 61 6d 65 20 24 70 61 73 73 77 6f 72 64 4e 61  Name $passwordNa
24f0: 6d 65 73 20 7b 0a 09 09 70 75 74 73 20 22 24 70  mes {...puts "$p
2500: 61 73 73 77 6f 72 64 4e 61 6d 65 20 2d 20 5b 6a  asswordName - [j
2510: 6f 69 6e 20 5b 5f 67 65 74 55 73 65 72 73 46 6f  oin [_getUsersFo
2520: 72 50 61 73 73 77 6f 72 64 20 5b 6c 69 73 74 20  rPassword [list 
2530: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5d 5d 20  $passwordName]] 
2540: 7b 2c 20 7d 5d 22 0a 09 7d 0a 7d 0a 0a 70 72 6f  {, }]"..}.}..pro
2550: 63 20 6c 69 73 74 50 61 73 73 77 6f 72 64 73 20  c listPasswords 
2560: 7b 7d 20 7b 0a 09 64 62 20 65 76 61 6c 20 7b 53  {} {..db eval {S
2570: 45 4c 45 43 54 20 44 49 53 54 49 4e 43 54 20 6e  ELECT DISTINCT n
2580: 61 6d 65 20 46 52 4f 4d 20 70 61 73 73 77 6f 72  ame FROM passwor
2590: 64 73 3b 7d 20 72 6f 77 20 7b 0a 09 09 70 75 74  ds;} row {...put
25a0: 73 20 22 24 72 6f 77 28 6e 61 6d 65 29 20 2d 20  s "$row(name) - 
25b0: 5b 6a 6f 69 6e 20 5b 5f 67 65 74 55 73 65 72 73  [join [_getUsers
25c0: 46 6f 72 50 61 73 73 77 6f 72 64 20 5b 6c 69 73  ForPassword [lis
25d0: 74 20 24 72 6f 77 28 6e 61 6d 65 29 5d 5d 20 7b  t $row(name)]] {
25e0: 2c 20 7d 5d 22 0a 09 7d 0a 7d 0a 0a 70 72 6f 63  , }]"..}.}..proc
25f0: 20 6c 69 73 74 55 73 65 72 73 20 7b 7d 20 7b 0a   listUsers {} {.
2600: 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54  .db eval {SELECT
2610: 20 44 49 53 54 49 4e 43 54 20 6e 61 6d 65 20 46   DISTINCT name F
2620: 52 4f 4d 20 75 73 65 72 73 3b 7d 20 72 6f 77 20  ROM users;} row 
2630: 7b 0a 09 09 70 75 74 73 20 22 24 72 6f 77 28 6e  {...puts "$row(n
2640: 61 6d 65 29 20 2d 20 5b 6a 6f 69 6e 20 5b 5f 67  ame) - [join [_g
2650: 65 74 50 61 73 73 77 6f 72 64 73 46 6f 72 55 73  etPasswordsForUs
2660: 65 72 20 5b 6c 69 73 74 20 24 72 6f 77 28 6e 61  er [list $row(na
2670: 6d 65 29 5d 5d 20 7b 2c 20 7d 5d 22 0a 09 7d 0a  me)]] {, }]"..}.
2680: 7d 0a 0a 70 72 6f 63 20 61 64 64 55 73 65 72 20  }..proc addUser 
2690: 7b 75 73 65 72 4e 61 6d 65 20 6b 65 79 7d 20 7b  {userName key} {
26a0: 0a 09 73 65 74 20 6b 65 79 52 61 77 20 5b 62 69  ..set keyRaw [bi
26b0: 6e 61 72 79 20 64 65 63 6f 64 65 20 62 61 73 65  nary decode base
26c0: 36 34 20 24 6b 65 79 5d 0a 09 73 65 74 20 6b 65  64 $key]..set ke
26d0: 79 56 65 72 69 66 79 20 5b 3a 3a 70 6b 69 3a 3a  yVerify [::pki::
26e0: 70 6b 63 73 3a 3a 70 61 72 73 65 5f 70 75 62 6c  pkcs::parse_publ
26f0: 69 63 5f 6b 65 79 20 24 6b 65 79 52 61 77 5d 0a  ic_key $keyRaw].
2700: 0a 09 64 62 20 65 76 61 6c 20 7b 49 4e 53 45 52  ..db eval {INSER
2710: 54 20 49 4e 54 4f 20 75 73 65 72 73 20 28 6e 61  T INTO users (na
2720: 6d 65 2c 20 70 75 62 6c 69 63 4b 65 79 29 20 56  me, publicKey) V
2730: 41 4c 55 45 53 20 28 24 75 73 65 72 4e 61 6d 65  ALUES ($userName
2740: 2c 20 40 6b 65 79 29 3b 7d 0a 0a 09 23 20 58 58  , @key);}...# XX
2750: 58 3a 54 4f 44 4f 3a 47 6f 20 74 68 72 6f 75 67  X:TODO:Go throug
2760: 68 20 61 6e 64 20 72 65 2d 61 75 74 68 6f 72 69  h and re-authori
2770: 7a 65 20 69 66 20 70 6f 73 73 69 62 6c 65 0a 7d  ze if possible.}
2780: 0a 0a 70 72 6f 63 20 64 65 6c 65 74 65 55 73 65  ..proc deleteUse
2790: 72 20 7b 75 73 65 72 4e 61 6d 65 7d 20 7b 0a 09  r {userName} {..
27a0: 23 20 58 58 58 3a 54 4f 44 4f 3a 20 47 6f 20 74  # XXX:TODO: Go t
27b0: 68 72 6f 75 67 68 20 61 6e 64 20 64 65 2d 61 75  hrough and de-au
27c0: 74 68 6f 72 69 7a 65 0a 7d 0a 0a 70 72 6f 63 20  thorize.}..proc 
27d0: 61 64 64 50 61 73 73 77 6f 72 64 20 7b 70 61 73  addPassword {pas
27e0: 73 77 6f 72 64 4e 61 6d 65 20 70 61 73 73 77 6f  swordName passwo
27f0: 72 64 20 61 72 67 73 7d 20 7b 0a 09 73 65 74 20  rd args} {..set 
2800: 69 6e 69 74 69 61 6c 55 73 65 72 73 20 24 61 72  initialUsers $ar
2810: 67 73 0a 0a 09 69 66 20 7b 24 70 61 73 73 77 6f  gs...if {$passwo
2820: 72 64 20 65 71 20 22 22 7d 20 7b 0a 09 09 73 65  rd eq ""} {...se
2830: 74 20 70 61 73 73 77 6f 72 64 20 5b 5f 70 72 6f  t password [_pro
2840: 6d 70 74 20 22 50 6c 65 61 73 65 20 65 6e 74 65  mpt "Please ente
2850: 72 20 74 68 65 20 6e 65 77 20 70 61 73 73 77 6f  r the new passwo
2860: 72 64 3a 20 22 5d 0a 09 7d 0a 0a 09 23 20 56 65  rd: "]..}...# Ve
2870: 72 69 66 79 20 74 68 61 74 20 74 68 69 73 20 70  rify that this p
2880: 61 73 73 77 6f 72 64 20 64 6f 65 73 20 6e 6f 74  assword does not
2890: 20 61 6c 72 65 61 64 79 20 65 78 69 73 74 0a 09   already exist..
28a0: 73 65 74 20 65 78 69 73 74 73 20 5b 64 62 20 65  set exists [db e
28b0: 76 61 6c 20 7b 53 45 4c 45 43 54 20 31 20 46 52  val {SELECT 1 FR
28c0: 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48 45  OM passwords WHE
28d0: 52 45 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77  RE name = $passw
28e0: 6f 72 64 4e 61 6d 65 20 4c 49 4d 49 54 20 31 3b  ordName LIMIT 1;
28f0: 7d 5d 0a 09 69 66 20 7b 24 65 78 69 73 74 73 20  }]..if {$exists 
2900: 3d 3d 20 22 31 22 7d 20 7b 0a 09 09 72 65 74 75  == "1"} {...retu
2910: 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22  rn -code error "
2920: 50 61 73 73 77 6f 72 64 20 5c 22 24 70 61 73 73  Password \"$pass
2930: 77 6f 72 64 4e 61 6d 65 5c 22 20 61 6c 72 65 61  wordName\" alrea
2940: 64 79 20 65 78 69 73 74 73 2c 20 63 61 6e 6e 6f  dy exists, canno
2950: 74 20 61 64 64 2e 22 0a 09 7d 0a 0a 09 23 20 47  t add."..}...# G
2960: 65 74 20 6b 65 79 73 20 66 6f 72 20 69 6e 69 74  et keys for init
2970: 69 61 6c 20 75 73 65 72 73 0a 09 73 65 74 20 70  ial users..set p
2980: 75 62 6c 69 63 4b 65 79 73 20 5b 6c 69 73 74 5d  ublicKeys [list]
2990: 0a 09 66 6f 72 65 61 63 68 20 75 73 65 72 20 24  ..foreach user $
29a0: 69 6e 69 74 69 61 6c 55 73 65 72 73 20 7b 0a 09  initialUsers {..
29b0: 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61  .unset -nocompla
29c0: 69 6e 20 72 6f 77 0a 09 09 64 62 20 65 76 61 6c  in row...db eval
29d0: 20 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b   {SELECT publicK
29e0: 65 79 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48  ey FROM users WH
29f0: 45 52 45 20 6e 61 6d 65 20 3d 20 24 75 73 65 72  ERE name = $user
2a00: 3b 7d 20 72 6f 77 20 7b 0a 09 09 09 6c 61 70 70  ;} row {....lapp
2a10: 65 6e 64 20 70 75 62 6c 69 63 4b 65 79 73 20 24  end publicKeys $
2a20: 72 6f 77 28 70 75 62 6c 69 63 4b 65 79 29 0a 09  row(publicKey)..
2a30: 09 7d 0a 09 7d 0a 0a 09 5f 61 64 64 50 61 73 73  .}..}..._addPass
2a40: 77 6f 72 64 20 24 70 61 73 73 77 6f 72 64 4e 61  word $passwordNa
2a50: 6d 65 20 24 70 61 73 73 77 6f 72 64 20 24 70 75  me $password $pu
2a60: 62 6c 69 63 4b 65 79 73 0a 7d 0a 0a 70 72 6f 63  blicKeys.}..proc
2a70: 20 67 65 74 50 61 73 73 77 6f 72 64 20 7b 70 61   getPassword {pa
2a80: 73 73 77 6f 72 64 4e 61 6d 65 7d 20 7b 0a 09 70  sswordName} {..p
2a90: 75 74 73 20 5b 5f 67 65 74 50 61 73 73 77 6f 72  uts [_getPasswor
2aa0: 64 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5d  d $passwordName]
2ab0: 0a 7d 0a 0a 70 72 6f 63 20 75 70 64 61 74 65 50  .}..proc updateP
2ac0: 61 73 73 77 6f 72 64 20 7b 70 61 73 73 77 6f 72  assword {passwor
2ad0: 64 4e 61 6d 65 20 70 61 73 73 77 6f 72 64 7d 20  dName password} 
2ae0: 7b 0a 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45  {..db eval {SELE
2af0: 43 54 20 70 75 62 6c 69 63 4b 65 79 20 46 52 4f  CT publicKey FRO
2b00: 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52  M passwords WHER
2b10: 45 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77 6f  E name = $passwo
2b20: 72 64 4e 61 6d 65 3b 7d 20 72 6f 77 20 7b 0a 09  rdName;} row {..
2b30: 09 6c 61 70 70 65 6e 64 20 70 75 62 6c 69 63 4b  .lappend publicK
2b40: 65 79 73 20 24 72 6f 77 28 70 75 62 6c 69 63 4b  eys $row(publicK
2b50: 65 79 29 0a 09 7d 0a 0a 09 5f 61 64 64 50 61 73  ey)..}..._addPas
2b60: 73 77 6f 72 64 20 24 70 61 73 73 77 6f 72 64 4e  sword $passwordN
2b70: 61 6d 65 20 24 70 61 73 73 77 6f 72 64 20 24 70  ame $password $p
2b80: 75 62 6c 69 63 4b 65 79 73 0a 7d 0a 0a 70 72 6f  ublicKeys.}..pro
2b90: 63 20 64 65 6c 65 74 65 50 61 73 73 77 6f 72 64  c deletePassword
2ba0: 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 7d 20   {passwordName} 
2bb0: 7b 0a 09 64 62 20 65 76 61 6c 20 7b 44 45 4c 45  {..db eval {DELE
2bc0: 54 45 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64  TE FROM password
2bd0: 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24  s WHERE name = $
2be0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 3b 7d 0a 7d  passwordName;}.}
2bf0: 0a 0a 70 72 6f 63 20 61 75 74 68 6f 72 69 7a 65  ..proc authorize
2c00: 55 73 65 72 73 20 7b 70 61 73 73 77 6f 72 64 4e  Users {passwordN
2c10: 61 6d 65 20 61 72 67 73 7d 20 7b 0a 09 73 65 74  ame args} {..set
2c20: 20 75 73 65 72 73 20 24 61 72 67 73 0a 0a 09 5f   users $args..._
2c30: 6d 6f 64 69 66 79 50 75 62 6c 69 63 4b 65 79 73  modifyPublicKeys
2c40: 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24   $passwordName $
2c50: 75 73 65 72 73 20 7b 0a 09 09 69 66 20 7b 24 72  users {...if {$r
2c60: 6f 77 28 70 75 62 6c 69 63 4b 65 79 29 20 69 6e  ow(publicKey) in
2c70: 20 24 70 75 62 6c 69 63 4b 65 79 73 7d 20 7b 0a   $publicKeys} {.
2c80: 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 7d 0a  ...continue...}.
2c90: 0a 09 09 6c 61 70 70 65 6e 64 20 70 75 62 6c 69  ...lappend publi
2ca0: 63 4b 65 79 73 20 24 72 6f 77 28 70 75 62 6c 69  cKeys $row(publi
2cb0: 63 4b 65 79 29 0a 0a 09 09 73 65 74 20 63 68 61  cKey)....set cha
2cc0: 6e 67 65 52 65 71 75 69 72 65 64 20 31 0a 09 7d  ngeRequired 1..}
2cd0: 0a 7d 0a 0a 70 72 6f 63 20 61 75 74 68 6f 72 69  .}..proc authori
2ce0: 7a 65 55 73 65 72 20 7b 70 61 73 73 77 6f 72 64  zeUser {password
2cf0: 4e 61 6d 65 20 75 73 65 72 4e 61 6d 65 7d 20 7b  Name userName} {
2d00: 0a 09 72 65 74 75 72 6e 20 5b 61 75 74 68 6f 72  ..return [author
2d10: 69 7a 65 55 73 65 72 73 20 24 70 61 73 73 77 6f  izeUsers $passwo
2d20: 72 64 4e 61 6d 65 20 24 75 73 65 72 4e 61 6d 65  rdName $userName
2d30: 5d 0a 7d 0a 0a 70 72 6f 63 20 64 65 61 75 74 68  ].}..proc deauth
2d40: 6f 72 69 7a 65 55 73 65 72 73 20 7b 70 61 73 73  orizeUsers {pass
2d50: 77 6f 72 64 4e 61 6d 65 20 61 72 67 73 7d 20 7b  wordName args} {
2d60: 0a 09 73 65 74 20 75 73 65 72 73 20 24 61 72 67  ..set users $arg
2d70: 73 0a 0a 09 5f 6d 6f 64 69 66 79 50 75 62 6c 69  s..._modifyPubli
2d80: 63 4b 65 79 73 20 24 70 61 73 73 77 6f 72 64 4e  cKeys $passwordN
2d90: 61 6d 65 20 24 75 73 65 72 73 20 7b 0a 09 09 73  ame $users {...s
2da0: 65 74 20 69 64 78 20 5b 6c 73 65 61 72 63 68 20  et idx [lsearch 
2db0: 2d 65 78 61 63 74 20 24 70 75 62 6c 69 63 4b 65  -exact $publicKe
2dc0: 79 73 20 24 72 6f 77 28 70 75 62 6c 69 63 4b 65  ys $row(publicKe
2dd0: 79 29 5d 0a 09 09 69 66 20 7b 24 69 64 78 20 3d  y)]...if {$idx =
2de0: 3d 20 2d 31 7d 20 7b 0a 09 09 09 63 6f 6e 74 69  = -1} {....conti
2df0: 6e 75 65 0a 09 09 7d 0a 0a 09 09 73 65 74 20 70  nue...}....set p
2e00: 75 62 6c 69 63 4b 65 79 73 20 5b 6c 72 65 70 6c  ublicKeys [lrepl
2e10: 61 63 65 20 24 70 75 62 6c 69 63 4b 65 79 73 20  ace $publicKeys 
2e20: 24 69 64 78 20 24 69 64 78 5d 0a 0a 09 09 73 65  $idx $idx]....se
2e30: 74 20 63 68 61 6e 67 65 52 65 71 75 69 72 65 64  t changeRequired
2e40: 20 31 0a 09 7d 0a 7d 0a 0a 70 72 6f 63 20 64 65   1..}.}..proc de
2e50: 61 75 74 68 6f 72 69 7a 65 55 73 65 72 20 7b 70  authorizeUser {p
2e60: 61 73 73 77 6f 72 64 4e 61 6d 65 20 75 73 65 72  asswordName user
2e70: 4e 61 6d 65 7d 20 7b 0a 09 72 65 74 75 72 6e 20  Name} {..return 
2e80: 5b 64 65 61 75 74 68 6f 72 69 7a 65 55 73 65 72  [deauthorizeUser
2e90: 73 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20  s $passwordName 
2ea0: 24 75 73 65 72 4e 61 6d 65 5d 0a 7d 0a 0a 70 72  $userName].}..pr
2eb0: 6f 63 20 68 65 6c 70 20 7b 7b 61 63 74 69 6f 6e  oc help {{action
2ec0: 20 22 22 7d 7d 20 7b 0a 09 5f 70 72 69 6e 74 48   ""}} {.._printH
2ed0: 65 6c 70 20 73 74 64 6f 75 74 20 24 61 63 74 69  elp stdout $acti
2ee0: 6f 6e 0a 7d 0a 23 20 45 6e 64 20 75 73 65 72 20  on.}.# End user 
2ef0: 43 4c 49 20 66 75 6e 63 74 69 6f 6e 73 0a 0a 23  CLI functions..#
2f00: 23 23 20 4d 41 49 4e 0a 0a 73 71 6c 69 74 65 33  ## MAIN..sqlite3
2f10: 20 64 62 20 24 70 61 73 73 77 6f 72 64 46 69 6c   db $passwordFil
2f20: 65 0a 0a 64 62 20 65 76 61 6c 20 7b 0a 09 43 52  e..db eval {..CR
2f30: 45 41 54 45 20 54 41 42 4c 45 20 49 46 20 4e 4f  EATE TABLE IF NO
2f40: 54 20 45 58 49 53 54 53 20 75 73 65 72 73 28 6e  T EXISTS users(n
2f50: 61 6d 65 2c 20 70 75 62 6c 69 63 4b 65 79 20 42  ame, publicKey B
2f60: 4c 4f 42 29 3b 0a 09 43 52 45 41 54 45 20 54 41  LOB);..CREATE TA
2f70: 42 4c 45 20 49 46 20 4e 4f 54 20 45 58 49 53 54  BLE IF NOT EXIST
2f80: 53 20 70 61 73 73 77 6f 72 64 73 28 6e 61 6d 65  S passwords(name
2f90: 2c 20 65 6e 63 72 79 70 74 65 64 50 61 73 73 20  , encryptedPass 
2fa0: 42 4c 4f 42 2c 20 65 6e 63 72 79 70 74 65 64 4b  BLOB, encryptedK
2fb0: 65 79 20 42 4c 4f 42 2c 20 70 75 62 6c 69 63 4b  ey BLOB, publicK
2fc0: 65 79 20 42 4c 4f 42 29 3b 0a 7d 0a 0a 69 66 20  ey BLOB);.}..if 
2fd0: 7b 24 61 63 74 69 6f 6e 20 69 6e 20 24 76 61 6c  {$action in $val
2fe0: 69 64 43 6f 6d 6d 61 6e 64 73 7d 20 7b 0a 09 24  idCommands} {..$
2ff0: 61 63 74 69 6f 6e 20 7b 2a 7d 24 61 72 67 76 0a  action {*}$argv.
3000: 7d 20 65 6c 73 65 20 7b 0a 09 70 75 74 73 20 73  } else {..puts s
3010: 74 64 65 72 72 20 22 49 6e 76 61 6c 69 64 20 61  tderr "Invalid a
3020: 63 74 69 6f 6e 22 0a 0a 09 65 78 69 74 20 31 0a  ction"...exit 1.
3030: 7d 0a 0a 65 78 69 74 20 30 0a 0a                 }..exit 0..