Hex Artifact Content

Artifact 60941617be4c86caaccef4643cfbd13427930708:


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 73  word {name} {..s
1e70: 65 74 20 65 78 69 73 74 73 20 5b 64 62 20 65 76  et exists [db ev
1e80: 61 6c 20 7b 53 45 4c 45 43 54 20 31 20 46 52 4f  al {SELECT 1 FRO
1e90: 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52  M passwords WHER
1ea0: 45 20 6e 61 6d 65 20 3d 20 24 6e 61 6d 65 20 4c  E name = $name L
1eb0: 49 4d 49 54 20 31 3b 7d 5d 0a 09 69 66 20 7b 24  IMIT 1;}]..if {$
1ec0: 65 78 69 73 74 73 20 21 3d 20 22 31 22 7d 20 7b  exists != "1"} {
1ed0: 0a 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20  ...return -code 
1ee0: 65 72 72 6f 72 20 22 50 61 73 73 77 6f 72 64 20  error "Password 
1ef0: 5c 22 24 6e 61 6d 65 5c 22 20 64 6f 65 73 20 6e  \"$name\" does n
1f00: 6f 74 20 65 78 69 73 74 73 2e 22 0a 09 7d 0a 0a  ot exists."..}..
1f10: 09 66 6f 72 65 61 63 68 20 73 6c 6f 74 49 6e 66  .foreach slotInf
1f20: 6f 44 69 63 74 20 5b 5f 6c 69 73 74 43 65 72 74  oDict [_listCert
1f30: 69 66 69 63 61 74 65 73 5d 20 7b 0a 09 09 75 6e  ificates] {...un
1f40: 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20  set -nocomplain 
1f50: 73 6c 6f 74 49 6e 66 6f 0a 09 09 61 72 72 61 79  slotInfo...array
1f60: 20 73 65 74 20 73 6c 6f 74 49 6e 66 6f 20 24 73   set slotInfo $s
1f70: 6c 6f 74 49 6e 66 6f 44 69 63 74 0a 0a 09 09 73  lotInfoDict....s
1f80: 65 74 20 70 75 62 6b 65 79 20 24 73 6c 6f 74 49  et pubkey $slotI
1f90: 6e 66 6f 28 70 75 62 6b 65 79 29 0a 09 09 73 65  nfo(pubkey)...se
1fa0: 74 20 70 72 6f 6d 70 74 20 24 73 6c 6f 74 49 6e  t prompt $slotIn
1fb0: 66 6f 28 70 72 6f 6d 70 74 29 0a 0a 09 09 69 66  fo(prompt)....if
1fc0: 20 7b 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 70   {[info exists p
1fd0: 72 6f 6d 70 74 65 64 28 24 73 6c 6f 74 49 6e 66  rompted($slotInf
1fe0: 6f 28 69 64 29 29 5d 7d 20 7b 0a 09 09 09 73 65  o(id))]} {....se
1ff0: 74 20 70 72 6f 6d 70 74 20 66 61 6c 73 65 0a 09  t prompt false..
2000: 09 7d 0a 0a 09 09 69 66 20 7b 24 70 72 6f 6d 70  .}....if {$promp
2010: 74 7d 20 7b 0a 09 09 09 73 65 74 20 50 49 4e 20  t} {....set PIN 
2020: 5b 5f 70 72 6f 6d 70 74 20 22 50 6c 65 61 73 65  [_prompt "Please
2030: 20 65 6e 74 65 72 20 74 68 65 20 50 49 4e 20 66   enter the PIN f
2040: 6f 72 20 5b 64 69 63 74 20 67 65 74 20 24 73 6c  or [dict get $sl
2050: 6f 74 49 6e 66 6f 28 63 65 72 74 29 20 73 75 62  otInfo(cert) sub
2060: 6a 65 63 74 5d 3a 20 22 5d 0a 0a 09 09 09 69 66  ject]: "].....if
2070: 20 7b 21 5b 3a 3a 70 6b 69 3a 3a 70 6b 63 73 31   {![::pki::pkcs1
2080: 31 3a 3a 6c 6f 67 69 6e 20 24 73 6c 6f 74 49 6e  1::login $slotIn
2090: 66 6f 28 68 61 6e 64 6c 65 29 20 24 73 6c 6f 74  fo(handle) $slot
20a0: 49 6e 66 6f 28 69 64 29 20 24 50 49 4e 5d 7d 20  Info(id) $PIN]} 
20b0: 7b 0a 09 09 09 09 72 65 74 75 72 6e 20 2d 63 6f  {.....return -co
20c0: 64 65 20 65 72 72 6f 72 20 22 55 6e 61 62 6c 65  de error "Unable
20d0: 20 74 6f 20 61 75 74 68 65 6e 74 69 63 61 74 65   to authenticate
20e0: 22 0a 09 09 09 7d 0a 0a 09 09 09 73 65 74 20 70  "....}.....set p
20f0: 72 6f 6d 70 74 65 64 28 24 73 6c 6f 74 49 6e 66  rompted($slotInf
2100: 6f 28 69 64 29 29 20 31 0a 09 09 7d 0a 0a 09 09  o(id)) 1...}....
2110: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20  db eval {SELECT 
2120: 65 6e 63 72 79 70 74 65 64 50 61 73 73 2c 20 65  encryptedPass, e
2130: 6e 63 72 79 70 74 65 64 4b 65 79 20 46 52 4f 4d  ncryptedKey FROM
2140: 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45   passwords WHERE
2150: 20 6e 61 6d 65 20 3d 20 24 6e 61 6d 65 20 41 4e   name = $name AN
2160: 44 20 70 75 62 6c 69 63 4b 65 79 20 3d 20 24 70  D publicKey = $p
2170: 75 62 6b 65 79 3b 7d 20 72 6f 77 20 7b 0a 09 09  ubkey;} row {...
2180: 09 73 65 74 20 6b 65 79 20 5b 3a 3a 70 6b 69 3a  .set key [::pki:
2190: 3a 64 65 63 72 79 70 74 20 2d 62 69 6e 61 72 79  :decrypt -binary
21a0: 20 2d 70 72 69 76 20 2d 2d 20 5b 62 69 6e 61 72   -priv -- [binar
21b0: 79 20 64 65 63 6f 64 65 20 62 61 73 65 36 34 20  y decode base64 
21c0: 24 72 6f 77 28 65 6e 63 72 79 70 74 65 64 4b 65  $row(encryptedKe
21d0: 79 29 5d 20 24 73 6c 6f 74 49 6e 66 6f 28 63 65  y)] $slotInfo(ce
21e0: 72 74 29 5d 0a 09 09 09 73 65 74 20 70 61 73 73  rt)]....set pass
21f0: 77 6f 72 64 20 5b 3a 3a 61 65 73 3a 3a 61 65 73  word [::aes::aes
2200: 20 2d 64 69 72 20 64 65 63 72 79 70 74 20 2d 6b   -dir decrypt -k
2210: 65 79 20 24 6b 65 79 20 2d 2d 20 5b 62 69 6e 61  ey $key -- [bina
2220: 72 79 20 64 65 63 6f 64 65 20 62 61 73 65 36 34  ry decode base64
2230: 20 24 72 6f 77 28 65 6e 63 72 79 70 74 65 64 50   $row(encryptedP
2240: 61 73 73 29 5d 5d 0a 0a 09 09 09 72 65 74 75 72  ass)]].....retur
2250: 6e 20 24 70 61 73 73 77 6f 72 64 0a 09 09 7d 0a  n $password...}.
2260: 09 7d 0a 0a 09 72 65 74 75 72 6e 20 2d 63 6f 64  .}...return -cod
2270: 65 20 65 72 72 6f 72 20 22 4e 6f 20 76 61 6c 69  e error "No vali
2280: 64 20 6b 65 79 73 22 0a 7d 0a 0a 70 72 6f 63 20  d keys".}..proc 
2290: 5f 6d 6f 64 69 66 79 50 75 62 6c 69 63 4b 65 79  _modifyPublicKey
22a0: 73 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 20  s {passwordName 
22b0: 75 73 65 72 4e 61 6d 65 73 20 73 71 6c 7d 20 7b  userNames sql} {
22c0: 0a 09 73 65 74 20 65 78 69 73 74 73 20 5b 64 62  ..set exists [db
22d0: 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 31 20   eval {SELECT 1 
22e0: 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57  FROM passwords W
22f0: 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 70 61 73  HERE name = $pas
2300: 73 77 6f 72 64 4e 61 6d 65 20 4c 49 4d 49 54 20  swordName LIMIT 
2310: 31 3b 7d 5d 0a 09 69 66 20 7b 24 65 78 69 73 74  1;}]..if {$exist
2320: 73 20 21 3d 20 22 31 22 7d 20 7b 0a 09 09 72 65  s != "1"} {...re
2330: 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72  turn -code error
2340: 20 22 50 61 73 73 77 6f 72 64 20 5c 22 24 70 61   "Password \"$pa
2350: 73 73 77 6f 72 64 4e 61 6d 65 5c 22 20 64 6f 65  sswordName\" doe
2360: 73 20 6e 6f 74 20 65 78 69 73 74 73 2e 22 0a 09  s not exists."..
2370: 7d 0a 0a 09 73 65 74 20 70 75 62 6c 69 63 4b 65  }...set publicKe
2380: 79 73 20 5b 6c 69 73 74 5d 0a 0a 09 64 62 20 65  ys [list]...db e
2390: 76 61 6c 20 7b 53 45 4c 45 43 54 20 70 75 62 6c  val {SELECT publ
23a0: 69 63 4b 65 79 20 46 52 4f 4d 20 70 61 73 73 77  icKey FROM passw
23b0: 6f 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20  ords WHERE name 
23c0: 3d 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 3b  = $passwordName;
23d0: 7d 20 72 6f 77 20 7b 0a 09 09 6c 61 70 70 65 6e  } row {...lappen
23e0: 64 20 70 75 62 6c 69 63 4b 65 79 73 20 24 72 6f  d publicKeys $ro
23f0: 77 28 70 75 62 6c 69 63 4b 65 79 29 0a 09 7d 0a  w(publicKey)..}.
2400: 0a 09 73 65 74 20 63 68 61 6e 67 65 52 65 71 75  ..set changeRequ
2410: 69 72 65 64 20 30 0a 09 66 6f 72 65 61 63 68 20  ired 0..foreach 
2420: 75 73 65 72 20 24 75 73 65 72 4e 61 6d 65 73 20  user $userNames 
2430: 7b 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d  {...unset -nocom
2440: 70 6c 61 69 6e 20 72 6f 77 0a 09 09 64 62 20 65  plain row...db e
2450: 76 61 6c 20 7b 53 45 4c 45 43 54 20 70 75 62 6c  val {SELECT publ
2460: 69 63 4b 65 79 20 46 52 4f 4d 20 75 73 65 72 73  icKey FROM users
2470: 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 75   WHERE name = $u
2480: 73 65 72 3b 7d 20 72 6f 77 20 24 73 71 6c 0a 09  ser;} row $sql..
2490: 7d 0a 0a 09 69 66 20 7b 21 24 63 68 61 6e 67 65  }...if {!$change
24a0: 52 65 71 75 69 72 65 64 7d 20 7b 0a 09 09 72 65  Required} {...re
24b0: 74 75 72 6e 0a 09 7d 0a 0a 09 73 65 74 20 70 61  turn..}...set pa
24c0: 73 73 77 6f 72 64 20 5b 5f 67 65 74 50 61 73 73  ssword [_getPass
24d0: 77 6f 72 64 20 24 70 61 73 73 77 6f 72 64 4e 61  word $passwordNa
24e0: 6d 65 5d 0a 0a 09 5f 61 64 64 50 61 73 73 77 6f  me]..._addPasswo
24f0: 72 64 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65  rd $passwordName
2500: 20 24 70 61 73 73 77 6f 72 64 20 24 70 75 62 6c   $password $publ
2510: 69 63 4b 65 79 73 0a 7d 0a 0a 70 72 6f 63 20 5f  icKeys.}..proc _
2520: 67 65 74 55 73 65 72 73 46 6f 72 50 61 73 73 77  getUsersForPassw
2530: 6f 72 64 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d  ord {passwordNam
2540: 65 73 7d 20 7b 0a 09 73 65 74 20 75 73 65 72 4e  es} {..set userN
2550: 61 6d 65 73 20 5b 6c 69 73 74 5d 0a 0a 09 66 6f  ames [list]...fo
2560: 72 65 61 63 68 20 70 61 73 73 77 6f 72 64 4e 61  reach passwordNa
2570: 6d 65 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65  me $passwordName
2580: 73 20 7b 0a 09 09 64 62 20 65 76 61 6c 20 7b 53  s {...db eval {S
2590: 45 4c 45 43 54 20 70 75 62 6c 69 63 4b 65 79 20  ELECT publicKey 
25a0: 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57  FROM passwords W
25b0: 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 70 61 73  HERE name = $pas
25c0: 73 77 6f 72 64 4e 61 6d 65 3b 7d 20 70 61 73 73  swordName;} pass
25d0: 77 6f 72 64 52 6f 77 20 7b 0a 09 09 09 64 62 20  wordRow {....db 
25e0: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 6e 61 6d  eval {SELECT nam
25f0: 65 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48 45  e FROM users WHE
2600: 52 45 20 70 75 62 6c 69 63 4b 65 79 20 3d 20 24  RE publicKey = $
2610: 70 61 73 73 77 6f 72 64 52 6f 77 28 70 75 62 6c  passwordRow(publ
2620: 69 63 4b 65 79 29 7d 20 75 73 65 72 52 6f 77 20  icKey)} userRow 
2630: 7b 0a 09 09 09 09 69 66 20 7b 24 75 73 65 72 52  {.....if {$userR
2640: 6f 77 28 6e 61 6d 65 29 20 69 6e 20 24 75 73 65  ow(name) in $use
2650: 72 4e 61 6d 65 73 7d 20 7b 0a 09 09 09 09 09 63  rNames} {......c
2660: 6f 6e 74 69 6e 75 65 0a 09 09 09 09 7d 0a 0a 09  ontinue.....}...
2670: 09 09 09 6c 61 70 70 65 6e 64 20 75 73 65 72 4e  ...lappend userN
2680: 61 6d 65 73 20 24 75 73 65 72 52 6f 77 28 6e 61  ames $userRow(na
2690: 6d 65 29 0a 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a  me)....}...}..}.
26a0: 0a 09 72 65 74 75 72 6e 20 24 75 73 65 72 4e 61  ..return $userNa
26b0: 6d 65 73 0a 7d 0a 0a 70 72 6f 63 20 5f 67 65 74  mes.}..proc _get
26c0: 50 61 73 73 77 6f 72 64 73 46 6f 72 55 73 65 72  PasswordsForUser
26d0: 20 7b 75 73 65 72 4e 61 6d 65 73 7d 20 7b 0a 09   {userNames} {..
26e0: 73 65 74 20 70 61 73 73 77 6f 72 64 4e 61 6d 65  set passwordName
26f0: 73 20 5b 6c 69 73 74 5d 0a 0a 09 66 6f 72 65 61  s [list]...forea
2700: 63 68 20 75 73 65 72 4e 61 6d 65 20 24 75 73 65  ch userName $use
2710: 72 4e 61 6d 65 73 20 7b 0a 09 09 64 62 20 65 76  rNames {...db ev
2720: 61 6c 20 7b 53 45 4c 45 43 54 20 70 75 62 6c 69  al {SELECT publi
2730: 63 4b 65 79 20 46 52 4f 4d 20 75 73 65 72 73 20  cKey FROM users 
2740: 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 75 73  WHERE name = $us
2750: 65 72 4e 61 6d 65 3b 7d 20 75 73 65 72 52 6f 77  erName;} userRow
2760: 20 7b 0a 09 09 09 64 62 20 65 76 61 6c 20 7b 53   {....db eval {S
2770: 45 4c 45 43 54 20 6e 61 6d 65 20 46 52 4f 4d 20  ELECT name FROM 
2780: 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45 20  passwords WHERE 
2790: 70 75 62 6c 69 63 4b 65 79 20 3d 20 24 75 73 65  publicKey = $use
27a0: 72 52 6f 77 28 70 75 62 6c 69 63 4b 65 79 29 7d  rRow(publicKey)}
27b0: 20 70 61 73 73 77 6f 72 64 52 6f 77 20 7b 0a 09   passwordRow {..
27c0: 09 09 09 69 66 20 7b 24 70 61 73 73 77 6f 72 64  ...if {$password
27d0: 52 6f 77 28 6e 61 6d 65 29 20 69 6e 20 24 70 61  Row(name) in $pa
27e0: 73 73 77 6f 72 64 4e 61 6d 65 73 7d 20 7b 0a 09  sswordNames} {..
27f0: 09 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09  ....continue....
2800: 09 7d 0a 0a 09 09 09 09 6c 61 70 70 65 6e 64 20  .}......lappend 
2810: 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 20 24 70  passwordNames $p
2820: 61 73 73 77 6f 72 64 52 6f 77 28 6e 61 6d 65 29  asswordRow(name)
2830: 0a 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a 0a 09 72  ....}...}..}...r
2840: 65 74 75 72 6e 20 24 70 61 73 73 77 6f 72 64 4e  eturn $passwordN
2850: 61 6d 65 73 0a 7d 0a 23 20 45 6e 64 20 69 6e 74  ames.}.# End int
2860: 65 72 6e 61 6c 20 66 75 6e 63 74 69 6f 6e 73 0a  ernal functions.
2870: 0a 23 20 53 74 61 72 74 20 75 73 65 72 20 43 4c  .# Start user CL
2880: 49 20 66 75 6e 63 74 69 6f 6e 73 0a 70 72 6f 63  I functions.proc
2890: 20 6c 69 73 74 4c 6f 63 61 6c 4b 65 79 73 20 7b   listLocalKeys {
28a0: 7d 20 7b 0a 09 66 6f 72 65 61 63 68 20 73 6c 6f  } {..foreach slo
28b0: 74 49 6e 66 6f 44 69 63 74 20 5b 5f 6c 69 73 74  tInfoDict [_list
28c0: 43 65 72 74 69 66 69 63 61 74 65 73 5d 20 7b 0a  Certificates] {.
28d0: 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c  ..unset -nocompl
28e0: 61 69 6e 20 73 6c 6f 74 49 6e 66 6f 0a 09 09 61  ain slotInfo...a
28f0: 72 72 61 79 20 73 65 74 20 73 6c 6f 74 49 6e 66  rray set slotInf
2900: 6f 20 24 73 6c 6f 74 49 6e 66 6f 44 69 63 74 0a  o $slotInfoDict.
2910: 0a 09 09 73 65 74 20 73 75 62 6a 65 63 74 20 5b  ...set subject [
2920: 64 69 63 74 20 67 65 74 20 24 73 6c 6f 74 49 6e  dict get $slotIn
2930: 66 6f 28 63 65 72 74 29 20 73 75 62 6a 65 63 74  fo(cert) subject
2940: 5d 0a 09 09 73 65 74 20 70 75 62 6b 65 79 20 20  ]...set pubkey  
2950: 24 73 6c 6f 74 49 6e 66 6f 28 70 75 62 6b 65 79  $slotInfo(pubkey
2960: 29 0a 0a 09 09 6c 61 70 70 65 6e 64 20 70 75 62  )....lappend pub
2970: 6c 69 63 4b 65 79 73 28 24 73 75 62 6a 65 63 74  licKeys($subject
2980: 29 20 24 70 75 62 6b 65 79 0a 09 7d 0a 0a 09 66  ) $pubkey..}...f
2990: 6f 72 65 61 63 68 20 7b 73 75 62 6a 65 63 74 20  oreach {subject 
29a0: 70 75 62 6b 65 79 73 7d 20 5b 61 72 72 61 79 20  pubkeys} [array 
29b0: 67 65 74 20 70 75 62 6c 69 63 4b 65 79 73 5d 20  get publicKeys] 
29c0: 7b 0a 09 09 70 75 74 73 20 22 24 73 75 62 6a 65  {...puts "$subje
29d0: 63 74 22 0a 0a 09 09 66 6f 72 65 61 63 68 20 70  ct"....foreach p
29e0: 75 62 6b 65 79 20 24 70 75 62 6b 65 79 73 20 7b  ubkey $pubkeys {
29f0: 0a 09 09 09 70 75 74 73 20 22 20 20 7c 2d 3e 20  ....puts "  |-> 
2a00: 24 70 75 62 6b 65 79 22 0a 09 09 7d 0a 09 7d 0a  $pubkey"...}..}.
2a10: 7d 0a 0a 70 72 6f 63 20 6c 69 73 74 41 76 61 69  }..proc listAvai
2a20: 6c 61 62 6c 65 50 61 73 73 77 6f 72 64 73 20 7b  lablePasswords {
2a30: 7d 20 7b 0a 09 73 65 74 20 70 61 73 73 77 6f 72  } {..set passwor
2a40: 64 4e 61 6d 65 73 20 5b 6c 69 73 74 5d 0a 09 66  dNames [list]..f
2a50: 6f 72 65 61 63 68 20 73 6c 6f 74 49 6e 66 6f 44  oreach slotInfoD
2a60: 69 63 74 20 5b 5f 6c 69 73 74 43 65 72 74 69 66  ict [_listCertif
2a70: 69 63 61 74 65 73 5d 20 7b 0a 09 09 75 6e 73 65  icates] {...unse
2a80: 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 73 6c  t -nocomplain sl
2a90: 6f 74 49 6e 66 6f 0a 09 09 61 72 72 61 79 20 73  otInfo...array s
2aa0: 65 74 20 73 6c 6f 74 49 6e 66 6f 20 24 73 6c 6f  et slotInfo $slo
2ab0: 74 49 6e 66 6f 44 69 63 74 0a 0a 09 09 73 65 74  tInfoDict....set
2ac0: 20 70 75 62 6b 65 79 20 24 73 6c 6f 74 49 6e 66   pubkey $slotInf
2ad0: 6f 28 70 75 62 6b 65 79 29 0a 0a 09 09 75 6e 73  o(pubkey)....uns
2ae0: 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 72  et -nocomplain r
2af0: 6f 77 0a 09 09 64 62 20 65 76 61 6c 20 7b 53 45  ow...db eval {SE
2b00: 4c 45 43 54 20 6e 61 6d 65 20 46 52 4f 4d 20 70  LECT name FROM p
2b10: 61 73 73 77 6f 72 64 73 20 57 48 45 52 45 20 70  asswords WHERE p
2b20: 75 62 6c 69 63 4b 65 79 20 3d 20 24 70 75 62 6b  ublicKey = $pubk
2b30: 65 79 3b 7d 20 72 6f 77 20 7b 0a 09 09 09 69 66  ey;} row {....if
2b40: 20 7b 24 72 6f 77 28 6e 61 6d 65 29 20 69 6e 20   {$row(name) in 
2b50: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 7d 20  $passwordNames} 
2b60: 7b 0a 09 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09  {.....continue..
2b70: 09 09 7d 0a 0a 09 09 09 6c 61 70 70 65 6e 64 20  ..}.....lappend 
2b80: 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 20 24 72  passwordNames $r
2b90: 6f 77 28 6e 61 6d 65 29 0a 09 09 7d 0a 09 7d 0a  ow(name)...}..}.
2ba0: 0a 0a 09 66 6f 72 65 61 63 68 20 70 61 73 73 77  ...foreach passw
2bb0: 6f 72 64 4e 61 6d 65 20 24 70 61 73 73 77 6f 72  ordName $passwor
2bc0: 64 4e 61 6d 65 73 20 7b 0a 09 09 70 75 74 73 20  dNames {...puts 
2bd0: 22 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 2d  "$passwordName -
2be0: 20 5b 6a 6f 69 6e 20 5b 5f 67 65 74 55 73 65 72   [join [_getUser
2bf0: 73 46 6f 72 50 61 73 73 77 6f 72 64 20 5b 6c 69  sForPassword [li
2c00: 73 74 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65  st $passwordName
2c10: 5d 5d 20 7b 2c 20 7d 5d 22 0a 09 7d 0a 7d 0a 0a  ]] {, }]"..}.}..
2c20: 70 72 6f 63 20 6c 69 73 74 50 61 73 73 77 6f 72  proc listPasswor
2c30: 64 73 20 7b 7d 20 7b 0a 09 64 62 20 65 76 61 6c  ds {} {..db eval
2c40: 20 7b 53 45 4c 45 43 54 20 44 49 53 54 49 4e 43   {SELECT DISTINC
2c50: 54 20 6e 61 6d 65 20 46 52 4f 4d 20 70 61 73 73  T name FROM pass
2c60: 77 6f 72 64 73 3b 7d 20 72 6f 77 20 7b 0a 09 09  words;} row {...
2c70: 70 75 74 73 20 22 24 72 6f 77 28 6e 61 6d 65 29  puts "$row(name)
2c80: 20 2d 20 5b 6a 6f 69 6e 20 5b 5f 67 65 74 55 73   - [join [_getUs
2c90: 65 72 73 46 6f 72 50 61 73 73 77 6f 72 64 20 5b  ersForPassword [
2ca0: 6c 69 73 74 20 24 72 6f 77 28 6e 61 6d 65 29 5d  list $row(name)]
2cb0: 5d 20 7b 2c 20 7d 5d 22 0a 09 7d 0a 7d 0a 0a 70  ] {, }]"..}.}..p
2cc0: 72 6f 63 20 6c 69 73 74 55 73 65 72 73 20 7b 7d  roc listUsers {}
2cd0: 20 7b 0a 09 64 62 20 65 76 61 6c 20 7b 53 45 4c   {..db eval {SEL
2ce0: 45 43 54 20 44 49 53 54 49 4e 43 54 20 6e 61 6d  ECT DISTINCT nam
2cf0: 65 20 46 52 4f 4d 20 75 73 65 72 73 3b 7d 20 72  e FROM users;} r
2d00: 6f 77 20 7b 0a 09 09 70 75 74 73 20 22 24 72 6f  ow {...puts "$ro
2d10: 77 28 6e 61 6d 65 29 20 2d 20 5b 6a 6f 69 6e 20  w(name) - [join 
2d20: 5b 5f 67 65 74 50 61 73 73 77 6f 72 64 73 46 6f  [_getPasswordsFo
2d30: 72 55 73 65 72 20 5b 6c 69 73 74 20 24 72 6f 77  rUser [list $row
2d40: 28 6e 61 6d 65 29 5d 5d 20 7b 2c 20 7d 5d 22 0a  (name)]] {, }]".
2d50: 09 7d 0a 7d 0a 0a 70 72 6f 63 20 61 64 64 55 73  .}.}..proc addUs
2d60: 65 72 20 7b 75 73 65 72 4e 61 6d 65 20 6b 65 79  er {userName key
2d70: 7d 20 7b 0a 09 73 65 74 20 6b 65 79 52 61 77 20  } {..set keyRaw 
2d80: 5b 62 69 6e 61 72 79 20 64 65 63 6f 64 65 20 62  [binary decode b
2d90: 61 73 65 36 34 20 24 6b 65 79 5d 0a 09 73 65 74  ase64 $key]..set
2da0: 20 6b 65 79 56 65 72 69 66 79 20 5b 3a 3a 70 6b   keyVerify [::pk
2db0: 69 3a 3a 70 6b 63 73 3a 3a 70 61 72 73 65 5f 70  i::pkcs::parse_p
2dc0: 75 62 6c 69 63 5f 6b 65 79 20 24 6b 65 79 52 61  ublic_key $keyRa
2dd0: 77 5d 0a 0a 09 64 62 20 65 76 61 6c 20 7b 49 4e  w]...db eval {IN
2de0: 53 45 52 54 20 49 4e 54 4f 20 75 73 65 72 73 20  SERT INTO users 
2df0: 28 6e 61 6d 65 2c 20 70 75 62 6c 69 63 4b 65 79  (name, publicKey
2e00: 29 20 56 41 4c 55 45 53 20 28 24 75 73 65 72 4e  ) VALUES ($userN
2e10: 61 6d 65 2c 20 40 6b 65 79 29 3b 7d 0a 0a 09 23  ame, @key);}...#
2e20: 20 58 58 58 3a 54 4f 44 4f 3a 47 6f 20 74 68 72   XXX:TODO:Go thr
2e30: 6f 75 67 68 20 61 6e 64 20 72 65 2d 61 75 74 68  ough and re-auth
2e40: 6f 72 69 7a 65 20 69 66 20 70 6f 73 73 69 62 6c  orize if possibl
2e50: 65 0a 7d 0a 0a 70 72 6f 63 20 64 65 6c 65 74 65  e.}..proc delete
2e60: 55 73 65 72 20 7b 75 73 65 72 4e 61 6d 65 7d 20  User {userName} 
2e70: 7b 0a 09 23 20 58 58 58 3a 54 4f 44 4f 3a 20 47  {..# XXX:TODO: G
2e80: 6f 20 74 68 72 6f 75 67 68 20 61 6e 64 20 64 65  o through and de
2e90: 2d 61 75 74 68 6f 72 69 7a 65 0a 7d 0a 0a 70 72  -authorize.}..pr
2ea0: 6f 63 20 61 64 64 50 61 73 73 77 6f 72 64 20 7b  oc addPassword {
2eb0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 70 61 73  passwordName pas
2ec0: 73 77 6f 72 64 20 61 72 67 73 7d 20 7b 0a 09 73  sword args} {..s
2ed0: 65 74 20 69 6e 69 74 69 61 6c 55 73 65 72 73 20  et initialUsers 
2ee0: 24 61 72 67 73 0a 0a 09 69 66 20 7b 24 70 61 73  $args...if {$pas
2ef0: 73 77 6f 72 64 20 65 71 20 22 22 7d 20 7b 0a 09  sword eq ""} {..
2f00: 09 73 65 74 20 70 61 73 73 77 6f 72 64 20 5b 5f  .set password [_
2f10: 70 72 6f 6d 70 74 20 22 50 6c 65 61 73 65 20 65  prompt "Please e
2f20: 6e 74 65 72 20 74 68 65 20 6e 65 77 20 70 61 73  nter the new pas
2f30: 73 77 6f 72 64 3a 20 22 5d 0a 09 7d 0a 0a 09 23  sword: "]..}...#
2f40: 20 56 65 72 69 66 79 20 74 68 61 74 20 74 68 69   Verify that thi
2f50: 73 20 70 61 73 73 77 6f 72 64 20 64 6f 65 73 20  s password does 
2f60: 6e 6f 74 20 61 6c 72 65 61 64 79 20 65 78 69 73  not already exis
2f70: 74 0a 09 73 65 74 20 65 78 69 73 74 73 20 5b 64  t..set exists [d
2f80: 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 31  b eval {SELECT 1
2f90: 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20   FROM passwords 
2fa0: 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 70 61  WHERE name = $pa
2fb0: 73 73 77 6f 72 64 4e 61 6d 65 20 4c 49 4d 49 54  sswordName LIMIT
2fc0: 20 31 3b 7d 5d 0a 09 69 66 20 7b 24 65 78 69 73   1;}]..if {$exis
2fd0: 74 73 20 3d 3d 20 22 31 22 7d 20 7b 0a 09 09 72  ts == "1"} {...r
2fe0: 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f  eturn -code erro
2ff0: 72 20 22 50 61 73 73 77 6f 72 64 20 5c 22 24 70  r "Password \"$p
3000: 61 73 73 77 6f 72 64 4e 61 6d 65 5c 22 20 61 6c  asswordName\" al
3010: 72 65 61 64 79 20 65 78 69 73 74 73 2c 20 63 61  ready exists, ca
3020: 6e 6e 6f 74 20 61 64 64 2e 22 0a 09 7d 0a 0a 09  nnot add."..}...
3030: 23 20 47 65 74 20 6b 65 79 73 20 66 6f 72 20 69  # Get keys for i
3040: 6e 69 74 69 61 6c 20 75 73 65 72 73 0a 09 73 65  nitial users..se
3050: 74 20 70 75 62 6c 69 63 4b 65 79 73 20 5b 6c 69  t publicKeys [li
3060: 73 74 5d 0a 09 66 6f 72 65 61 63 68 20 75 73 65  st]..foreach use
3070: 72 20 24 69 6e 69 74 69 61 6c 55 73 65 72 73 20  r $initialUsers 
3080: 7b 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d  {...unset -nocom
3090: 70 6c 61 69 6e 20 72 6f 77 0a 09 09 64 62 20 65  plain row...db e
30a0: 76 61 6c 20 7b 53 45 4c 45 43 54 20 70 75 62 6c  val {SELECT publ
30b0: 69 63 4b 65 79 20 46 52 4f 4d 20 75 73 65 72 73  icKey FROM users
30c0: 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 75   WHERE name = $u
30d0: 73 65 72 3b 7d 20 72 6f 77 20 7b 0a 09 09 09 6c  ser;} row {....l
30e0: 61 70 70 65 6e 64 20 70 75 62 6c 69 63 4b 65 79  append publicKey
30f0: 73 20 24 72 6f 77 28 70 75 62 6c 69 63 4b 65 79  s $row(publicKey
3100: 29 0a 09 09 7d 0a 09 7d 0a 0a 09 5f 61 64 64 50  )...}..}..._addP
3110: 61 73 73 77 6f 72 64 20 24 70 61 73 73 77 6f 72  assword $passwor
3120: 64 4e 61 6d 65 20 24 70 61 73 73 77 6f 72 64 20  dName $password 
3130: 24 70 75 62 6c 69 63 4b 65 79 73 0a 7d 0a 0a 70  $publicKeys.}..p
3140: 72 6f 63 20 67 65 74 50 61 73 73 77 6f 72 64 20  roc getPassword 
3150: 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 7d 20 7b  {passwordName} {
3160: 0a 09 70 75 74 73 20 5b 5f 67 65 74 50 61 73 73  ..puts [_getPass
3170: 77 6f 72 64 20 24 70 61 73 73 77 6f 72 64 4e 61  word $passwordNa
3180: 6d 65 5d 0a 7d 0a 0a 70 72 6f 63 20 75 70 64 61  me].}..proc upda
3190: 74 65 50 61 73 73 77 6f 72 64 20 7b 70 61 73 73  tePassword {pass
31a0: 77 6f 72 64 4e 61 6d 65 20 70 61 73 73 77 6f 72  wordName passwor
31b0: 64 7d 20 7b 0a 09 69 66 20 7b 24 70 61 73 73 77  d} {..if {$passw
31c0: 6f 72 64 20 65 71 20 22 22 7d 20 7b 0a 09 09 73  ord eq ""} {...s
31d0: 65 74 20 70 61 73 73 77 6f 72 64 20 5b 5f 70 72  et password [_pr
31e0: 6f 6d 70 74 20 22 50 6c 65 61 73 65 20 65 6e 74  ompt "Please ent
31f0: 65 72 20 74 68 65 20 6e 65 77 20 70 61 73 73 77  er the new passw
3200: 6f 72 64 3a 20 22 5d 0a 09 7d 0a 0a 09 64 62 20  ord: "]..}...db 
3210: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 70 75 62  eval {SELECT pub
3220: 6c 69 63 4b 65 79 20 46 52 4f 4d 20 70 61 73 73  licKey FROM pass
3230: 77 6f 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65  words WHERE name
3240: 20 3d 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65   = $passwordName
3250: 3b 7d 20 72 6f 77 20 7b 0a 09 09 6c 61 70 70 65  ;} row {...lappe
3260: 6e 64 20 70 75 62 6c 69 63 4b 65 79 73 20 24 72  nd publicKeys $r
3270: 6f 77 28 70 75 62 6c 69 63 4b 65 79 29 0a 09 7d  ow(publicKey)..}
3280: 0a 0a 09 5f 61 64 64 50 61 73 73 77 6f 72 64 20  ..._addPassword 
3290: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 70  $passwordName $p
32a0: 61 73 73 77 6f 72 64 20 24 70 75 62 6c 69 63 4b  assword $publicK
32b0: 65 79 73 0a 7d 0a 0a 70 72 6f 63 20 64 65 6c 65  eys.}..proc dele
32c0: 74 65 50 61 73 73 77 6f 72 64 20 7b 70 61 73 73  tePassword {pass
32d0: 77 6f 72 64 4e 61 6d 65 7d 20 7b 0a 09 64 62 20  wordName} {..db 
32e0: 65 76 61 6c 20 7b 44 45 4c 45 54 45 20 46 52 4f  eval {DELETE FRO
32f0: 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52  M passwords WHER
3300: 45 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77 6f  E name = $passwo
3310: 72 64 4e 61 6d 65 3b 7d 0a 7d 0a 0a 70 72 6f 63  rdName;}.}..proc
3320: 20 61 75 74 68 6f 72 69 7a 65 55 73 65 72 73 20   authorizeUsers 
3330: 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 61 72  {passwordName ar
3340: 67 73 7d 20 7b 0a 09 73 65 74 20 75 73 65 72 73  gs} {..set users
3350: 20 24 61 72 67 73 0a 0a 09 5f 6d 6f 64 69 66 79   $args..._modify
3360: 50 75 62 6c 69 63 4b 65 79 73 20 24 70 61 73 73  PublicKeys $pass
3370: 77 6f 72 64 4e 61 6d 65 20 24 75 73 65 72 73 20  wordName $users 
3380: 7b 0a 09 09 69 66 20 7b 24 72 6f 77 28 70 75 62  {...if {$row(pub
3390: 6c 69 63 4b 65 79 29 20 69 6e 20 24 70 75 62 6c  licKey) in $publ
33a0: 69 63 4b 65 79 73 7d 20 7b 0a 09 09 09 63 6f 6e  icKeys} {....con
33b0: 74 69 6e 75 65 0a 09 09 7d 0a 0a 09 09 6c 61 70  tinue...}....lap
33c0: 70 65 6e 64 20 70 75 62 6c 69 63 4b 65 79 73 20  pend publicKeys 
33d0: 24 72 6f 77 28 70 75 62 6c 69 63 4b 65 79 29 0a  $row(publicKey).
33e0: 0a 09 09 73 65 74 20 63 68 61 6e 67 65 52 65 71  ...set changeReq
33f0: 75 69 72 65 64 20 31 0a 09 7d 0a 7d 0a 0a 70 72  uired 1..}.}..pr
3400: 6f 63 20 61 75 74 68 6f 72 69 7a 65 55 73 65 72  oc authorizeUser
3410: 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 75   {passwordName u
3420: 73 65 72 4e 61 6d 65 7d 20 7b 0a 09 72 65 74 75  serName} {..retu
3430: 72 6e 20 5b 61 75 74 68 6f 72 69 7a 65 55 73 65  rn [authorizeUse
3440: 72 73 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65  rs $passwordName
3450: 20 24 75 73 65 72 4e 61 6d 65 5d 0a 7d 0a 0a 70   $userName].}..p
3460: 72 6f 63 20 64 65 61 75 74 68 6f 72 69 7a 65 55  roc deauthorizeU
3470: 73 65 72 73 20 7b 70 61 73 73 77 6f 72 64 4e 61  sers {passwordNa
3480: 6d 65 20 61 72 67 73 7d 20 7b 0a 09 73 65 74 20  me args} {..set 
3490: 75 73 65 72 73 20 24 61 72 67 73 0a 0a 09 5f 6d  users $args..._m
34a0: 6f 64 69 66 79 50 75 62 6c 69 63 4b 65 79 73 20  odifyPublicKeys 
34b0: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 75  $passwordName $u
34c0: 73 65 72 73 20 7b 0a 09 09 73 65 74 20 69 64 78  sers {...set idx
34d0: 20 5b 6c 73 65 61 72 63 68 20 2d 65 78 61 63 74   [lsearch -exact
34e0: 20 24 70 75 62 6c 69 63 4b 65 79 73 20 24 72 6f   $publicKeys $ro
34f0: 77 28 70 75 62 6c 69 63 4b 65 79 29 5d 0a 09 09  w(publicKey)]...
3500: 69 66 20 7b 24 69 64 78 20 3d 3d 20 2d 31 7d 20  if {$idx == -1} 
3510: 7b 0a 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09  {....continue...
3520: 7d 0a 0a 09 09 73 65 74 20 70 75 62 6c 69 63 4b  }....set publicK
3530: 65 79 73 20 5b 6c 72 65 70 6c 61 63 65 20 24 70  eys [lreplace $p
3540: 75 62 6c 69 63 4b 65 79 73 20 24 69 64 78 20 24  ublicKeys $idx $
3550: 69 64 78 5d 0a 0a 09 09 73 65 74 20 63 68 61 6e  idx]....set chan
3560: 67 65 52 65 71 75 69 72 65 64 20 31 0a 09 7d 0a  geRequired 1..}.
3570: 7d 0a 0a 70 72 6f 63 20 64 65 61 75 74 68 6f 72  }..proc deauthor
3580: 69 7a 65 55 73 65 72 20 7b 70 61 73 73 77 6f 72  izeUser {passwor
3590: 64 4e 61 6d 65 20 75 73 65 72 4e 61 6d 65 7d 20  dName userName} 
35a0: 7b 0a 09 72 65 74 75 72 6e 20 5b 64 65 61 75 74  {..return [deaut
35b0: 68 6f 72 69 7a 65 55 73 65 72 73 20 24 70 61 73  horizeUsers $pas
35c0: 73 77 6f 72 64 4e 61 6d 65 20 24 75 73 65 72 4e  swordName $userN
35d0: 61 6d 65 5d 0a 7d 0a 0a 70 72 6f 63 20 68 65 6c  ame].}..proc hel
35e0: 70 20 7b 7b 61 63 74 69 6f 6e 20 22 22 7d 7d 20  p {{action ""}} 
35f0: 7b 0a 09 5f 70 72 69 6e 74 48 65 6c 70 20 73 74  {.._printHelp st
3600: 64 6f 75 74 20 24 61 63 74 69 6f 6e 0a 7d 0a 23  dout $action.}.#
3610: 20 45 6e 64 20 75 73 65 72 20 43 4c 49 20 66 75   End user CLI fu
3620: 6e 63 74 69 6f 6e 73 0a 0a 23 23 23 20 4d 41 49  nctions..### MAI
3630: 4e 0a 0a 73 71 6c 69 74 65 33 20 64 62 20 24 70  N..sqlite3 db $p
3640: 61 73 73 77 6f 72 64 46 69 6c 65 0a 0a 64 62 20  asswordFile..db 
3650: 65 76 61 6c 20 7b 0a 09 43 52 45 41 54 45 20 54  eval {..CREATE T
3660: 41 42 4c 45 20 49 46 20 4e 4f 54 20 45 58 49 53  ABLE IF NOT EXIS
3670: 54 53 20 75 73 65 72 73 28 6e 61 6d 65 2c 20 70  TS users(name, p
3680: 75 62 6c 69 63 4b 65 79 20 42 4c 4f 42 29 3b 0a  ublicKey BLOB);.
3690: 09 43 52 45 41 54 45 20 54 41 42 4c 45 20 49 46  .CREATE TABLE IF
36a0: 20 4e 4f 54 20 45 58 49 53 54 53 20 70 61 73 73   NOT EXISTS pass
36b0: 77 6f 72 64 73 28 6e 61 6d 65 2c 20 65 6e 63 72  words(name, encr
36c0: 79 70 74 65 64 50 61 73 73 20 42 4c 4f 42 2c 20  yptedPass BLOB, 
36d0: 65 6e 63 72 79 70 74 65 64 4b 65 79 20 42 4c 4f  encryptedKey BLO
36e0: 42 2c 20 70 75 62 6c 69 63 4b 65 79 20 42 4c 4f  B, publicKey BLO
36f0: 42 29 3b 0a 7d 0a 0a 69 66 20 7b 24 61 63 74 69  B);.}..if {$acti
3700: 6f 6e 20 69 6e 20 24 76 61 6c 69 64 43 6f 6d 6d  on in $validComm
3710: 61 6e 64 73 7d 20 7b 0a 09 24 61 63 74 69 6f 6e  ands} {..$action
3720: 20 7b 2a 7d 24 61 72 67 76 0a 7d 20 65 6c 73 65   {*}$argv.} else
3730: 20 7b 0a 09 70 75 74 73 20 73 74 64 65 72 72 20   {..puts stderr 
3740: 22 49 6e 76 61 6c 69 64 20 61 63 74 69 6f 6e 22  "Invalid action"
3750: 0a 0a 09 65 78 69 74 20 31 0a 7d 0a 0a 65 78 69  ...exit 1.}..exi
3760: 74 20 30 0a 0a                                   t 0..