Hex Artifact Content

Artifact 25b5870365080c3c3a7fbaf82a7b838892b75d46:


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 0a 23  e require aes..#
0d50: 20 42 61 63 6b 70 6f 72 74 73 20 66 6f 72 20 6f   Backports for o
0d60: 6c 64 65 72 20 76 65 72 73 69 6f 6e 73 20 6f 66  lder versions of
0d70: 20 22 70 6b 69 22 0a 70 72 6f 63 20 3a 3a 70 6b   "pki".proc ::pk
0d80: 69 3a 3a 70 6b 63 73 3a 3a 70 61 72 73 65 5f 70  i::pkcs::parse_p
0d90: 75 62 6c 69 63 5f 6b 65 79 20 7b 6b 65 79 20 7b  ublic_key {key {
0da0: 70 61 73 73 77 6f 72 64 20 22 22 7d 7d 20 7b 0a  password ""}} {.
0db0: 20 20 20 20 20 20 20 20 61 72 72 61 79 20 73 65          array se
0dc0: 74 20 70 61 72 73 65 64 5f 6b 65 79 20 5b 3a 3a  t parsed_key [::
0dd0: 70 6b 69 3a 3a 5f 70 61 72 73 65 5f 70 65 6d 20  pki::_parse_pem 
0de0: 24 6b 65 79 20 22 2d 2d 2d 2d 2d 42 45 47 49 4e  $key "-----BEGIN
0df0: 20 50 55 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d   PUBLIC KEY-----
0e00: 22 20 22 2d 2d 2d 2d 2d 45 4e 44 20 50 55 42 4c  " "-----END PUBL
0e10: 49 43 20 4b 45 59 2d 2d 2d 2d 2d 22 20 24 70 61  IC KEY-----" $pa
0e20: 73 73 77 6f 72 64 5d 0a 0a 20 20 20 20 20 20 20  ssword]..       
0e30: 20 73 65 74 20 6b 65 79 5f 73 65 71 20 24 70 61   set key_seq $pa
0e40: 72 73 65 64 5f 6b 65 79 28 64 61 74 61 29 0a 0a  rsed_key(data)..
0e50: 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61          ::asn::a
0e60: 73 6e 47 65 74 53 65 71 75 65 6e 63 65 20 6b 65  snGetSequence ke
0e70: 79 5f 73 65 71 20 70 75 62 6b 65 79 69 6e 66 6f  y_seq pubkeyinfo
0e80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
0e90: 20 3a 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 53 65   ::asn::asnGetSe
0ea0: 71 75 65 6e 63 65 20 70 75 62 6b 65 79 69 6e 66  quence pubkeyinf
0eb0: 6f 20 70 75 62 6b 65 79 5f 61 6c 67 6f 69 64 0a  o pubkey_algoid.
0ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ed0: 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61          ::asn::a
0ee0: 73 6e 47 65 74 4f 62 6a 65 63 74 49 64 65 6e 74  snGetObjectIdent
0ef0: 69 66 69 65 72 20 70 75 62 6b 65 79 5f 61 6c 67  ifier pubkey_alg
0f00: 6f 69 64 20 6f 69 64 0a 20 20 20 20 20 20 20 20  oid oid.        
0f10: 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61          ::asn::a
0f20: 73 6e 47 65 74 42 69 74 53 74 72 69 6e 67 20 70  snGetBitString p
0f30: 75 62 6b 65 79 69 6e 66 6f 20 70 75 62 6b 65 79  ubkeyinfo pubkey
0f40: 0a 20 20 20 20 20 20 20 20 73 65 74 20 72 65 74  .        set ret
0f50: 28 70 75 62 6b 65 79 5f 61 6c 67 6f 29 20 5b 3a  (pubkey_algo) [:
0f60: 3a 70 6b 69 3a 3a 5f 6f 69 64 5f 6e 75 6d 62 65  :pki::_oid_numbe
0f70: 72 5f 74 6f 5f 6e 61 6d 65 20 24 6f 69 64 5d 0a  r_to_name $oid].
0f80: 0a 20 20 20 20 20 20 20 20 73 77 69 74 63 68 20  .        switch 
0f90: 2d 2d 20 24 72 65 74 28 70 75 62 6b 65 79 5f 61  -- $ret(pubkey_a
0fa0: 6c 67 6f 29 20 7b 0a 20 20 20 20 20 20 20 20 20  lgo) {.         
0fb0: 20 20 20 20 20 20 20 22 72 73 61 45 6e 63 72 79         "rsaEncry
0fc0: 70 74 69 6f 6e 22 20 7b 0a 20 20 20 20 20 20 20  ption" {.       
0fd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0fe0: 20 73 65 74 20 70 75 62 6b 65 79 20 5b 62 69 6e   set pubkey [bin
0ff0: 61 72 79 20 66 6f 72 6d 61 74 20 42 2a 20 24 70  ary format B* $p
1000: 75 62 6b 65 79 5d 0a 0a 20 20 20 20 20 20 20 20  ubkey]..        
1010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1020: 3a 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 53 65 71  ::asn::asnGetSeq
1030: 75 65 6e 63 65 20 70 75 62 6b 65 79 20 70 75 62  uence pubkey pub
1040: 6b 65 79 5f 70 61 72 74 73 0a 20 20 20 20 20 20  key_parts.      
1050: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1060: 20 20 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a            ::asn:
1070: 3a 61 73 6e 47 65 74 42 69 67 49 6e 74 65 67 65  :asnGetBigIntege
1080: 72 20 70 75 62 6b 65 79 5f 70 61 72 74 73 20 72  r pubkey_parts r
1090: 65 74 28 6e 29 0a 20 20 20 20 20 20 20 20 20 20  et(n).          
10a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
10b0: 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61 73 6e        ::asn::asn
10c0: 47 65 74 42 69 67 49 6e 74 65 67 65 72 20 70 75  GetBigInteger pu
10d0: 62 6b 65 79 5f 70 61 72 74 73 20 72 65 74 28 65  bkey_parts ret(e
10e0: 29 0a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  )..             
10f0: 20 20 20 20 20 20 20 20 20 20 20 73 65 74 20 72             set r
1100: 65 74 28 6e 29 20 5b 3a 3a 6d 61 74 68 3a 3a 62  et(n) [::math::b
1110: 69 67 6e 75 6d 3a 3a 74 6f 73 74 72 20 24 72 65  ignum::tostr $re
1120: 74 28 6e 29 5d 0a 20 20 20 20 20 20 20 20 20 20  t(n)].          
1130: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
1140: 74 20 72 65 74 28 65 29 20 5b 3a 3a 6d 61 74 68  t ret(e) [::math
1150: 3a 3a 62 69 67 6e 75 6d 3a 3a 74 6f 73 74 72 20  ::bignum::tostr 
1160: 24 72 65 74 28 65 29 5d 0a 20 20 20 20 20 20 20  $ret(e)].       
1170: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1180: 20 73 65 74 20 72 65 74 28 6c 29 20 5b 65 78 70   set ret(l) [exp
1190: 72 20 7b 69 6e 74 28 5b 3a 3a 70 6b 69 3a 3a 5f  r {int([::pki::_
11a0: 62 69 74 73 20 24 72 65 74 28 6e 29 5d 20 2f 20  bits $ret(n)] / 
11b0: 38 2e 30 30 30 30 20 2b 20 30 2e 35 29 20 2a 20  8.0000 + 0.5) * 
11c0: 38 7d 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  8}].            
11d0: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 74 20              set 
11e0: 72 65 74 28 74 79 70 65 29 20 72 73 61 0a 20 20  ret(type) rsa.  
11f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7d 0a                }.
1200: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1210: 64 65 66 61 75 6c 74 20 7b 0a 20 20 20 20 20 20  default {.      
1220: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1230: 20 20 65 72 72 6f 72 20 22 55 6e 6b 6e 6f 77 6e    error "Unknown
1240: 20 61 6c 67 6f 72 69 74 68 6d 22 0a 20 20 20 20   algorithm".    
1250: 20 20 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20              }.  
1260: 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 20        }..       
1270: 20 72 65 74 75 72 6e 20 5b 61 72 72 61 79 20 67   return [array g
1280: 65 74 20 72 65 74 5d 0a 7d 0a 0a 70 72 6f 63 20  et ret].}..proc 
1290: 3a 3a 70 6b 69 3a 3a 72 73 61 3a 3a 73 65 72 69  ::pki::rsa::seri
12a0: 61 6c 69 7a 65 5f 70 75 62 6c 69 63 5f 6b 65 79  alize_public_key
12b0: 20 7b 6b 65 79 6c 69 73 74 7d 20 7b 0a 20 20 20   {keylist} {.   
12c0: 20 20 20 20 20 61 72 72 61 79 20 73 65 74 20 6b       array set k
12d0: 65 79 20 24 6b 65 79 6c 69 73 74 0a 0a 20 20 20  ey $keylist..   
12e0: 20 20 20 20 20 66 6f 72 65 61 63 68 20 65 6e 74       foreach ent
12f0: 72 79 20 5b 6c 69 73 74 20 6e 20 65 5d 20 7b 0a  ry [list n e] {.
1300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1310: 69 66 20 7b 21 5b 69 6e 66 6f 20 65 78 69 73 74  if {![info exist
1320: 73 20 6b 65 79 28 24 65 6e 74 72 79 29 5d 7d 20  s key($entry)]} 
1330: 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  {.              
1340: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
1350: 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 4b 65   -code error "Ke
1360: 79 20 64 6f 65 73 20 6e 6f 74 20 63 6f 6e 74 61  y does not conta
1370: 69 6e 20 61 6e 20 65 6c 65 6d 65 6e 74 20 24 65  in an element $e
1380: 6e 74 72 79 22 0a 20 20 20 20 20 20 20 20 20 20  ntry".          
1390: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20        }.        
13a0: 7d 0a 0a 20 20 20 20 20 20 20 20 73 65 74 20 70  }..        set p
13b0: 75 62 6b 65 79 20 5b 3a 3a 61 73 6e 3a 3a 61 73  ubkey [::asn::as
13c0: 6e 53 65 71 75 65 6e 63 65 20 5c 0a 20 20 20 20  nSequence \.    
13d0: 20 20 20 20 20 20 20 20 20 20 20 20 5b 3a 3a 61              [::a
13e0: 73 6e 3a 3a 61 73 6e 42 69 67 49 6e 74 65 67 65  sn::asnBigIntege
13f0: 72 20 5b 3a 3a 6d 61 74 68 3a 3a 62 69 67 6e 75  r [::math::bignu
1400: 6d 3a 3a 66 72 6f 6d 73 74 72 20 24 6b 65 79 28  m::fromstr $key(
1410: 6e 29 5d 5d 20 5c 0a 20 20 20 20 20 20 20 20 20  n)]] \.         
1420: 20 20 20 20 20 20 20 5b 3a 3a 61 73 6e 3a 3a 61         [::asn::a
1430: 73 6e 42 69 67 49 6e 74 65 67 65 72 20 5b 3a 3a  snBigInteger [::
1440: 6d 61 74 68 3a 3a 62 69 67 6e 75 6d 3a 3a 66 72  math::bignum::fr
1450: 6f 6d 73 74 72 20 24 6b 65 79 28 65 29 5d 5d 20  omstr $key(e)]] 
1460: 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  \.              
1470: 20 20 5d 20 20 0a 20 20 20 20 20 20 20 20 73 65    ]  .        se
1480: 74 20 70 75 62 6b 65 79 5f 61 6c 67 6f 5f 70 61  t pubkey_algo_pa
1490: 72 61 6d 73 20 5b 3a 3a 61 73 6e 3a 3a 61 73 6e  rams [::asn::asn
14a0: 4e 75 6c 6c 5d 0a 0a 20 20 20 20 20 20 20 20 62  Null]..        b
14b0: 69 6e 61 72 79 20 73 63 61 6e 20 24 70 75 62 6b  inary scan $pubk
14c0: 65 79 20 42 2a 20 70 75 62 6b 65 79 5f 62 69 74  ey B* pubkey_bit
14d0: 73 74 72 69 6e 67 0a 0a 20 20 20 20 20 20 20 20  string..        
14e0: 73 65 74 20 72 65 74 20 5b 3a 3a 61 73 6e 3a 3a  set ret [::asn::
14f0: 61 73 6e 53 65 71 75 65 6e 63 65 20 5c 0a 20 20  asnSequence \.  
1500: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 5b 3a                [:
1510: 3a 61 73 6e 3a 3a 61 73 6e 53 65 71 75 65 6e 63  :asn::asnSequenc
1520: 65 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20  e \.            
1530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1540: 20 20 20 20 5b 3a 3a 61 73 6e 3a 3a 61 73 6e 4f      [::asn::asnO
1550: 62 6a 65 63 74 49 64 65 6e 74 69 66 69 65 72 20  bjectIdentifier 
1560: 5b 3a 3a 70 6b 69 3a 3a 5f 6f 69 64 5f 6e 61 6d  [::pki::_oid_nam
1570: 65 5f 74 6f 5f 6e 75 6d 62 65 72 20 72 73 61 45  e_to_number rsaE
1580: 6e 63 72 79 70 74 69 6f 6e 5d 5d 20 5c 0a 20 20  ncryption]] \.  
1590: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 24 70                $p
15b0: 75 62 6b 65 79 5f 61 6c 67 6f 5f 70 61 72 61 6d  ubkey_algo_param
15c0: 73 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20  s \.            
15d0: 20 20 20 20 20 20 20 20 20 20 20 20 5d 20 5c 0a              ] \.
15e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15f0: 20 20 20 20 20 20 20 20 5b 3a 3a 61 73 6e 3a 3a          [::asn::
1600: 61 73 6e 42 69 74 53 74 72 69 6e 67 20 24 70 75  asnBitString $pu
1610: 62 6b 65 79 5f 62 69 74 73 74 72 69 6e 67 5d 20  bkey_bitstring] 
1620: 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  \.              
1630: 20 20 20 20 20 20 20 20 20 20 5d 0a 0a 20 20 20            ]..   
1640: 20 20 20 20 20 72 65 74 75 72 6e 20 5b 6c 69 73       return [lis
1650: 74 20 64 61 74 61 20 24 72 65 74 20 62 65 67 69  t data $ret begi
1660: 6e 20 22 2d 2d 2d 2d 2d 42 45 47 49 4e 20 50 55  n "-----BEGIN PU
1670: 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d 22 20 65  BLIC KEY-----" e
1680: 6e 64 20 22 2d 2d 2d 2d 2d 45 4e 44 20 50 55 42  nd "-----END PUB
1690: 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d 22 5d 0a 7d  LIC KEY-----"].}
16a0: 0a 23 20 45 6e 64 20 62 61 63 6b 70 6f 72 74 73  .# End backports
16b0: 0a 0a 23 20 53 74 61 72 74 20 69 6e 74 65 72 6e  ..# Start intern
16c0: 61 6c 20 66 75 6e 63 74 69 6f 6e 73 0a 70 72 6f  al functions.pro
16d0: 63 20 5f 6c 69 73 74 43 65 72 74 69 66 69 63 61  c _listCertifica
16e0: 74 65 73 20 7b 7d 20 7b 0a 09 69 66 20 7b 21 5b  tes {} {..if {![
16f0: 69 6e 66 6f 20 65 78 69 73 74 73 20 3a 3a 65 6e  info exists ::en
1700: 76 28 50 4b 43 53 31 31 4d 4f 44 55 4c 45 29 5d  v(PKCS11MODULE)]
1710: 7d 20 7b 0a 09 09 72 65 74 75 72 6e 20 5b 6c 69  } {...return [li
1720: 73 74 5d 0a 09 7d 0a 0a 09 73 65 74 20 3a 3a 65  st]..}...set ::e
1730: 6e 76 28 43 41 43 4b 45 59 5f 4e 4f 5f 45 58 54  nv(CACKEY_NO_EXT
1740: 52 41 5f 43 45 52 54 53 29 20 31 0a 0a 09 73 65  RA_CERTS) 1...se
1750: 74 20 68 61 6e 64 6c 65 20 5b 3a 3a 70 6b 69 3a  t handle [::pki:
1760: 3a 70 6b 63 73 31 31 3a 3a 6c 6f 61 64 6d 6f 64  :pkcs11::loadmod
1770: 75 6c 65 20 24 3a 3a 65 6e 76 28 50 4b 43 53 31  ule $::env(PKCS1
1780: 31 4d 4f 44 55 4c 45 29 5d 0a 0a 09 73 65 74 20  1MODULE)]...set 
1790: 73 6c 6f 74 49 6e 66 6f 20 5b 6c 69 73 74 5d 0a  slotInfo [list].
17a0: 09 66 6f 72 65 61 63 68 20 73 6c 6f 74 20 5b 3a  .foreach slot [:
17b0: 3a 70 6b 69 3a 3a 70 6b 63 73 31 31 3a 3a 6c 69  :pki::pkcs11::li
17c0: 73 74 73 6c 6f 74 73 20 24 68 61 6e 64 6c 65 5d  stslots $handle]
17d0: 20 7b 0a 09 09 73 65 74 20 73 6c 6f 74 49 44 20   {...set slotID 
17e0: 5b 6c 69 6e 64 65 78 20 24 73 6c 6f 74 20 30 5d  [lindex $slot 0]
17f0: 0a 09 09 73 65 74 20 73 6c 6f 74 4c 61 62 65 6c  ...set slotLabel
1800: 20 5b 6c 69 6e 64 65 78 20 24 73 6c 6f 74 20 31   [lindex $slot 1
1810: 5d 0a 09 09 73 65 74 20 73 6c 6f 74 46 6c 61 67  ]...set slotFlag
1820: 73 20 5b 6c 69 6e 64 65 78 20 24 73 6c 6f 74 20  s [lindex $slot 
1830: 32 5d 0a 0a 09 09 69 66 20 7b 22 54 4f 4b 45 4e  2]....if {"TOKEN
1840: 5f 50 52 45 53 45 4e 54 22 20 6e 69 20 24 73 6c  _PRESENT" ni $sl
1850: 6f 74 46 6c 61 67 73 7d 20 7b 0a 09 09 09 63 6f  otFlags} {....co
1860: 6e 74 69 6e 75 65 0a 09 09 7d 0a 0a 09 09 69 66  ntinue...}....if
1870: 20 7b 22 54 4f 4b 45 4e 5f 49 4e 49 54 49 41 4c   {"TOKEN_INITIAL
1880: 49 5a 45 44 22 20 6e 69 20 24 73 6c 6f 74 46 6c  IZED" ni $slotFl
1890: 61 67 73 7d 20 7b 0a 09 09 09 63 6f 6e 74 69 6e  ags} {....contin
18a0: 75 65 0a 09 09 7d 0a 0a 09 09 73 65 74 20 73 6c  ue...}....set sl
18b0: 6f 74 50 72 6f 6d 70 74 46 6f 72 50 49 4e 20 66  otPromptForPIN f
18c0: 61 6c 73 65 0a 09 09 69 66 20 7b 22 50 52 4f 54  alse...if {"PROT
18d0: 45 43 54 45 44 5f 41 55 54 48 45 4e 54 49 43 41  ECTED_AUTHENTICA
18e0: 54 49 4f 4e 5f 50 41 54 48 22 20 6e 69 20 24 73  TION_PATH" ni $s
18f0: 6c 6f 74 46 6c 61 67 73 7d 20 7b 0a 09 09 09 69  lotFlags} {....i
1900: 66 20 7b 22 4c 4f 47 49 4e 5f 52 45 51 55 49 52  f {"LOGIN_REQUIR
1910: 45 44 22 20 69 6e 20 24 73 6c 6f 74 46 6c 61 67  ED" in $slotFlag
1920: 73 7d 20 7b 0a 09 09 09 09 73 65 74 20 73 6c 6f  s} {.....set slo
1930: 74 50 72 6f 6d 70 74 46 6f 72 50 49 4e 20 74 72  tPromptForPIN tr
1940: 75 65 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 09 66  ue....}...}....f
1950: 6f 72 65 61 63 68 20 63 65 72 74 20 5b 3a 3a 70  oreach cert [::p
1960: 6b 69 3a 3a 70 6b 63 73 31 31 3a 3a 6c 69 73 74  ki::pkcs11::list
1970: 63 65 72 74 73 20 24 68 61 6e 64 6c 65 20 24 73  certs $handle $s
1980: 6c 6f 74 49 44 5d 20 7b 0a 09 09 09 73 65 74 20  lotID] {....set 
1990: 70 75 62 6b 65 79 20 5b 62 69 6e 61 72 79 20 65  pubkey [binary e
19a0: 6e 63 6f 64 65 20 62 61 73 65 36 34 20 5b 64 69  ncode base64 [di
19b0: 63 74 20 67 65 74 20 5b 3a 3a 70 6b 69 3a 3a 72  ct get [::pki::r
19c0: 73 61 3a 3a 73 65 72 69 61 6c 69 7a 65 5f 70 75  sa::serialize_pu
19d0: 62 6c 69 63 5f 6b 65 79 20 24 63 65 72 74 5d 20  blic_key $cert] 
19e0: 64 61 74 61 5d 5d 0a 0a 09 09 09 6c 61 70 70 65  data]].....lappe
19f0: 6e 64 20 73 6c 6f 74 49 6e 66 6f 20 5b 6c 69 73  nd slotInfo [lis
1a00: 74 20 68 61 6e 64 6c 65 20 24 68 61 6e 64 6c 65  t handle $handle
1a10: 20 69 64 20 24 73 6c 6f 74 49 44 20 70 72 6f 6d   id $slotID prom
1a20: 70 74 20 24 73 6c 6f 74 50 72 6f 6d 70 74 46 6f  pt $slotPromptFo
1a30: 72 50 49 4e 20 63 65 72 74 20 24 63 65 72 74 20  rPIN cert $cert 
1a40: 70 75 62 6b 65 79 20 24 70 75 62 6b 65 79 5d 0a  pubkey $pubkey].
1a50: 09 09 7d 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 20  ..}..}...return 
1a60: 24 73 6c 6f 74 49 6e 66 6f 0a 7d 0a 0a 70 72 6f  $slotInfo.}..pro
1a70: 63 20 5f 61 64 64 50 61 73 73 77 6f 72 64 20 7b  c _addPassword {
1a80: 6e 61 6d 65 20 70 61 73 73 77 6f 72 64 20 70 75  name password pu
1a90: 62 6c 69 63 4b 65 79 73 7d 20 7b 0a 09 73 65 74  blicKeys} {..set
1aa0: 20 66 64 20 5b 6f 70 65 6e 20 22 2f 64 65 76 2f   fd [open "/dev/
1ab0: 75 72 61 6e 64 6f 6d 22 20 72 5d 0a 09 66 63 6f  urandom" r]..fco
1ac0: 6e 66 69 67 75 72 65 20 24 66 64 20 2d 74 72 61  nfigure $fd -tra
1ad0: 6e 73 6c 61 74 69 6f 6e 20 62 69 6e 61 72 79 0a  nslation binary.
1ae0: 0a 09 64 62 20 65 76 61 6c 20 7b 44 45 4c 45 54  ..db eval {DELET
1af0: 45 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73  E FROM passwords
1b00: 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 6e   WHERE name = $n
1b10: 61 6d 65 3b 7d 0a 0a 09 66 6f 72 65 61 63 68 20  ame;}...foreach 
1b20: 70 75 62 6c 69 63 4b 65 79 20 24 70 75 62 6c 69  publicKey $publi
1b30: 63 4b 65 79 73 20 7b 0a 09 09 73 65 74 20 6b 65  cKeys {...set ke
1b40: 79 20 5b 72 65 61 64 20 24 66 64 20 31 36 5d 0a  y [read $fd 16].
1b50: 09 09 69 66 20 7b 5b 73 74 72 69 6e 67 20 6c 65  ..if {[string le
1b60: 6e 67 74 68 20 24 6b 65 79 5d 20 21 3d 20 31 36  ngth $key] != 16
1b70: 7d 20 7b 0a 09 09 09 63 6c 6f 73 65 20 24 66 64  } {....close $fd
1b80: 0a 0a 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64  .....return -cod
1b90: 65 20 65 72 72 6f 72 20 22 45 52 52 4f 52 3a 20  e error "ERROR: 
1ba0: 53 68 6f 72 74 20 72 65 61 64 20 66 72 6f 6d 20  Short read from 
1bb0: 72 61 6e 64 6f 6d 20 64 65 76 69 63 65 22 0a 09  random device"..
1bc0: 09 7d 0a 0a 09 09 73 65 74 20 70 75 62 6c 69 63  .}....set public
1bd0: 4b 65 79 49 74 65 6d 20 5b 3a 3a 70 6b 69 3a 3a  KeyItem [::pki::
1be0: 70 6b 63 73 3a 3a 70 61 72 73 65 5f 70 75 62 6c  pkcs::parse_publ
1bf0: 69 63 5f 6b 65 79 20 5b 62 69 6e 61 72 79 20 64  ic_key [binary d
1c00: 65 63 6f 64 65 20 62 61 73 65 36 34 20 24 70 75  ecode base64 $pu
1c10: 62 6c 69 63 4b 65 79 5d 5d 0a 0a 09 09 73 65 74  blicKey]]....set
1c20: 20 65 6e 63 72 79 70 74 65 64 4b 65 79 20 5b 62   encryptedKey [b
1c30: 69 6e 61 72 79 20 65 6e 63 6f 64 65 20 62 61 73  inary encode bas
1c40: 65 36 34 20 5b 3a 3a 70 6b 69 3a 3a 65 6e 63 72  e64 [::pki::encr
1c50: 79 70 74 20 2d 70 75 62 20 2d 62 69 6e 61 72 79  ypt -pub -binary
1c60: 20 2d 2d 20 24 6b 65 79 20 24 70 75 62 6c 69 63   -- $key $public
1c70: 4b 65 79 49 74 65 6d 5d 5d 0a 0a 09 09 73 65 74  KeyItem]]....set
1c80: 20 65 6e 63 72 79 70 74 65 64 50 61 73 73 20 5b   encryptedPass [
1c90: 62 69 6e 61 72 79 20 65 6e 63 6f 64 65 20 62 61  binary encode ba
1ca0: 73 65 36 34 20 5b 3a 3a 61 65 73 3a 3a 61 65 73  se64 [::aes::aes
1cb0: 20 2d 64 69 72 20 65 6e 63 72 79 70 74 20 2d 6b   -dir encrypt -k
1cc0: 65 79 20 24 6b 65 79 20 2d 2d 20 24 70 61 73 73  ey $key -- $pass
1cd0: 77 6f 72 64 5d 5d 0a 0a 09 09 64 62 20 65 76 61  word]]....db eva
1ce0: 6c 20 7b 49 4e 53 45 52 54 20 49 4e 54 4f 20 70  l {INSERT INTO p
1cf0: 61 73 73 77 6f 72 64 73 20 28 6e 61 6d 65 2c 20  asswords (name, 
1d00: 65 6e 63 72 79 70 74 65 64 50 61 73 73 2c 20 65  encryptedPass, e
1d10: 6e 63 72 79 70 74 65 64 4b 65 79 2c 20 70 75 62  ncryptedKey, pub
1d20: 6c 69 63 4b 65 79 29 20 56 41 4c 55 45 53 20 28  licKey) VALUES (
1d30: 24 6e 61 6d 65 2c 20 40 65 6e 63 72 79 70 74 65  $name, @encrypte
1d40: 64 50 61 73 73 2c 20 40 65 6e 63 72 79 70 74 65  dPass, @encrypte
1d50: 64 4b 65 79 2c 20 40 70 75 62 6c 69 63 4b 65 79  dKey, @publicKey
1d60: 29 3b 7d 0a 09 7d 0a 0a 09 63 6c 6f 73 65 20 24  );}..}...close $
1d70: 66 64 0a 7d 0a 0a 70 72 6f 63 20 5f 70 72 6f 6d  fd.}..proc _prom
1d80: 70 74 20 7b 70 72 6f 6d 70 74 7d 20 7b 0a 09 70  pt {prompt} {..p
1d90: 75 74 73 20 2d 6e 6f 6e 65 77 6c 69 6e 65 20 24  uts -nonewline $
1da0: 70 72 6f 6d 70 74 0a 09 66 6c 75 73 68 20 73 74  prompt..flush st
1db0: 64 6f 75 74 0a 0a 09 70 75 74 73 20 2d 6e 6f 6e  dout...puts -non
1dc0: 65 77 6c 69 6e 65 20 5b 65 78 65 63 20 73 74 74  ewline [exec stt
1dd0: 79 20 2d 65 63 68 6f 5d 0a 09 66 6c 75 73 68 20  y -echo]..flush 
1de0: 73 74 64 6f 75 74 0a 0a 09 73 65 74 20 70 61 73  stdout...set pas
1df0: 73 77 6f 72 64 20 5b 67 65 74 73 20 73 74 64 69  sword [gets stdi
1e00: 6e 5d 0a 0a 09 70 75 74 73 20 2d 6e 6f 6e 65 77  n]...puts -nonew
1e10: 6c 69 6e 65 20 5b 65 78 65 63 20 73 74 74 79 20  line [exec stty 
1e20: 65 63 68 6f 5d 0a 09 70 75 74 73 20 22 22 0a 09  echo]..puts ""..
1e30: 66 6c 75 73 68 20 73 74 64 6f 75 74 0a 0a 09 72  flush stdout...r
1e40: 65 74 75 72 6e 20 24 70 61 73 73 77 6f 72 64 0a  eturn $password.
1e50: 7d 0a 0a 70 72 6f 63 20 5f 67 65 74 50 61 73 73  }..proc _getPass
1e60: 77 6f 72 64 20 7b 6e 61 6d 65 7d 20 7b 0a 09 66  word {name} {..f
1e70: 6f 72 65 61 63 68 20 73 6c 6f 74 49 6e 66 6f 44  oreach slotInfoD
1e80: 69 63 74 20 5b 5f 6c 69 73 74 43 65 72 74 69 66  ict [_listCertif
1e90: 69 63 61 74 65 73 5d 20 7b 0a 09 09 75 6e 73 65  icates] {...unse
1ea0: 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 73 6c  t -nocomplain sl
1eb0: 6f 74 49 6e 66 6f 0a 09 09 61 72 72 61 79 20 73  otInfo...array s
1ec0: 65 74 20 73 6c 6f 74 49 6e 66 6f 20 24 73 6c 6f  et slotInfo $slo
1ed0: 74 49 6e 66 6f 44 69 63 74 0a 0a 09 09 73 65 74  tInfoDict....set
1ee0: 20 70 75 62 6b 65 79 20 24 73 6c 6f 74 49 6e 66   pubkey $slotInf
1ef0: 6f 28 70 75 62 6b 65 79 29 0a 09 09 73 65 74 20  o(pubkey)...set 
1f00: 70 72 6f 6d 70 74 20 24 73 6c 6f 74 49 6e 66 6f  prompt $slotInfo
1f10: 28 70 72 6f 6d 70 74 29 0a 0a 09 09 69 66 20 7b  (prompt)....if {
1f20: 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 70 72 6f  [info exists pro
1f30: 6d 70 74 65 64 28 24 73 6c 6f 74 49 6e 66 6f 28  mpted($slotInfo(
1f40: 69 64 29 29 5d 7d 20 7b 0a 09 09 09 73 65 74 20  id))]} {....set 
1f50: 70 72 6f 6d 70 74 20 66 61 6c 73 65 0a 09 09 7d  prompt false...}
1f60: 0a 0a 09 09 69 66 20 7b 24 70 72 6f 6d 70 74 7d  ....if {$prompt}
1f70: 20 7b 0a 09 09 09 73 65 74 20 50 49 4e 20 5b 5f   {....set PIN [_
1f80: 70 72 6f 6d 70 74 20 22 50 6c 65 61 73 65 20 65  prompt "Please e
1f90: 6e 74 65 72 20 74 68 65 20 50 49 4e 20 66 6f 72  nter the PIN for
1fa0: 20 5b 64 69 63 74 20 67 65 74 20 24 73 6c 6f 74   [dict get $slot
1fb0: 49 6e 66 6f 28 63 65 72 74 29 20 73 75 62 6a 65  Info(cert) subje
1fc0: 63 74 5d 3a 20 22 5d 0a 0a 09 09 09 69 66 20 7b  ct]: "].....if {
1fd0: 21 5b 3a 3a 70 6b 69 3a 3a 70 6b 63 73 31 31 3a  ![::pki::pkcs11:
1fe0: 3a 6c 6f 67 69 6e 20 24 73 6c 6f 74 49 6e 66 6f  :login $slotInfo
1ff0: 28 68 61 6e 64 6c 65 29 20 24 73 6c 6f 74 49 6e  (handle) $slotIn
2000: 66 6f 28 69 64 29 20 24 50 49 4e 5d 7d 20 7b 0a  fo(id) $PIN]} {.
2010: 09 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65  ....return -code
2020: 20 65 72 72 6f 72 20 22 55 6e 61 62 6c 65 20 74   error "Unable t
2030: 6f 20 61 75 74 68 65 6e 74 69 63 61 74 65 22 0a  o authenticate".
2040: 09 09 09 7d 0a 0a 09 09 09 73 65 74 20 70 72 6f  ...}.....set pro
2050: 6d 70 74 65 64 28 24 73 6c 6f 74 49 6e 66 6f 28  mpted($slotInfo(
2060: 69 64 29 29 20 31 0a 09 09 7d 0a 0a 09 09 64 62  id)) 1...}....db
2070: 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 65 6e   eval {SELECT en
2080: 63 72 79 70 74 65 64 50 61 73 73 2c 20 65 6e 63  cryptedPass, enc
2090: 72 79 70 74 65 64 4b 65 79 20 46 52 4f 4d 20 70  ryptedKey FROM p
20a0: 61 73 73 77 6f 72 64 73 20 57 48 45 52 45 20 6e  asswords WHERE n
20b0: 61 6d 65 20 3d 20 24 6e 61 6d 65 20 41 4e 44 20  ame = $name AND 
20c0: 70 75 62 6c 69 63 4b 65 79 20 3d 20 24 70 75 62  publicKey = $pub
20d0: 6b 65 79 3b 7d 20 72 6f 77 20 7b 0a 09 09 09 73  key;} row {....s
20e0: 65 74 20 6b 65 79 20 5b 3a 3a 70 6b 69 3a 3a 64  et key [::pki::d
20f0: 65 63 72 79 70 74 20 2d 62 69 6e 61 72 79 20 2d  ecrypt -binary -
2100: 70 72 69 76 20 2d 2d 20 5b 62 69 6e 61 72 79 20  priv -- [binary 
2110: 64 65 63 6f 64 65 20 62 61 73 65 36 34 20 24 72  decode base64 $r
2120: 6f 77 28 65 6e 63 72 79 70 74 65 64 4b 65 79 29  ow(encryptedKey)
2130: 5d 20 24 73 6c 6f 74 49 6e 66 6f 28 63 65 72 74  ] $slotInfo(cert
2140: 29 5d 0a 09 09 09 73 65 74 20 70 61 73 73 77 6f  )]....set passwo
2150: 72 64 20 5b 3a 3a 61 65 73 3a 3a 61 65 73 20 2d  rd [::aes::aes -
2160: 64 69 72 20 64 65 63 72 79 70 74 20 2d 6b 65 79  dir decrypt -key
2170: 20 24 6b 65 79 20 2d 2d 20 5b 62 69 6e 61 72 79   $key -- [binary
2180: 20 64 65 63 6f 64 65 20 62 61 73 65 36 34 20 24   decode base64 $
2190: 72 6f 77 28 65 6e 63 72 79 70 74 65 64 50 61 73  row(encryptedPas
21a0: 73 29 5d 5d 0a 0a 09 09 09 72 65 74 75 72 6e 20  s)]].....return 
21b0: 24 70 61 73 73 77 6f 72 64 0a 09 09 7d 0a 09 7d  $password...}..}
21c0: 0a 0a 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20  ...return -code 
21d0: 65 72 72 6f 72 20 22 4e 6f 20 76 61 6c 69 64 20  error "No valid 
21e0: 6b 65 79 73 22 0a 7d 0a 0a 70 72 6f 63 20 5f 6d  keys".}..proc _m
21f0: 6f 64 69 66 79 50 75 62 6c 69 63 4b 65 79 73 20  odifyPublicKeys 
2200: 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 75 73  {passwordName us
2210: 65 72 4e 61 6d 65 73 20 73 71 6c 7d 20 7b 0a 09  erNames sql} {..
2220: 73 65 74 20 70 75 62 6c 69 63 4b 65 79 73 20 5b  set publicKeys [
2230: 6c 69 73 74 5d 0a 0a 09 64 62 20 65 76 61 6c 20  list]...db eval 
2240: 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b 65  {SELECT publicKe
2250: 79 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73  y FROM passwords
2260: 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 70   WHERE name = $p
2270: 61 73 73 77 6f 72 64 4e 61 6d 65 3b 7d 20 72 6f  asswordName;} ro
2280: 77 20 7b 0a 09 09 6c 61 70 70 65 6e 64 20 70 75  w {...lappend pu
2290: 62 6c 69 63 4b 65 79 73 20 24 72 6f 77 28 70 75  blicKeys $row(pu
22a0: 62 6c 69 63 4b 65 79 29 0a 09 7d 0a 0a 09 73 65  blicKey)..}...se
22b0: 74 20 63 68 61 6e 67 65 52 65 71 75 69 72 65 64  t changeRequired
22c0: 20 30 0a 09 66 6f 72 65 61 63 68 20 75 73 65 72   0..foreach user
22d0: 20 24 75 73 65 72 4e 61 6d 65 73 20 7b 0a 09 09   $userNames {...
22e0: 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69  unset -nocomplai
22f0: 6e 20 72 6f 77 0a 09 09 64 62 20 65 76 61 6c 20  n row...db eval 
2300: 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b 65  {SELECT publicKe
2310: 79 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48 45  y FROM users WHE
2320: 52 45 20 6e 61 6d 65 20 3d 20 24 75 73 65 72 3b  RE name = $user;
2330: 7d 20 72 6f 77 20 24 73 71 6c 0a 09 7d 0a 0a 09  } row $sql..}...
2340: 69 66 20 7b 21 24 63 68 61 6e 67 65 52 65 71 75  if {!$changeRequ
2350: 69 72 65 64 7d 20 7b 0a 09 09 72 65 74 75 72 6e  ired} {...return
2360: 0a 09 7d 0a 0a 09 73 65 74 20 70 61 73 73 77 6f  ..}...set passwo
2370: 72 64 20 5b 5f 67 65 74 50 61 73 73 77 6f 72 64  rd [_getPassword
2380: 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5d 0a   $passwordName].
2390: 0a 09 5f 61 64 64 50 61 73 73 77 6f 72 64 20 24  .._addPassword $
23a0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 70 61  passwordName $pa
23b0: 73 73 77 6f 72 64 20 24 70 75 62 6c 69 63 4b 65  ssword $publicKe
23c0: 79 73 0a 7d 0a 0a 70 72 6f 63 20 5f 67 65 74 55  ys.}..proc _getU
23d0: 73 65 72 73 46 6f 72 50 61 73 73 77 6f 72 64 20  sersForPassword 
23e0: 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 7d 20  {passwordNames} 
23f0: 7b 0a 09 73 65 74 20 75 73 65 72 4e 61 6d 65 73  {..set userNames
2400: 20 5b 6c 69 73 74 5d 0a 0a 09 66 6f 72 65 61 63   [list]...foreac
2410: 68 20 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24  h passwordName $
2420: 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 20 7b 0a  passwordNames {.
2430: 09 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43  ..db eval {SELEC
2440: 54 20 70 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d  T publicKey FROM
2450: 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45   passwords WHERE
2460: 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77 6f 72   name = $passwor
2470: 64 4e 61 6d 65 3b 7d 20 70 61 73 73 77 6f 72 64  dName;} password
2480: 52 6f 77 20 7b 0a 09 09 09 64 62 20 65 76 61 6c  Row {....db eval
2490: 20 7b 53 45 4c 45 43 54 20 6e 61 6d 65 20 46 52   {SELECT name FR
24a0: 4f 4d 20 75 73 65 72 73 20 57 48 45 52 45 20 70  OM users WHERE p
24b0: 75 62 6c 69 63 4b 65 79 20 3d 20 24 70 61 73 73  ublicKey = $pass
24c0: 77 6f 72 64 52 6f 77 28 70 75 62 6c 69 63 4b 65  wordRow(publicKe
24d0: 79 29 7d 20 75 73 65 72 52 6f 77 20 7b 0a 09 09  y)} userRow {...
24e0: 09 09 69 66 20 7b 24 75 73 65 72 52 6f 77 28 6e  ..if {$userRow(n
24f0: 61 6d 65 29 20 69 6e 20 24 75 73 65 72 4e 61 6d  ame) in $userNam
2500: 65 73 7d 20 7b 0a 09 09 09 09 09 63 6f 6e 74 69  es} {......conti
2510: 6e 75 65 0a 09 09 09 09 7d 0a 0a 09 09 09 09 6c  nue.....}......l
2520: 61 70 70 65 6e 64 20 75 73 65 72 4e 61 6d 65 73  append userNames
2530: 20 24 75 73 65 72 52 6f 77 28 6e 61 6d 65 29 0a   $userRow(name).
2540: 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a 0a 09 72 65  ...}...}..}...re
2550: 74 75 72 6e 20 24 75 73 65 72 4e 61 6d 65 73 0a  turn $userNames.
2560: 7d 0a 0a 70 72 6f 63 20 5f 67 65 74 50 61 73 73  }..proc _getPass
2570: 77 6f 72 64 73 46 6f 72 55 73 65 72 20 7b 75 73  wordsForUser {us
2580: 65 72 4e 61 6d 65 73 7d 20 7b 0a 09 73 65 74 20  erNames} {..set 
2590: 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 20 5b 6c  passwordNames [l
25a0: 69 73 74 5d 0a 0a 09 66 6f 72 65 61 63 68 20 75  ist]...foreach u
25b0: 73 65 72 4e 61 6d 65 20 24 75 73 65 72 4e 61 6d  serName $userNam
25c0: 65 73 20 7b 0a 09 09 64 62 20 65 76 61 6c 20 7b  es {...db eval {
25d0: 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b 65 79  SELECT publicKey
25e0: 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48 45 52   FROM users WHER
25f0: 45 20 6e 61 6d 65 20 3d 20 24 75 73 65 72 4e 61  E name = $userNa
2600: 6d 65 3b 7d 20 75 73 65 72 52 6f 77 20 7b 0a 09  me;} userRow {..
2610: 09 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43  ..db eval {SELEC
2620: 54 20 6e 61 6d 65 20 46 52 4f 4d 20 70 61 73 73  T name FROM pass
2630: 77 6f 72 64 73 20 57 48 45 52 45 20 70 75 62 6c  words WHERE publ
2640: 69 63 4b 65 79 20 3d 20 24 75 73 65 72 52 6f 77  icKey = $userRow
2650: 28 70 75 62 6c 69 63 4b 65 79 29 7d 20 70 61 73  (publicKey)} pas
2660: 73 77 6f 72 64 52 6f 77 20 7b 0a 09 09 09 09 69  swordRow {.....i
2670: 66 20 7b 24 70 61 73 73 77 6f 72 64 52 6f 77 28  f {$passwordRow(
2680: 6e 61 6d 65 29 20 69 6e 20 24 70 61 73 73 77 6f  name) in $passwo
2690: 72 64 4e 61 6d 65 73 7d 20 7b 0a 09 09 09 09 09  rdNames} {......
26a0: 63 6f 6e 74 69 6e 75 65 0a 09 09 09 09 7d 0a 0a  continue.....}..
26b0: 09 09 09 09 6c 61 70 70 65 6e 64 20 70 61 73 73  ....lappend pass
26c0: 77 6f 72 64 4e 61 6d 65 73 20 24 70 61 73 73 77  wordNames $passw
26d0: 6f 72 64 52 6f 77 28 6e 61 6d 65 29 0a 09 09 09  ordRow(name)....
26e0: 7d 0a 09 09 7d 0a 09 7d 0a 0a 09 72 65 74 75 72  }...}..}...retur
26f0: 6e 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 73  n $passwordNames
2700: 0a 7d 0a 23 20 45 6e 64 20 69 6e 74 65 72 6e 61  .}.# End interna
2710: 6c 20 66 75 6e 63 74 69 6f 6e 73 0a 0a 23 20 53  l functions..# S
2720: 74 61 72 74 20 75 73 65 72 20 43 4c 49 20 66 75  tart user CLI fu
2730: 6e 63 74 69 6f 6e 73 0a 70 72 6f 63 20 6c 69 73  nctions.proc lis
2740: 74 4c 6f 63 61 6c 4b 65 79 73 20 7b 7d 20 7b 0a  tLocalKeys {} {.
2750: 09 66 6f 72 65 61 63 68 20 73 6c 6f 74 49 6e 66  .foreach slotInf
2760: 6f 44 69 63 74 20 5b 5f 6c 69 73 74 43 65 72 74  oDict [_listCert
2770: 69 66 69 63 61 74 65 73 5d 20 7b 0a 09 09 75 6e  ificates] {...un
2780: 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20  set -nocomplain 
2790: 73 6c 6f 74 49 6e 66 6f 0a 09 09 61 72 72 61 79  slotInfo...array
27a0: 20 73 65 74 20 73 6c 6f 74 49 6e 66 6f 20 24 73   set slotInfo $s
27b0: 6c 6f 74 49 6e 66 6f 44 69 63 74 0a 0a 09 09 73  lotInfoDict....s
27c0: 65 74 20 73 75 62 6a 65 63 74 20 5b 64 69 63 74  et subject [dict
27d0: 20 67 65 74 20 24 73 6c 6f 74 49 6e 66 6f 28 63   get $slotInfo(c
27e0: 65 72 74 29 20 73 75 62 6a 65 63 74 5d 0a 09 09  ert) subject]...
27f0: 73 65 74 20 70 75 62 6b 65 79 20 20 24 73 6c 6f  set pubkey  $slo
2800: 74 49 6e 66 6f 28 70 75 62 6b 65 79 29 0a 0a 09  tInfo(pubkey)...
2810: 09 6c 61 70 70 65 6e 64 20 70 75 62 6c 69 63 4b  .lappend publicK
2820: 65 79 73 28 24 73 75 62 6a 65 63 74 29 20 24 70  eys($subject) $p
2830: 75 62 6b 65 79 0a 09 7d 0a 0a 09 66 6f 72 65 61  ubkey..}...forea
2840: 63 68 20 7b 73 75 62 6a 65 63 74 20 70 75 62 6b  ch {subject pubk
2850: 65 79 73 7d 20 5b 61 72 72 61 79 20 67 65 74 20  eys} [array get 
2860: 70 75 62 6c 69 63 4b 65 79 73 5d 20 7b 0a 09 09  publicKeys] {...
2870: 70 75 74 73 20 22 24 73 75 62 6a 65 63 74 22 0a  puts "$subject".
2880: 0a 09 09 66 6f 72 65 61 63 68 20 70 75 62 6b 65  ...foreach pubke
2890: 79 20 24 70 75 62 6b 65 79 73 20 7b 0a 09 09 09  y $pubkeys {....
28a0: 70 75 74 73 20 22 20 20 7c 2d 3e 20 24 70 75 62  puts "  |-> $pub
28b0: 6b 65 79 22 0a 09 09 7d 0a 09 7d 0a 7d 0a 0a 70  key"...}..}.}..p
28c0: 72 6f 63 20 6c 69 73 74 41 76 61 69 6c 61 62 6c  roc listAvailabl
28d0: 65 50 61 73 73 77 6f 72 64 73 20 7b 7d 20 7b 0a  ePasswords {} {.
28e0: 09 73 65 74 20 70 61 73 73 77 6f 72 64 4e 61 6d  .set passwordNam
28f0: 65 73 20 5b 6c 69 73 74 5d 0a 09 66 6f 72 65 61  es [list]..forea
2900: 63 68 20 73 6c 6f 74 49 6e 66 6f 44 69 63 74 20  ch slotInfoDict 
2910: 5b 5f 6c 69 73 74 43 65 72 74 69 66 69 63 61 74  [_listCertificat
2920: 65 73 5d 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e  es] {...unset -n
2930: 6f 63 6f 6d 70 6c 61 69 6e 20 73 6c 6f 74 49 6e  ocomplain slotIn
2940: 66 6f 0a 09 09 61 72 72 61 79 20 73 65 74 20 73  fo...array set s
2950: 6c 6f 74 49 6e 66 6f 20 24 73 6c 6f 74 49 6e 66  lotInfo $slotInf
2960: 6f 44 69 63 74 0a 0a 09 09 73 65 74 20 70 75 62  oDict....set pub
2970: 6b 65 79 20 24 73 6c 6f 74 49 6e 66 6f 28 70 75  key $slotInfo(pu
2980: 62 6b 65 79 29 0a 0a 09 09 75 6e 73 65 74 20 2d  bkey)....unset -
2990: 6e 6f 63 6f 6d 70 6c 61 69 6e 20 72 6f 77 0a 09  nocomplain row..
29a0: 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54  .db eval {SELECT
29b0: 20 6e 61 6d 65 20 46 52 4f 4d 20 70 61 73 73 77   name FROM passw
29c0: 6f 72 64 73 20 57 48 45 52 45 20 70 75 62 6c 69  ords WHERE publi
29d0: 63 4b 65 79 20 3d 20 24 70 75 62 6b 65 79 3b 7d  cKey = $pubkey;}
29e0: 20 72 6f 77 20 7b 0a 09 09 09 69 66 20 7b 24 72   row {....if {$r
29f0: 6f 77 28 6e 61 6d 65 29 20 69 6e 20 24 70 61 73  ow(name) in $pas
2a00: 73 77 6f 72 64 4e 61 6d 65 73 7d 20 7b 0a 09 09  swordNames} {...
2a10: 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 7d 0a  ..continue....}.
2a20: 0a 09 09 09 6c 61 70 70 65 6e 64 20 70 61 73 73  ....lappend pass
2a30: 77 6f 72 64 4e 61 6d 65 73 20 24 72 6f 77 28 6e  wordNames $row(n
2a40: 61 6d 65 29 0a 09 09 7d 0a 09 7d 0a 0a 0a 09 66  ame)...}..}....f
2a50: 6f 72 65 61 63 68 20 70 61 73 73 77 6f 72 64 4e  oreach passwordN
2a60: 61 6d 65 20 24 70 61 73 73 77 6f 72 64 4e 61 6d  ame $passwordNam
2a70: 65 73 20 7b 0a 09 09 70 75 74 73 20 22 24 70 61  es {...puts "$pa
2a80: 73 73 77 6f 72 64 4e 61 6d 65 20 2d 20 5b 6a 6f  sswordName - [jo
2a90: 69 6e 20 5b 5f 67 65 74 55 73 65 72 73 46 6f 72  in [_getUsersFor
2aa0: 50 61 73 73 77 6f 72 64 20 5b 6c 69 73 74 20 24  Password [list $
2ab0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 5d 5d 20 7b  passwordName]] {
2ac0: 2c 20 7d 5d 22 0a 09 7d 0a 7d 0a 0a 70 72 6f 63  , }]"..}.}..proc
2ad0: 20 6c 69 73 74 50 61 73 73 77 6f 72 64 73 20 7b   listPasswords {
2ae0: 7d 20 7b 0a 09 64 62 20 65 76 61 6c 20 7b 53 45  } {..db eval {SE
2af0: 4c 45 43 54 20 44 49 53 54 49 4e 43 54 20 6e 61  LECT DISTINCT na
2b00: 6d 65 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64  me FROM password
2b10: 73 3b 7d 20 72 6f 77 20 7b 0a 09 09 70 75 74 73  s;} row {...puts
2b20: 20 22 24 72 6f 77 28 6e 61 6d 65 29 20 2d 20 5b   "$row(name) - [
2b30: 6a 6f 69 6e 20 5b 5f 67 65 74 55 73 65 72 73 46  join [_getUsersF
2b40: 6f 72 50 61 73 73 77 6f 72 64 20 5b 6c 69 73 74  orPassword [list
2b50: 20 24 72 6f 77 28 6e 61 6d 65 29 5d 5d 20 7b 2c   $row(name)]] {,
2b60: 20 7d 5d 22 0a 09 7d 0a 7d 0a 0a 70 72 6f 63 20   }]"..}.}..proc 
2b70: 6c 69 73 74 55 73 65 72 73 20 7b 7d 20 7b 0a 09  listUsers {} {..
2b80: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20  db eval {SELECT 
2b90: 44 49 53 54 49 4e 43 54 20 6e 61 6d 65 20 46 52  DISTINCT name FR
2ba0: 4f 4d 20 75 73 65 72 73 3b 7d 20 72 6f 77 20 7b  OM users;} row {
2bb0: 0a 09 09 70 75 74 73 20 22 24 72 6f 77 28 6e 61  ...puts "$row(na
2bc0: 6d 65 29 20 2d 20 5b 6a 6f 69 6e 20 5b 5f 67 65  me) - [join [_ge
2bd0: 74 50 61 73 73 77 6f 72 64 73 46 6f 72 55 73 65  tPasswordsForUse
2be0: 72 20 5b 6c 69 73 74 20 24 72 6f 77 28 6e 61 6d  r [list $row(nam
2bf0: 65 29 5d 5d 20 7b 2c 20 7d 5d 22 0a 09 7d 0a 7d  e)]] {, }]"..}.}
2c00: 0a 0a 70 72 6f 63 20 61 64 64 55 73 65 72 20 7b  ..proc addUser {
2c10: 75 73 65 72 4e 61 6d 65 20 6b 65 79 7d 20 7b 0a  userName key} {.
2c20: 09 73 65 74 20 6b 65 79 52 61 77 20 5b 62 69 6e  .set keyRaw [bin
2c30: 61 72 79 20 64 65 63 6f 64 65 20 62 61 73 65 36  ary decode base6
2c40: 34 20 24 6b 65 79 5d 0a 09 73 65 74 20 6b 65 79  4 $key]..set key
2c50: 56 65 72 69 66 79 20 5b 3a 3a 70 6b 69 3a 3a 70  Verify [::pki::p
2c60: 6b 63 73 3a 3a 70 61 72 73 65 5f 70 75 62 6c 69  kcs::parse_publi
2c70: 63 5f 6b 65 79 20 24 6b 65 79 52 61 77 5d 0a 0a  c_key $keyRaw]..
2c80: 09 64 62 20 65 76 61 6c 20 7b 49 4e 53 45 52 54  .db eval {INSERT
2c90: 20 49 4e 54 4f 20 75 73 65 72 73 20 28 6e 61 6d   INTO users (nam
2ca0: 65 2c 20 70 75 62 6c 69 63 4b 65 79 29 20 56 41  e, publicKey) VA
2cb0: 4c 55 45 53 20 28 24 75 73 65 72 4e 61 6d 65 2c  LUES ($userName,
2cc0: 20 40 6b 65 79 29 3b 7d 0a 0a 09 23 20 58 58 58   @key);}...# XXX
2cd0: 3a 54 4f 44 4f 3a 47 6f 20 74 68 72 6f 75 67 68  :TODO:Go through
2ce0: 20 61 6e 64 20 72 65 2d 61 75 74 68 6f 72 69 7a   and re-authoriz
2cf0: 65 20 69 66 20 70 6f 73 73 69 62 6c 65 0a 7d 0a  e if possible.}.
2d00: 0a 70 72 6f 63 20 64 65 6c 65 74 65 55 73 65 72  .proc deleteUser
2d10: 20 7b 75 73 65 72 4e 61 6d 65 7d 20 7b 0a 09 23   {userName} {..#
2d20: 20 58 58 58 3a 54 4f 44 4f 3a 20 47 6f 20 74 68   XXX:TODO: Go th
2d30: 72 6f 75 67 68 20 61 6e 64 20 64 65 2d 61 75 74  rough and de-aut
2d40: 68 6f 72 69 7a 65 0a 7d 0a 0a 70 72 6f 63 20 61  horize.}..proc a
2d50: 64 64 50 61 73 73 77 6f 72 64 20 7b 70 61 73 73  ddPassword {pass
2d60: 77 6f 72 64 4e 61 6d 65 20 70 61 73 73 77 6f 72  wordName passwor
2d70: 64 20 61 72 67 73 7d 20 7b 0a 09 73 65 74 20 69  d args} {..set i
2d80: 6e 69 74 69 61 6c 55 73 65 72 73 20 24 61 72 67  nitialUsers $arg
2d90: 73 0a 0a 09 69 66 20 7b 24 70 61 73 73 77 6f 72  s...if {$passwor
2da0: 64 20 65 71 20 22 22 7d 20 7b 0a 09 09 73 65 74  d eq ""} {...set
2db0: 20 70 61 73 73 77 6f 72 64 20 5b 5f 70 72 6f 6d   password [_prom
2dc0: 70 74 20 22 50 6c 65 61 73 65 20 65 6e 74 65 72  pt "Please enter
2dd0: 20 74 68 65 20 6e 65 77 20 70 61 73 73 77 6f 72   the new passwor
2de0: 64 3a 20 22 5d 0a 09 7d 0a 0a 09 23 20 56 65 72  d: "]..}...# Ver
2df0: 69 66 79 20 74 68 61 74 20 74 68 69 73 20 70 61  ify that this pa
2e00: 73 73 77 6f 72 64 20 64 6f 65 73 20 6e 6f 74 20  ssword does not 
2e10: 61 6c 72 65 61 64 79 20 65 78 69 73 74 0a 09 73  already exist..s
2e20: 65 74 20 65 78 69 73 74 73 20 5b 64 62 20 65 76  et exists [db ev
2e30: 61 6c 20 7b 53 45 4c 45 43 54 20 31 20 46 52 4f  al {SELECT 1 FRO
2e40: 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52  M passwords WHER
2e50: 45 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77 6f  E name = $passwo
2e60: 72 64 4e 61 6d 65 20 4c 49 4d 49 54 20 31 3b 7d  rdName LIMIT 1;}
2e70: 5d 0a 09 69 66 20 7b 24 65 78 69 73 74 73 20 3d  ]..if {$exists =
2e80: 3d 20 22 31 22 7d 20 7b 0a 09 09 72 65 74 75 72  = "1"} {...retur
2e90: 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 50  n -code error "P
2ea0: 61 73 73 77 6f 72 64 20 5c 22 24 70 61 73 73 77  assword \"$passw
2eb0: 6f 72 64 4e 61 6d 65 5c 22 20 61 6c 72 65 61 64  ordName\" alread
2ec0: 79 20 65 78 69 73 74 73 2c 20 63 61 6e 6e 6f 74  y exists, cannot
2ed0: 20 61 64 64 2e 22 0a 09 7d 0a 0a 09 23 20 47 65   add."..}...# Ge
2ee0: 74 20 6b 65 79 73 20 66 6f 72 20 69 6e 69 74 69  t keys for initi
2ef0: 61 6c 20 75 73 65 72 73 0a 09 73 65 74 20 70 75  al users..set pu
2f00: 62 6c 69 63 4b 65 79 73 20 5b 6c 69 73 74 5d 0a  blicKeys [list].
2f10: 09 66 6f 72 65 61 63 68 20 75 73 65 72 20 24 69  .foreach user $i
2f20: 6e 69 74 69 61 6c 55 73 65 72 73 20 7b 0a 09 09  nitialUsers {...
2f30: 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69  unset -nocomplai
2f40: 6e 20 72 6f 77 0a 09 09 64 62 20 65 76 61 6c 20  n row...db eval 
2f50: 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b 65  {SELECT publicKe
2f60: 79 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48 45  y FROM users WHE
2f70: 52 45 20 6e 61 6d 65 20 3d 20 24 75 73 65 72 3b  RE name = $user;
2f80: 7d 20 72 6f 77 20 7b 0a 09 09 09 6c 61 70 70 65  } row {....lappe
2f90: 6e 64 20 70 75 62 6c 69 63 4b 65 79 73 20 24 72  nd publicKeys $r
2fa0: 6f 77 28 70 75 62 6c 69 63 4b 65 79 29 0a 09 09  ow(publicKey)...
2fb0: 7d 0a 09 7d 0a 0a 09 5f 61 64 64 50 61 73 73 77  }..}..._addPassw
2fc0: 6f 72 64 20 24 70 61 73 73 77 6f 72 64 4e 61 6d  ord $passwordNam
2fd0: 65 20 24 70 61 73 73 77 6f 72 64 20 24 70 75 62  e $password $pub
2fe0: 6c 69 63 4b 65 79 73 0a 7d 0a 0a 70 72 6f 63 20  licKeys.}..proc 
2ff0: 67 65 74 50 61 73 73 77 6f 72 64 20 7b 70 61 73  getPassword {pas
3000: 73 77 6f 72 64 4e 61 6d 65 7d 20 7b 0a 09 70 75  swordName} {..pu
3010: 74 73 20 5b 5f 67 65 74 50 61 73 73 77 6f 72 64  ts [_getPassword
3020: 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5d 0a   $passwordName].
3030: 7d 0a 0a 70 72 6f 63 20 75 70 64 61 74 65 50 61  }..proc updatePa
3040: 73 73 77 6f 72 64 20 7b 70 61 73 73 77 6f 72 64  ssword {password
3050: 4e 61 6d 65 20 70 61 73 73 77 6f 72 64 7d 20 7b  Name password} {
3060: 0a 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43  ..db eval {SELEC
3070: 54 20 70 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d  T publicKey FROM
3080: 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45   passwords WHERE
3090: 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77 6f 72   name = $passwor
30a0: 64 4e 61 6d 65 3b 7d 20 72 6f 77 20 7b 0a 09 09  dName;} row {...
30b0: 6c 61 70 70 65 6e 64 20 70 75 62 6c 69 63 4b 65  lappend publicKe
30c0: 79 73 20 24 72 6f 77 28 70 75 62 6c 69 63 4b 65  ys $row(publicKe
30d0: 79 29 0a 09 7d 0a 0a 09 5f 61 64 64 50 61 73 73  y)..}..._addPass
30e0: 77 6f 72 64 20 24 70 61 73 73 77 6f 72 64 4e 61  word $passwordNa
30f0: 6d 65 20 24 70 61 73 73 77 6f 72 64 20 24 70 75  me $password $pu
3100: 62 6c 69 63 4b 65 79 73 0a 7d 0a 0a 70 72 6f 63  blicKeys.}..proc
3110: 20 64 65 6c 65 74 65 50 61 73 73 77 6f 72 64 20   deletePassword 
3120: 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 7d 20 7b  {passwordName} {
3130: 0a 09 64 62 20 65 76 61 6c 20 7b 44 45 4c 45 54  ..db eval {DELET
3140: 45 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73  E FROM passwords
3150: 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 70   WHERE name = $p
3160: 61 73 73 77 6f 72 64 4e 61 6d 65 3b 7d 0a 7d 0a  asswordName;}.}.
3170: 0a 70 72 6f 63 20 61 75 74 68 6f 72 69 7a 65 55  .proc authorizeU
3180: 73 65 72 73 20 7b 70 61 73 73 77 6f 72 64 4e 61  sers {passwordNa
3190: 6d 65 20 61 72 67 73 7d 20 7b 0a 09 73 65 74 20  me args} {..set 
31a0: 75 73 65 72 73 20 24 61 72 67 73 0a 0a 09 5f 6d  users $args..._m
31b0: 6f 64 69 66 79 50 75 62 6c 69 63 4b 65 79 73 20  odifyPublicKeys 
31c0: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 75  $passwordName $u
31d0: 73 65 72 73 20 7b 0a 09 09 69 66 20 7b 24 72 6f  sers {...if {$ro
31e0: 77 28 70 75 62 6c 69 63 4b 65 79 29 20 69 6e 20  w(publicKey) in 
31f0: 24 70 75 62 6c 69 63 4b 65 79 73 7d 20 7b 0a 09  $publicKeys} {..
3200: 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 7d 0a 0a  ..continue...}..
3210: 09 09 6c 61 70 70 65 6e 64 20 70 75 62 6c 69 63  ..lappend public
3220: 4b 65 79 73 20 24 72 6f 77 28 70 75 62 6c 69 63  Keys $row(public
3230: 4b 65 79 29 0a 0a 09 09 73 65 74 20 63 68 61 6e  Key)....set chan
3240: 67 65 52 65 71 75 69 72 65 64 20 31 0a 09 7d 0a  geRequired 1..}.
3250: 7d 0a 0a 70 72 6f 63 20 61 75 74 68 6f 72 69 7a  }..proc authoriz
3260: 65 55 73 65 72 20 7b 70 61 73 73 77 6f 72 64 4e  eUser {passwordN
3270: 61 6d 65 20 75 73 65 72 4e 61 6d 65 7d 20 7b 0a  ame userName} {.
3280: 09 72 65 74 75 72 6e 20 5b 61 75 74 68 6f 72 69  .return [authori
3290: 7a 65 55 73 65 72 73 20 24 70 61 73 73 77 6f 72  zeUsers $passwor
32a0: 64 4e 61 6d 65 20 24 75 73 65 72 4e 61 6d 65 5d  dName $userName]
32b0: 0a 7d 0a 0a 70 72 6f 63 20 64 65 61 75 74 68 6f  .}..proc deautho
32c0: 72 69 7a 65 55 73 65 72 73 20 7b 70 61 73 73 77  rizeUsers {passw
32d0: 6f 72 64 4e 61 6d 65 20 61 72 67 73 7d 20 7b 0a  ordName args} {.
32e0: 09 73 65 74 20 75 73 65 72 73 20 24 61 72 67 73  .set users $args
32f0: 0a 0a 09 5f 6d 6f 64 69 66 79 50 75 62 6c 69 63  ..._modifyPublic
3300: 4b 65 79 73 20 24 70 61 73 73 77 6f 72 64 4e 61  Keys $passwordNa
3310: 6d 65 20 24 75 73 65 72 73 20 7b 0a 09 09 73 65  me $users {...se
3320: 74 20 69 64 78 20 5b 6c 73 65 61 72 63 68 20 2d  t idx [lsearch -
3330: 65 78 61 63 74 20 24 70 75 62 6c 69 63 4b 65 79  exact $publicKey
3340: 73 20 24 72 6f 77 28 70 75 62 6c 69 63 4b 65 79  s $row(publicKey
3350: 29 5d 0a 09 09 69 66 20 7b 24 69 64 78 20 3d 3d  )]...if {$idx ==
3360: 20 2d 31 7d 20 7b 0a 09 09 09 63 6f 6e 74 69 6e   -1} {....contin
3370: 75 65 0a 09 09 7d 0a 0a 09 09 73 65 74 20 70 75  ue...}....set pu
3380: 62 6c 69 63 4b 65 79 73 20 5b 6c 72 65 70 6c 61  blicKeys [lrepla
3390: 63 65 20 24 70 75 62 6c 69 63 4b 65 79 73 20 24  ce $publicKeys $
33a0: 69 64 78 20 24 69 64 78 5d 0a 0a 09 09 73 65 74  idx $idx]....set
33b0: 20 63 68 61 6e 67 65 52 65 71 75 69 72 65 64 20   changeRequired 
33c0: 31 0a 09 7d 0a 7d 0a 0a 70 72 6f 63 20 64 65 61  1..}.}..proc dea
33d0: 75 74 68 6f 72 69 7a 65 55 73 65 72 20 7b 70 61  uthorizeUser {pa
33e0: 73 73 77 6f 72 64 4e 61 6d 65 20 75 73 65 72 4e  sswordName userN
33f0: 61 6d 65 7d 20 7b 0a 09 72 65 74 75 72 6e 20 5b  ame} {..return [
3400: 64 65 61 75 74 68 6f 72 69 7a 65 55 73 65 72 73  deauthorizeUsers
3410: 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24   $passwordName $
3420: 75 73 65 72 4e 61 6d 65 5d 0a 7d 0a 0a 70 72 6f  userName].}..pro
3430: 63 20 68 65 6c 70 20 7b 7b 61 63 74 69 6f 6e 20  c help {{action 
3440: 22 22 7d 7d 20 7b 0a 09 5f 70 72 69 6e 74 48 65  ""}} {.._printHe
3450: 6c 70 20 73 74 64 6f 75 74 20 24 61 63 74 69 6f  lp stdout $actio
3460: 6e 0a 7d 0a 23 20 45 6e 64 20 75 73 65 72 20 43  n.}.# End user C
3470: 4c 49 20 66 75 6e 63 74 69 6f 6e 73 0a 0a 23 23  LI functions..##
3480: 23 20 4d 41 49 4e 0a 0a 73 71 6c 69 74 65 33 20  # MAIN..sqlite3 
3490: 64 62 20 24 70 61 73 73 77 6f 72 64 46 69 6c 65  db $passwordFile
34a0: 0a 0a 64 62 20 65 76 61 6c 20 7b 0a 09 43 52 45  ..db eval {..CRE
34b0: 41 54 45 20 54 41 42 4c 45 20 49 46 20 4e 4f 54  ATE TABLE IF NOT
34c0: 20 45 58 49 53 54 53 20 75 73 65 72 73 28 6e 61   EXISTS users(na
34d0: 6d 65 2c 20 70 75 62 6c 69 63 4b 65 79 20 42 4c  me, publicKey BL
34e0: 4f 42 29 3b 0a 09 43 52 45 41 54 45 20 54 41 42  OB);..CREATE TAB
34f0: 4c 45 20 49 46 20 4e 4f 54 20 45 58 49 53 54 53  LE IF NOT EXISTS
3500: 20 70 61 73 73 77 6f 72 64 73 28 6e 61 6d 65 2c   passwords(name,
3510: 20 65 6e 63 72 79 70 74 65 64 50 61 73 73 20 42   encryptedPass B
3520: 4c 4f 42 2c 20 65 6e 63 72 79 70 74 65 64 4b 65  LOB, encryptedKe
3530: 79 20 42 4c 4f 42 2c 20 70 75 62 6c 69 63 4b 65  y BLOB, publicKe
3540: 79 20 42 4c 4f 42 29 3b 0a 7d 0a 0a 69 66 20 7b  y BLOB);.}..if {
3550: 24 61 63 74 69 6f 6e 20 69 6e 20 24 76 61 6c 69  $action in $vali
3560: 64 43 6f 6d 6d 61 6e 64 73 7d 20 7b 0a 09 24 61  dCommands} {..$a
3570: 63 74 69 6f 6e 20 7b 2a 7d 24 61 72 67 76 0a 7d  ction {*}$argv.}
3580: 20 65 6c 73 65 20 7b 0a 09 70 75 74 73 20 73 74   else {..puts st
3590: 64 65 72 72 20 22 49 6e 76 61 6c 69 64 20 61 63  derr "Invalid ac
35a0: 74 69 6f 6e 22 0a 0a 09 65 78 69 74 20 31 0a 7d  tion"...exit 1.}
35b0: 0a 0a 65 78 69 74 20 30 0a 0a                    ..exit 0..