Hex Artifact Content

Artifact e039ea66c1f6fd81e7823d8c98a878f959b3cdba:


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 23 20 43 6f 70 79 72 69 67  tclsh..# Copyrig
0020: 68 74 20 28 63 29 20 32 30 31 36 2c 20 52 6f 79  ht (c) 2016, Roy
0030: 20 4b 65 65 6e 65 0a 23 20 41 6c 6c 20 72 69 67   Keene.# All rig
0040: 68 74 73 20 72 65 73 65 72 76 65 64 2e 0a 23 20  hts reserved..# 
0050: 0a 23 20 52 65 64 69 73 74 72 69 62 75 74 69 6f  .# Redistributio
0060: 6e 20 61 6e 64 20 75 73 65 20 69 6e 20 73 6f 75  n and use in sou
0070: 72 63 65 20 61 6e 64 20 62 69 6e 61 72 79 20 66  rce and binary f
0080: 6f 72 6d 73 2c 20 77 69 74 68 20 6f 72 20 77 69  orms, with or wi
0090: 74 68 6f 75 74 0a 23 20 6d 6f 64 69 66 69 63 61  thout.# modifica
00a0: 74 69 6f 6e 2c 20 61 72 65 20 70 65 72 6d 69 74  tion, are permit
00b0: 74 65 64 20 70 72 6f 76 69 64 65 64 20 74 68 61  ted provided tha
00c0: 74 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20  t the following 
00d0: 63 6f 6e 64 69 74 69 6f 6e 73 20 61 72 65 0a 23  conditions are.#
00e0: 20 6d 65 74 3a 0a 23 20 20 20 20 20 20 20 20 20   met:.#         
00f0: 31 2e 20 52 65 64 69 73 74 72 69 62 75 74 69 6f  1. Redistributio
0100: 6e 73 20 6f 66 20 73 6f 75 72 63 65 20 63 6f 64  ns of source cod
0110: 65 20 6d 75 73 74 20 72 65 74 61 69 6e 20 74 68  e must retain th
0120: 65 20 61 62 6f 76 65 20 63 6f 70 79 72 69 67 68  e above copyrigh
0130: 74 0a 23 20 20 20 20 20 20 20 20 20 20 20 20 6e  t.#            n
0140: 6f 74 69 63 65 2c 20 74 68 69 73 20 6c 69 73 74  otice, this list
0150: 20 6f 66 20 63 6f 6e 64 69 74 69 6f 6e 73 20 61   of conditions a
0160: 6e 64 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67  nd the following
0170: 20 64 69 73 63 6c 61 69 6d 65 72 2e 0a 23 20 0a   disclaimer..# .
0180: 23 20 20 20 20 20 20 20 20 20 32 2e 20 52 65 64  #         2. Red
0190: 69 73 74 72 69 62 75 74 69 6f 6e 73 20 69 6e 20  istributions in 
01a0: 62 69 6e 61 72 79 20 66 6f 72 6d 20 6d 75 73 74  binary form must
01b0: 20 72 65 70 72 6f 64 75 63 65 20 74 68 65 20 61   reproduce the a
01c0: 62 6f 76 65 0a 23 20 20 20 20 20 20 20 20 20 20  bove.#          
01d0: 20 20 63 6f 70 79 72 69 67 68 74 20 6e 6f 74 69    copyright noti
01e0: 63 65 2c 20 74 68 69 73 20 6c 69 73 74 20 6f 66  ce, this list of
01f0: 20 63 6f 6e 64 69 74 69 6f 6e 73 20 61 6e 64 20   conditions and 
0200: 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 0a 23 20  the following.# 
0210: 20 20 20 20 20 20 20 20 20 20 20 64 69 73 63 6c             discl
0220: 61 69 6d 65 72 20 69 6e 20 74 68 65 20 64 6f 63  aimer in the doc
0230: 75 6d 65 6e 74 61 74 69 6f 6e 20 61 6e 64 2f 6f  umentation and/o
0240: 72 20 6f 74 68 65 72 20 6d 61 74 65 72 69 61 6c  r other material
0250: 73 0a 23 20 20 20 20 20 20 20 20 20 20 20 20 70  s.#            p
0260: 72 6f 76 69 64 65 64 20 77 69 74 68 20 74 68 65  rovided with the
0270: 20 64 69 73 74 72 69 62 75 74 69 6f 6e 2e 0a 23   distribution..#
0280: 0a 23 20 54 48 49 53 20 53 4f 46 54 57 41 52 45  .# THIS SOFTWARE
0290: 20 49 53 20 50 52 4f 56 49 44 45 44 20 42 59 20   IS PROVIDED BY 
02a0: 54 48 45 20 43 4f 50 59 52 49 47 48 54 20 48 4f  THE COPYRIGHT HO
02b0: 4c 44 45 52 53 20 41 4e 44 20 43 4f 4e 54 52 49  LDERS AND CONTRI
02c0: 42 55 54 4f 52 53 20 22 41 53 20 0a 23 20 49 53  BUTORS "AS .# IS
02d0: 22 20 41 4e 44 20 41 4e 59 20 45 58 50 52 45 53  " AND ANY EXPRES
02e0: 53 20 4f 52 20 49 4d 50 4c 49 45 44 20 57 41 52  S OR IMPLIED WAR
02f0: 52 41 4e 54 49 45 53 2c 20 49 4e 43 4c 55 44 49  RANTIES, INCLUDI
0300: 4e 47 2c 20 42 55 54 20 4e 4f 54 20 4c 49 4d 49  NG, BUT NOT LIMI
0310: 54 45 44 20 0a 23 20 54 4f 2c 20 54 48 45 20 49  TED .# TO, THE I
0320: 4d 50 4c 49 45 44 20 57 41 52 52 41 4e 54 49 45  MPLIED WARRANTIE
0330: 53 20 4f 46 20 4d 45 52 43 48 41 4e 54 41 42 49  S OF MERCHANTABI
0340: 4c 49 54 59 20 41 4e 44 20 46 49 54 4e 45 53 53  LITY AND FITNESS
0350: 20 46 4f 52 20 41 20 0a 23 20 50 41 52 54 49 43   FOR A .# PARTIC
0360: 55 4c 41 52 20 50 55 52 50 4f 53 45 20 41 52 45  ULAR PURPOSE ARE
0370: 20 44 49 53 43 4c 41 49 4d 45 44 2e 20 49 4e 20   DISCLAIMED. IN 
0380: 4e 4f 20 45 56 45 4e 54 20 53 48 41 4c 4c 20 54  NO EVENT SHALL T
0390: 48 45 20 43 4f 50 59 52 49 47 48 54 20 0a 23 20  HE COPYRIGHT .# 
03a0: 48 4f 4c 44 45 52 20 4f 52 20 43 4f 4e 54 52 49  HOLDER OR CONTRI
03b0: 42 55 54 4f 52 53 20 42 45 20 4c 49 41 42 4c 45  BUTORS BE LIABLE
03c0: 20 46 4f 52 20 41 4e 59 20 44 49 52 45 43 54 2c   FOR ANY DIRECT,
03d0: 20 49 4e 44 49 52 45 43 54 2c 20 49 4e 43 49 44   INDIRECT, INCID
03e0: 45 4e 54 41 4c 2c 20 0a 23 20 53 50 45 43 49 41  ENTAL, .# SPECIA
03f0: 4c 2c 20 45 58 45 4d 50 4c 41 52 59 2c 20 4f 52  L, EXEMPLARY, OR
0400: 20 43 4f 4e 53 45 51 55 45 4e 54 49 41 4c 20 44   CONSEQUENTIAL D
0410: 41 4d 41 47 45 53 20 28 49 4e 43 4c 55 44 49 4e  AMAGES (INCLUDIN
0420: 47 2c 20 42 55 54 20 4e 4f 54 20 4c 49 4d 49 54  G, BUT NOT LIMIT
0430: 45 44 20 0a 23 20 54 4f 2c 20 50 52 4f 43 55 52  ED .# TO, PROCUR
0440: 45 4d 45 4e 54 20 4f 46 20 53 55 42 53 54 49 54  EMENT OF SUBSTIT
0450: 55 54 45 20 47 4f 4f 44 53 20 4f 52 20 53 45 52  UTE GOODS OR SER
0460: 56 49 43 45 53 3b 20 4c 4f 53 53 20 4f 46 20 55  VICES; LOSS OF U
0470: 53 45 2c 20 44 41 54 41 2c 20 4f 52 20 0a 23 20  SE, DATA, OR .# 
0480: 50 52 4f 46 49 54 53 3b 20 4f 52 20 42 55 53 49  PROFITS; OR BUSI
0490: 4e 45 53 53 20 49 4e 54 45 52 52 55 50 54 49 4f  NESS INTERRUPTIO
04a0: 4e 29 20 48 4f 57 45 56 45 52 20 43 41 55 53 45  N) HOWEVER CAUSE
04b0: 44 20 41 4e 44 20 4f 4e 20 41 4e 59 20 54 48 45  D AND ON ANY THE
04c0: 4f 52 59 20 4f 46 20 0a 23 20 4c 49 41 42 49 4c  ORY OF .# LIABIL
04d0: 49 54 59 2c 20 57 48 45 54 48 45 52 20 49 4e 20  ITY, WHETHER IN 
04e0: 43 4f 4e 54 52 41 43 54 2c 20 53 54 52 49 43 54  CONTRACT, STRICT
04f0: 20 4c 49 41 42 49 4c 49 54 59 2c 20 4f 52 20 54   LIABILITY, OR T
0500: 4f 52 54 20 28 49 4e 43 4c 55 44 49 4e 47 20 0a  ORT (INCLUDING .
0510: 23 20 4e 45 47 4c 49 47 45 4e 43 45 20 4f 52 20  # NEGLIGENCE OR 
0520: 4f 54 48 45 52 57 49 53 45 29 20 41 52 49 53 49  OTHERWISE) ARISI
0530: 4e 47 20 49 4e 20 41 4e 59 20 57 41 59 20 4f 55  NG IN ANY WAY OU
0540: 54 20 4f 46 20 54 48 45 20 55 53 45 20 4f 46 20  T OF THE USE OF 
0550: 54 48 49 53 20 0a 23 20 53 4f 46 54 57 41 52 45  THIS .# SOFTWARE
0560: 2c 20 45 56 45 4e 20 49 46 20 41 44 56 49 53 45  , EVEN IF ADVISE
0570: 44 20 4f 46 20 54 48 45 20 50 4f 53 53 49 42 49  D OF THE POSSIBI
0580: 4c 49 54 59 20 4f 46 20 53 55 43 48 20 44 41 4d  LITY OF SUCH DAM
0590: 41 47 45 2e 0a 0a 73 65 74 20 70 61 73 73 77 6f  AGE...set passwo
05a0: 72 64 46 69 6c 65 20 5b 6c 69 6e 64 65 78 20 24  rdFile [lindex $
05b0: 61 72 67 76 20 30 5d 0a 73 65 74 20 61 63 74 69  argv 0].set acti
05c0: 6f 6e 20 5b 6c 69 6e 64 65 78 20 24 61 72 67 76  on [lindex $argv
05d0: 20 31 5d 0a 0a 73 65 74 20 76 61 6c 69 64 43 6f   1]..set validCo
05e0: 6d 6d 61 6e 64 73 20 5b 6c 69 73 74 20 22 6c 69  mmands [list "li
05f0: 73 74 4c 6f 63 61 6c 4b 65 79 73 22 20 22 6c 69  stLocalKeys" "li
0600: 73 74 50 61 73 73 77 6f 72 64 73 22 20 22 6c 69  stPasswords" "li
0610: 73 74 41 76 61 69 6c 61 62 6c 65 50 61 73 73 77  stAvailablePassw
0620: 6f 72 64 73 22 20 22 6c 69 73 74 55 73 65 72 73  ords" "listUsers
0630: 22 20 22 61 64 64 55 73 65 72 22 20 22 61 64 64  " "addUser" "add
0640: 50 61 73 73 77 6f 72 64 22 20 22 61 75 74 68 6f  Password" "autho
0650: 72 69 7a 65 55 73 65 72 22 20 22 61 75 74 68 6f  rizeUser" "autho
0660: 72 69 7a 65 55 73 65 72 73 22 20 22 64 65 61 75  rizeUsers" "deau
0670: 74 68 6f 72 69 7a 65 55 73 65 72 22 20 22 64 65  thorizeUser" "de
0680: 61 75 74 68 6f 72 69 7a 65 55 73 65 72 73 22 20  authorizeUsers" 
0690: 22 67 65 74 50 61 73 73 77 6f 72 64 22 20 22 75  "getPassword" "u
06a0: 70 64 61 74 65 50 61 73 73 77 6f 72 64 22 20 22  pdatePassword" "
06b0: 64 65 6c 65 74 65 50 61 73 73 77 6f 72 64 22 20  deletePassword" 
06c0: 22 68 65 6c 70 22 5d 0a 0a 70 72 6f 63 20 5f 61  "help"]..proc _a
06d0: 72 67 44 65 73 63 72 69 70 74 69 6f 6e 20 7b 63  rgDescription {c
06e0: 6f 6d 6d 61 6e 64 20 61 72 67 4e 61 6d 65 7d 20  ommand argName} 
06f0: 7b 0a 09 73 77 69 74 63 68 20 2d 2d 20 24 61 72  {..switch -- $ar
0700: 67 4e 61 6d 65 20 7b 0a 09 09 22 70 61 73 73 77  gName {..."passw
0710: 6f 72 64 4e 61 6d 65 22 20 7b 0a 09 09 09 72 65  ordName" {....re
0720: 74 75 72 6e 20 22 24 61 72 67 4e 61 6d 65 20 2d  turn "$argName -
0730: 20 4e 61 6d 65 20 6f 66 20 74 68 65 20 70 61 73   Name of the pas
0740: 73 77 6f 72 64 20 65 6e 74 72 79 22 0a 09 09 7d  sword entry"...}
0750: 0a 09 09 22 6b 65 79 22 20 7b 0a 09 09 09 72 65  ..."key" {....re
0760: 74 75 72 6e 20 22 24 61 72 67 4e 61 6d 65 20 2d  turn "$argName -
0770: 20 50 75 62 6c 69 63 20 6b 65 79 20 6f 66 20 74   Public key of t
0780: 68 65 20 75 73 65 72 22 0a 09 09 7d 0a 09 09 22  he user"...}..."
0790: 70 61 73 73 77 6f 72 64 22 20 7b 0a 09 09 09 72  password" {....r
07a0: 65 74 75 72 6e 20 22 24 61 72 67 4e 61 6d 65 20  eturn "$argName 
07b0: 2d 20 41 20 70 6c 61 69 6e 2d 74 65 78 74 20 70  - A plain-text p
07c0: 61 73 73 77 6f 72 64 22 0a 09 09 7d 0a 09 09 22  assword"...}..."
07d0: 75 73 65 72 4e 61 6d 65 22 20 7b 0a 09 09 09 72  userName" {....r
07e0: 65 74 75 72 6e 20 22 24 61 72 67 4e 61 6d 65 20  eturn "$argName 
07f0: 2d 20 41 20 75 73 65 72 20 6e 61 6d 65 22 0a 09  - A user name"..
0800: 09 7d 0a 09 09 22 61 63 74 69 6f 6e 22 20 7b 0a  .}..."action" {.
0810: 09 09 09 72 65 74 75 72 6e 20 22 24 61 72 67 4e  ...return "$argN
0820: 61 6d 65 20 2d 20 41 6e 20 61 63 74 69 6f 6e 20  ame - An action 
0830: 6e 61 6d 65 20 66 6f 72 20 68 65 6c 70 20 77 69  name for help wi
0840: 74 68 22 0a 09 09 7d 0a 09 09 22 61 72 67 73 22  th"...}..."args"
0850: 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 22 75 73   {....return "us
0860: 65 72 4c 69 73 74 20 2d 20 41 20 6c 69 73 74 20  erList - A list 
0870: 6f 66 20 75 73 65 72 6e 61 6d 65 73 22 0a 09 09  of usernames"...
0880: 7d 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 20 22 3c  }..}...return "<
0890: 55 4e 4b 4e 4f 57 4e 3e 22 0a 7d 0a 0a 70 72 6f  UNKNOWN>".}..pro
08a0: 63 20 5f 70 72 69 6e 74 48 65 6c 70 20 7b 63 68  c _printHelp {ch
08b0: 61 6e 6e 65 6c 20 63 6f 6d 6d 61 6e 64 7d 20 7b  annel command} {
08c0: 0a 09 69 66 20 7b 24 63 6f 6d 6d 61 6e 64 20 3d  ..if {$command =
08d0: 3d 20 22 22 7d 20 7b 0a 09 09 70 75 74 73 20 24  = ""} {...puts $
08e0: 63 68 61 6e 6e 65 6c 20 22 55 73 61 67 65 3a 20  channel "Usage: 
08f0: 68 75 6e 74 65 72 32 20 3c 70 61 73 73 77 6f 72  hunter2 <passwor
0900: 64 46 69 6c 65 3e 20 3c 61 63 74 69 6f 6e 3e 20  dFile> <action> 
0910: 5c 5b 3c 61 63 74 69 6f 6e 41 72 67 73 2e 2e 2e  \[<actionArgs...
0920: 3e 5c 5d 22 0a 09 09 70 75 74 73 20 24 63 68 61  >\]"...puts $cha
0930: 6e 6e 65 6c 20 22 22 0a 09 09 70 75 74 73 20 24  nnel ""...puts $
0940: 63 68 61 6e 6e 65 6c 20 22 41 63 74 69 6f 6e 73  channel "Actions
0950: 3a 22 0a 09 09 70 75 74 73 20 24 63 68 61 6e 6e  :"...puts $chann
0960: 65 6c 20 22 20 20 20 20 5b 6a 6f 69 6e 20 24 3a  el "    [join $:
0970: 3a 76 61 6c 69 64 43 6f 6d 6d 61 6e 64 73 20 7b  :validCommands {
0980: 2c 20 7d 5d 22 0a 09 09 70 75 74 73 20 24 63 68  , }]"...puts $ch
0990: 61 6e 6e 65 6c 20 22 22 0a 09 09 70 75 74 73 20  annel ""...puts 
09a0: 24 63 68 61 6e 6e 65 6c 20 22 20 20 20 20 68 75  $channel "    hu
09b0: 6e 74 65 72 32 20 3c 66 69 6c 65 3e 20 68 65 6c  nter2 <file> hel
09c0: 70 20 3c 61 63 74 69 6f 6e 3e 20 20 20 20 66 6f  p <action>    fo
09d0: 72 20 68 65 6c 70 20 77 69 74 68 20 61 6e 20 61  r help with an a
09e0: 63 74 69 6f 6e 22 0a 09 7d 20 65 6c 73 65 20 7b  ction"..} else {
09f0: 0a 09 09 73 65 74 20 61 72 67 73 20 5b 69 6e 66  ...set args [inf
0a00: 6f 20 61 72 67 73 20 24 63 6f 6d 6d 61 6e 64 5d  o args $command]
0a10: 0a 09 09 73 65 74 20 70 72 69 6e 74 41 72 67 73  ...set printArgs
0a20: 20 5b 6c 69 73 74 5d 0a 09 09 66 6f 72 65 61 63   [list]...foreac
0a30: 68 20 61 72 67 20 24 61 72 67 73 20 7b 0a 09 09  h arg $args {...
0a40: 09 69 66 20 7b 24 61 72 67 20 3d 3d 20 22 61 72  .if {$arg == "ar
0a50: 67 73 22 7d 20 7b 0a 09 09 09 09 73 65 74 20 61  gs"} {.....set a
0a60: 72 67 20 22 75 73 65 72 4c 69 73 74 22 0a 09 09  rg "userList"...
0a70: 09 7d 0a 09 09 09 6c 61 70 70 65 6e 64 20 70 72  .}....lappend pr
0a80: 69 6e 74 41 72 67 73 20 22 3c 24 61 72 67 3e 22  intArgs "<$arg>"
0a90: 0a 09 09 7d 0a 0a 09 09 70 75 74 73 20 24 63 68  ...}....puts $ch
0aa0: 61 6e 6e 65 6c 20 22 55 73 61 67 65 3a 20 68 75  annel "Usage: hu
0ab0: 6e 74 65 72 32 20 3c 70 61 73 73 77 6f 72 64 46  nter2 <passwordF
0ac0: 69 6c 65 3e 20 24 63 6f 6d 6d 61 6e 64 20 5b 6a  ile> $command [j
0ad0: 6f 69 6e 20 24 70 72 69 6e 74 41 72 67 73 5d 22  oin $printArgs]"
0ae0: 0a 0a 09 09 69 66 20 7b 5b 6c 6c 65 6e 67 74 68  ....if {[llength
0af0: 20 24 61 72 67 73 5d 20 3e 20 30 7d 20 7b 0a 09   $args] > 0} {..
0b00: 09 09 70 75 74 73 20 24 63 68 61 6e 6e 65 6c 20  ..puts $channel 
0b10: 22 22 0a 09 09 09 70 75 74 73 20 24 63 68 61 6e  ""....puts $chan
0b20: 6e 65 6c 20 22 41 72 67 75 6d 65 6e 74 73 3a 22  nel "Arguments:"
0b30: 0a 09 09 09 66 6f 72 65 61 63 68 20 61 72 67 20  ....foreach arg 
0b40: 24 61 72 67 73 20 7b 0a 09 09 09 09 70 75 74 73  $args {.....puts
0b50: 20 24 63 68 61 6e 6e 65 6c 20 22 20 20 20 20 5b   $channel "    [
0b60: 5f 61 72 67 44 65 73 63 72 69 70 74 69 6f 6e 20  _argDescription 
0b70: 24 63 6f 6d 6d 61 6e 64 20 24 61 72 67 5d 22 0a  $command $arg]".
0b80: 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a 7d 0a 0a 69  ...}...}..}.}..i
0b90: 66 20 7b 5b 6c 6c 65 6e 67 74 68 20 24 61 72 67  f {[llength $arg
0ba0: 76 5d 20 3c 20 32 7d 20 7b 0a 09 5f 70 72 69 6e  v] < 2} {.._prin
0bb0: 74 48 65 6c 70 20 73 74 64 65 72 72 20 22 22 0a  tHelp stderr "".
0bc0: 0a 09 65 78 69 74 20 31 0a 7d 0a 0a 73 65 74 20  ..exit 1.}..set 
0bd0: 61 72 67 76 20 5b 6c 72 61 6e 67 65 20 24 61 72  argv [lrange $ar
0be0: 67 76 20 32 20 65 6e 64 5d 0a 0a 70 61 63 6b 61  gv 2 end]..packa
0bf0: 67 65 20 72 65 71 75 69 72 65 20 73 71 6c 69 74  ge require sqlit
0c00: 65 33 0a 70 61 63 6b 61 67 65 20 72 65 71 75 69  e3.package requi
0c10: 72 65 20 70 6c 61 74 66 6f 72 6d 0a 0a 6c 61 70  re platform..lap
0c20: 70 65 6e 64 20 3a 3a 61 75 74 6f 5f 70 61 74 68  pend ::auto_path
0c30: 20 5b 66 69 6c 65 20 6a 6f 69 6e 20 5b 66 69 6c   [file join [fil
0c40: 65 20 64 69 72 6e 61 6d 65 20 5b 69 6e 66 6f 20  e dirname [info 
0c50: 73 63 72 69 70 74 5d 5d 20 6c 69 62 20 5b 70 6c  script]] lib [pl
0c60: 61 74 66 6f 72 6d 3a 3a 69 64 65 6e 74 69 66 79  atform::identify
0c70: 5d 5d 0a 6c 61 70 70 65 6e 64 20 3a 3a 61 75 74  ]].lappend ::aut
0c80: 6f 5f 70 61 74 68 20 5b 66 69 6c 65 20 6a 6f 69  o_path [file joi
0c90: 6e 20 5b 66 69 6c 65 20 64 69 72 6e 61 6d 65 20  n [file dirname 
0ca0: 5b 69 6e 66 6f 20 73 63 72 69 70 74 5d 5d 20 6c  [info script]] l
0cb0: 69 62 20 5b 70 6c 61 74 66 6f 72 6d 3a 3a 67 65  ib [platform::ge
0cc0: 6e 65 72 69 63 5d 5d 0a 6c 61 70 70 65 6e 64 20  neric]].lappend 
0cd0: 3a 3a 61 75 74 6f 5f 70 61 74 68 20 5b 66 69 6c  ::auto_path [fil
0ce0: 65 20 6a 6f 69 6e 20 5b 66 69 6c 65 20 64 69 72  e join [file dir
0cf0: 6e 61 6d 65 20 5b 69 6e 66 6f 20 73 63 72 69 70  name [info scrip
0d00: 74 5d 5d 20 6c 69 62 5d 0a 0a 70 61 63 6b 61 67  t]] lib]..packag
0d10: 65 20 72 65 71 75 69 72 65 20 70 6b 69 0a 70 61  e require pki.pa
0d20: 63 6b 61 67 65 20 72 65 71 75 69 72 65 20 70 6b  ckage require pk
0d30: 69 3a 3a 70 6b 63 73 31 31 0a 70 61 63 6b 61 67  i::pkcs11.packag
0d40: 65 20 72 65 71 75 69 72 65 20 61 65 73 0a 70 61  e require aes.pa
0d50: 63 6b 61 67 65 20 72 65 71 75 69 72 65 20 73 68  ckage require sh
0d60: 61 32 35 36 0a 0a 23 20 42 61 63 6b 70 6f 72 74  a256..# Backport
0d70: 73 20 66 6f 72 20 6f 6c 64 65 72 20 76 65 72 73  s for older vers
0d80: 69 6f 6e 73 20 6f 66 20 22 70 6b 69 22 0a 70 72  ions of "pki".pr
0d90: 6f 63 20 3a 3a 70 6b 69 3a 3a 70 6b 63 73 3a 3a  oc ::pki::pkcs::
0da0: 70 61 72 73 65 5f 70 75 62 6c 69 63 5f 6b 65 79  parse_public_key
0db0: 20 7b 6b 65 79 20 7b 70 61 73 73 77 6f 72 64 20   {key {password 
0dc0: 22 22 7d 7d 20 7b 0a 20 20 20 20 20 20 20 20 61  ""}} {.        a
0dd0: 72 72 61 79 20 73 65 74 20 70 61 72 73 65 64 5f  rray set parsed_
0de0: 6b 65 79 20 5b 3a 3a 70 6b 69 3a 3a 5f 70 61 72  key [::pki::_par
0df0: 73 65 5f 70 65 6d 20 24 6b 65 79 20 22 2d 2d 2d  se_pem $key "---
0e00: 2d 2d 42 45 47 49 4e 20 50 55 42 4c 49 43 20 4b  --BEGIN PUBLIC K
0e10: 45 59 2d 2d 2d 2d 2d 22 20 22 2d 2d 2d 2d 2d 45  EY-----" "-----E
0e20: 4e 44 20 50 55 42 4c 49 43 20 4b 45 59 2d 2d 2d  ND PUBLIC KEY---
0e30: 2d 2d 22 20 24 70 61 73 73 77 6f 72 64 5d 0a 0a  --" $password]..
0e40: 20 20 20 20 20 20 20 20 73 65 74 20 6b 65 79 5f          set key_
0e50: 73 65 71 20 24 70 61 72 73 65 64 5f 6b 65 79 28  seq $parsed_key(
0e60: 64 61 74 61 29 0a 0a 20 20 20 20 20 20 20 20 3a  data)..        :
0e70: 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 53 65 71 75  :asn::asnGetSequ
0e80: 65 6e 63 65 20 6b 65 79 5f 73 65 71 20 70 75 62  ence key_seq pub
0e90: 6b 65 79 69 6e 66 6f 0a 20 20 20 20 20 20 20 20  keyinfo.        
0ea0: 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61          ::asn::a
0eb0: 73 6e 47 65 74 53 65 71 75 65 6e 63 65 20 70 75  snGetSequence pu
0ec0: 62 6b 65 79 69 6e 66 6f 20 70 75 62 6b 65 79 5f  bkeyinfo pubkey_
0ed0: 61 6c 67 6f 69 64 0a 20 20 20 20 20 20 20 20 20  algoid.         
0ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 3a                 :
0ef0: 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 4f 62 6a 65  :asn::asnGetObje
0f00: 63 74 49 64 65 6e 74 69 66 69 65 72 20 70 75 62  ctIdentifier pub
0f10: 6b 65 79 5f 61 6c 67 6f 69 64 20 6f 69 64 0a 20  key_algoid oid. 
0f20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 3a                 :
0f30: 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 42 69 74 53  :asn::asnGetBitS
0f40: 74 72 69 6e 67 20 70 75 62 6b 65 79 69 6e 66 6f  tring pubkeyinfo
0f50: 20 70 75 62 6b 65 79 0a 20 20 20 20 20 20 20 20   pubkey.        
0f60: 73 65 74 20 72 65 74 28 70 75 62 6b 65 79 5f 61  set ret(pubkey_a
0f70: 6c 67 6f 29 20 5b 3a 3a 70 6b 69 3a 3a 5f 6f 69  lgo) [::pki::_oi
0f80: 64 5f 6e 75 6d 62 65 72 5f 74 6f 5f 6e 61 6d 65  d_number_to_name
0f90: 20 24 6f 69 64 5d 0a 0a 20 20 20 20 20 20 20 20   $oid]..        
0fa0: 73 77 69 74 63 68 20 2d 2d 20 24 72 65 74 28 70  switch -- $ret(p
0fb0: 75 62 6b 65 79 5f 61 6c 67 6f 29 20 7b 0a 20 20  ubkey_algo) {.  
0fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 72                "r
0fd0: 73 61 45 6e 63 72 79 70 74 69 6f 6e 22 20 7b 0a  saEncryption" {.
0fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ff0: 20 20 20 20 20 20 20 20 73 65 74 20 70 75 62 6b          set pubk
1000: 65 79 20 5b 62 69 6e 61 72 79 20 66 6f 72 6d 61  ey [binary forma
1010: 74 20 42 2a 20 24 70 75 62 6b 65 79 5d 0a 0a 20  t B* $pubkey].. 
1020: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1030: 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61 73         ::asn::as
1040: 6e 47 65 74 53 65 71 75 65 6e 63 65 20 70 75 62  nGetSequence pub
1050: 6b 65 79 20 70 75 62 6b 65 79 5f 70 61 72 74 73  key pubkey_parts
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 20 20 20 20 20 20 20                  
1080: 20 3a 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 42 69   ::asn::asnGetBi
1090: 67 49 6e 74 65 67 65 72 20 70 75 62 6b 65 79 5f  gInteger pubkey_
10a0: 70 61 72 74 73 20 72 65 74 28 6e 29 0a 20 20 20  parts ret(n).   
10b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
10c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 3a 3a 61               ::a
10d0: 73 6e 3a 3a 61 73 6e 47 65 74 42 69 67 49 6e 74  sn::asnGetBigInt
10e0: 65 67 65 72 20 70 75 62 6b 65 79 5f 70 61 72 74  eger pubkey_part
10f0: 73 20 72 65 74 28 65 29 0a 0a 20 20 20 20 20 20  s ret(e)..      
1100: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1110: 20 20 73 65 74 20 72 65 74 28 6e 29 20 5b 3a 3a    set ret(n) [::
1120: 6d 61 74 68 3a 3a 62 69 67 6e 75 6d 3a 3a 74 6f  math::bignum::to
1130: 73 74 72 20 24 72 65 74 28 6e 29 5d 0a 20 20 20  str $ret(n)].   
1140: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1150: 20 20 20 20 20 73 65 74 20 72 65 74 28 65 29 20       set ret(e) 
1160: 5b 3a 3a 6d 61 74 68 3a 3a 62 69 67 6e 75 6d 3a  [::math::bignum:
1170: 3a 74 6f 73 74 72 20 24 72 65 74 28 65 29 5d 0a  :tostr $ret(e)].
1180: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1190: 20 20 20 20 20 20 20 20 73 65 74 20 72 65 74 28          set ret(
11a0: 6c 29 20 5b 65 78 70 72 20 7b 69 6e 74 28 5b 3a  l) [expr {int([:
11b0: 3a 70 6b 69 3a 3a 5f 62 69 74 73 20 24 72 65 74  :pki::_bits $ret
11c0: 28 6e 29 5d 20 2f 20 38 2e 30 30 30 30 20 2b 20  (n)] / 8.0000 + 
11d0: 30 2e 35 29 20 2a 20 38 7d 5d 0a 20 20 20 20 20  0.5) * 8}].     
11e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
11f0: 20 20 20 73 65 74 20 72 65 74 28 74 79 70 65 29     set ret(type)
1200: 20 72 73 61 0a 20 20 20 20 20 20 20 20 20 20 20   rsa.           
1210: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 20       }.         
1220: 20 20 20 20 20 20 20 64 65 66 61 75 6c 74 20 7b         default {
1230: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1240: 20 20 20 20 20 20 20 20 20 65 72 72 6f 72 20 22           error "
1250: 55 6e 6b 6e 6f 77 6e 20 61 6c 67 6f 72 69 74 68  Unknown algorith
1260: 6d 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  m".             
1270: 20 20 20 7d 0a 20 20 20 20 20 20 20 20 7d 0a 0a     }.        }..
1280: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b          return [
1290: 61 72 72 61 79 20 67 65 74 20 72 65 74 5d 0a 7d  array get ret].}
12a0: 0a 0a 70 72 6f 63 20 3a 3a 70 6b 69 3a 3a 72 73  ..proc ::pki::rs
12b0: 61 3a 3a 73 65 72 69 61 6c 69 7a 65 5f 70 75 62  a::serialize_pub
12c0: 6c 69 63 5f 6b 65 79 20 7b 6b 65 79 6c 69 73 74  lic_key {keylist
12d0: 7d 20 7b 0a 20 20 20 20 20 20 20 20 61 72 72 61  } {.        arra
12e0: 79 20 73 65 74 20 6b 65 79 20 24 6b 65 79 6c 69  y set key $keyli
12f0: 73 74 0a 0a 20 20 20 20 20 20 20 20 66 6f 72 65  st..        fore
1300: 61 63 68 20 65 6e 74 72 79 20 5b 6c 69 73 74 20  ach entry [list 
1310: 6e 20 65 5d 20 7b 0a 20 20 20 20 20 20 20 20 20  n e] {.         
1320: 20 20 20 20 20 20 20 69 66 20 7b 21 5b 69 6e 66         if {![inf
1330: 6f 20 65 78 69 73 74 73 20 6b 65 79 28 24 65 6e  o exists key($en
1340: 74 72 79 29 5d 7d 20 7b 0a 20 20 20 20 20 20 20  try)]} {.       
1350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1360: 20 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72   return -code er
1370: 72 6f 72 20 22 4b 65 79 20 64 6f 65 73 20 6e 6f  ror "Key does no
1380: 74 20 63 6f 6e 74 61 69 6e 20 61 6e 20 65 6c 65  t contain an ele
1390: 6d 65 6e 74 20 24 65 6e 74 72 79 22 0a 20 20 20  ment $entry".   
13a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 7d 0a 20               }. 
13b0: 20 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20         }..      
13c0: 20 20 73 65 74 20 70 75 62 6b 65 79 20 5b 3a 3a    set pubkey [::
13d0: 61 73 6e 3a 3a 61 73 6e 53 65 71 75 65 6e 63 65  asn::asnSequence
13e0: 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   \.             
13f0: 20 20 20 5b 3a 3a 61 73 6e 3a 3a 61 73 6e 42 69     [::asn::asnBi
1400: 67 49 6e 74 65 67 65 72 20 5b 3a 3a 6d 61 74 68  gInteger [::math
1410: 3a 3a 62 69 67 6e 75 6d 3a 3a 66 72 6f 6d 73 74  ::bignum::fromst
1420: 72 20 24 6b 65 79 28 6e 29 5d 5d 20 5c 0a 20 20  r $key(n)]] \.  
1430: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 5b 3a                [:
1440: 3a 61 73 6e 3a 3a 61 73 6e 42 69 67 49 6e 74 65  :asn::asnBigInte
1450: 67 65 72 20 5b 3a 3a 6d 61 74 68 3a 3a 62 69 67  ger [::math::big
1460: 6e 75 6d 3a 3a 66 72 6f 6d 73 74 72 20 24 6b 65  num::fromstr $ke
1470: 79 28 65 29 5d 5d 20 5c 0a 20 20 20 20 20 20 20  y(e)]] \.       
1480: 20 20 20 20 20 20 20 20 20 5d 20 20 0a 20 20 20           ]  .   
1490: 20 20 20 20 20 73 65 74 20 70 75 62 6b 65 79 5f       set pubkey_
14a0: 61 6c 67 6f 5f 70 61 72 61 6d 73 20 5b 3a 3a 61  algo_params [::a
14b0: 73 6e 3a 3a 61 73 6e 4e 75 6c 6c 5d 0a 0a 20 20  sn::asnNull]..  
14c0: 20 20 20 20 20 20 62 69 6e 61 72 79 20 73 63 61        binary sca
14d0: 6e 20 24 70 75 62 6b 65 79 20 42 2a 20 70 75 62  n $pubkey B* pub
14e0: 6b 65 79 5f 62 69 74 73 74 72 69 6e 67 0a 0a 20  key_bitstring.. 
14f0: 20 20 20 20 20 20 20 73 65 74 20 72 65 74 20 5b         set ret [
1500: 3a 3a 61 73 6e 3a 3a 61 73 6e 53 65 71 75 65 6e  ::asn::asnSequen
1510: 63 65 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20  ce \.           
1520: 20 20 20 20 20 5b 3a 3a 61 73 6e 3a 3a 61 73 6e       [::asn::asn
1530: 53 65 71 75 65 6e 63 65 20 5c 0a 20 20 20 20 20  Sequence \.     
1540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1550: 20 20 20 20 20 20 20 20 20 20 20 5b 3a 3a 61 73             [::as
1560: 6e 3a 3a 61 73 6e 4f 62 6a 65 63 74 49 64 65 6e  n::asnObjectIden
1570: 74 69 66 69 65 72 20 5b 3a 3a 70 6b 69 3a 3a 5f  tifier [::pki::_
1580: 6f 69 64 5f 6e 61 6d 65 5f 74 6f 5f 6e 75 6d 62  oid_name_to_numb
1590: 65 72 20 72 73 61 45 6e 63 72 79 70 74 69 6f 6e  er rsaEncryption
15a0: 5d 5d 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20  ]] \.           
15b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15c0: 20 20 20 20 20 24 70 75 62 6b 65 79 5f 61 6c 67       $pubkey_alg
15d0: 6f 5f 70 61 72 61 6d 73 20 5c 0a 20 20 20 20 20  o_params \.     
15e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15f0: 20 20 20 5d 20 5c 0a 20 20 20 20 20 20 20 20 20     ] \.         
1600: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 5b                 [
1610: 3a 3a 61 73 6e 3a 3a 61 73 6e 42 69 74 53 74 72  ::asn::asnBitStr
1620: 69 6e 67 20 24 70 75 62 6b 65 79 5f 62 69 74 73  ing $pubkey_bits
1630: 74 72 69 6e 67 5d 20 5c 0a 20 20 20 20 20 20 20  tring] \.       
1640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1650: 20 5d 0a 0a 20 20 20 20 20 20 20 20 72 65 74 75   ]..        retu
1660: 72 6e 20 5b 6c 69 73 74 20 64 61 74 61 20 24 72  rn [list data $r
1670: 65 74 20 62 65 67 69 6e 20 22 2d 2d 2d 2d 2d 42  et begin "-----B
1680: 45 47 49 4e 20 50 55 42 4c 49 43 20 4b 45 59 2d  EGIN PUBLIC KEY-
1690: 2d 2d 2d 2d 22 20 65 6e 64 20 22 2d 2d 2d 2d 2d  ----" end "-----
16a0: 45 4e 44 20 50 55 42 4c 49 43 20 4b 45 59 2d 2d  END PUBLIC KEY--
16b0: 2d 2d 2d 22 5d 0a 7d 0a 23 20 45 6e 64 20 62 61  ---"].}.# End ba
16c0: 63 6b 70 6f 72 74 73 0a 0a 23 20 53 74 61 72 74  ckports..# Start
16d0: 20 69 6e 74 65 72 6e 61 6c 20 66 75 6e 63 74 69   internal functi
16e0: 6f 6e 73 0a 70 72 6f 63 20 5f 6c 69 73 74 43 65  ons.proc _listCe
16f0: 72 74 69 66 69 63 61 74 65 73 20 7b 7d 20 7b 0a  rtificates {} {.
1700: 09 69 66 20 7b 21 5b 69 6e 66 6f 20 65 78 69 73  .if {![info exis
1710: 74 73 20 3a 3a 65 6e 76 28 50 4b 43 53 31 31 4d  ts ::env(PKCS11M
1720: 4f 44 55 4c 45 29 5d 7d 20 7b 0a 09 09 72 65 74  ODULE)]} {...ret
1730: 75 72 6e 20 5b 6c 69 73 74 5d 0a 09 7d 0a 0a 09  urn [list]..}...
1740: 73 65 74 20 3a 3a 65 6e 76 28 43 41 43 4b 45 59  set ::env(CACKEY
1750: 5f 4e 4f 5f 45 58 54 52 41 5f 43 45 52 54 53 29  _NO_EXTRA_CERTS)
1760: 20 31 0a 0a 09 73 65 74 20 68 61 6e 64 6c 65 20   1...set handle 
1770: 5b 3a 3a 70 6b 69 3a 3a 70 6b 63 73 31 31 3a 3a  [::pki::pkcs11::
1780: 6c 6f 61 64 6d 6f 64 75 6c 65 20 24 3a 3a 65 6e  loadmodule $::en
1790: 76 28 50 4b 43 53 31 31 4d 4f 44 55 4c 45 29 5d  v(PKCS11MODULE)]
17a0: 0a 0a 09 73 65 74 20 73 6c 6f 74 49 6e 66 6f 20  ...set slotInfo 
17b0: 5b 6c 69 73 74 5d 0a 09 66 6f 72 65 61 63 68 20  [list]..foreach 
17c0: 73 6c 6f 74 20 5b 3a 3a 70 6b 69 3a 3a 70 6b 63  slot [::pki::pkc
17d0: 73 31 31 3a 3a 6c 69 73 74 73 6c 6f 74 73 20 24  s11::listslots $
17e0: 68 61 6e 64 6c 65 5d 20 7b 0a 09 09 73 65 74 20  handle] {...set 
17f0: 73 6c 6f 74 49 44 20 5b 6c 69 6e 64 65 78 20 24  slotID [lindex $
1800: 73 6c 6f 74 20 30 5d 0a 09 09 73 65 74 20 73 6c  slot 0]...set sl
1810: 6f 74 4c 61 62 65 6c 20 5b 6c 69 6e 64 65 78 20  otLabel [lindex 
1820: 24 73 6c 6f 74 20 31 5d 0a 09 09 73 65 74 20 73  $slot 1]...set s
1830: 6c 6f 74 46 6c 61 67 73 20 5b 6c 69 6e 64 65 78  lotFlags [lindex
1840: 20 24 73 6c 6f 74 20 32 5d 0a 0a 09 09 69 66 20   $slot 2]....if 
1850: 7b 22 54 4f 4b 45 4e 5f 50 52 45 53 45 4e 54 22  {"TOKEN_PRESENT"
1860: 20 6e 69 20 24 73 6c 6f 74 46 6c 61 67 73 7d 20   ni $slotFlags} 
1870: 7b 0a 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09  {....continue...
1880: 7d 0a 0a 09 09 69 66 20 7b 22 54 4f 4b 45 4e 5f  }....if {"TOKEN_
1890: 49 4e 49 54 49 41 4c 49 5a 45 44 22 20 6e 69 20  INITIALIZED" ni 
18a0: 24 73 6c 6f 74 46 6c 61 67 73 7d 20 7b 0a 09 09  $slotFlags} {...
18b0: 09 63 6f 6e 74 69 6e 75 65 0a 09 09 7d 0a 0a 09  .continue...}...
18c0: 09 73 65 74 20 73 6c 6f 74 50 72 6f 6d 70 74 46  .set slotPromptF
18d0: 6f 72 50 49 4e 20 66 61 6c 73 65 0a 09 09 69 66  orPIN false...if
18e0: 20 7b 22 50 52 4f 54 45 43 54 45 44 5f 41 55 54   {"PROTECTED_AUT
18f0: 48 45 4e 54 49 43 41 54 49 4f 4e 5f 50 41 54 48  HENTICATION_PATH
1900: 22 20 6e 69 20 24 73 6c 6f 74 46 6c 61 67 73 7d  " ni $slotFlags}
1910: 20 7b 0a 09 09 09 69 66 20 7b 22 4c 4f 47 49 4e   {....if {"LOGIN
1920: 5f 52 45 51 55 49 52 45 44 22 20 69 6e 20 24 73  _REQUIRED" in $s
1930: 6c 6f 74 46 6c 61 67 73 7d 20 7b 0a 09 09 09 09  lotFlags} {.....
1940: 73 65 74 20 73 6c 6f 74 50 72 6f 6d 70 74 46 6f  set slotPromptFo
1950: 72 50 49 4e 20 74 72 75 65 0a 09 09 09 7d 0a 09  rPIN true....}..
1960: 09 7d 0a 0a 09 09 66 6f 72 65 61 63 68 20 63 65  .}....foreach ce
1970: 72 74 20 5b 3a 3a 70 6b 69 3a 3a 70 6b 63 73 31  rt [::pki::pkcs1
1980: 31 3a 3a 6c 69 73 74 63 65 72 74 73 20 24 68 61  1::listcerts $ha
1990: 6e 64 6c 65 20 24 73 6c 6f 74 49 44 5d 20 7b 0a  ndle $slotID] {.
19a0: 09 09 09 73 65 74 20 70 75 62 6b 65 79 20 5b 62  ...set pubkey [b
19b0: 69 6e 61 72 79 20 65 6e 63 6f 64 65 20 62 61 73  inary encode bas
19c0: 65 36 34 20 5b 64 69 63 74 20 67 65 74 20 5b 3a  e64 [dict get [:
19d0: 3a 70 6b 69 3a 3a 72 73 61 3a 3a 73 65 72 69 61  :pki::rsa::seria
19e0: 6c 69 7a 65 5f 70 75 62 6c 69 63 5f 6b 65 79 20  lize_public_key 
19f0: 24 63 65 72 74 5d 20 64 61 74 61 5d 5d 0a 0a 09  $cert] data]]...
1a00: 09 09 6c 61 70 70 65 6e 64 20 73 6c 6f 74 49 6e  ..lappend slotIn
1a10: 66 6f 20 5b 6c 69 73 74 20 68 61 6e 64 6c 65 20  fo [list handle 
1a20: 24 68 61 6e 64 6c 65 20 69 64 20 24 73 6c 6f 74  $handle id $slot
1a30: 49 44 20 70 72 6f 6d 70 74 20 24 73 6c 6f 74 50  ID prompt $slotP
1a40: 72 6f 6d 70 74 46 6f 72 50 49 4e 20 63 65 72 74  romptForPIN cert
1a50: 20 24 63 65 72 74 20 70 75 62 6b 65 79 20 24 70   $cert pubkey $p
1a60: 75 62 6b 65 79 5d 0a 09 09 7d 0a 09 7d 0a 0a 09  ubkey]...}..}...
1a70: 72 65 74 75 72 6e 20 24 73 6c 6f 74 49 6e 66 6f  return $slotInfo
1a80: 0a 7d 0a 0a 70 72 6f 63 20 5f 76 65 72 69 66 79  .}..proc _verify
1a90: 50 61 73 73 77 6f 72 64 20 7b 6e 61 6d 65 20 70  Password {name p
1aa0: 61 73 73 77 6f 72 64 7d 20 7b 0a 09 73 65 74 20  assword} {..set 
1ab0: 70 75 62 6c 69 63 4b 65 79 73 20 5b 6c 69 73 74  publicKeys [list
1ac0: 5d 0a 0a 09 64 62 20 65 76 61 6c 20 7b 53 45 4c  ]...db eval {SEL
1ad0: 45 43 54 20 70 75 62 6c 69 63 4b 65 79 2c 20 76  ECT publicKey, v
1ae0: 65 72 69 66 69 63 61 74 69 6f 6e 20 46 52 4f 4d  erification FROM
1af0: 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45   passwords WHERE
1b00: 20 6e 61 6d 65 20 3d 20 24 6e 61 6d 65 7d 20 72   name = $name} r
1b10: 6f 77 20 7b 0a 09 09 73 65 74 20 73 61 6c 74 20  ow {...set salt 
1b20: 5b 64 69 63 74 20 67 65 74 20 24 72 6f 77 28 76  [dict get $row(v
1b30: 65 72 69 66 69 63 61 74 69 6f 6e 29 20 73 61 6c  erification) sal
1b40: 74 5d 0a 09 09 73 65 74 20 68 61 73 68 41 6c 67  t]...set hashAlg
1b50: 6f 72 69 74 68 6d 20 5b 64 69 63 74 20 67 65 74  orithm [dict get
1b60: 20 24 72 6f 77 28 76 65 72 69 66 69 63 61 74 69   $row(verificati
1b70: 6f 6e 29 20 68 61 73 68 41 6c 67 6f 72 69 74 68  on) hashAlgorith
1b80: 6d 5d 0a 09 09 73 65 74 20 70 75 62 6c 69 63 4b  m]...set publicK
1b90: 65 79 20 24 72 6f 77 28 70 75 62 6c 69 63 4b 65  ey $row(publicKe
1ba0: 79 29 0a 0a 09 09 73 65 74 20 70 6c 61 69 6e 74  y)....set plaint
1bb0: 65 78 74 20 22 24 7b 73 61 6c 74 7d 7c 24 7b 70  ext "${salt}|${p
1bc0: 75 62 6c 69 63 4b 65 79 7d 7c 24 7b 70 61 73 73  ublicKey}|${pass
1bd0: 77 6f 72 64 7d 22 0a 0a 09 09 73 77 69 74 63 68  word}"....switch
1be0: 20 2d 2d 20 24 68 61 73 68 41 6c 67 6f 72 69 74   -- $hashAlgorit
1bf0: 68 6d 20 7b 0a 09 09 09 22 73 68 61 32 35 36 22  hm {...."sha256"
1c00: 20 7b 0a 09 09 09 09 73 65 74 20 76 65 72 69 66   {.....set verif
1c10: 69 63 61 74 69 6f 6e 48 61 73 68 20 5b 73 68 61  icationHash [sha
1c20: 32 3a 3a 73 68 61 32 35 36 20 2d 68 65 78 20 2d  2::sha256 -hex -
1c30: 2d 20 24 70 6c 61 69 6e 74 65 78 74 5d 0a 09 09  - $plaintext]...
1c40: 09 7d 0a 09 09 09 64 65 66 61 75 6c 74 20 7b 0a  .}....default {.
1c50: 09 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65  ....return -code
1c60: 20 65 72 72 6f 72 20 22 55 6e 6b 6e 6f 77 6e 20   error "Unknown 
1c70: 68 61 73 68 69 6e 67 20 61 6c 67 6f 72 69 74 68  hashing algorith
1c80: 6d 3a 20 24 68 61 73 68 41 6c 67 6f 72 69 74 68  m: $hashAlgorith
1c90: 6d 22 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 09 73  m"....}...}....s
1ca0: 65 74 20 72 6f 77 28 76 65 72 69 66 69 63 61 74  et row(verificat
1cb0: 69 6f 6e 48 61 73 68 29 20 5b 64 69 63 74 20 67  ionHash) [dict g
1cc0: 65 74 20 24 72 6f 77 28 76 65 72 69 66 69 63 61  et $row(verifica
1cd0: 74 69 6f 6e 29 20 68 61 73 68 5d 0a 0a 09 09 69  tion) hash]....i
1ce0: 66 20 7b 24 76 65 72 69 66 69 63 61 74 69 6f 6e  f {$verification
1cf0: 48 61 73 68 20 6e 65 20 24 72 6f 77 28 76 65 72  Hash ne $row(ver
1d00: 69 66 69 63 61 74 69 6f 6e 48 61 73 68 29 7d 20  ificationHash)} 
1d10: 7b 0a 09 09 09 70 75 74 73 20 73 74 64 65 72 72  {....puts stderr
1d20: 20 22 46 41 49 4c 45 44 3a 20 76 65 72 69 66 69   "FAILED: verifi
1d30: 63 61 74 69 6f 6e 20 66 61 69 6c 65 64 20 66 6f  cation failed fo
1d40: 72 20 24 6e 61 6d 65 20 77 69 74 68 20 70 75 62  r $name with pub
1d50: 6c 69 63 20 6b 65 79 20 24 70 75 62 6c 69 63 4b  lic key $publicK
1d60: 65 79 20 2d 2d 20 69 74 20 77 69 6c 6c 20 6e 6f  ey -- it will no
1d70: 74 20 67 65 74 20 74 68 65 20 6e 65 77 20 70 61  t get the new pa
1d80: 73 73 77 6f 72 64 2e 22 0a 0a 09 09 09 63 6f 6e  ssword.".....con
1d90: 74 69 6e 75 65 0a 09 09 7d 0a 0a 09 09 6c 61 70  tinue...}....lap
1da0: 70 65 6e 64 20 70 75 62 6c 69 63 4b 65 79 73 20  pend publicKeys 
1db0: 24 70 75 62 6c 69 63 4b 65 79 0a 09 7d 0a 0a 09  $publicKey..}...
1dc0: 72 65 74 75 72 6e 20 24 70 75 62 6c 69 63 4b 65  return $publicKe
1dd0: 79 73 0a 7d 0a 0a 70 72 6f 63 20 5f 61 64 64 50  ys.}..proc _addP
1de0: 61 73 73 77 6f 72 64 20 7b 6e 61 6d 65 20 70 61  assword {name pa
1df0: 73 73 77 6f 72 64 20 70 75 62 6c 69 63 4b 65 79  ssword publicKey
1e00: 73 7d 20 7b 0a 09 73 65 74 20 66 64 20 5b 6f 70  s} {..set fd [op
1e10: 65 6e 20 22 2f 64 65 76 2f 75 72 61 6e 64 6f 6d  en "/dev/urandom
1e20: 22 20 72 5d 0a 09 66 63 6f 6e 66 69 67 75 72 65  " r]..fconfigure
1e30: 20 24 66 64 20 2d 74 72 61 6e 73 6c 61 74 69 6f   $fd -translatio
1e40: 6e 20 62 69 6e 61 72 79 0a 0a 09 73 65 74 20 6b  n binary...set k
1e50: 65 79 53 69 7a 65 20 31 36 0a 0a 09 23 20 50 61  eySize 16...# Pa
1e60: 64 20 74 68 65 20 70 61 73 73 77 6f 72 64 20 77  d the password w
1e70: 69 74 68 20 30 20 62 79 74 65 73 20 75 6e 74 69  ith 0 bytes unti
1e80: 6c 20 69 74 20 69 73 20 61 20 6d 75 6c 74 69 70  l it is a multip
1e90: 6c 65 20 6f 66 20 74 68 65 20 6b 65 79 20 73 69  le of the key si
1ea0: 7a 65 0a 09 73 65 74 20 62 6c 6f 63 6b 50 61 73  ze..set blockPas
1eb0: 73 77 6f 72 64 20 24 70 61 73 73 77 6f 72 64 0a  sword $password.
1ec0: 09 61 70 70 65 6e 64 20 62 6c 6f 63 6b 50 61 73  .append blockPas
1ed0: 73 77 6f 72 64 20 5b 73 74 72 69 6e 67 20 72 65  sword [string re
1ee0: 70 65 61 74 20 22 5c 78 30 30 22 20 5b 65 78 70  peat "\x00" [exp
1ef0: 72 20 7b 2d 5b 73 74 72 69 6e 67 20 6c 65 6e 67  r {-[string leng
1f00: 74 68 20 24 70 61 73 73 77 6f 72 64 5d 20 25 20  th $password] % 
1f10: 24 6b 65 79 53 69 7a 65 7d 5d 5d 0a 0a 09 64 62  $keySize}]]...db
1f20: 20 74 72 61 6e 73 61 63 74 69 6f 6e 20 7b 0a 09   transaction {..
1f30: 09 64 62 20 65 76 61 6c 20 7b 44 45 4c 45 54 45  .db eval {DELETE
1f40: 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20   FROM passwords 
1f50: 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 6e 61  WHERE name = $na
1f60: 6d 65 3b 7d 0a 0a 09 09 66 6f 72 65 61 63 68 20  me;}....foreach 
1f70: 70 75 62 6c 69 63 4b 65 79 20 24 70 75 62 6c 69  publicKey $publi
1f80: 63 4b 65 79 73 20 7b 0a 09 09 09 73 65 74 20 6b  cKeys {....set k
1f90: 65 79 20 5b 72 65 61 64 20 24 66 64 20 24 6b 65  ey [read $fd $ke
1fa0: 79 53 69 7a 65 5d 0a 09 09 09 69 66 20 7b 5b 73  ySize]....if {[s
1fb0: 74 72 69 6e 67 20 6c 65 6e 67 74 68 20 24 6b 65  tring length $ke
1fc0: 79 5d 20 21 3d 20 24 6b 65 79 53 69 7a 65 7d 20  y] != $keySize} 
1fd0: 7b 0a 09 09 09 09 63 6c 6f 73 65 20 24 66 64 0a  {.....close $fd.
1fe0: 0a 09 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64  .....return -cod
1ff0: 65 20 65 72 72 6f 72 20 22 45 52 52 4f 52 3a 20  e error "ERROR: 
2000: 53 68 6f 72 74 20 72 65 61 64 20 66 72 6f 6d 20  Short read from 
2010: 72 61 6e 64 6f 6d 20 64 65 76 69 63 65 22 0a 09  random device"..
2020: 09 09 7d 0a 0a 09 09 09 73 65 74 20 73 61 6c 74  ..}.....set salt
2030: 20 5b 72 65 61 64 20 24 66 64 20 24 6b 65 79 53   [read $fd $keyS
2040: 69 7a 65 5d 0a 09 09 09 73 65 74 20 73 61 6c 74  ize]....set salt
2050: 20 5b 62 69 6e 61 72 79 20 65 6e 63 6f 64 65 20   [binary encode 
2060: 62 61 73 65 36 34 20 24 73 61 6c 74 5d 0a 0a 09  base64 $salt]...
2070: 09 09 73 65 74 20 70 75 62 6c 69 63 4b 65 79 49  ..set publicKeyI
2080: 74 65 6d 20 5b 3a 3a 70 6b 69 3a 3a 70 6b 63 73  tem [::pki::pkcs
2090: 3a 3a 70 61 72 73 65 5f 70 75 62 6c 69 63 5f 6b  ::parse_public_k
20a0: 65 79 20 5b 62 69 6e 61 72 79 20 64 65 63 6f 64  ey [binary decod
20b0: 65 20 62 61 73 65 36 34 20 24 70 75 62 6c 69 63  e base64 $public
20c0: 4b 65 79 5d 5d 0a 0a 09 09 09 73 65 74 20 65 6e  Key]].....set en
20d0: 63 72 79 70 74 65 64 4b 65 79 20 5b 62 69 6e 61  cryptedKey [bina
20e0: 72 79 20 65 6e 63 6f 64 65 20 62 61 73 65 36 34  ry encode base64
20f0: 20 5b 3a 3a 70 6b 69 3a 3a 65 6e 63 72 79 70 74   [::pki::encrypt
2100: 20 2d 70 75 62 20 2d 62 69 6e 61 72 79 20 2d 2d   -pub -binary --
2110: 20 24 6b 65 79 20 24 70 75 62 6c 69 63 4b 65 79   $key $publicKey
2120: 49 74 65 6d 5d 5d 0a 0a 09 09 09 73 65 74 20 65  Item]].....set e
2130: 6e 63 72 79 70 74 65 64 50 61 73 73 20 5b 62 69  ncryptedPass [bi
2140: 6e 61 72 79 20 65 6e 63 6f 64 65 20 62 61 73 65  nary encode base
2150: 36 34 20 5b 3a 3a 61 65 73 3a 3a 61 65 73 20 2d  64 [::aes::aes -
2160: 64 69 72 20 65 6e 63 72 79 70 74 20 2d 6b 65 79  dir encrypt -key
2170: 20 24 6b 65 79 20 2d 2d 20 24 62 6c 6f 63 6b 50   $key -- $blockP
2180: 61 73 73 77 6f 72 64 5d 5d 0a 0a 09 09 09 73 65  assword]].....se
2190: 74 20 76 65 72 69 66 69 63 61 74 69 6f 6e 48 61  t verificationHa
21a0: 73 68 20 5b 73 68 61 32 3a 3a 73 68 61 32 35 36  sh [sha2::sha256
21b0: 20 2d 68 65 78 20 2d 2d 20 22 24 7b 73 61 6c 74   -hex -- "${salt
21c0: 7d 7c 24 7b 70 75 62 6c 69 63 4b 65 79 7d 7c 24  }|${publicKey}|$
21d0: 7b 70 61 73 73 77 6f 72 64 7d 22 5d 0a 09 09 09  {password}"]....
21e0: 73 65 74 20 76 65 72 69 66 69 63 61 74 69 6f 6e  set verification
21f0: 20 5b 6c 69 73 74 20 73 61 6c 74 20 24 73 61 6c   [list salt $sal
2200: 74 20 68 61 73 68 41 6c 67 6f 72 69 74 68 6d 20  t hashAlgorithm 
2210: 73 68 61 32 35 36 20 68 61 73 68 20 24 76 65 72  sha256 hash $ver
2220: 69 66 69 63 61 74 69 6f 6e 48 61 73 68 5d 0a 0a  ificationHash]..
2230: 09 09 09 64 62 20 65 76 61 6c 20 7b 49 4e 53 45  ...db eval {INSE
2240: 52 54 20 49 4e 54 4f 20 70 61 73 73 77 6f 72 64  RT INTO password
2250: 73 20 28 6e 61 6d 65 2c 20 65 6e 63 72 79 70 74  s (name, encrypt
2260: 65 64 50 61 73 73 2c 20 65 6e 63 72 79 70 74 65  edPass, encrypte
2270: 64 4b 65 79 2c 20 70 75 62 6c 69 63 4b 65 79 2c  dKey, publicKey,
2280: 20 76 65 72 69 66 69 63 61 74 69 6f 6e 29 20 56   verification) V
2290: 41 4c 55 45 53 20 28 24 6e 61 6d 65 2c 20 40 65  ALUES ($name, @e
22a0: 6e 63 72 79 70 74 65 64 50 61 73 73 2c 20 40 65  ncryptedPass, @e
22b0: 6e 63 72 79 70 74 65 64 4b 65 79 2c 20 40 70 75  ncryptedKey, @pu
22c0: 62 6c 69 63 4b 65 79 2c 20 40 76 65 72 69 66 69  blicKey, @verifi
22d0: 63 61 74 69 6f 6e 29 3b 7d 0a 09 09 7d 0a 09 7d  cation);}...}..}
22e0: 0a 0a 09 63 6c 6f 73 65 20 24 66 64 0a 7d 0a 0a  ...close $fd.}..
22f0: 70 72 6f 63 20 5f 70 72 6f 6d 70 74 20 7b 70 72  proc _prompt {pr
2300: 6f 6d 70 74 7d 20 7b 0a 09 70 75 74 73 20 2d 6e  ompt} {..puts -n
2310: 6f 6e 65 77 6c 69 6e 65 20 24 70 72 6f 6d 70 74  onewline $prompt
2320: 0a 09 66 6c 75 73 68 20 73 74 64 6f 75 74 0a 0a  ..flush stdout..
2330: 09 70 75 74 73 20 2d 6e 6f 6e 65 77 6c 69 6e 65  .puts -nonewline
2340: 20 5b 65 78 65 63 20 73 74 74 79 20 2d 65 63 68   [exec stty -ech
2350: 6f 5d 0a 09 66 6c 75 73 68 20 73 74 64 6f 75 74  o]..flush stdout
2360: 0a 0a 09 73 65 74 20 70 61 73 73 77 6f 72 64 20  ...set password 
2370: 5b 67 65 74 73 20 73 74 64 69 6e 5d 0a 0a 09 70  [gets stdin]...p
2380: 75 74 73 20 2d 6e 6f 6e 65 77 6c 69 6e 65 20 5b  uts -nonewline [
2390: 65 78 65 63 20 73 74 74 79 20 65 63 68 6f 5d 0a  exec stty echo].
23a0: 09 70 75 74 73 20 22 22 0a 09 66 6c 75 73 68 20  .puts ""..flush 
23b0: 73 74 64 6f 75 74 0a 0a 09 72 65 74 75 72 6e 20  stdout...return 
23c0: 24 70 61 73 73 77 6f 72 64 0a 7d 0a 0a 70 72 6f  $password.}..pro
23d0: 63 20 5f 67 65 74 50 61 73 73 77 6f 72 64 20 7b  c _getPassword {
23e0: 6e 61 6d 65 7d 20 7b 0a 09 73 65 74 20 65 78 69  name} {..set exi
23f0: 73 74 73 20 5b 64 62 20 65 76 61 6c 20 7b 53 45  sts [db eval {SE
2400: 4c 45 43 54 20 31 20 46 52 4f 4d 20 70 61 73 73  LECT 1 FROM pass
2410: 77 6f 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65  words WHERE name
2420: 20 3d 20 24 6e 61 6d 65 20 4c 49 4d 49 54 20 31   = $name LIMIT 1
2430: 3b 7d 5d 0a 09 69 66 20 7b 24 65 78 69 73 74 73  ;}]..if {$exists
2440: 20 21 3d 20 22 31 22 7d 20 7b 0a 09 09 72 65 74   != "1"} {...ret
2450: 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20  urn -code error 
2460: 22 50 61 73 73 77 6f 72 64 20 5c 22 24 6e 61 6d  "Password \"$nam
2470: 65 5c 22 20 64 6f 65 73 20 6e 6f 74 20 65 78 69  e\" does not exi
2480: 73 74 73 2e 22 0a 09 7d 0a 0a 09 66 6f 72 65 61  sts."..}...forea
2490: 63 68 20 73 6c 6f 74 49 6e 66 6f 44 69 63 74 20  ch slotInfoDict 
24a0: 5b 5f 6c 69 73 74 43 65 72 74 69 66 69 63 61 74  [_listCertificat
24b0: 65 73 5d 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e  es] {...unset -n
24c0: 6f 63 6f 6d 70 6c 61 69 6e 20 73 6c 6f 74 49 6e  ocomplain slotIn
24d0: 66 6f 0a 09 09 61 72 72 61 79 20 73 65 74 20 73  fo...array set s
24e0: 6c 6f 74 49 6e 66 6f 20 24 73 6c 6f 74 49 6e 66  lotInfo $slotInf
24f0: 6f 44 69 63 74 0a 0a 09 09 73 65 74 20 70 75 62  oDict....set pub
2500: 6b 65 79 20 24 73 6c 6f 74 49 6e 66 6f 28 70 75  key $slotInfo(pu
2510: 62 6b 65 79 29 0a 09 09 73 65 74 20 70 72 6f 6d  bkey)...set prom
2520: 70 74 20 24 73 6c 6f 74 49 6e 66 6f 28 70 72 6f  pt $slotInfo(pro
2530: 6d 70 74 29 0a 0a 09 09 69 66 20 7b 5b 69 6e 66  mpt)....if {[inf
2540: 6f 20 65 78 69 73 74 73 20 70 72 6f 6d 70 74 65  o exists prompte
2550: 64 28 24 73 6c 6f 74 49 6e 66 6f 28 69 64 29 29  d($slotInfo(id))
2560: 5d 7d 20 7b 0a 09 09 09 73 65 74 20 70 72 6f 6d  ]} {....set prom
2570: 70 74 20 66 61 6c 73 65 0a 09 09 7d 0a 0a 09 09  pt false...}....
2580: 69 66 20 7b 24 70 72 6f 6d 70 74 7d 20 7b 0a 09  if {$prompt} {..
2590: 09 09 73 65 74 20 50 49 4e 20 5b 5f 70 72 6f 6d  ..set PIN [_prom
25a0: 70 74 20 22 50 6c 65 61 73 65 20 65 6e 74 65 72  pt "Please enter
25b0: 20 74 68 65 20 50 49 4e 20 66 6f 72 20 5b 64 69   the PIN for [di
25c0: 63 74 20 67 65 74 20 24 73 6c 6f 74 49 6e 66 6f  ct get $slotInfo
25d0: 28 63 65 72 74 29 20 73 75 62 6a 65 63 74 5d 3a  (cert) subject]:
25e0: 20 22 5d 0a 0a 09 09 09 69 66 20 7b 21 5b 3a 3a   "].....if {![::
25f0: 70 6b 69 3a 3a 70 6b 63 73 31 31 3a 3a 6c 6f 67  pki::pkcs11::log
2600: 69 6e 20 24 73 6c 6f 74 49 6e 66 6f 28 68 61 6e  in $slotInfo(han
2610: 64 6c 65 29 20 24 73 6c 6f 74 49 6e 66 6f 28 69  dle) $slotInfo(i
2620: 64 29 20 24 50 49 4e 5d 7d 20 7b 0a 09 09 09 09  d) $PIN]} {.....
2630: 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72  return -code err
2640: 6f 72 20 22 55 6e 61 62 6c 65 20 74 6f 20 61 75  or "Unable to au
2650: 74 68 65 6e 74 69 63 61 74 65 22 0a 09 09 09 7d  thenticate"....}
2660: 0a 0a 09 09 09 73 65 74 20 70 72 6f 6d 70 74 65  .....set prompte
2670: 64 28 24 73 6c 6f 74 49 6e 66 6f 28 69 64 29 29  d($slotInfo(id))
2680: 20 31 0a 09 09 7d 0a 0a 09 09 64 62 20 65 76 61   1...}....db eva
2690: 6c 20 7b 53 45 4c 45 43 54 20 65 6e 63 72 79 70  l {SELECT encryp
26a0: 74 65 64 50 61 73 73 2c 20 65 6e 63 72 79 70 74  tedPass, encrypt
26b0: 65 64 4b 65 79 20 46 52 4f 4d 20 70 61 73 73 77  edKey FROM passw
26c0: 6f 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20  ords WHERE name 
26d0: 3d 20 24 6e 61 6d 65 20 41 4e 44 20 70 75 62 6c  = $name AND publ
26e0: 69 63 4b 65 79 20 3d 20 24 70 75 62 6b 65 79 3b  icKey = $pubkey;
26f0: 7d 20 72 6f 77 20 7b 0a 09 09 09 73 65 74 20 6b  } row {....set k
2700: 65 79 20 5b 3a 3a 70 6b 69 3a 3a 64 65 63 72 79  ey [::pki::decry
2710: 70 74 20 2d 62 69 6e 61 72 79 20 2d 70 72 69 76  pt -binary -priv
2720: 20 2d 2d 20 5b 62 69 6e 61 72 79 20 64 65 63 6f   -- [binary deco
2730: 64 65 20 62 61 73 65 36 34 20 24 72 6f 77 28 65  de base64 $row(e
2740: 6e 63 72 79 70 74 65 64 4b 65 79 29 5d 20 24 73  ncryptedKey)] $s
2750: 6c 6f 74 49 6e 66 6f 28 63 65 72 74 29 5d 0a 09  lotInfo(cert)]..
2760: 09 09 73 65 74 20 70 61 73 73 77 6f 72 64 20 5b  ..set password [
2770: 3a 3a 61 65 73 3a 3a 61 65 73 20 2d 64 69 72 20  ::aes::aes -dir 
2780: 64 65 63 72 79 70 74 20 2d 6b 65 79 20 24 6b 65  decrypt -key $ke
2790: 79 20 2d 2d 20 5b 62 69 6e 61 72 79 20 64 65 63  y -- [binary dec
27a0: 6f 64 65 20 62 61 73 65 36 34 20 24 72 6f 77 28  ode base64 $row(
27b0: 65 6e 63 72 79 70 74 65 64 50 61 73 73 29 5d 5d  encryptedPass)]]
27c0: 0a 0a 09 09 09 72 65 74 75 72 6e 20 5b 73 74 72  .....return [str
27d0: 69 6e 67 20 74 72 69 6d 72 69 67 68 74 20 24 70  ing trimright $p
27e0: 61 73 73 77 6f 72 64 20 22 5c 78 30 30 22 5d 0a  assword "\x00"].
27f0: 09 09 7d 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 20  ..}..}...return 
2800: 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 4e 6f 20  -code error "No 
2810: 76 61 6c 69 64 20 6b 65 79 73 22 0a 7d 0a 0a 70  valid keys".}..p
2820: 72 6f 63 20 5f 6d 6f 64 69 66 79 50 75 62 6c 69  roc _modifyPubli
2830: 63 4b 65 79 73 20 7b 70 61 73 73 77 6f 72 64 4e  cKeys {passwordN
2840: 61 6d 65 20 75 73 65 72 4e 61 6d 65 73 20 73 71  ame userNames sq
2850: 6c 7d 20 7b 0a 09 73 65 74 20 65 78 69 73 74 73  l} {..set exists
2860: 20 5b 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43   [db eval {SELEC
2870: 54 20 31 20 46 52 4f 4d 20 70 61 73 73 77 6f 72  T 1 FROM passwor
2880: 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20  ds WHERE name = 
2890: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 4c 49  $passwordName LI
28a0: 4d 49 54 20 31 3b 7d 5d 0a 09 69 66 20 7b 24 65  MIT 1;}]..if {$e
28b0: 78 69 73 74 73 20 21 3d 20 22 31 22 7d 20 7b 0a  xists != "1"} {.
28c0: 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65  ..return -code e
28d0: 72 72 6f 72 20 22 50 61 73 73 77 6f 72 64 20 5c  rror "Password \
28e0: 22 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5c 22  "$passwordName\"
28f0: 20 64 6f 65 73 20 6e 6f 74 20 65 78 69 73 74 73   does not exists
2900: 2e 22 0a 09 7d 0a 0a 09 73 65 74 20 70 75 62 6c  ."..}...set publ
2910: 69 63 4b 65 79 73 20 5b 6c 69 73 74 5d 0a 0a 09  icKeys [list]...
2920: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20  db eval {SELECT 
2930: 70 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d 20 70  publicKey FROM p
2940: 61 73 73 77 6f 72 64 73 20 57 48 45 52 45 20 6e  asswords WHERE n
2950: 61 6d 65 20 3d 20 24 70 61 73 73 77 6f 72 64 4e  ame = $passwordN
2960: 61 6d 65 3b 7d 20 72 6f 77 20 7b 0a 09 09 6c 61  ame;} row {...la
2970: 70 70 65 6e 64 20 70 75 62 6c 69 63 4b 65 79 73  ppend publicKeys
2980: 20 24 72 6f 77 28 70 75 62 6c 69 63 4b 65 79 29   $row(publicKey)
2990: 0a 09 7d 0a 0a 09 73 65 74 20 63 68 61 6e 67 65  ..}...set change
29a0: 52 65 71 75 69 72 65 64 20 30 0a 09 66 6f 72 65  Required 0..fore
29b0: 61 63 68 20 75 73 65 72 20 24 75 73 65 72 4e 61  ach user $userNa
29c0: 6d 65 73 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e  mes {...unset -n
29d0: 6f 63 6f 6d 70 6c 61 69 6e 20 72 6f 77 0a 09 09  ocomplain row...
29e0: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20  db eval {SELECT 
29f0: 70 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d 20 75  publicKey FROM u
2a00: 73 65 72 73 20 57 48 45 52 45 20 6e 61 6d 65 20  sers WHERE name 
2a10: 3d 20 24 75 73 65 72 3b 7d 20 72 6f 77 20 24 73  = $user;} row $s
2a20: 71 6c 0a 09 7d 0a 0a 09 69 66 20 7b 21 24 63 68  ql..}...if {!$ch
2a30: 61 6e 67 65 52 65 71 75 69 72 65 64 7d 20 7b 0a  angeRequired} {.
2a40: 09 09 72 65 74 75 72 6e 0a 09 7d 0a 0a 09 73 65  ..return..}...se
2a50: 74 20 70 61 73 73 77 6f 72 64 20 5b 5f 67 65 74  t password [_get
2a60: 50 61 73 73 77 6f 72 64 20 24 70 61 73 73 77 6f  Password $passwo
2a70: 72 64 4e 61 6d 65 5d 0a 0a 09 5f 61 64 64 50 61  rdName]..._addPa
2a80: 73 73 77 6f 72 64 20 24 70 61 73 73 77 6f 72 64  ssword $password
2a90: 4e 61 6d 65 20 24 70 61 73 73 77 6f 72 64 20 24  Name $password $
2aa0: 70 75 62 6c 69 63 4b 65 79 73 0a 7d 0a 0a 70 72  publicKeys.}..pr
2ab0: 6f 63 20 5f 67 65 74 55 73 65 72 73 46 6f 72 50  oc _getUsersForP
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 73 7d 20 7b 0a 09 73 65 74 20 75  dNames} {..set u
2ae0: 73 65 72 4e 61 6d 65 73 20 5b 6c 69 73 74 5d 0a  serNames [list].
2af0: 0a 09 66 6f 72 65 61 63 68 20 70 61 73 73 77 6f  ..foreach passwo
2b00: 72 64 4e 61 6d 65 20 24 70 61 73 73 77 6f 72 64  rdName $password
2b10: 4e 61 6d 65 73 20 7b 0a 09 09 64 62 20 65 76 61  Names {...db eva
2b20: 6c 20 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63  l {SELECT public
2b30: 4b 65 79 20 46 52 4f 4d 20 70 61 73 73 77 6f 72  Key FROM passwor
2b40: 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20  ds WHERE name = 
2b50: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 3b 7d 20  $passwordName;} 
2b60: 70 61 73 73 77 6f 72 64 52 6f 77 20 7b 0a 09 09  passwordRow {...
2b70: 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54  .db eval {SELECT
2b80: 20 6e 61 6d 65 20 46 52 4f 4d 20 75 73 65 72 73   name FROM users
2b90: 20 57 48 45 52 45 20 70 75 62 6c 69 63 4b 65 79   WHERE publicKey
2ba0: 20 3d 20 24 70 61 73 73 77 6f 72 64 52 6f 77 28   = $passwordRow(
2bb0: 70 75 62 6c 69 63 4b 65 79 29 7d 20 75 73 65 72  publicKey)} user
2bc0: 52 6f 77 20 7b 0a 09 09 09 09 69 66 20 7b 24 75  Row {.....if {$u
2bd0: 73 65 72 52 6f 77 28 6e 61 6d 65 29 20 69 6e 20  serRow(name) in 
2be0: 24 75 73 65 72 4e 61 6d 65 73 7d 20 7b 0a 09 09  $userNames} {...
2bf0: 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 09  ...continue.....
2c00: 7d 0a 0a 09 09 09 09 6c 61 70 70 65 6e 64 20 75  }......lappend u
2c10: 73 65 72 4e 61 6d 65 73 20 24 75 73 65 72 52 6f  serNames $userRo
2c20: 77 28 6e 61 6d 65 29 0a 09 09 09 7d 0a 09 09 7d  w(name)....}...}
2c30: 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 20 24 75 73  ..}...return $us
2c40: 65 72 4e 61 6d 65 73 0a 7d 0a 0a 70 72 6f 63 20  erNames.}..proc 
2c50: 5f 67 65 74 50 61 73 73 77 6f 72 64 73 46 6f 72  _getPasswordsFor
2c60: 55 73 65 72 20 7b 75 73 65 72 4e 61 6d 65 73 7d  User {userNames}
2c70: 20 7b 0a 09 73 65 74 20 70 61 73 73 77 6f 72 64   {..set password
2c80: 4e 61 6d 65 73 20 5b 6c 69 73 74 5d 0a 0a 09 66  Names [list]...f
2c90: 6f 72 65 61 63 68 20 75 73 65 72 4e 61 6d 65 20  oreach userName 
2ca0: 24 75 73 65 72 4e 61 6d 65 73 20 7b 0a 09 09 64  $userNames {...d
2cb0: 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 70  b eval {SELECT p
2cc0: 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d 20 75 73  ublicKey FROM us
2cd0: 65 72 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d  ers WHERE name =
2ce0: 20 24 75 73 65 72 4e 61 6d 65 3b 7d 20 75 73 65   $userName;} use
2cf0: 72 52 6f 77 20 7b 0a 09 09 09 64 62 20 65 76 61  rRow {....db eva
2d00: 6c 20 7b 53 45 4c 45 43 54 20 6e 61 6d 65 20 46  l {SELECT name F
2d10: 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48  ROM passwords WH
2d20: 45 52 45 20 70 75 62 6c 69 63 4b 65 79 20 3d 20  ERE publicKey = 
2d30: 24 75 73 65 72 52 6f 77 28 70 75 62 6c 69 63 4b  $userRow(publicK
2d40: 65 79 29 7d 20 70 61 73 73 77 6f 72 64 52 6f 77  ey)} passwordRow
2d50: 20 7b 0a 09 09 09 09 69 66 20 7b 24 70 61 73 73   {.....if {$pass
2d60: 77 6f 72 64 52 6f 77 28 6e 61 6d 65 29 20 69 6e  wordRow(name) in
2d70: 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 7d   $passwordNames}
2d80: 20 7b 0a 09 09 09 09 09 63 6f 6e 74 69 6e 75 65   {......continue
2d90: 0a 09 09 09 09 7d 0a 0a 09 09 09 09 6c 61 70 70  .....}......lapp
2da0: 65 6e 64 20 70 61 73 73 77 6f 72 64 4e 61 6d 65  end passwordName
2db0: 73 20 24 70 61 73 73 77 6f 72 64 52 6f 77 28 6e  s $passwordRow(n
2dc0: 61 6d 65 29 0a 09 09 09 7d 0a 09 09 7d 0a 09 7d  ame)....}...}..}
2dd0: 0a 0a 09 72 65 74 75 72 6e 20 24 70 61 73 73 77  ...return $passw
2de0: 6f 72 64 4e 61 6d 65 73 0a 7d 0a 23 20 45 6e 64  ordNames.}.# End
2df0: 20 69 6e 74 65 72 6e 61 6c 20 66 75 6e 63 74 69   internal functi
2e00: 6f 6e 73 0a 0a 23 20 53 74 61 72 74 20 75 73 65  ons..# Start use
2e10: 72 20 43 4c 49 20 66 75 6e 63 74 69 6f 6e 73 0a  r CLI functions.
2e20: 70 72 6f 63 20 6c 69 73 74 4c 6f 63 61 6c 4b 65  proc listLocalKe
2e30: 79 73 20 7b 7d 20 7b 0a 09 66 6f 72 65 61 63 68  ys {} {..foreach
2e40: 20 73 6c 6f 74 49 6e 66 6f 44 69 63 74 20 5b 5f   slotInfoDict [_
2e50: 6c 69 73 74 43 65 72 74 69 66 69 63 61 74 65 73  listCertificates
2e60: 5d 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63  ] {...unset -noc
2e70: 6f 6d 70 6c 61 69 6e 20 73 6c 6f 74 49 6e 66 6f  omplain slotInfo
2e80: 0a 09 09 61 72 72 61 79 20 73 65 74 20 73 6c 6f  ...array set slo
2e90: 74 49 6e 66 6f 20 24 73 6c 6f 74 49 6e 66 6f 44  tInfo $slotInfoD
2ea0: 69 63 74 0a 0a 09 09 73 65 74 20 73 75 62 6a 65  ict....set subje
2eb0: 63 74 20 5b 64 69 63 74 20 67 65 74 20 24 73 6c  ct [dict get $sl
2ec0: 6f 74 49 6e 66 6f 28 63 65 72 74 29 20 73 75 62  otInfo(cert) sub
2ed0: 6a 65 63 74 5d 0a 09 09 73 65 74 20 70 75 62 6b  ject]...set pubk
2ee0: 65 79 20 20 24 73 6c 6f 74 49 6e 66 6f 28 70 75  ey  $slotInfo(pu
2ef0: 62 6b 65 79 29 0a 0a 09 09 6c 61 70 70 65 6e 64  bkey)....lappend
2f00: 20 70 75 62 6c 69 63 4b 65 79 73 28 24 73 75 62   publicKeys($sub
2f10: 6a 65 63 74 29 20 24 70 75 62 6b 65 79 0a 09 7d  ject) $pubkey..}
2f20: 0a 0a 09 66 6f 72 65 61 63 68 20 7b 73 75 62 6a  ...foreach {subj
2f30: 65 63 74 20 70 75 62 6b 65 79 73 7d 20 5b 61 72  ect pubkeys} [ar
2f40: 72 61 79 20 67 65 74 20 70 75 62 6c 69 63 4b 65  ray get publicKe
2f50: 79 73 5d 20 7b 0a 09 09 70 75 74 73 20 22 24 73  ys] {...puts "$s
2f60: 75 62 6a 65 63 74 22 0a 0a 09 09 66 6f 72 65 61  ubject"....forea
2f70: 63 68 20 70 75 62 6b 65 79 20 24 70 75 62 6b 65  ch pubkey $pubke
2f80: 79 73 20 7b 0a 09 09 09 70 75 74 73 20 22 20 20  ys {....puts "  
2f90: 7c 2d 3e 20 24 70 75 62 6b 65 79 22 0a 09 09 7d  |-> $pubkey"...}
2fa0: 0a 09 7d 0a 7d 0a 0a 70 72 6f 63 20 6c 69 73 74  ..}.}..proc list
2fb0: 41 76 61 69 6c 61 62 6c 65 50 61 73 73 77 6f 72  AvailablePasswor
2fc0: 64 73 20 7b 7d 20 7b 0a 09 73 65 74 20 70 61 73  ds {} {..set pas
2fd0: 73 77 6f 72 64 4e 61 6d 65 73 20 5b 6c 69 73 74  swordNames [list
2fe0: 5d 0a 09 66 6f 72 65 61 63 68 20 73 6c 6f 74 49  ]..foreach slotI
2ff0: 6e 66 6f 44 69 63 74 20 5b 5f 6c 69 73 74 43 65  nfoDict [_listCe
3000: 72 74 69 66 69 63 61 74 65 73 5d 20 7b 0a 09 09  rtificates] {...
3010: 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69  unset -nocomplai
3020: 6e 20 73 6c 6f 74 49 6e 66 6f 0a 09 09 61 72 72  n slotInfo...arr
3030: 61 79 20 73 65 74 20 73 6c 6f 74 49 6e 66 6f 20  ay set slotInfo 
3040: 24 73 6c 6f 74 49 6e 66 6f 44 69 63 74 0a 0a 09  $slotInfoDict...
3050: 09 73 65 74 20 70 75 62 6b 65 79 20 24 73 6c 6f  .set pubkey $slo
3060: 74 49 6e 66 6f 28 70 75 62 6b 65 79 29 0a 0a 09  tInfo(pubkey)...
3070: 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61  .unset -nocompla
3080: 69 6e 20 72 6f 77 0a 09 09 64 62 20 65 76 61 6c  in row...db eval
3090: 20 7b 53 45 4c 45 43 54 20 6e 61 6d 65 20 46 52   {SELECT name FR
30a0: 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48 45  OM passwords WHE
30b0: 52 45 20 70 75 62 6c 69 63 4b 65 79 20 3d 20 24  RE publicKey = $
30c0: 70 75 62 6b 65 79 3b 7d 20 72 6f 77 20 7b 0a 09  pubkey;} row {..
30d0: 09 09 69 66 20 7b 24 72 6f 77 28 6e 61 6d 65 29  ..if {$row(name)
30e0: 20 69 6e 20 24 70 61 73 73 77 6f 72 64 4e 61 6d   in $passwordNam
30f0: 65 73 7d 20 7b 0a 09 09 09 09 63 6f 6e 74 69 6e  es} {.....contin
3100: 75 65 0a 09 09 09 7d 0a 0a 09 09 09 6c 61 70 70  ue....}.....lapp
3110: 65 6e 64 20 70 61 73 73 77 6f 72 64 4e 61 6d 65  end passwordName
3120: 73 20 24 72 6f 77 28 6e 61 6d 65 29 0a 09 09 7d  s $row(name)...}
3130: 0a 09 7d 0a 0a 0a 09 66 6f 72 65 61 63 68 20 70  ..}....foreach p
3140: 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 70 61 73  asswordName $pas
3150: 73 77 6f 72 64 4e 61 6d 65 73 20 7b 0a 09 09 70  swordNames {...p
3160: 75 74 73 20 22 24 70 61 73 73 77 6f 72 64 4e 61  uts "$passwordNa
3170: 6d 65 20 2d 20 5b 6a 6f 69 6e 20 5b 5f 67 65 74  me - [join [_get
3180: 55 73 65 72 73 46 6f 72 50 61 73 73 77 6f 72 64  UsersForPassword
3190: 20 5b 6c 69 73 74 20 24 70 61 73 73 77 6f 72 64   [list $password
31a0: 4e 61 6d 65 5d 5d 20 7b 2c 20 7d 5d 22 0a 09 7d  Name]] {, }]"..}
31b0: 0a 7d 0a 0a 70 72 6f 63 20 6c 69 73 74 50 61 73  .}..proc listPas
31c0: 73 77 6f 72 64 73 20 7b 7d 20 7b 0a 09 64 62 20  swords {} {..db 
31d0: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 44 49 53  eval {SELECT DIS
31e0: 54 49 4e 43 54 20 6e 61 6d 65 20 46 52 4f 4d 20  TINCT name FROM 
31f0: 70 61 73 73 77 6f 72 64 73 3b 7d 20 72 6f 77 20  passwords;} row 
3200: 7b 0a 09 09 70 75 74 73 20 22 24 72 6f 77 28 6e  {...puts "$row(n
3210: 61 6d 65 29 20 2d 20 5b 6a 6f 69 6e 20 5b 5f 67  ame) - [join [_g
3220: 65 74 55 73 65 72 73 46 6f 72 50 61 73 73 77 6f  etUsersForPasswo
3230: 72 64 20 5b 6c 69 73 74 20 24 72 6f 77 28 6e 61  rd [list $row(na
3240: 6d 65 29 5d 5d 20 7b 2c 20 7d 5d 22 0a 09 7d 0a  me)]] {, }]"..}.
3250: 7d 0a 0a 70 72 6f 63 20 6c 69 73 74 55 73 65 72  }..proc listUser
3260: 73 20 7b 7d 20 7b 0a 09 64 62 20 65 76 61 6c 20  s {} {..db eval 
3270: 7b 53 45 4c 45 43 54 20 44 49 53 54 49 4e 43 54  {SELECT DISTINCT
3280: 20 6e 61 6d 65 20 46 52 4f 4d 20 75 73 65 72 73   name FROM users
3290: 3b 7d 20 72 6f 77 20 7b 0a 09 09 70 75 74 73 20  ;} row {...puts 
32a0: 22 24 72 6f 77 28 6e 61 6d 65 29 20 2d 20 5b 6a  "$row(name) - [j
32b0: 6f 69 6e 20 5b 5f 67 65 74 50 61 73 73 77 6f 72  oin [_getPasswor
32c0: 64 73 46 6f 72 55 73 65 72 20 5b 6c 69 73 74 20  dsForUser [list 
32d0: 24 72 6f 77 28 6e 61 6d 65 29 5d 5d 20 7b 2c 20  $row(name)]] {, 
32e0: 7d 5d 22 0a 09 7d 0a 7d 0a 0a 70 72 6f 63 20 61  }]"..}.}..proc a
32f0: 64 64 55 73 65 72 20 7b 75 73 65 72 4e 61 6d 65  ddUser {userName
3300: 20 6b 65 79 7d 20 7b 0a 09 73 65 74 20 6b 65 79   key} {..set key
3310: 52 61 77 20 5b 62 69 6e 61 72 79 20 64 65 63 6f  Raw [binary deco
3320: 64 65 20 62 61 73 65 36 34 20 24 6b 65 79 5d 0a  de base64 $key].
3330: 09 73 65 74 20 6b 65 79 56 65 72 69 66 79 20 5b  .set keyVerify [
3340: 3a 3a 70 6b 69 3a 3a 70 6b 63 73 3a 3a 70 61 72  ::pki::pkcs::par
3350: 73 65 5f 70 75 62 6c 69 63 5f 6b 65 79 20 24 6b  se_public_key $k
3360: 65 79 52 61 77 5d 0a 0a 09 64 62 20 65 76 61 6c  eyRaw]...db eval
3370: 20 7b 49 4e 53 45 52 54 20 49 4e 54 4f 20 75 73   {INSERT INTO us
3380: 65 72 73 20 28 6e 61 6d 65 2c 20 70 75 62 6c 69  ers (name, publi
3390: 63 4b 65 79 29 20 56 41 4c 55 45 53 20 28 24 75  cKey) VALUES ($u
33a0: 73 65 72 4e 61 6d 65 2c 20 40 6b 65 79 29 3b 7d  serName, @key);}
33b0: 0a 0a 09 23 20 58 58 58 3a 54 4f 44 4f 3a 47 6f  ...# XXX:TODO:Go
33c0: 20 74 68 72 6f 75 67 68 20 61 6e 64 20 72 65 2d   through and re-
33d0: 61 75 74 68 6f 72 69 7a 65 20 69 66 20 70 6f 73  authorize if pos
33e0: 73 69 62 6c 65 0a 7d 0a 0a 70 72 6f 63 20 64 65  sible.}..proc de
33f0: 6c 65 74 65 55 73 65 72 20 7b 75 73 65 72 4e 61  leteUser {userNa
3400: 6d 65 7d 20 7b 0a 09 23 20 58 58 58 3a 54 4f 44  me} {..# XXX:TOD
3410: 4f 3a 20 47 6f 20 74 68 72 6f 75 67 68 20 61 6e  O: Go through an
3420: 64 20 64 65 2d 61 75 74 68 6f 72 69 7a 65 0a 7d  d de-authorize.}
3430: 0a 0a 70 72 6f 63 20 61 64 64 50 61 73 73 77 6f  ..proc addPasswo
3440: 72 64 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65  rd {passwordName
3450: 20 70 61 73 73 77 6f 72 64 20 61 72 67 73 7d 20   password args} 
3460: 7b 0a 09 73 65 74 20 69 6e 69 74 69 61 6c 55 73  {..set initialUs
3470: 65 72 73 20 24 61 72 67 73 0a 0a 09 69 66 20 7b  ers $args...if {
3480: 24 70 61 73 73 77 6f 72 64 20 65 71 20 22 22 7d  $password eq ""}
3490: 20 7b 0a 09 09 73 65 74 20 70 61 73 73 77 6f 72   {...set passwor
34a0: 64 20 5b 5f 70 72 6f 6d 70 74 20 22 50 6c 65 61  d [_prompt "Plea
34b0: 73 65 20 65 6e 74 65 72 20 74 68 65 20 6e 65 77  se enter the new
34c0: 20 70 61 73 73 77 6f 72 64 3a 20 22 5d 0a 09 7d   password: "]..}
34d0: 0a 0a 09 23 20 56 65 72 69 66 79 20 74 68 61 74  ...# Verify that
34e0: 20 74 68 69 73 20 70 61 73 73 77 6f 72 64 20 64   this password d
34f0: 6f 65 73 20 6e 6f 74 20 61 6c 72 65 61 64 79 20  oes not already 
3500: 65 78 69 73 74 0a 09 73 65 74 20 65 78 69 73 74  exist..set exist
3510: 73 20 5b 64 62 20 65 76 61 6c 20 7b 53 45 4c 45  s [db eval {SELE
3520: 43 54 20 31 20 46 52 4f 4d 20 70 61 73 73 77 6f  CT 1 FROM passwo
3530: 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d  rds WHERE name =
3540: 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 4c   $passwordName L
3550: 49 4d 49 54 20 31 3b 7d 5d 0a 09 69 66 20 7b 24  IMIT 1;}]..if {$
3560: 65 78 69 73 74 73 20 3d 3d 20 22 31 22 7d 20 7b  exists == "1"} {
3570: 0a 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20  ...return -code 
3580: 65 72 72 6f 72 20 22 50 61 73 73 77 6f 72 64 20  error "Password 
3590: 5c 22 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5c  \"$passwordName\
35a0: 22 20 61 6c 72 65 61 64 79 20 65 78 69 73 74 73  " already exists
35b0: 2c 20 63 61 6e 6e 6f 74 20 61 64 64 2e 22 0a 09  , cannot add."..
35c0: 7d 0a 0a 09 23 20 47 65 74 20 6b 65 79 73 20 66  }...# Get keys f
35d0: 6f 72 20 69 6e 69 74 69 61 6c 20 75 73 65 72 73  or initial users
35e0: 0a 09 73 65 74 20 70 75 62 6c 69 63 4b 65 79 73  ..set publicKeys
35f0: 20 5b 6c 69 73 74 5d 0a 09 66 6f 72 65 61 63 68   [list]..foreach
3600: 20 75 73 65 72 20 24 69 6e 69 74 69 61 6c 55 73   user $initialUs
3610: 65 72 73 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e  ers {...unset -n
3620: 6f 63 6f 6d 70 6c 61 69 6e 20 72 6f 77 0a 09 09  ocomplain row...
3630: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20  db eval {SELECT 
3640: 70 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d 20 75  publicKey FROM u
3650: 73 65 72 73 20 57 48 45 52 45 20 6e 61 6d 65 20  sers WHERE name 
3660: 3d 20 24 75 73 65 72 3b 7d 20 72 6f 77 20 7b 0a  = $user;} row {.
3670: 09 09 09 6c 61 70 70 65 6e 64 20 70 75 62 6c 69  ...lappend publi
3680: 63 4b 65 79 73 20 24 72 6f 77 28 70 75 62 6c 69  cKeys $row(publi
3690: 63 4b 65 79 29 0a 09 09 7d 0a 09 7d 0a 0a 09 5f  cKey)...}..}..._
36a0: 61 64 64 50 61 73 73 77 6f 72 64 20 24 70 61 73  addPassword $pas
36b0: 73 77 6f 72 64 4e 61 6d 65 20 24 70 61 73 73 77  swordName $passw
36c0: 6f 72 64 20 24 70 75 62 6c 69 63 4b 65 79 73 0a  ord $publicKeys.
36d0: 7d 0a 0a 70 72 6f 63 20 67 65 74 50 61 73 73 77  }..proc getPassw
36e0: 6f 72 64 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d  ord {passwordNam
36f0: 65 7d 20 7b 0a 09 70 75 74 73 20 5b 5f 67 65 74  e} {..puts [_get
3700: 50 61 73 73 77 6f 72 64 20 24 70 61 73 73 77 6f  Password $passwo
3710: 72 64 4e 61 6d 65 5d 0a 7d 0a 0a 70 72 6f 63 20  rdName].}..proc 
3720: 75 70 64 61 74 65 50 61 73 73 77 6f 72 64 20 7b  updatePassword {
3730: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 70 61 73  passwordName pas
3740: 73 77 6f 72 64 7d 20 7b 0a 09 69 66 20 7b 24 70  sword} {..if {$p
3750: 61 73 73 77 6f 72 64 20 65 71 20 22 22 7d 20 7b  assword eq ""} {
3760: 0a 09 09 73 65 74 20 70 61 73 73 77 6f 72 64 20  ...set password 
3770: 5b 5f 70 72 6f 6d 70 74 20 22 50 6c 65 61 73 65  [_prompt "Please
3780: 20 65 6e 74 65 72 20 74 68 65 20 6e 65 77 20 70   enter the new p
3790: 61 73 73 77 6f 72 64 3a 20 22 5d 0a 09 7d 0a 0a  assword: "]..}..
37a0: 09 73 65 74 20 6f 6c 64 50 61 73 73 77 6f 72 64  .set oldPassword
37b0: 20 5b 5f 67 65 74 50 61 73 73 77 6f 72 64 20 24   [_getPassword $
37c0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 5d 0a 0a 09  passwordName]...
37d0: 73 65 74 20 70 75 62 6c 69 63 4b 65 79 73 20 5b  set publicKeys [
37e0: 5f 76 65 72 69 66 79 50 61 73 73 77 6f 72 64 20  _verifyPassword 
37f0: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 6f  $passwordName $o
3800: 6c 64 50 61 73 73 77 6f 72 64 5d 0a 0a 09 69 66  ldPassword]...if
3810: 20 7b 5b 6c 6c 65 6e 67 74 68 20 24 70 75 62 6c   {[llength $publ
3820: 69 63 4b 65 79 73 5d 20 3d 3d 20 30 7d 20 7b 0a  icKeys] == 0} {.
3830: 09 09 70 75 74 73 20 73 74 64 65 72 72 20 22 57  ..puts stderr "W
3840: 61 72 6e 69 6e 67 3a 20 54 68 69 73 20 77 69 6c  arning: This wil
3850: 6c 20 64 65 6c 65 74 65 20 74 68 65 20 70 61 73  l delete the pas
3860: 73 77 6f 72 64 20 73 69 6e 63 65 20 74 68 65 72  sword since ther
3870: 65 20 61 72 65 20 6e 6f 20 76 61 6c 69 64 20 70  e are no valid p
3880: 75 62 6c 69 63 20 6b 65 79 73 2e 22 0a 09 7d 0a  ublic keys."..}.
3890: 0a 09 5f 61 64 64 50 61 73 73 77 6f 72 64 20 24  .._addPassword $
38a0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 70 61  passwordName $pa
38b0: 73 73 77 6f 72 64 20 24 70 75 62 6c 69 63 4b 65  ssword $publicKe
38c0: 79 73 0a 7d 0a 0a 70 72 6f 63 20 64 65 6c 65 74  ys.}..proc delet
38d0: 65 50 61 73 73 77 6f 72 64 20 7b 70 61 73 73 77  ePassword {passw
38e0: 6f 72 64 4e 61 6d 65 7d 20 7b 0a 09 64 62 20 65  ordName} {..db e
38f0: 76 61 6c 20 7b 44 45 4c 45 54 45 20 46 52 4f 4d  val {DELETE FROM
3900: 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45   passwords WHERE
3910: 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77 6f 72   name = $passwor
3920: 64 4e 61 6d 65 3b 7d 0a 7d 0a 0a 70 72 6f 63 20  dName;}.}..proc 
3930: 61 75 74 68 6f 72 69 7a 65 55 73 65 72 73 20 7b  authorizeUsers {
3940: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 61 72 67  passwordName arg
3950: 73 7d 20 7b 0a 09 73 65 74 20 75 73 65 72 73 20  s} {..set users 
3960: 24 61 72 67 73 0a 0a 09 5f 6d 6f 64 69 66 79 50  $args..._modifyP
3970: 75 62 6c 69 63 4b 65 79 73 20 24 70 61 73 73 77  ublicKeys $passw
3980: 6f 72 64 4e 61 6d 65 20 24 75 73 65 72 73 20 7b  ordName $users {
3990: 0a 09 09 69 66 20 7b 24 72 6f 77 28 70 75 62 6c  ...if {$row(publ
39a0: 69 63 4b 65 79 29 20 69 6e 20 24 70 75 62 6c 69  icKey) in $publi
39b0: 63 4b 65 79 73 7d 20 7b 0a 09 09 09 63 6f 6e 74  cKeys} {....cont
39c0: 69 6e 75 65 0a 09 09 7d 0a 0a 09 09 6c 61 70 70  inue...}....lapp
39d0: 65 6e 64 20 70 75 62 6c 69 63 4b 65 79 73 20 24  end publicKeys $
39e0: 72 6f 77 28 70 75 62 6c 69 63 4b 65 79 29 0a 0a  row(publicKey)..
39f0: 09 09 73 65 74 20 63 68 61 6e 67 65 52 65 71 75  ..set changeRequ
3a00: 69 72 65 64 20 31 0a 09 7d 0a 7d 0a 0a 70 72 6f  ired 1..}.}..pro
3a10: 63 20 61 75 74 68 6f 72 69 7a 65 55 73 65 72 20  c authorizeUser 
3a20: 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 75 73  {passwordName us
3a30: 65 72 4e 61 6d 65 7d 20 7b 0a 09 72 65 74 75 72  erName} {..retur
3a40: 6e 20 5b 61 75 74 68 6f 72 69 7a 65 55 73 65 72  n [authorizeUser
3a50: 73 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20  s $passwordName 
3a60: 24 75 73 65 72 4e 61 6d 65 5d 0a 7d 0a 0a 70 72  $userName].}..pr
3a70: 6f 63 20 64 65 61 75 74 68 6f 72 69 7a 65 55 73  oc deauthorizeUs
3a80: 65 72 73 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d  ers {passwordNam
3a90: 65 20 61 72 67 73 7d 20 7b 0a 09 73 65 74 20 75  e args} {..set u
3aa0: 73 65 72 73 20 24 61 72 67 73 0a 0a 09 5f 6d 6f  sers $args..._mo
3ab0: 64 69 66 79 50 75 62 6c 69 63 4b 65 79 73 20 24  difyPublicKeys $
3ac0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 75 73  passwordName $us
3ad0: 65 72 73 20 7b 0a 09 09 73 65 74 20 69 64 78 20  ers {...set idx 
3ae0: 5b 6c 73 65 61 72 63 68 20 2d 65 78 61 63 74 20  [lsearch -exact 
3af0: 24 70 75 62 6c 69 63 4b 65 79 73 20 24 72 6f 77  $publicKeys $row
3b00: 28 70 75 62 6c 69 63 4b 65 79 29 5d 0a 09 09 69  (publicKey)]...i
3b10: 66 20 7b 24 69 64 78 20 3d 3d 20 2d 31 7d 20 7b  f {$idx == -1} {
3b20: 0a 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 7d  ....continue...}
3b30: 0a 0a 09 09 73 65 74 20 70 75 62 6c 69 63 4b 65  ....set publicKe
3b40: 79 73 20 5b 6c 72 65 70 6c 61 63 65 20 24 70 75  ys [lreplace $pu
3b50: 62 6c 69 63 4b 65 79 73 20 24 69 64 78 20 24 69  blicKeys $idx $i
3b60: 64 78 5d 0a 0a 09 09 73 65 74 20 63 68 61 6e 67  dx]....set chang
3b70: 65 52 65 71 75 69 72 65 64 20 31 0a 09 7d 0a 7d  eRequired 1..}.}
3b80: 0a 0a 70 72 6f 63 20 64 65 61 75 74 68 6f 72 69  ..proc deauthori
3b90: 7a 65 55 73 65 72 20 7b 70 61 73 73 77 6f 72 64  zeUser {password
3ba0: 4e 61 6d 65 20 75 73 65 72 4e 61 6d 65 7d 20 7b  Name userName} {
3bb0: 0a 09 72 65 74 75 72 6e 20 5b 64 65 61 75 74 68  ..return [deauth
3bc0: 6f 72 69 7a 65 55 73 65 72 73 20 24 70 61 73 73  orizeUsers $pass
3bd0: 77 6f 72 64 4e 61 6d 65 20 24 75 73 65 72 4e 61  wordName $userNa
3be0: 6d 65 5d 0a 7d 0a 0a 70 72 6f 63 20 68 65 6c 70  me].}..proc help
3bf0: 20 7b 7b 61 63 74 69 6f 6e 20 22 22 7d 7d 20 7b   {{action ""}} {
3c00: 0a 09 5f 70 72 69 6e 74 48 65 6c 70 20 73 74 64  .._printHelp std
3c10: 6f 75 74 20 24 61 63 74 69 6f 6e 0a 7d 0a 23 20  out $action.}.# 
3c20: 45 6e 64 20 75 73 65 72 20 43 4c 49 20 66 75 6e  End user CLI fun
3c30: 63 74 69 6f 6e 73 0a 0a 23 23 23 20 4d 41 49 4e  ctions..### MAIN
3c40: 0a 0a 73 71 6c 69 74 65 33 20 64 62 20 24 70 61  ..sqlite3 db $pa
3c50: 73 73 77 6f 72 64 46 69 6c 65 0a 0a 64 62 20 65  sswordFile..db e
3c60: 76 61 6c 20 7b 0a 09 43 52 45 41 54 45 20 54 41  val {..CREATE TA
3c70: 42 4c 45 20 49 46 20 4e 4f 54 20 45 58 49 53 54  BLE IF NOT EXIST
3c80: 53 20 75 73 65 72 73 28 6e 61 6d 65 2c 20 70 75  S users(name, pu
3c90: 62 6c 69 63 4b 65 79 20 42 4c 4f 42 29 3b 0a 09  blicKey BLOB);..
3ca0: 43 52 45 41 54 45 20 54 41 42 4c 45 20 49 46 20  CREATE TABLE IF 
3cb0: 4e 4f 54 20 45 58 49 53 54 53 20 70 61 73 73 77  NOT EXISTS passw
3cc0: 6f 72 64 73 28 6e 61 6d 65 2c 20 65 6e 63 72 79  ords(name, encry
3cd0: 70 74 65 64 50 61 73 73 20 42 4c 4f 42 2c 20 65  ptedPass BLOB, e
3ce0: 6e 63 72 79 70 74 65 64 4b 65 79 20 42 4c 4f 42  ncryptedKey BLOB
3cf0: 2c 20 70 75 62 6c 69 63 4b 65 79 20 42 4c 4f 42  , publicKey BLOB
3d00: 2c 20 76 65 72 69 66 69 63 61 74 69 6f 6e 20 42  , verification B
3d10: 4c 4f 42 29 3b 0a 7d 0a 0a 69 66 20 7b 24 61 63  LOB);.}..if {$ac
3d20: 74 69 6f 6e 20 69 6e 20 24 76 61 6c 69 64 43 6f  tion in $validCo
3d30: 6d 6d 61 6e 64 73 7d 20 7b 0a 09 69 66 20 7b 5b  mmands} {..if {[
3d40: 63 61 74 63 68 20 7b 0a 09 09 24 61 63 74 69 6f  catch {...$actio
3d50: 6e 20 7b 2a 7d 24 61 72 67 76 0a 09 7d 20 65 72  n {*}$argv..} er
3d60: 72 6f 72 5d 7d 20 7b 0a 09 09 70 75 74 73 20 73  ror]} {...puts s
3d70: 74 64 65 72 72 20 22 45 72 72 6f 72 3a 20 24 65  tderr "Error: $e
3d80: 72 72 6f 72 22 0a 0a 09 09 65 78 69 74 20 31 0a  rror"....exit 1.
3d90: 09 7d 0a 7d 20 65 6c 73 65 20 7b 0a 09 70 75 74  .}.} else {..put
3da0: 73 20 73 74 64 65 72 72 20 22 49 6e 76 61 6c 69  s stderr "Invali
3db0: 64 20 61 63 74 69 6f 6e 22 0a 0a 09 65 78 69 74  d action"...exit
3dc0: 20 31 0a 7d 0a 0a 65 78 69 74 20 30 0a 0a         1.}..exit 0..