Hex Artifact Content

Artifact ec608c91c1112671e89c0f3153c5aad9d17a48ae:


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 20 22 77 68 6f 61 6d 69 22 5d  "help" "whoami"]
06d0: 0a 0a 70 72 6f 63 20 5f 61 72 67 44 65 73 63 72  ..proc _argDescr
06e0: 69 70 74 69 6f 6e 20 7b 63 6f 6d 6d 61 6e 64 20  iption {command 
06f0: 61 72 67 4e 61 6d 65 7d 20 7b 0a 09 73 77 69 74  argName} {..swit
0700: 63 68 20 2d 2d 20 24 61 72 67 4e 61 6d 65 20 7b  ch -- $argName {
0710: 0a 09 09 22 70 61 73 73 77 6f 72 64 4e 61 6d 65  ..."passwordName
0720: 22 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 22 24  " {....return "$
0730: 61 72 67 4e 61 6d 65 20 2d 20 4e 61 6d 65 20 6f  argName - Name o
0740: 66 20 74 68 65 20 70 61 73 73 77 6f 72 64 20 65  f the password e
0750: 6e 74 72 79 22 0a 09 09 7d 0a 09 09 22 6b 65 79  ntry"...}..."key
0760: 22 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 22 24  " {....return "$
0770: 61 72 67 4e 61 6d 65 20 2d 20 50 75 62 6c 69 63  argName - Public
0780: 20 6b 65 79 20 6f 66 20 74 68 65 20 75 73 65 72   key of the user
0790: 22 0a 09 09 7d 0a 09 09 22 70 61 73 73 77 6f 72  "...}..."passwor
07a0: 64 22 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 22  d" {....return "
07b0: 24 61 72 67 4e 61 6d 65 20 2d 20 41 20 70 6c 61  $argName - A pla
07c0: 69 6e 2d 74 65 78 74 20 70 61 73 73 77 6f 72 64  in-text password
07d0: 22 0a 09 09 7d 0a 09 09 22 75 73 65 72 4e 61 6d  "...}..."userNam
07e0: 65 22 20 7b 0a 09 09 09 72 65 74 75 72 6e 20 22  e" {....return "
07f0: 24 61 72 67 4e 61 6d 65 20 2d 20 41 20 75 73 65  $argName - A use
0800: 72 20 6e 61 6d 65 22 0a 09 09 7d 0a 09 09 22 61  r name"...}..."a
0810: 63 74 69 6f 6e 22 20 7b 0a 09 09 09 72 65 74 75  ction" {....retu
0820: 72 6e 20 22 24 61 72 67 4e 61 6d 65 20 2d 20 41  rn "$argName - A
0830: 6e 20 61 63 74 69 6f 6e 20 6e 61 6d 65 20 66 6f  n action name fo
0840: 72 20 68 65 6c 70 20 77 69 74 68 22 0a 09 09 7d  r help with"...}
0850: 0a 09 09 22 61 72 67 73 22 20 7b 0a 09 09 09 72  ..."args" {....r
0860: 65 74 75 72 6e 20 22 75 73 65 72 4c 69 73 74 20  eturn "userList 
0870: 2d 20 41 20 6c 69 73 74 20 6f 66 20 75 73 65 72  - A list of user
0880: 6e 61 6d 65 73 22 0a 09 09 7d 0a 09 7d 0a 0a 09  names"...}..}...
0890: 72 65 74 75 72 6e 20 22 3c 55 4e 4b 4e 4f 57 4e  return "<UNKNOWN
08a0: 3e 22 0a 7d 0a 0a 70 72 6f 63 20 5f 70 72 69 6e  >".}..proc _prin
08b0: 74 48 65 6c 70 20 7b 63 68 61 6e 6e 65 6c 20 63  tHelp {channel c
08c0: 6f 6d 6d 61 6e 64 7d 20 7b 0a 09 69 66 20 7b 24  ommand} {..if {$
08d0: 63 6f 6d 6d 61 6e 64 20 3d 3d 20 22 22 7d 20 7b  command == ""} {
08e0: 0a 09 09 70 75 74 73 20 24 63 68 61 6e 6e 65 6c  ...puts $channel
08f0: 20 22 55 73 61 67 65 3a 20 68 75 6e 74 65 72 32   "Usage: hunter2
0900: 20 3c 70 61 73 73 77 6f 72 64 46 69 6c 65 3e 20   <passwordFile> 
0910: 3c 61 63 74 69 6f 6e 3e 20 5c 5b 3c 61 63 74 69  <action> \[<acti
0920: 6f 6e 41 72 67 73 2e 2e 2e 3e 5c 5d 22 0a 09 09  onArgs...>\]"...
0930: 70 75 74 73 20 24 63 68 61 6e 6e 65 6c 20 22 22  puts $channel ""
0940: 0a 09 09 70 75 74 73 20 24 63 68 61 6e 6e 65 6c  ...puts $channel
0950: 20 22 41 63 74 69 6f 6e 73 3a 22 0a 09 09 70 75   "Actions:"...pu
0960: 74 73 20 24 63 68 61 6e 6e 65 6c 20 22 20 20 20  ts $channel "   
0970: 20 5b 6a 6f 69 6e 20 24 3a 3a 76 61 6c 69 64 43   [join $::validC
0980: 6f 6d 6d 61 6e 64 73 20 7b 2c 20 7d 5d 22 0a 09  ommands {, }]"..
0990: 09 70 75 74 73 20 24 63 68 61 6e 6e 65 6c 20 22  .puts $channel "
09a0: 22 0a 09 09 70 75 74 73 20 24 63 68 61 6e 6e 65  "...puts $channe
09b0: 6c 20 22 20 20 20 20 68 75 6e 74 65 72 32 20 3c  l "    hunter2 <
09c0: 66 69 6c 65 3e 20 68 65 6c 70 20 3c 61 63 74 69  file> help <acti
09d0: 6f 6e 3e 20 20 20 20 66 6f 72 20 68 65 6c 70 20  on>    for help 
09e0: 77 69 74 68 20 61 6e 20 61 63 74 69 6f 6e 22 0a  with an action".
09f0: 09 7d 20 65 6c 73 65 20 7b 0a 09 09 73 65 74 20  .} else {...set 
0a00: 61 72 67 73 20 5b 69 6e 66 6f 20 61 72 67 73 20  args [info args 
0a10: 24 63 6f 6d 6d 61 6e 64 5d 0a 09 09 73 65 74 20  $command]...set 
0a20: 70 72 69 6e 74 41 72 67 73 20 5b 6c 69 73 74 5d  printArgs [list]
0a30: 0a 09 09 66 6f 72 65 61 63 68 20 61 72 67 20 24  ...foreach arg $
0a40: 61 72 67 73 20 7b 0a 09 09 09 69 66 20 7b 24 61  args {....if {$a
0a50: 72 67 20 3d 3d 20 22 61 72 67 73 22 7d 20 7b 0a  rg == "args"} {.
0a60: 09 09 09 09 73 65 74 20 61 72 67 20 22 75 73 65  ....set arg "use
0a70: 72 4c 69 73 74 22 0a 09 09 09 7d 0a 09 09 09 6c  rList"....}....l
0a80: 61 70 70 65 6e 64 20 70 72 69 6e 74 41 72 67 73  append printArgs
0a90: 20 22 3c 24 61 72 67 3e 22 0a 09 09 7d 0a 0a 09   "<$arg>"...}...
0aa0: 09 70 75 74 73 20 24 63 68 61 6e 6e 65 6c 20 22  .puts $channel "
0ab0: 55 73 61 67 65 3a 20 68 75 6e 74 65 72 32 20 3c  Usage: hunter2 <
0ac0: 70 61 73 73 77 6f 72 64 46 69 6c 65 3e 20 24 63  passwordFile> $c
0ad0: 6f 6d 6d 61 6e 64 20 5b 6a 6f 69 6e 20 24 70 72  ommand [join $pr
0ae0: 69 6e 74 41 72 67 73 5d 22 0a 0a 09 09 69 66 20  intArgs]"....if 
0af0: 7b 5b 6c 6c 65 6e 67 74 68 20 24 61 72 67 73 5d  {[llength $args]
0b00: 20 3e 20 30 7d 20 7b 0a 09 09 09 70 75 74 73 20   > 0} {....puts 
0b10: 24 63 68 61 6e 6e 65 6c 20 22 22 0a 09 09 09 70  $channel ""....p
0b20: 75 74 73 20 24 63 68 61 6e 6e 65 6c 20 22 41 72  uts $channel "Ar
0b30: 67 75 6d 65 6e 74 73 3a 22 0a 09 09 09 66 6f 72  guments:"....for
0b40: 65 61 63 68 20 61 72 67 20 24 61 72 67 73 20 7b  each arg $args {
0b50: 0a 09 09 09 09 70 75 74 73 20 24 63 68 61 6e 6e  .....puts $chann
0b60: 65 6c 20 22 20 20 20 20 5b 5f 61 72 67 44 65 73  el "    [_argDes
0b70: 63 72 69 70 74 69 6f 6e 20 24 63 6f 6d 6d 61 6e  cription $comman
0b80: 64 20 24 61 72 67 5d 22 0a 09 09 09 7d 0a 09 09  d $arg]"....}...
0b90: 7d 0a 09 7d 0a 7d 0a 0a 69 66 20 7b 5b 6c 6c 65  }..}.}..if {[lle
0ba0: 6e 67 74 68 20 24 61 72 67 76 5d 20 3c 20 32 7d  ngth $argv] < 2}
0bb0: 20 7b 0a 09 5f 70 72 69 6e 74 48 65 6c 70 20 73   {.._printHelp s
0bc0: 74 64 65 72 72 20 22 22 0a 0a 09 65 78 69 74 20  tderr ""...exit 
0bd0: 31 0a 7d 0a 0a 73 65 74 20 61 72 67 76 20 5b 6c  1.}..set argv [l
0be0: 72 61 6e 67 65 20 24 61 72 67 76 20 32 20 65 6e  range $argv 2 en
0bf0: 64 5d 0a 0a 23 20 57 65 20 6e 65 65 64 20 54 63  d]..# We need Tc
0c00: 6c 20 38 2e 36 20 66 6f 72 20 5b 62 69 6e 61 72  l 8.6 for [binar
0c10: 79 20 65 6e 63 6f 64 65 20 62 61 73 65 36 34 5d  y encode base64]
0c20: 0a 70 61 63 6b 61 67 65 20 72 65 71 75 69 72 65  .package require
0c30: 20 54 63 6c 20 38 2e 36 0a 70 61 63 6b 61 67 65   Tcl 8.6.package
0c40: 20 72 65 71 75 69 72 65 20 73 71 6c 69 74 65 33   require sqlite3
0c50: 0a 70 61 63 6b 61 67 65 20 72 65 71 75 69 72 65  .package require
0c60: 20 70 6c 61 74 66 6f 72 6d 0a 0a 6c 61 70 70 65   platform..lappe
0c70: 6e 64 20 3a 3a 61 75 74 6f 5f 70 61 74 68 20 5b  nd ::auto_path [
0c80: 66 69 6c 65 20 6a 6f 69 6e 20 5b 66 69 6c 65 20  file join [file 
0c90: 64 69 72 6e 61 6d 65 20 5b 69 6e 66 6f 20 73 63  dirname [info sc
0ca0: 72 69 70 74 5d 5d 20 6c 69 62 20 5b 70 6c 61 74  ript]] lib [plat
0cb0: 66 6f 72 6d 3a 3a 69 64 65 6e 74 69 66 79 5d 5d  form::identify]]
0cc0: 0a 6c 61 70 70 65 6e 64 20 3a 3a 61 75 74 6f 5f  .lappend ::auto_
0cd0: 70 61 74 68 20 5b 66 69 6c 65 20 6a 6f 69 6e 20  path [file join 
0ce0: 5b 66 69 6c 65 20 64 69 72 6e 61 6d 65 20 5b 69  [file dirname [i
0cf0: 6e 66 6f 20 73 63 72 69 70 74 5d 5d 20 6c 69 62  nfo script]] lib
0d00: 20 5b 70 6c 61 74 66 6f 72 6d 3a 3a 67 65 6e 65   [platform::gene
0d10: 72 69 63 5d 5d 0a 6c 61 70 70 65 6e 64 20 3a 3a  ric]].lappend ::
0d20: 61 75 74 6f 5f 70 61 74 68 20 5b 66 69 6c 65 20  auto_path [file 
0d30: 6a 6f 69 6e 20 5b 66 69 6c 65 20 64 69 72 6e 61  join [file dirna
0d40: 6d 65 20 5b 69 6e 66 6f 20 73 63 72 69 70 74 5d  me [info script]
0d50: 5d 20 6c 69 62 5d 0a 0a 70 61 63 6b 61 67 65 20  ] lib]..package 
0d60: 72 65 71 75 69 72 65 20 70 6b 69 0a 70 61 63 6b  require pki.pack
0d70: 61 67 65 20 72 65 71 75 69 72 65 20 70 6b 69 3a  age require pki:
0d80: 3a 70 6b 63 73 31 31 0a 70 61 63 6b 61 67 65 20  :pkcs11.package 
0d90: 72 65 71 75 69 72 65 20 61 65 73 0a 70 61 63 6b  require aes.pack
0da0: 61 67 65 20 72 65 71 75 69 72 65 20 73 68 61 32  age require sha2
0db0: 35 36 0a 0a 23 20 42 61 63 6b 70 6f 72 74 73 20  56..# Backports 
0dc0: 66 6f 72 20 6f 6c 64 65 72 20 76 65 72 73 69 6f  for older versio
0dd0: 6e 73 20 6f 66 20 22 70 6b 69 22 0a 70 72 6f 63  ns of "pki".proc
0de0: 20 3a 3a 70 6b 69 3a 3a 70 6b 63 73 3a 3a 70 61   ::pki::pkcs::pa
0df0: 72 73 65 5f 70 75 62 6c 69 63 5f 6b 65 79 20 7b  rse_public_key {
0e00: 6b 65 79 20 7b 70 61 73 73 77 6f 72 64 20 22 22  key {password ""
0e10: 7d 7d 20 7b 0a 20 20 20 20 20 20 20 20 61 72 72  }} {.        arr
0e20: 61 79 20 73 65 74 20 70 61 72 73 65 64 5f 6b 65  ay set parsed_ke
0e30: 79 20 5b 3a 3a 70 6b 69 3a 3a 5f 70 61 72 73 65  y [::pki::_parse
0e40: 5f 70 65 6d 20 24 6b 65 79 20 22 2d 2d 2d 2d 2d  _pem $key "-----
0e50: 42 45 47 49 4e 20 50 55 42 4c 49 43 20 4b 45 59  BEGIN PUBLIC KEY
0e60: 2d 2d 2d 2d 2d 22 20 22 2d 2d 2d 2d 2d 45 4e 44  -----" "-----END
0e70: 20 50 55 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d   PUBLIC KEY-----
0e80: 22 20 24 70 61 73 73 77 6f 72 64 5d 0a 0a 20 20  " $password]..  
0e90: 20 20 20 20 20 20 73 65 74 20 6b 65 79 5f 73 65        set key_se
0ea0: 71 20 24 70 61 72 73 65 64 5f 6b 65 79 28 64 61  q $parsed_key(da
0eb0: 74 61 29 0a 0a 20 20 20 20 20 20 20 20 3a 3a 61  ta)..        ::a
0ec0: 73 6e 3a 3a 61 73 6e 47 65 74 53 65 71 75 65 6e  sn::asnGetSequen
0ed0: 63 65 20 6b 65 79 5f 73 65 71 20 70 75 62 6b 65  ce key_seq pubke
0ee0: 79 69 6e 66 6f 0a 20 20 20 20 20 20 20 20 20 20  yinfo.          
0ef0: 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61 73 6e        ::asn::asn
0f00: 47 65 74 53 65 71 75 65 6e 63 65 20 70 75 62 6b  GetSequence pubk
0f10: 65 79 69 6e 66 6f 20 70 75 62 6b 65 79 5f 61 6c  eyinfo pubkey_al
0f20: 67 6f 69 64 0a 20 20 20 20 20 20 20 20 20 20 20  goid.           
0f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 3a 3a 61               ::a
0f40: 73 6e 3a 3a 61 73 6e 47 65 74 4f 62 6a 65 63 74  sn::asnGetObject
0f50: 49 64 65 6e 74 69 66 69 65 72 20 70 75 62 6b 65  Identifier pubke
0f60: 79 5f 61 6c 67 6f 69 64 20 6f 69 64 0a 20 20 20  y_algoid oid.   
0f70: 20 20 20 20 20 20 20 20 20 20 20 20 20 3a 3a 61               ::a
0f80: 73 6e 3a 3a 61 73 6e 47 65 74 42 69 74 53 74 72  sn::asnGetBitStr
0f90: 69 6e 67 20 70 75 62 6b 65 79 69 6e 66 6f 20 70  ing pubkeyinfo p
0fa0: 75 62 6b 65 79 0a 20 20 20 20 20 20 20 20 73 65  ubkey.        se
0fb0: 74 20 72 65 74 28 70 75 62 6b 65 79 5f 61 6c 67  t ret(pubkey_alg
0fc0: 6f 29 20 5b 3a 3a 70 6b 69 3a 3a 5f 6f 69 64 5f  o) [::pki::_oid_
0fd0: 6e 75 6d 62 65 72 5f 74 6f 5f 6e 61 6d 65 20 24  number_to_name $
0fe0: 6f 69 64 5d 0a 0a 20 20 20 20 20 20 20 20 73 77  oid]..        sw
0ff0: 69 74 63 68 20 2d 2d 20 24 72 65 74 28 70 75 62  itch -- $ret(pub
1000: 6b 65 79 5f 61 6c 67 6f 29 20 7b 0a 20 20 20 20  key_algo) {.    
1010: 20 20 20 20 20 20 20 20 20 20 20 20 22 72 73 61              "rsa
1020: 45 6e 63 72 79 70 74 69 6f 6e 22 20 7b 0a 20 20  Encryption" {.  
1030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1040: 20 20 20 20 20 20 73 65 74 20 70 75 62 6b 65 79        set pubkey
1050: 20 5b 62 69 6e 61 72 79 20 66 6f 72 6d 61 74 20   [binary format 
1060: 42 2a 20 24 70 75 62 6b 65 79 5d 0a 0a 20 20 20  B* $pubkey]..   
1070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1080: 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61 73 6e 47       ::asn::asnG
1090: 65 74 53 65 71 75 65 6e 63 65 20 70 75 62 6b 65  etSequence pubke
10a0: 79 20 70 75 62 6b 65 79 5f 70 61 72 74 73 0a 20  y pubkey_parts. 
10b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
10c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 3a                 :
10d0: 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 42 69 67 49  :asn::asnGetBigI
10e0: 6e 74 65 67 65 72 20 70 75 62 6b 65 79 5f 70 61  nteger pubkey_pa
10f0: 72 74 73 20 72 65 74 28 6e 29 0a 20 20 20 20 20  rts ret(n).     
1100: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1110: 20 20 20 20 20 20 20 20 20 20 20 3a 3a 61 73 6e             ::asn
1120: 3a 3a 61 73 6e 47 65 74 42 69 67 49 6e 74 65 67  ::asnGetBigInteg
1130: 65 72 20 70 75 62 6b 65 79 5f 70 61 72 74 73 20  er pubkey_parts 
1140: 72 65 74 28 65 29 0a 0a 20 20 20 20 20 20 20 20  ret(e)..        
1150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1160: 73 65 74 20 72 65 74 28 6e 29 20 5b 3a 3a 6d 61  set ret(n) [::ma
1170: 74 68 3a 3a 62 69 67 6e 75 6d 3a 3a 74 6f 73 74  th::bignum::tost
1180: 72 20 24 72 65 74 28 6e 29 5d 0a 20 20 20 20 20  r $ret(n)].     
1190: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
11a0: 20 20 20 73 65 74 20 72 65 74 28 65 29 20 5b 3a     set ret(e) [:
11b0: 3a 6d 61 74 68 3a 3a 62 69 67 6e 75 6d 3a 3a 74  :math::bignum::t
11c0: 6f 73 74 72 20 24 72 65 74 28 65 29 5d 0a 20 20  ostr $ret(e)].  
11d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
11e0: 20 20 20 20 20 20 73 65 74 20 72 65 74 28 6c 29        set ret(l)
11f0: 20 5b 65 78 70 72 20 7b 69 6e 74 28 5b 3a 3a 70   [expr {int([::p
1200: 6b 69 3a 3a 5f 62 69 74 73 20 24 72 65 74 28 6e  ki::_bits $ret(n
1210: 29 5d 20 2f 20 38 2e 30 30 30 30 20 2b 20 30 2e  )] / 8.0000 + 0.
1220: 35 29 20 2a 20 38 7d 5d 0a 20 20 20 20 20 20 20  5) * 8}].       
1230: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1240: 20 73 65 74 20 72 65 74 28 74 79 70 65 29 20 72   set ret(type) r
1250: 73 61 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  sa.             
1260: 20 20 20 7d 0a 20 20 20 20 20 20 20 20 20 20 20     }.           
1270: 20 20 20 20 20 64 65 66 61 75 6c 74 20 7b 0a 20       default {. 
1280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1290: 20 20 20 20 20 20 20 65 72 72 6f 72 20 22 55 6e         error "Un
12a0: 6b 6e 6f 77 6e 20 61 6c 67 6f 72 69 74 68 6d 22  known algorithm"
12b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
12c0: 20 7d 0a 20 20 20 20 20 20 20 20 7d 0a 0a 20 20   }.        }..  
12d0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 61 72        return [ar
12e0: 72 61 79 20 67 65 74 20 72 65 74 5d 0a 7d 0a 0a  ray get ret].}..
12f0: 70 72 6f 63 20 3a 3a 70 6b 69 3a 3a 72 73 61 3a  proc ::pki::rsa:
1300: 3a 73 65 72 69 61 6c 69 7a 65 5f 70 75 62 6c 69  :serialize_publi
1310: 63 5f 6b 65 79 20 7b 6b 65 79 6c 69 73 74 7d 20  c_key {keylist} 
1320: 7b 0a 20 20 20 20 20 20 20 20 61 72 72 61 79 20  {.        array 
1330: 73 65 74 20 6b 65 79 20 24 6b 65 79 6c 69 73 74  set key $keylist
1340: 0a 0a 20 20 20 20 20 20 20 20 66 6f 72 65 61 63  ..        foreac
1350: 68 20 65 6e 74 72 79 20 5b 6c 69 73 74 20 6e 20  h entry [list n 
1360: 65 5d 20 7b 0a 20 20 20 20 20 20 20 20 20 20 20  e] {.           
1370: 20 20 20 20 20 69 66 20 7b 21 5b 69 6e 66 6f 20       if {![info 
1380: 65 78 69 73 74 73 20 6b 65 79 28 24 65 6e 74 72  exists key($entr
1390: 79 29 5d 7d 20 7b 0a 20 20 20 20 20 20 20 20 20  y)]} {.         
13a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72                 r
13b0: 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f  eturn -code erro
13c0: 72 20 22 4b 65 79 20 64 6f 65 73 20 6e 6f 74 20  r "Key does not 
13d0: 63 6f 6e 74 61 69 6e 20 61 6e 20 65 6c 65 6d 65  contain an eleme
13e0: 6e 74 20 24 65 6e 74 72 79 22 0a 20 20 20 20 20  nt $entry".     
13f0: 20 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20             }.   
1400: 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 20 20       }..        
1410: 73 65 74 20 70 75 62 6b 65 79 20 5b 3a 3a 61 73  set pubkey [::as
1420: 6e 3a 3a 61 73 6e 53 65 71 75 65 6e 63 65 20 5c  n::asnSequence \
1430: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1440: 20 5b 3a 3a 61 73 6e 3a 3a 61 73 6e 42 69 67 49   [::asn::asnBigI
1450: 6e 74 65 67 65 72 20 5b 3a 3a 6d 61 74 68 3a 3a  nteger [::math::
1460: 62 69 67 6e 75 6d 3a 3a 66 72 6f 6d 73 74 72 20  bignum::fromstr 
1470: 24 6b 65 79 28 6e 29 5d 5d 20 5c 0a 20 20 20 20  $key(n)]] \.    
1480: 20 20 20 20 20 20 20 20 20 20 20 20 5b 3a 3a 61              [::a
1490: 73 6e 3a 3a 61 73 6e 42 69 67 49 6e 74 65 67 65  sn::asnBigIntege
14a0: 72 20 5b 3a 3a 6d 61 74 68 3a 3a 62 69 67 6e 75  r [::math::bignu
14b0: 6d 3a 3a 66 72 6f 6d 73 74 72 20 24 6b 65 79 28  m::fromstr $key(
14c0: 65 29 5d 5d 20 5c 0a 20 20 20 20 20 20 20 20 20  e)]] \.         
14d0: 20 20 20 20 20 20 20 5d 20 20 0a 20 20 20 20 20         ]  .     
14e0: 20 20 20 73 65 74 20 70 75 62 6b 65 79 5f 61 6c     set pubkey_al
14f0: 67 6f 5f 70 61 72 61 6d 73 20 5b 3a 3a 61 73 6e  go_params [::asn
1500: 3a 3a 61 73 6e 4e 75 6c 6c 5d 0a 0a 20 20 20 20  ::asnNull]..    
1510: 20 20 20 20 62 69 6e 61 72 79 20 73 63 61 6e 20      binary scan 
1520: 24 70 75 62 6b 65 79 20 42 2a 20 70 75 62 6b 65  $pubkey B* pubke
1530: 79 5f 62 69 74 73 74 72 69 6e 67 0a 0a 20 20 20  y_bitstring..   
1540: 20 20 20 20 20 73 65 74 20 72 65 74 20 5b 3a 3a       set ret [::
1550: 61 73 6e 3a 3a 61 73 6e 53 65 71 75 65 6e 63 65  asn::asnSequence
1560: 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   \.             
1570: 20 20 20 5b 3a 3a 61 73 6e 3a 3a 61 73 6e 53 65     [::asn::asnSe
1580: 71 75 65 6e 63 65 20 5c 0a 20 20 20 20 20 20 20  quence \.       
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 5b 3a 3a 61 73 6e 3a           [::asn:
15b0: 3a 61 73 6e 4f 62 6a 65 63 74 49 64 65 6e 74 69  :asnObjectIdenti
15c0: 66 69 65 72 20 5b 3a 3a 70 6b 69 3a 3a 5f 6f 69  fier [::pki::_oi
15d0: 64 5f 6e 61 6d 65 5f 74 6f 5f 6e 75 6d 62 65 72  d_name_to_number
15e0: 20 72 73 61 45 6e 63 72 79 70 74 69 6f 6e 5d 5d   rsaEncryption]]
15f0: 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   \.             
1600: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1610: 20 20 20 24 70 75 62 6b 65 79 5f 61 6c 67 6f 5f     $pubkey_algo_
1620: 70 61 72 61 6d 73 20 5c 0a 20 20 20 20 20 20 20  params \.       
1630: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1640: 20 5d 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20   ] \.           
1650: 20 20 20 20 20 20 20 20 20 20 20 20 20 5b 3a 3a               [::
1660: 61 73 6e 3a 3a 61 73 6e 42 69 74 53 74 72 69 6e  asn::asnBitStrin
1670: 67 20 24 70 75 62 6b 65 79 5f 62 69 74 73 74 72  g $pubkey_bitstr
1680: 69 6e 67 5d 20 5c 0a 20 20 20 20 20 20 20 20 20  ing] \.         
1690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 5d                 ]
16a0: 0a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ..        return
16b0: 20 5b 6c 69 73 74 20 64 61 74 61 20 24 72 65 74   [list data $ret
16c0: 20 62 65 67 69 6e 20 22 2d 2d 2d 2d 2d 42 45 47   begin "-----BEG
16d0: 49 4e 20 50 55 42 4c 49 43 20 4b 45 59 2d 2d 2d  IN PUBLIC KEY---
16e0: 2d 2d 22 20 65 6e 64 20 22 2d 2d 2d 2d 2d 45 4e  --" end "-----EN
16f0: 44 20 50 55 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d  D PUBLIC KEY----
1700: 2d 22 5d 0a 7d 0a 23 20 45 6e 64 20 62 61 63 6b  -"].}.# End back
1710: 70 6f 72 74 73 0a 0a 23 20 53 74 61 72 74 20 69  ports..# Start i
1720: 6e 74 65 72 6e 61 6c 20 66 75 6e 63 74 69 6f 6e  nternal function
1730: 73 0a 70 72 6f 63 20 5f 6c 6f 61 64 44 42 20 7b  s.proc _loadDB {
1740: 64 62 43 6d 64 20 66 69 6c 65 4e 61 6d 65 7d 20  dbCmd fileName} 
1750: 7b 0a 09 73 65 74 20 3a 3a 73 61 76 65 52 65 71  {..set ::saveReq
1760: 75 69 72 65 64 20 31 0a 0a 09 69 66 20 7b 5b 66  uired 1...if {[f
1770: 69 6c 65 20 65 78 69 73 74 73 20 24 66 69 6c 65  ile exists $file
1780: 4e 61 6d 65 5d 7d 20 7b 0a 09 09 73 65 74 20 66  Name]} {...set f
1790: 64 20 5b 6f 70 65 6e 20 24 66 69 6c 65 4e 61 6d  d [open $fileNam
17a0: 65 5d 0a 0a 09 09 23 20 56 65 72 69 66 79 20 74  e]....# Verify t
17b0: 68 61 74 20 77 65 20 68 61 76 65 20 61 20 76 61  hat we have a va
17c0: 6c 69 64 20 66 69 6c 65 0a 09 09 67 65 74 73 20  lid file...gets 
17d0: 24 66 64 20 68 65 61 64 65 72 0a 0a 09 09 23 20  $fd header....# 
17e0: 49 67 6e 6f 72 65 20 74 68 65 20 66 69 72 73 74  Ignore the first
17f0: 20 6c 69 6e 65 20 69 66 20 69 74 20 69 73 20 61   line if it is a
1800: 20 68 61 73 68 2d 62 61 6e 67 20 61 73 20 77 65   hash-bang as we
1810: 6c 6c 0a 09 09 69 66 20 7b 5b 73 74 72 69 6e 67  ll...if {[string
1820: 20 72 61 6e 67 65 20 24 68 65 61 64 65 72 20 30   range $header 0
1830: 20 31 5d 20 3d 3d 20 22 23 21 22 7d 20 7b 0a 09   1] == "#!"} {..
1840: 09 09 73 65 74 20 3a 3a 67 6c 6f 62 61 6c 48 65  ..set ::globalHe
1850: 61 64 65 72 28 24 64 62 43 6d 64 29 20 24 68 65  ader($dbCmd) $he
1860: 61 64 65 72 0a 0a 09 09 09 67 65 74 73 20 24 66  ader.....gets $f
1870: 64 20 68 65 61 64 65 72 0a 09 09 7d 0a 0a 09 09  d header...}....
1880: 69 66 20 7b 24 68 65 61 64 65 72 20 6e 65 20 22  if {$header ne "
1890: 23 20 3c 41 7a 75 72 65 44 69 61 6d 6f 6e 64 3e  # <AzureDiamond>
18a0: 20 6f 68 2c 20 6f 6b 2e 22 7d 20 7b 0a 09 09 09   oh, ok."} {....
18b0: 23 20 54 68 69 73 20 6d 61 79 20 62 65 20 61 6e  # This may be an
18c0: 20 6f 6c 64 20 53 51 4c 69 74 65 33 20 44 42 2c   old SQLite3 DB,
18d0: 20 63 6f 6e 76 65 72 74 20 69 74 0a 09 09 09 63   convert it....c
18e0: 6c 6f 73 65 20 24 66 64 0a 0a 09 09 09 73 71 6c  lose $fd.....sql
18f0: 69 74 65 33 20 24 64 62 43 6d 64 20 24 66 69 6c  ite3 $dbCmd $fil
1900: 65 4e 61 6d 65 0a 0a 09 09 09 5f 73 61 76 65 44  eName....._saveD
1910: 42 20 24 64 62 43 6d 64 20 24 66 69 6c 65 4e 61  B $dbCmd $fileNa
1920: 6d 65 0a 0a 09 09 09 24 64 62 43 6d 64 20 63 6c  me.....$dbCmd cl
1930: 6f 73 65 0a 0a 09 09 09 72 65 74 75 72 6e 20 5b  ose.....return [
1940: 5f 6c 6f 61 64 44 42 20 24 64 62 43 6d 64 20 24  _loadDB $dbCmd $
1950: 66 69 6c 65 4e 61 6d 65 5d 0a 09 09 7d 0a 0a 09  fileName]...}...
1960: 09 73 65 74 20 64 61 74 61 20 5b 72 65 61 64 20  .set data [read 
1970: 24 66 64 5d 0a 0a 09 09 63 6c 6f 73 65 20 24 66  $fd]....close $f
1980: 64 0a 09 7d 20 65 6c 73 65 20 7b 0a 09 09 73 65  d..} else {...se
1990: 74 20 64 61 74 61 20 22 22 0a 09 7d 0a 0a 09 73  t data ""..}...s
19a0: 71 6c 69 74 65 33 20 24 64 62 43 6d 64 20 22 3a  qlite3 $dbCmd ":
19b0: 6d 65 6d 6f 72 79 3a 22 0a 0a 09 24 64 62 43 6d  memory:"...$dbCm
19c0: 64 20 65 76 61 6c 20 7b 0a 09 09 43 52 45 41 54  d eval {...CREAT
19d0: 45 20 54 41 42 4c 45 20 49 46 20 4e 4f 54 20 45  E TABLE IF NOT E
19e0: 58 49 53 54 53 20 75 73 65 72 73 28 6e 61 6d 65  XISTS users(name
19f0: 2c 20 70 75 62 6c 69 63 4b 65 79 20 42 4c 4f 42  , publicKey BLOB
1a00: 29 3b 0a 09 09 43 52 45 41 54 45 20 54 41 42 4c  );...CREATE TABL
1a10: 45 20 49 46 20 4e 4f 54 20 45 58 49 53 54 53 20  E IF NOT EXISTS 
1a20: 70 61 73 73 77 6f 72 64 73 28 6e 61 6d 65 2c 20  passwords(name, 
1a30: 65 6e 63 72 79 70 74 65 64 50 61 73 73 20 42 4c  encryptedPass BL
1a40: 4f 42 2c 20 65 6e 63 72 79 70 74 65 64 4b 65 79  OB, encryptedKey
1a50: 20 42 4c 4f 42 2c 20 70 75 62 6c 69 63 4b 65 79   BLOB, publicKey
1a60: 20 42 4c 4f 42 2c 20 76 65 72 69 66 69 63 61 74   BLOB, verificat
1a70: 69 6f 6e 20 42 4c 4f 42 29 3b 0a 09 7d 0a 0a 09  ion BLOB);..}...
1a80: 24 64 62 43 6d 64 20 74 72 61 6e 73 61 63 74 69  $dbCmd transacti
1a90: 6f 6e 20 7b 0a 09 09 66 6f 72 65 61 63 68 20 6c  on {...foreach l
1aa0: 69 6e 65 20 5b 73 70 6c 69 74 20 24 64 61 74 61  ine [split $data
1ab0: 20 22 5c 6e 22 5d 20 7b 0a 09 09 09 69 66 20 7b   "\n"] {....if {
1ac0: 5b 73 74 72 69 6e 67 20 74 72 69 6d 20 24 6c 69  [string trim $li
1ad0: 6e 65 5d 20 65 71 20 22 22 7d 20 7b 0a 09 09 09  ne] eq ""} {....
1ae0: 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 7d 0a 0a  .continue....}..
1af0: 09 09 09 73 65 74 20 74 61 62 6c 65 20 5b 6c 69  ...set table [li
1b00: 6e 64 65 78 20 24 6c 69 6e 65 20 30 5d 0a 09 09  ndex $line 0]...
1b10: 09 73 65 74 20 6c 69 6e 65 20 5b 6c 72 61 6e 67  .set line [lrang
1b20: 65 20 24 6c 69 6e 65 20 31 20 65 6e 64 5d 0a 0a  e $line 1 end]..
1b30: 09 09 09 73 65 74 20 6b 65 79 73 20 5b 6c 69 73  ...set keys [lis
1b40: 74 5d 0a 09 09 09 73 65 74 20 76 61 6c 75 65 73  t]....set values
1b50: 20 5b 6c 69 73 74 5d 0a 09 09 09 75 6e 73 65 74   [list]....unset
1b60: 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e 20 76 61 6c   -nocomplain val
1b70: 75 65 41 72 72 61 79 0a 0a 09 09 09 66 6f 72 65  ueArray.....fore
1b80: 61 63 68 20 7b 6b 65 79 20 76 61 6c 75 65 7d 20  ach {key value} 
1b90: 24 6c 69 6e 65 20 7b 0a 09 09 09 09 69 66 20 7b  $line {.....if {
1ba0: 5b 73 74 72 69 6e 67 20 69 6e 64 65 78 20 24 6b  [string index $k
1bb0: 65 79 20 30 5d 20 3d 3d 20 22 3a 22 7d 20 7b 0a  ey 0] == ":"} {.
1bc0: 09 09 09 09 09 73 65 74 20 6b 65 79 20 5b 73 74  .....set key [st
1bd0: 72 69 6e 67 20 72 61 6e 67 65 20 24 6b 65 79 20  ring range $key 
1be0: 31 20 65 6e 64 5d 0a 09 09 09 09 09 73 65 74 20  1 end]......set 
1bf0: 76 61 6c 75 65 42 61 73 65 36 34 45 6e 63 6f 64  valueBase64Encod
1c00: 65 64 20 31 0a 09 09 09 09 7d 20 65 6c 73 65 20  ed 1.....} else 
1c10: 7b 0a 09 09 09 09 09 73 65 74 20 76 61 6c 75 65  {......set value
1c20: 42 61 73 65 36 34 45 6e 63 6f 64 65 64 20 30 0a  Base64Encoded 0.
1c30: 09 09 09 09 7d 0a 0a 09 09 09 09 69 66 20 7b 24  ....}......if {$
1c40: 76 61 6c 75 65 42 61 73 65 36 34 45 6e 63 6f 64  valueBase64Encod
1c50: 65 64 7d 20 7b 0a 09 09 09 09 09 73 65 74 20 76  ed} {......set v
1c60: 61 6c 75 65 20 5b 62 69 6e 61 72 79 20 64 65 63  alue [binary dec
1c70: 6f 64 65 20 62 61 73 65 36 34 20 24 76 61 6c 75  ode base64 $valu
1c80: 65 5d 0a 09 09 09 09 7d 0a 0a 09 09 09 09 69 66  e].....}......if
1c90: 20 7b 21 5b 72 65 67 65 78 70 20 7b 5e 5b 61 2d   {![regexp {^[a-
1ca0: 7a 41 2d 5a 5d 2b 24 7d 20 24 6b 65 79 5d 7d 20  zA-Z]+$} $key]} 
1cb0: 7b 0a 09 09 09 09 09 72 65 74 75 72 6e 20 2d 63  {......return -c
1cc0: 6f 64 65 20 65 72 72 6f 72 20 22 49 6e 76 61 6c  ode error "Inval
1cd0: 69 64 20 6b 65 79 20 6e 61 6d 65 3a 20 24 6b 65  id key name: $ke
1ce0: 79 22 0a 09 09 09 09 7d 0a 0a 09 09 09 09 73 77  y".....}......sw
1cf0: 69 74 63 68 20 2d 2d 20 24 6b 65 79 20 7b 0a 09  itch -- $key {..
1d00: 09 09 09 09 22 6e 61 6d 65 22 20 7b 0a 09 09 09  ...."name" {....
1d10: 09 09 09 73 65 74 20 74 79 70 65 20 22 22 0a 09  ...set type ""..
1d20: 09 09 09 09 09 73 65 74 20 74 79 70 65 49 6e 73  .....set typeIns
1d30: 65 72 74 43 68 61 72 20 7b 24 7d 0a 0a 09 09 09  ertChar {$}.....
1d40: 09 09 09 23 20 43 6f 6e 76 65 72 74 20 74 68 69  ...# Convert thi
1d50: 73 20 74 6f 20 61 20 73 74 72 69 6e 67 2d 69 66  s to a string-if
1d60: 69 65 64 20 76 61 6c 75 65 0a 09 09 09 09 09 09  ied value.......
1d70: 73 65 74 20 76 61 6c 75 65 20 5b 73 74 72 69 6e  set value [strin
1d80: 67 20 72 61 6e 67 65 20 22 78 24 76 61 6c 75 65  g range "x$value
1d90: 22 20 31 20 65 6e 64 5d 0a 09 09 09 09 09 7d 0a  " 1 end]......}.
1da0: 09 09 09 09 09 64 65 66 61 75 6c 74 20 7b 0a 09  .....default {..
1db0: 09 09 09 09 09 73 65 74 20 74 79 70 65 20 22 42  .....set type "B
1dc0: 4c 4f 42 22 0a 09 09 09 09 09 09 73 65 74 20 74  LOB".......set t
1dd0: 79 70 65 49 6e 73 65 72 74 43 68 61 72 20 22 40  ypeInsertChar "@
1de0: 22 0a 09 09 09 09 09 7d 0a 09 09 09 09 7d 0a 0a  "......}.....}..
1df0: 09 09 09 09 6c 61 70 70 65 6e 64 20 6b 65 79 73  ....lappend keys
1e00: 20 24 6b 65 79 0a 0a 09 09 09 09 73 65 74 20 76   $key......set v
1e10: 61 6c 75 65 41 72 72 61 79 28 24 6b 65 79 29 20  alueArray($key) 
1e20: 24 76 61 6c 75 65 0a 0a 09 09 09 09 6c 61 70 70  $value......lapp
1e30: 65 6e 64 20 76 61 6c 75 65 73 20 24 7b 74 79 70  end values ${typ
1e40: 65 49 6e 73 65 72 74 43 68 61 72 7d 76 61 6c 75  eInsertChar}valu
1e50: 65 41 72 72 61 79 28 24 6b 65 79 29 0a 09 09 09  eArray($key)....
1e60: 7d 0a 0a 09 09 09 24 64 62 43 6d 64 20 65 76 61  }.....$dbCmd eva
1e70: 6c 20 22 49 4e 53 45 52 54 20 49 4e 54 4f 20 24  l "INSERT INTO $
1e80: 74 61 62 6c 65 20 28 5b 6a 6f 69 6e 20 24 6b 65  table ([join $ke
1e90: 79 73 20 7b 2c 20 7d 5d 29 20 56 41 4c 55 45 53  ys {, }]) VALUES
1ea0: 20 28 5b 6a 6f 69 6e 20 24 76 61 6c 75 65 73 20   ([join $values 
1eb0: 7b 2c 20 7d 5d 29 3b 22 0a 09 09 7d 0a 09 7d 0a  {, }]);"...}..}.
1ec0: 7d 0a 0a 70 72 6f 63 20 5f 73 61 76 65 44 42 20  }..proc _saveDB 
1ed0: 7b 64 62 43 6d 64 20 66 69 6c 65 4e 61 6d 65 7d  {dbCmd fileName}
1ee0: 20 7b 0a 09 69 66 20 7b 5b 69 6e 66 6f 20 65 78   {..if {[info ex
1ef0: 69 73 74 73 20 3a 3a 67 6c 6f 62 61 6c 48 65 61  ists ::globalHea
1f00: 64 65 72 28 24 64 62 43 6d 64 29 5d 7d 20 7b 0a  der($dbCmd)]} {.
1f10: 09 09 6c 61 70 70 65 6e 64 20 6f 75 74 70 75 74  ..lappend output
1f20: 20 24 3a 3a 67 6c 6f 62 61 6c 48 65 61 64 65 72   $::globalHeader
1f30: 28 24 64 62 43 6d 64 29 0a 0a 09 09 75 6e 73 65  ($dbCmd)....unse
1f40: 74 20 3a 3a 67 6c 6f 62 61 6c 48 65 61 64 65 72  t ::globalHeader
1f50: 28 24 64 62 43 6d 64 29 0a 09 7d 0a 0a 09 6c 61  ($dbCmd)..}...la
1f60: 70 70 65 6e 64 20 6f 75 74 70 75 74 20 22 23 20  ppend output "# 
1f70: 3c 41 7a 75 72 65 44 69 61 6d 6f 6e 64 3e 20 6f  <AzureDiamond> o
1f80: 68 2c 20 6f 6b 2e 22 0a 0a 09 66 6f 72 65 61 63  h, ok."...foreac
1f90: 68 20 74 61 62 6c 65 20 5b 6c 69 73 74 20 75 73  h table [list us
1fa0: 65 72 73 20 70 61 73 73 77 6f 72 64 73 5d 20 7b  ers passwords] {
1fb0: 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70  ...unset -nocomp
1fc0: 6c 61 69 6e 20 72 6f 77 0a 09 09 24 64 62 43 6d  lain row...$dbCm
1fd0: 64 20 65 76 61 6c 20 22 53 45 4c 45 43 54 20 2a  d eval "SELECT *
1fe0: 20 46 52 4f 4d 20 24 74 61 62 6c 65 20 4f 52 44   FROM $table ORD
1ff0: 45 52 20 42 59 20 6e 61 6d 65 3b 22 20 72 6f 77  ER BY name;" row
2000: 20 7b 0a 09 09 09 73 65 74 20 6f 75 74 70 75 74   {....set output
2010: 4c 69 6e 65 20 5b 6c 69 73 74 20 24 74 61 62 6c  Line [list $tabl
2020: 65 5d 0a 0a 09 09 09 75 6e 73 65 74 20 2d 6e 6f  e].....unset -no
2030: 63 6f 6d 70 6c 61 69 6e 20 72 6f 77 28 2a 29 0a  complain row(*).
2040: 0a 09 09 09 66 6f 72 65 61 63 68 20 7b 6b 65 79  ....foreach {key
2050: 20 76 61 6c 75 65 7d 20 5b 61 72 72 61 79 20 67   value} [array g
2060: 65 74 20 72 6f 77 5d 20 7b 0a 09 09 09 09 69 66  et row] {.....if
2070: 20 7b 21 5b 72 65 67 65 78 70 20 7b 5e 5b 61 2d   {![regexp {^[a-
2080: 7a 41 2d 5a 5d 2b 24 7d 20 24 76 61 6c 75 65 5d  zA-Z]+$} $value]
2090: 7d 20 7b 0a 09 09 09 09 09 73 65 74 20 6b 65 79  } {......set key
20a0: 20 22 3a 24 6b 65 79 22 0a 09 09 09 09 09 73 65   ":$key"......se
20b0: 74 20 76 61 6c 75 65 20 5b 62 69 6e 61 72 79 20  t value [binary 
20c0: 65 6e 63 6f 64 65 20 62 61 73 65 36 34 20 24 76  encode base64 $v
20d0: 61 6c 75 65 5d 0a 09 09 09 09 7d 0a 0a 09 09 09  alue].....}.....
20e0: 09 6c 61 70 70 65 6e 64 20 6f 75 74 70 75 74 4c  .lappend outputL
20f0: 69 6e 65 20 24 6b 65 79 20 24 76 61 6c 75 65 0a  ine $key $value.
2100: 09 09 09 7d 0a 0a 09 09 09 6c 61 70 70 65 6e 64  ...}.....lappend
2110: 20 6f 75 74 70 75 74 20 24 6f 75 74 70 75 74 4c   output $outputL
2120: 69 6e 65 0a 09 09 7d 0a 09 7d 0a 0a 09 73 65 74  ine...}..}...set
2130: 20 66 64 20 5b 6f 70 65 6e 20 24 66 69 6c 65 4e   fd [open $fileN
2140: 61 6d 65 20 77 20 30 36 30 30 5d 0a 09 70 75 74  ame w 0600]..put
2150: 73 20 24 66 64 20 5b 6a 6f 69 6e 20 24 6f 75 74  s $fd [join $out
2160: 70 75 74 20 22 5c 6e 22 5d 0a 09 63 6c 6f 73 65  put "\n"]..close
2170: 20 24 66 64 0a 7d 0a 0a 70 72 6f 63 20 5f 6c 69   $fd.}..proc _li
2180: 73 74 43 65 72 74 69 66 69 63 61 74 65 73 20 7b  stCertificates {
2190: 7d 20 7b 0a 09 69 66 20 7b 21 5b 69 6e 66 6f 20  } {..if {![info 
21a0: 65 78 69 73 74 73 20 3a 3a 65 6e 76 28 50 4b 43  exists ::env(PKC
21b0: 53 31 31 4d 4f 44 55 4c 45 29 5d 7d 20 7b 0a 09  S11MODULE)]} {..
21c0: 09 72 65 74 75 72 6e 20 5b 6c 69 73 74 5d 0a 09  .return [list]..
21d0: 7d 0a 0a 09 73 65 74 20 3a 3a 65 6e 76 28 43 41  }...set ::env(CA
21e0: 43 4b 45 59 5f 4e 4f 5f 45 58 54 52 41 5f 43 45  CKEY_NO_EXTRA_CE
21f0: 52 54 53 29 20 31 0a 0a 09 73 65 74 20 68 61 6e  RTS) 1...set han
2200: 64 6c 65 20 5b 3a 3a 70 6b 69 3a 3a 70 6b 63 73  dle [::pki::pkcs
2210: 31 31 3a 3a 6c 6f 61 64 6d 6f 64 75 6c 65 20 24  11::loadmodule $
2220: 3a 3a 65 6e 76 28 50 4b 43 53 31 31 4d 4f 44 55  ::env(PKCS11MODU
2230: 4c 45 29 5d 0a 0a 09 73 65 74 20 73 6c 6f 74 49  LE)]...set slotI
2240: 6e 66 6f 20 5b 6c 69 73 74 5d 0a 09 66 6f 72 65  nfo [list]..fore
2250: 61 63 68 20 73 6c 6f 74 20 5b 3a 3a 70 6b 69 3a  ach slot [::pki:
2260: 3a 70 6b 63 73 31 31 3a 3a 6c 69 73 74 73 6c 6f  :pkcs11::listslo
2270: 74 73 20 24 68 61 6e 64 6c 65 5d 20 7b 0a 09 09  ts $handle] {...
2280: 73 65 74 20 73 6c 6f 74 49 44 20 5b 6c 69 6e 64  set slotID [lind
2290: 65 78 20 24 73 6c 6f 74 20 30 5d 0a 09 09 73 65  ex $slot 0]...se
22a0: 74 20 73 6c 6f 74 4c 61 62 65 6c 20 5b 6c 69 6e  t slotLabel [lin
22b0: 64 65 78 20 24 73 6c 6f 74 20 31 5d 0a 09 09 73  dex $slot 1]...s
22c0: 65 74 20 73 6c 6f 74 46 6c 61 67 73 20 5b 6c 69  et slotFlags [li
22d0: 6e 64 65 78 20 24 73 6c 6f 74 20 32 5d 0a 0a 09  ndex $slot 2]...
22e0: 09 69 66 20 7b 22 54 4f 4b 45 4e 5f 50 52 45 53  .if {"TOKEN_PRES
22f0: 45 4e 54 22 20 6e 69 20 24 73 6c 6f 74 46 6c 61  ENT" ni $slotFla
2300: 67 73 7d 20 7b 0a 09 09 09 63 6f 6e 74 69 6e 75  gs} {....continu
2310: 65 0a 09 09 7d 0a 0a 09 09 69 66 20 7b 22 54 4f  e...}....if {"TO
2320: 4b 45 4e 5f 49 4e 49 54 49 41 4c 49 5a 45 44 22  KEN_INITIALIZED"
2330: 20 6e 69 20 24 73 6c 6f 74 46 6c 61 67 73 7d 20   ni $slotFlags} 
2340: 7b 0a 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09  {....continue...
2350: 7d 0a 0a 09 09 73 65 74 20 73 6c 6f 74 50 72 6f  }....set slotPro
2360: 6d 70 74 46 6f 72 50 49 4e 20 66 61 6c 73 65 0a  mptForPIN false.
2370: 09 09 69 66 20 7b 22 50 52 4f 54 45 43 54 45 44  ..if {"PROTECTED
2380: 5f 41 55 54 48 45 4e 54 49 43 41 54 49 4f 4e 5f  _AUTHENTICATION_
2390: 50 41 54 48 22 20 6e 69 20 24 73 6c 6f 74 46 6c  PATH" ni $slotFl
23a0: 61 67 73 7d 20 7b 0a 09 09 09 69 66 20 7b 22 4c  ags} {....if {"L
23b0: 4f 47 49 4e 5f 52 45 51 55 49 52 45 44 22 20 69  OGIN_REQUIRED" i
23c0: 6e 20 24 73 6c 6f 74 46 6c 61 67 73 7d 20 7b 0a  n $slotFlags} {.
23d0: 09 09 09 09 73 65 74 20 73 6c 6f 74 50 72 6f 6d  ....set slotProm
23e0: 70 74 46 6f 72 50 49 4e 20 74 72 75 65 0a 09 09  ptForPIN true...
23f0: 09 7d 0a 09 09 7d 0a 0a 09 09 66 6f 72 65 61 63  .}...}....foreac
2400: 68 20 63 65 72 74 20 5b 3a 3a 70 6b 69 3a 3a 70  h cert [::pki::p
2410: 6b 63 73 31 31 3a 3a 6c 69 73 74 63 65 72 74 73  kcs11::listcerts
2420: 20 24 68 61 6e 64 6c 65 20 24 73 6c 6f 74 49 44   $handle $slotID
2430: 5d 20 7b 0a 09 09 09 73 65 74 20 70 75 62 6b 65  ] {....set pubke
2440: 79 20 5b 62 69 6e 61 72 79 20 65 6e 63 6f 64 65  y [binary encode
2450: 20 62 61 73 65 36 34 20 5b 64 69 63 74 20 67 65   base64 [dict ge
2460: 74 20 5b 3a 3a 70 6b 69 3a 3a 72 73 61 3a 3a 73  t [::pki::rsa::s
2470: 65 72 69 61 6c 69 7a 65 5f 70 75 62 6c 69 63 5f  erialize_public_
2480: 6b 65 79 20 24 63 65 72 74 5d 20 64 61 74 61 5d  key $cert] data]
2490: 5d 0a 0a 09 09 09 6c 61 70 70 65 6e 64 20 73 6c  ].....lappend sl
24a0: 6f 74 49 6e 66 6f 20 5b 6c 69 73 74 20 68 61 6e  otInfo [list han
24b0: 64 6c 65 20 24 68 61 6e 64 6c 65 20 69 64 20 24  dle $handle id $
24c0: 73 6c 6f 74 49 44 20 70 72 6f 6d 70 74 20 24 73  slotID prompt $s
24d0: 6c 6f 74 50 72 6f 6d 70 74 46 6f 72 50 49 4e 20  lotPromptForPIN 
24e0: 63 65 72 74 20 24 63 65 72 74 20 70 75 62 6b 65  cert $cert pubke
24f0: 79 20 24 70 75 62 6b 65 79 5d 0a 09 09 7d 0a 09  y $pubkey]...}..
2500: 7d 0a 0a 09 72 65 74 75 72 6e 20 24 73 6c 6f 74  }...return $slot
2510: 49 6e 66 6f 0a 7d 0a 0a 70 72 6f 63 20 5f 76 65  Info.}..proc _ve
2520: 72 69 66 79 50 61 73 73 77 6f 72 64 20 7b 6e 61  rifyPassword {na
2530: 6d 65 20 70 61 73 73 77 6f 72 64 7d 20 7b 0a 09  me password} {..
2540: 73 65 74 20 70 75 62 6c 69 63 4b 65 79 73 20 5b  set publicKeys [
2550: 6c 69 73 74 5d 0a 0a 09 64 62 20 65 76 61 6c 20  list]...db eval 
2560: 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b 65  {SELECT publicKe
2570: 79 2c 20 76 65 72 69 66 69 63 61 74 69 6f 6e 20  y, verification 
2580: 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57  FROM passwords W
2590: 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 6e 61 6d  HERE name = $nam
25a0: 65 7d 20 72 6f 77 20 7b 0a 09 09 73 65 74 20 73  e} row {...set s
25b0: 61 6c 74 20 5b 64 69 63 74 20 67 65 74 20 24 72  alt [dict get $r
25c0: 6f 77 28 76 65 72 69 66 69 63 61 74 69 6f 6e 29  ow(verification)
25d0: 20 73 61 6c 74 5d 0a 09 09 73 65 74 20 68 61 73   salt]...set has
25e0: 68 41 6c 67 6f 72 69 74 68 6d 20 5b 64 69 63 74  hAlgorithm [dict
25f0: 20 67 65 74 20 24 72 6f 77 28 76 65 72 69 66 69   get $row(verifi
2600: 63 61 74 69 6f 6e 29 20 68 61 73 68 41 6c 67 6f  cation) hashAlgo
2610: 72 69 74 68 6d 5d 0a 09 09 73 65 74 20 70 75 62  rithm]...set pub
2620: 6c 69 63 4b 65 79 20 24 72 6f 77 28 70 75 62 6c  licKey $row(publ
2630: 69 63 4b 65 79 29 0a 0a 09 09 73 65 74 20 70 6c  icKey)....set pl
2640: 61 69 6e 74 65 78 74 20 22 24 7b 73 61 6c 74 7d  aintext "${salt}
2650: 7c 24 7b 70 75 62 6c 69 63 4b 65 79 7d 7c 24 7b  |${publicKey}|${
2660: 70 61 73 73 77 6f 72 64 7d 22 0a 0a 09 09 73 77  password}"....sw
2670: 69 74 63 68 20 2d 2d 20 24 68 61 73 68 41 6c 67  itch -- $hashAlg
2680: 6f 72 69 74 68 6d 20 7b 0a 09 09 09 22 73 68 61  orithm {...."sha
2690: 32 35 36 22 20 7b 0a 09 09 09 09 73 65 74 20 76  256" {.....set v
26a0: 65 72 69 66 69 63 61 74 69 6f 6e 48 61 73 68 20  erificationHash 
26b0: 5b 73 68 61 32 3a 3a 73 68 61 32 35 36 20 2d 68  [sha2::sha256 -h
26c0: 65 78 20 2d 2d 20 24 70 6c 61 69 6e 74 65 78 74  ex -- $plaintext
26d0: 5d 0a 09 09 09 7d 0a 09 09 09 64 65 66 61 75 6c  ]....}....defaul
26e0: 74 20 7b 0a 09 09 09 09 72 65 74 75 72 6e 20 2d  t {.....return -
26f0: 63 6f 64 65 20 65 72 72 6f 72 20 22 55 6e 6b 6e  code error "Unkn
2700: 6f 77 6e 20 68 61 73 68 69 6e 67 20 61 6c 67 6f  own hashing algo
2710: 72 69 74 68 6d 3a 20 24 68 61 73 68 41 6c 67 6f  rithm: $hashAlgo
2720: 72 69 74 68 6d 22 0a 09 09 09 7d 0a 09 09 7d 0a  rithm"....}...}.
2730: 0a 09 09 73 65 74 20 72 6f 77 28 76 65 72 69 66  ...set row(verif
2740: 69 63 61 74 69 6f 6e 48 61 73 68 29 20 5b 64 69  icationHash) [di
2750: 63 74 20 67 65 74 20 24 72 6f 77 28 76 65 72 69  ct get $row(veri
2760: 66 69 63 61 74 69 6f 6e 29 20 68 61 73 68 5d 0a  fication) hash].
2770: 0a 09 09 69 66 20 7b 24 76 65 72 69 66 69 63 61  ...if {$verifica
2780: 74 69 6f 6e 48 61 73 68 20 6e 65 20 24 72 6f 77  tionHash ne $row
2790: 28 76 65 72 69 66 69 63 61 74 69 6f 6e 48 61 73  (verificationHas
27a0: 68 29 7d 20 7b 0a 09 09 09 72 65 74 75 72 6e 20  h)} {....return 
27b0: 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 46 41 49  -code error "FAI
27c0: 4c 45 44 3a 20 76 65 72 69 66 69 63 61 74 69 6f  LED: verificatio
27d0: 6e 20 66 61 69 6c 65 64 20 66 6f 72 20 24 6e 61  n failed for $na
27e0: 6d 65 20 77 69 74 68 20 70 75 62 6c 69 63 20 6b  me with public k
27f0: 65 79 20 24 70 75 62 6c 69 63 4b 65 79 20 2d 2d  ey $publicKey --
2800: 20 69 74 20 77 69 6c 6c 20 6e 6f 74 20 67 65 74   it will not get
2810: 20 74 68 65 20 6e 65 77 20 70 61 73 73 77 6f 72   the new passwor
2820: 64 2e 22 0a 0a 09 09 09 63 6f 6e 74 69 6e 75 65  d.".....continue
2830: 0a 09 09 7d 0a 0a 09 09 6c 61 70 70 65 6e 64 20  ...}....lappend 
2840: 70 75 62 6c 69 63 4b 65 79 73 20 24 70 75 62 6c  publicKeys $publ
2850: 69 63 4b 65 79 0a 09 7d 0a 0a 09 72 65 74 75 72  icKey..}...retur
2860: 6e 20 24 70 75 62 6c 69 63 4b 65 79 73 0a 7d 0a  n $publicKeys.}.
2870: 0a 70 72 6f 63 20 5f 61 64 64 50 61 73 73 77 6f  .proc _addPasswo
2880: 72 64 20 7b 6e 61 6d 65 20 70 61 73 73 77 6f 72  rd {name passwor
2890: 64 20 70 75 62 6c 69 63 4b 65 79 73 7d 20 7b 0a  d publicKeys} {.
28a0: 09 73 65 74 20 66 64 20 5b 6f 70 65 6e 20 22 2f  .set fd [open "/
28b0: 64 65 76 2f 75 72 61 6e 64 6f 6d 22 20 72 5d 0a  dev/urandom" r].
28c0: 09 66 63 6f 6e 66 69 67 75 72 65 20 24 66 64 20  .fconfigure $fd 
28d0: 2d 74 72 61 6e 73 6c 61 74 69 6f 6e 20 62 69 6e  -translation bin
28e0: 61 72 79 0a 0a 09 73 65 74 20 6b 65 79 53 69 7a  ary...set keySiz
28f0: 65 20 31 36 0a 0a 09 23 20 50 61 64 20 74 68 65  e 16...# Pad the
2900: 20 70 61 73 73 77 6f 72 64 20 77 69 74 68 20 30   password with 0
2910: 20 62 79 74 65 73 20 75 6e 74 69 6c 20 69 74 20   bytes until it 
2920: 69 73 20 61 20 6d 75 6c 74 69 70 6c 65 20 6f 66  is a multiple of
2930: 20 74 68 65 20 6b 65 79 20 73 69 7a 65 0a 09 73   the key size..s
2940: 65 74 20 62 6c 6f 63 6b 50 61 73 73 77 6f 72 64  et blockPassword
2950: 20 24 70 61 73 73 77 6f 72 64 0a 09 61 70 70 65   $password..appe
2960: 6e 64 20 62 6c 6f 63 6b 50 61 73 73 77 6f 72 64  nd blockPassword
2970: 20 5b 73 74 72 69 6e 67 20 72 65 70 65 61 74 20   [string repeat 
2980: 22 5c 78 30 30 22 20 5b 65 78 70 72 20 7b 2d 5b  "\x00" [expr {-[
2990: 73 74 72 69 6e 67 20 6c 65 6e 67 74 68 20 24 70  string length $p
29a0: 61 73 73 77 6f 72 64 5d 20 25 20 24 6b 65 79 53  assword] % $keyS
29b0: 69 7a 65 7d 5d 5d 0a 0a 09 64 62 20 74 72 61 6e  ize}]]...db tran
29c0: 73 61 63 74 69 6f 6e 20 7b 0a 09 09 64 62 20 65  saction {...db e
29d0: 76 61 6c 20 7b 44 45 4c 45 54 45 20 46 52 4f 4d  val {DELETE FROM
29e0: 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45   passwords WHERE
29f0: 20 6e 61 6d 65 20 3d 20 24 6e 61 6d 65 3b 7d 0a   name = $name;}.
2a00: 0a 09 09 66 6f 72 65 61 63 68 20 70 75 62 6c 69  ...foreach publi
2a10: 63 4b 65 79 20 24 70 75 62 6c 69 63 4b 65 79 73  cKey $publicKeys
2a20: 20 7b 0a 09 09 09 73 65 74 20 6b 65 79 20 5b 72   {....set key [r
2a30: 65 61 64 20 24 66 64 20 24 6b 65 79 53 69 7a 65  ead $fd $keySize
2a40: 5d 0a 09 09 09 69 66 20 7b 5b 73 74 72 69 6e 67  ]....if {[string
2a50: 20 6c 65 6e 67 74 68 20 24 6b 65 79 5d 20 21 3d   length $key] !=
2a60: 20 24 6b 65 79 53 69 7a 65 7d 20 7b 0a 09 09 09   $keySize} {....
2a70: 09 63 6c 6f 73 65 20 24 66 64 0a 0a 09 09 09 09  .close $fd......
2a80: 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72  return -code err
2a90: 6f 72 20 22 45 52 52 4f 52 3a 20 53 68 6f 72 74  or "ERROR: Short
2aa0: 20 72 65 61 64 20 66 72 6f 6d 20 72 61 6e 64 6f   read from rando
2ab0: 6d 20 64 65 76 69 63 65 22 0a 09 09 09 7d 0a 0a  m device"....}..
2ac0: 09 09 09 73 65 74 20 73 61 6c 74 20 5b 72 65 61  ...set salt [rea
2ad0: 64 20 24 66 64 20 24 6b 65 79 53 69 7a 65 5d 0a  d $fd $keySize].
2ae0: 09 09 09 73 65 74 20 73 61 6c 74 20 5b 62 69 6e  ...set salt [bin
2af0: 61 72 79 20 65 6e 63 6f 64 65 20 62 61 73 65 36  ary encode base6
2b00: 34 20 24 73 61 6c 74 5d 0a 0a 09 09 09 73 65 74  4 $salt].....set
2b10: 20 70 75 62 6c 69 63 4b 65 79 49 74 65 6d 20 5b   publicKeyItem [
2b20: 3a 3a 70 6b 69 3a 3a 70 6b 63 73 3a 3a 70 61 72  ::pki::pkcs::par
2b30: 73 65 5f 70 75 62 6c 69 63 5f 6b 65 79 20 5b 62  se_public_key [b
2b40: 69 6e 61 72 79 20 64 65 63 6f 64 65 20 62 61 73  inary decode bas
2b50: 65 36 34 20 24 70 75 62 6c 69 63 4b 65 79 5d 5d  e64 $publicKey]]
2b60: 0a 0a 09 09 09 73 65 74 20 65 6e 63 72 79 70 74  .....set encrypt
2b70: 65 64 4b 65 79 20 5b 62 69 6e 61 72 79 20 65 6e  edKey [binary en
2b80: 63 6f 64 65 20 62 61 73 65 36 34 20 5b 3a 3a 70  code base64 [::p
2b90: 6b 69 3a 3a 65 6e 63 72 79 70 74 20 2d 70 75 62  ki::encrypt -pub
2ba0: 20 2d 62 69 6e 61 72 79 20 2d 2d 20 24 6b 65 79   -binary -- $key
2bb0: 20 24 70 75 62 6c 69 63 4b 65 79 49 74 65 6d 5d   $publicKeyItem]
2bc0: 5d 0a 0a 09 09 09 73 65 74 20 65 6e 63 72 79 70  ].....set encryp
2bd0: 74 65 64 50 61 73 73 20 5b 62 69 6e 61 72 79 20  tedPass [binary 
2be0: 65 6e 63 6f 64 65 20 62 61 73 65 36 34 20 5b 3a  encode base64 [:
2bf0: 3a 61 65 73 3a 3a 61 65 73 20 2d 64 69 72 20 65  :aes::aes -dir e
2c00: 6e 63 72 79 70 74 20 2d 6b 65 79 20 24 6b 65 79  ncrypt -key $key
2c10: 20 2d 2d 20 24 62 6c 6f 63 6b 50 61 73 73 77 6f   -- $blockPasswo
2c20: 72 64 5d 5d 0a 0a 09 09 09 73 65 74 20 76 65 72  rd]].....set ver
2c30: 69 66 69 63 61 74 69 6f 6e 48 61 73 68 20 5b 73  ificationHash [s
2c40: 68 61 32 3a 3a 73 68 61 32 35 36 20 2d 68 65 78  ha2::sha256 -hex
2c50: 20 2d 2d 20 22 24 7b 73 61 6c 74 7d 7c 24 7b 70   -- "${salt}|${p
2c60: 75 62 6c 69 63 4b 65 79 7d 7c 24 7b 70 61 73 73  ublicKey}|${pass
2c70: 77 6f 72 64 7d 22 5d 0a 09 09 09 73 65 74 20 76  word}"]....set v
2c80: 65 72 69 66 69 63 61 74 69 6f 6e 20 5b 6c 69 73  erification [lis
2c90: 74 20 73 61 6c 74 20 24 73 61 6c 74 20 68 61 73  t salt $salt has
2ca0: 68 41 6c 67 6f 72 69 74 68 6d 20 73 68 61 32 35  hAlgorithm sha25
2cb0: 36 20 68 61 73 68 20 24 76 65 72 69 66 69 63 61  6 hash $verifica
2cc0: 74 69 6f 6e 48 61 73 68 5d 0a 0a 09 09 09 64 62  tionHash].....db
2cd0: 20 65 76 61 6c 20 7b 49 4e 53 45 52 54 20 49 4e   eval {INSERT IN
2ce0: 54 4f 20 70 61 73 73 77 6f 72 64 73 20 28 6e 61  TO passwords (na
2cf0: 6d 65 2c 20 65 6e 63 72 79 70 74 65 64 50 61 73  me, encryptedPas
2d00: 73 2c 20 65 6e 63 72 79 70 74 65 64 4b 65 79 2c  s, encryptedKey,
2d10: 20 70 75 62 6c 69 63 4b 65 79 2c 20 76 65 72 69   publicKey, veri
2d20: 66 69 63 61 74 69 6f 6e 29 20 56 41 4c 55 45 53  fication) VALUES
2d30: 20 28 24 6e 61 6d 65 2c 20 40 65 6e 63 72 79 70   ($name, @encryp
2d40: 74 65 64 50 61 73 73 2c 20 40 65 6e 63 72 79 70  tedPass, @encryp
2d50: 74 65 64 4b 65 79 2c 20 40 70 75 62 6c 69 63 4b  tedKey, @publicK
2d60: 65 79 2c 20 40 76 65 72 69 66 69 63 61 74 69 6f  ey, @verificatio
2d70: 6e 29 3b 7d 0a 09 09 7d 0a 09 7d 0a 0a 09 63 6c  n);}...}..}...cl
2d80: 6f 73 65 20 24 66 64 0a 7d 0a 0a 70 72 6f 63 20  ose $fd.}..proc 
2d90: 5f 70 72 6f 6d 70 74 20 7b 70 72 6f 6d 70 74 7d  _prompt {prompt}
2da0: 20 7b 0a 09 70 75 74 73 20 2d 6e 6f 6e 65 77 6c   {..puts -nonewl
2db0: 69 6e 65 20 24 70 72 6f 6d 70 74 0a 09 66 6c 75  ine $prompt..flu
2dc0: 73 68 20 73 74 64 6f 75 74 0a 0a 09 70 75 74 73  sh stdout...puts
2dd0: 20 2d 6e 6f 6e 65 77 6c 69 6e 65 20 5b 65 78 65   -nonewline [exe
2de0: 63 20 73 74 74 79 20 2d 65 63 68 6f 5d 0a 09 66  c stty -echo]..f
2df0: 6c 75 73 68 20 73 74 64 6f 75 74 0a 0a 09 73 65  lush stdout...se
2e00: 74 20 70 61 73 73 77 6f 72 64 20 5b 67 65 74 73  t password [gets
2e10: 20 73 74 64 69 6e 5d 0a 0a 09 70 75 74 73 20 2d   stdin]...puts -
2e20: 6e 6f 6e 65 77 6c 69 6e 65 20 5b 65 78 65 63 20  nonewline [exec 
2e30: 73 74 74 79 20 65 63 68 6f 5d 0a 09 70 75 74 73  stty echo]..puts
2e40: 20 22 22 0a 09 66 6c 75 73 68 20 73 74 64 6f 75   ""..flush stdou
2e50: 74 0a 0a 09 72 65 74 75 72 6e 20 24 70 61 73 73  t...return $pass
2e60: 77 6f 72 64 0a 7d 0a 0a 70 72 6f 63 20 5f 67 65  word.}..proc _ge
2e70: 74 50 61 73 73 77 6f 72 64 20 7b 6e 61 6d 65 7d  tPassword {name}
2e80: 20 7b 0a 09 73 65 74 20 65 78 69 73 74 73 20 5b   {..set exists [
2e90: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20  db eval {SELECT 
2ea0: 31 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73  1 FROM passwords
2eb0: 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 6e   WHERE name = $n
2ec0: 61 6d 65 20 4c 49 4d 49 54 20 31 3b 7d 5d 0a 09  ame LIMIT 1;}]..
2ed0: 69 66 20 7b 24 65 78 69 73 74 73 20 21 3d 20 22  if {$exists != "
2ee0: 31 22 7d 20 7b 0a 09 09 72 65 74 75 72 6e 20 2d  1"} {...return -
2ef0: 63 6f 64 65 20 65 72 72 6f 72 20 22 50 61 73 73  code error "Pass
2f00: 77 6f 72 64 20 5c 22 24 6e 61 6d 65 5c 22 20 64  word \"$name\" d
2f10: 6f 65 73 20 6e 6f 74 20 65 78 69 73 74 73 2e 22  oes not exists."
2f20: 0a 09 7d 0a 0a 09 66 6f 72 65 61 63 68 20 73 6c  ..}...foreach sl
2f30: 6f 74 49 6e 66 6f 44 69 63 74 20 5b 5f 6c 69 73  otInfoDict [_lis
2f40: 74 43 65 72 74 69 66 69 63 61 74 65 73 5d 20 7b  tCertificates] {
2f50: 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70  ...unset -nocomp
2f60: 6c 61 69 6e 20 73 6c 6f 74 49 6e 66 6f 0a 09 09  lain slotInfo...
2f70: 61 72 72 61 79 20 73 65 74 20 73 6c 6f 74 49 6e  array set slotIn
2f80: 66 6f 20 24 73 6c 6f 74 49 6e 66 6f 44 69 63 74  fo $slotInfoDict
2f90: 0a 0a 09 09 73 65 74 20 70 75 62 6b 65 79 20 24  ....set pubkey $
2fa0: 73 6c 6f 74 49 6e 66 6f 28 70 75 62 6b 65 79 29  slotInfo(pubkey)
2fb0: 0a 09 09 73 65 74 20 70 72 6f 6d 70 74 20 24 73  ...set prompt $s
2fc0: 6c 6f 74 49 6e 66 6f 28 70 72 6f 6d 70 74 29 0a  lotInfo(prompt).
2fd0: 0a 09 09 69 66 20 7b 5b 69 6e 66 6f 20 65 78 69  ...if {[info exi
2fe0: 73 74 73 20 70 72 6f 6d 70 74 65 64 28 24 73 6c  sts prompted($sl
2ff0: 6f 74 49 6e 66 6f 28 69 64 29 29 5d 7d 20 7b 0a  otInfo(id))]} {.
3000: 09 09 09 73 65 74 20 70 72 6f 6d 70 74 20 66 61  ...set prompt fa
3010: 6c 73 65 0a 09 09 7d 0a 0a 09 09 69 66 20 7b 24  lse...}....if {$
3020: 70 72 6f 6d 70 74 7d 20 7b 0a 09 09 09 73 65 74  prompt} {....set
3030: 20 50 49 4e 20 5b 5f 70 72 6f 6d 70 74 20 22 50   PIN [_prompt "P
3040: 6c 65 61 73 65 20 65 6e 74 65 72 20 74 68 65 20  lease enter the 
3050: 50 49 4e 20 66 6f 72 20 5b 64 69 63 74 20 67 65  PIN for [dict ge
3060: 74 20 24 73 6c 6f 74 49 6e 66 6f 28 63 65 72 74  t $slotInfo(cert
3070: 29 20 73 75 62 6a 65 63 74 5d 3a 20 22 5d 0a 0a  ) subject]: "]..
3080: 09 09 09 69 66 20 7b 21 5b 3a 3a 70 6b 69 3a 3a  ...if {![::pki::
3090: 70 6b 63 73 31 31 3a 3a 6c 6f 67 69 6e 20 24 73  pkcs11::login $s
30a0: 6c 6f 74 49 6e 66 6f 28 68 61 6e 64 6c 65 29 20  lotInfo(handle) 
30b0: 24 73 6c 6f 74 49 6e 66 6f 28 69 64 29 20 24 50  $slotInfo(id) $P
30c0: 49 4e 5d 7d 20 7b 0a 09 09 09 09 72 65 74 75 72  IN]} {.....retur
30d0: 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 55  n -code error "U
30e0: 6e 61 62 6c 65 20 74 6f 20 61 75 74 68 65 6e 74  nable to authent
30f0: 69 63 61 74 65 22 0a 09 09 09 7d 0a 0a 09 09 09  icate"....}.....
3100: 73 65 74 20 70 72 6f 6d 70 74 65 64 28 24 73 6c  set prompted($sl
3110: 6f 74 49 6e 66 6f 28 69 64 29 29 20 31 0a 09 09  otInfo(id)) 1...
3120: 7d 0a 0a 09 09 64 62 20 65 76 61 6c 20 7b 53 45  }....db eval {SE
3130: 4c 45 43 54 20 65 6e 63 72 79 70 74 65 64 50 61  LECT encryptedPa
3140: 73 73 2c 20 65 6e 63 72 79 70 74 65 64 4b 65 79  ss, encryptedKey
3150: 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20   FROM passwords 
3160: 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 6e 61  WHERE name = $na
3170: 6d 65 20 41 4e 44 20 70 75 62 6c 69 63 4b 65 79  me AND publicKey
3180: 20 3d 20 24 70 75 62 6b 65 79 3b 7d 20 72 6f 77   = $pubkey;} row
3190: 20 7b 0a 09 09 09 73 65 74 20 6b 65 79 20 5b 3a   {....set key [:
31a0: 3a 70 6b 69 3a 3a 64 65 63 72 79 70 74 20 2d 62  :pki::decrypt -b
31b0: 69 6e 61 72 79 20 2d 70 72 69 76 20 2d 2d 20 5b  inary -priv -- [
31c0: 62 69 6e 61 72 79 20 64 65 63 6f 64 65 20 62 61  binary decode ba
31d0: 73 65 36 34 20 24 72 6f 77 28 65 6e 63 72 79 70  se64 $row(encryp
31e0: 74 65 64 4b 65 79 29 5d 20 24 73 6c 6f 74 49 6e  tedKey)] $slotIn
31f0: 66 6f 28 63 65 72 74 29 5d 0a 09 09 09 73 65 74  fo(cert)]....set
3200: 20 70 61 73 73 77 6f 72 64 20 5b 3a 3a 61 65 73   password [::aes
3210: 3a 3a 61 65 73 20 2d 64 69 72 20 64 65 63 72 79  ::aes -dir decry
3220: 70 74 20 2d 6b 65 79 20 24 6b 65 79 20 2d 2d 20  pt -key $key -- 
3230: 5b 62 69 6e 61 72 79 20 64 65 63 6f 64 65 20 62  [binary decode b
3240: 61 73 65 36 34 20 24 72 6f 77 28 65 6e 63 72 79  ase64 $row(encry
3250: 70 74 65 64 50 61 73 73 29 5d 5d 0a 0a 09 09 09  ptedPass)]].....
3260: 72 65 74 75 72 6e 20 5b 73 74 72 69 6e 67 20 74  return [string t
3270: 72 69 6d 72 69 67 68 74 20 24 70 61 73 73 77 6f  rimright $passwo
3280: 72 64 20 22 5c 78 30 30 22 5d 0a 09 09 7d 0a 09  rd "\x00"]...}..
3290: 7d 0a 0a 09 72 65 74 75 72 6e 20 2d 63 6f 64 65  }...return -code
32a0: 20 65 72 72 6f 72 20 22 4e 6f 20 76 61 6c 69 64   error "No valid
32b0: 20 6b 65 79 73 22 0a 7d 0a 0a 70 72 6f 63 20 5f   keys".}..proc _
32c0: 6d 6f 64 69 66 79 50 75 62 6c 69 63 4b 65 79 73  modifyPublicKeys
32d0: 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 75   {passwordName u
32e0: 73 65 72 4e 61 6d 65 73 20 73 71 6c 7d 20 7b 0a  serNames sql} {.
32f0: 09 73 65 74 20 65 78 69 73 74 73 20 5b 64 62 20  .set exists [db 
3300: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 31 20 46  eval {SELECT 1 F
3310: 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48  ROM passwords WH
3320: 45 52 45 20 6e 61 6d 65 20 3d 20 24 70 61 73 73  ERE name = $pass
3330: 77 6f 72 64 4e 61 6d 65 20 4c 49 4d 49 54 20 31  wordName LIMIT 1
3340: 3b 7d 5d 0a 09 69 66 20 7b 24 65 78 69 73 74 73  ;}]..if {$exists
3350: 20 21 3d 20 22 31 22 7d 20 7b 0a 09 09 72 65 74   != "1"} {...ret
3360: 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20  urn -code error 
3370: 22 50 61 73 73 77 6f 72 64 20 5c 22 24 70 61 73  "Password \"$pas
3380: 73 77 6f 72 64 4e 61 6d 65 5c 22 20 64 6f 65 73  swordName\" does
3390: 20 6e 6f 74 20 65 78 69 73 74 73 2e 22 0a 09 7d   not exists."..}
33a0: 0a 0a 09 73 65 74 20 70 75 62 6c 69 63 4b 65 79  ...set publicKey
33b0: 73 20 5b 6c 69 73 74 5d 0a 0a 09 64 62 20 65 76  s [list]...db ev
33c0: 61 6c 20 7b 53 45 4c 45 43 54 20 70 75 62 6c 69  al {SELECT publi
33d0: 63 4b 65 79 20 46 52 4f 4d 20 70 61 73 73 77 6f  cKey FROM passwo
33e0: 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d  rds WHERE name =
33f0: 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 3b 7d   $passwordName;}
3400: 20 72 6f 77 20 7b 0a 09 09 6c 61 70 70 65 6e 64   row {...lappend
3410: 20 70 75 62 6c 69 63 4b 65 79 73 20 24 72 6f 77   publicKeys $row
3420: 28 70 75 62 6c 69 63 4b 65 79 29 0a 09 7d 0a 0a  (publicKey)..}..
3430: 09 73 65 74 20 63 68 61 6e 67 65 52 65 71 75 69  .set changeRequi
3440: 72 65 64 20 30 0a 09 66 6f 72 65 61 63 68 20 75  red 0..foreach u
3450: 73 65 72 20 24 75 73 65 72 4e 61 6d 65 73 20 7b  ser $userNames {
3460: 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70  ...unset -nocomp
3470: 6c 61 69 6e 20 72 6f 77 0a 09 09 64 62 20 65 76  lain row...db ev
3480: 61 6c 20 7b 53 45 4c 45 43 54 20 70 75 62 6c 69  al {SELECT publi
3490: 63 4b 65 79 20 46 52 4f 4d 20 75 73 65 72 73 20  cKey FROM users 
34a0: 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 75 73  WHERE name = $us
34b0: 65 72 3b 7d 20 72 6f 77 20 24 73 71 6c 0a 09 7d  er;} row $sql..}
34c0: 0a 0a 09 69 66 20 7b 21 24 63 68 61 6e 67 65 52  ...if {!$changeR
34d0: 65 71 75 69 72 65 64 7d 20 7b 0a 09 09 72 65 74  equired} {...ret
34e0: 75 72 6e 0a 09 7d 0a 0a 09 73 65 74 20 70 61 73  urn..}...set pas
34f0: 73 77 6f 72 64 20 5b 5f 67 65 74 50 61 73 73 77  sword [_getPassw
3500: 6f 72 64 20 24 70 61 73 73 77 6f 72 64 4e 61 6d  ord $passwordNam
3510: 65 5d 0a 0a 09 5f 61 64 64 50 61 73 73 77 6f 72  e]..._addPasswor
3520: 64 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20  d $passwordName 
3530: 24 70 61 73 73 77 6f 72 64 20 24 70 75 62 6c 69  $password $publi
3540: 63 4b 65 79 73 0a 7d 0a 0a 70 72 6f 63 20 5f 67  cKeys.}..proc _g
3550: 65 74 55 73 65 72 73 46 6f 72 50 61 73 73 77 6f  etUsersForPasswo
3560: 72 64 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65  rd {passwordName
3570: 73 7d 20 7b 0a 09 73 65 74 20 75 73 65 72 4e 61  s} {..set userNa
3580: 6d 65 73 20 5b 6c 69 73 74 5d 0a 0a 09 66 6f 72  mes [list]...for
3590: 65 61 63 68 20 70 61 73 73 77 6f 72 64 4e 61 6d  each passwordNam
35a0: 65 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 73  e $passwordNames
35b0: 20 7b 0a 09 09 64 62 20 65 76 61 6c 20 7b 53 45   {...db eval {SE
35c0: 4c 45 43 54 20 70 75 62 6c 69 63 4b 65 79 20 46  LECT publicKey F
35d0: 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48  ROM passwords WH
35e0: 45 52 45 20 6e 61 6d 65 20 3d 20 24 70 61 73 73  ERE name = $pass
35f0: 77 6f 72 64 4e 61 6d 65 3b 7d 20 70 61 73 73 77  wordName;} passw
3600: 6f 72 64 52 6f 77 20 7b 0a 09 09 09 64 62 20 65  ordRow {....db e
3610: 76 61 6c 20 7b 53 45 4c 45 43 54 20 6e 61 6d 65  val {SELECT name
3620: 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48 45 52   FROM users WHER
3630: 45 20 70 75 62 6c 69 63 4b 65 79 20 3d 20 24 70  E publicKey = $p
3640: 61 73 73 77 6f 72 64 52 6f 77 28 70 75 62 6c 69  asswordRow(publi
3650: 63 4b 65 79 29 7d 20 75 73 65 72 52 6f 77 20 7b  cKey)} userRow {
3660: 0a 09 09 09 09 69 66 20 7b 24 75 73 65 72 52 6f  .....if {$userRo
3670: 77 28 6e 61 6d 65 29 20 69 6e 20 24 75 73 65 72  w(name) in $user
3680: 4e 61 6d 65 73 7d 20 7b 0a 09 09 09 09 09 63 6f  Names} {......co
3690: 6e 74 69 6e 75 65 0a 09 09 09 09 7d 0a 0a 09 09  ntinue.....}....
36a0: 09 09 6c 61 70 70 65 6e 64 20 75 73 65 72 4e 61  ..lappend userNa
36b0: 6d 65 73 20 24 75 73 65 72 52 6f 77 28 6e 61 6d  mes $userRow(nam
36c0: 65 29 0a 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a 0a  e)....}...}..}..
36d0: 09 72 65 74 75 72 6e 20 24 75 73 65 72 4e 61 6d  .return $userNam
36e0: 65 73 0a 7d 0a 0a 70 72 6f 63 20 5f 67 65 74 50  es.}..proc _getP
36f0: 61 73 73 77 6f 72 64 73 46 6f 72 55 73 65 72 20  asswordsForUser 
3700: 7b 75 73 65 72 4e 61 6d 65 73 7d 20 7b 0a 09 73  {userNames} {..s
3710: 65 74 20 70 61 73 73 77 6f 72 64 4e 61 6d 65 73  et passwordNames
3720: 20 5b 6c 69 73 74 5d 0a 0a 09 66 6f 72 65 61 63   [list]...foreac
3730: 68 20 75 73 65 72 4e 61 6d 65 20 24 75 73 65 72  h userName $user
3740: 4e 61 6d 65 73 20 7b 0a 09 09 64 62 20 65 76 61  Names {...db eva
3750: 6c 20 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63  l {SELECT public
3760: 4b 65 79 20 46 52 4f 4d 20 75 73 65 72 73 20 57  Key FROM users W
3770: 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 75 73 65  HERE name = $use
3780: 72 4e 61 6d 65 3b 7d 20 75 73 65 72 52 6f 77 20  rName;} userRow 
3790: 7b 0a 09 09 09 64 62 20 65 76 61 6c 20 7b 53 45  {....db eval {SE
37a0: 4c 45 43 54 20 6e 61 6d 65 20 46 52 4f 4d 20 70  LECT name FROM p
37b0: 61 73 73 77 6f 72 64 73 20 57 48 45 52 45 20 70  asswords WHERE p
37c0: 75 62 6c 69 63 4b 65 79 20 3d 20 24 75 73 65 72  ublicKey = $user
37d0: 52 6f 77 28 70 75 62 6c 69 63 4b 65 79 29 7d 20  Row(publicKey)} 
37e0: 70 61 73 73 77 6f 72 64 52 6f 77 20 7b 0a 09 09  passwordRow {...
37f0: 09 09 69 66 20 7b 24 70 61 73 73 77 6f 72 64 52  ..if {$passwordR
3800: 6f 77 28 6e 61 6d 65 29 20 69 6e 20 24 70 61 73  ow(name) in $pas
3810: 73 77 6f 72 64 4e 61 6d 65 73 7d 20 7b 0a 09 09  swordNames} {...
3820: 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 09  ...continue.....
3830: 7d 0a 0a 09 09 09 09 6c 61 70 70 65 6e 64 20 70  }......lappend p
3840: 61 73 73 77 6f 72 64 4e 61 6d 65 73 20 24 70 61  asswordNames $pa
3850: 73 73 77 6f 72 64 52 6f 77 28 6e 61 6d 65 29 0a  sswordRow(name).
3860: 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a 0a 09 72 65  ...}...}..}...re
3870: 74 75 72 6e 20 24 70 61 73 73 77 6f 72 64 4e 61  turn $passwordNa
3880: 6d 65 73 0a 7d 0a 23 20 45 6e 64 20 69 6e 74 65  mes.}.# End inte
3890: 72 6e 61 6c 20 66 75 6e 63 74 69 6f 6e 73 0a 0a  rnal functions..
38a0: 23 20 53 74 61 72 74 20 75 73 65 72 20 43 4c 49  # Start user CLI
38b0: 20 66 75 6e 63 74 69 6f 6e 73 0a 70 72 6f 63 20   functions.proc 
38c0: 6c 69 73 74 4c 6f 63 61 6c 4b 65 79 73 20 7b 7d  listLocalKeys {}
38d0: 20 7b 0a 09 66 6f 72 65 61 63 68 20 73 6c 6f 74   {..foreach slot
38e0: 49 6e 66 6f 44 69 63 74 20 5b 5f 6c 69 73 74 43  InfoDict [_listC
38f0: 65 72 74 69 66 69 63 61 74 65 73 5d 20 7b 0a 09  ertificates] {..
3900: 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61  .unset -nocompla
3910: 69 6e 20 73 6c 6f 74 49 6e 66 6f 0a 09 09 61 72  in slotInfo...ar
3920: 72 61 79 20 73 65 74 20 73 6c 6f 74 49 6e 66 6f  ray set slotInfo
3930: 20 24 73 6c 6f 74 49 6e 66 6f 44 69 63 74 0a 0a   $slotInfoDict..
3940: 09 09 73 65 74 20 73 75 62 6a 65 63 74 20 5b 64  ..set subject [d
3950: 69 63 74 20 67 65 74 20 24 73 6c 6f 74 49 6e 66  ict get $slotInf
3960: 6f 28 63 65 72 74 29 20 73 75 62 6a 65 63 74 5d  o(cert) subject]
3970: 0a 09 09 73 65 74 20 70 75 62 6b 65 79 20 20 24  ...set pubkey  $
3980: 73 6c 6f 74 49 6e 66 6f 28 70 75 62 6b 65 79 29  slotInfo(pubkey)
3990: 0a 0a 09 09 6c 61 70 70 65 6e 64 20 70 75 62 6c  ....lappend publ
39a0: 69 63 4b 65 79 73 28 24 73 75 62 6a 65 63 74 29  icKeys($subject)
39b0: 20 24 70 75 62 6b 65 79 0a 09 7d 0a 0a 09 66 6f   $pubkey..}...fo
39c0: 72 65 61 63 68 20 7b 73 75 62 6a 65 63 74 20 70  reach {subject p
39d0: 75 62 6b 65 79 73 7d 20 5b 61 72 72 61 79 20 67  ubkeys} [array g
39e0: 65 74 20 70 75 62 6c 69 63 4b 65 79 73 5d 20 7b  et publicKeys] {
39f0: 0a 09 09 70 75 74 73 20 22 24 73 75 62 6a 65 63  ...puts "$subjec
3a00: 74 22 0a 0a 09 09 66 6f 72 65 61 63 68 20 70 75  t"....foreach pu
3a10: 62 6b 65 79 20 24 70 75 62 6b 65 79 73 20 7b 0a  bkey $pubkeys {.
3a20: 09 09 09 70 75 74 73 20 22 20 20 7c 2d 3e 20 24  ...puts "  |-> $
3a30: 70 75 62 6b 65 79 22 0a 09 09 7d 0a 09 7d 0a 0a  pubkey"...}..}..
3a40: 09 73 65 74 20 3a 3a 73 61 76 65 52 65 71 75 69  .set ::saveRequi
3a50: 72 65 64 20 30 0a 7d 0a 0a 70 72 6f 63 20 6c 69  red 0.}..proc li
3a60: 73 74 41 76 61 69 6c 61 62 6c 65 50 61 73 73 77  stAvailablePassw
3a70: 6f 72 64 73 20 7b 7d 20 7b 0a 09 73 65 74 20 70  ords {} {..set p
3a80: 61 73 73 77 6f 72 64 4e 61 6d 65 73 20 5b 6c 69  asswordNames [li
3a90: 73 74 5d 0a 09 66 6f 72 65 61 63 68 20 73 6c 6f  st]..foreach slo
3aa0: 74 49 6e 66 6f 44 69 63 74 20 5b 5f 6c 69 73 74  tInfoDict [_list
3ab0: 43 65 72 74 69 66 69 63 61 74 65 73 5d 20 7b 0a  Certificates] {.
3ac0: 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c  ..unset -nocompl
3ad0: 61 69 6e 20 73 6c 6f 74 49 6e 66 6f 0a 09 09 61  ain slotInfo...a
3ae0: 72 72 61 79 20 73 65 74 20 73 6c 6f 74 49 6e 66  rray set slotInf
3af0: 6f 20 24 73 6c 6f 74 49 6e 66 6f 44 69 63 74 0a  o $slotInfoDict.
3b00: 0a 09 09 73 65 74 20 70 75 62 6b 65 79 20 24 73  ...set pubkey $s
3b10: 6c 6f 74 49 6e 66 6f 28 70 75 62 6b 65 79 29 0a  lotInfo(pubkey).
3b20: 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70  ...unset -nocomp
3b30: 6c 61 69 6e 20 72 6f 77 0a 09 09 64 62 20 65 76  lain row...db ev
3b40: 61 6c 20 7b 53 45 4c 45 43 54 20 6e 61 6d 65 20  al {SELECT name 
3b50: 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57  FROM passwords W
3b60: 48 45 52 45 20 70 75 62 6c 69 63 4b 65 79 20 3d  HERE publicKey =
3b70: 20 24 70 75 62 6b 65 79 3b 7d 20 72 6f 77 20 7b   $pubkey;} row {
3b80: 0a 09 09 09 69 66 20 7b 24 72 6f 77 28 6e 61 6d  ....if {$row(nam
3b90: 65 29 20 69 6e 20 24 70 61 73 73 77 6f 72 64 4e  e) in $passwordN
3ba0: 61 6d 65 73 7d 20 7b 0a 09 09 09 09 63 6f 6e 74  ames} {.....cont
3bb0: 69 6e 75 65 0a 09 09 09 7d 0a 0a 09 09 09 6c 61  inue....}.....la
3bc0: 70 70 65 6e 64 20 70 61 73 73 77 6f 72 64 4e 61  ppend passwordNa
3bd0: 6d 65 73 20 24 72 6f 77 28 6e 61 6d 65 29 0a 09  mes $row(name)..
3be0: 09 7d 0a 09 7d 0a 0a 0a 09 66 6f 72 65 61 63 68  .}..}....foreach
3bf0: 20 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 70   passwordName $p
3c00: 61 73 73 77 6f 72 64 4e 61 6d 65 73 20 7b 0a 09  asswordNames {..
3c10: 09 70 75 74 73 20 22 24 70 61 73 73 77 6f 72 64  .puts "$password
3c20: 4e 61 6d 65 20 2d 20 5b 6a 6f 69 6e 20 5b 5f 67  Name - [join [_g
3c30: 65 74 55 73 65 72 73 46 6f 72 50 61 73 73 77 6f  etUsersForPasswo
3c40: 72 64 20 5b 6c 69 73 74 20 24 70 61 73 73 77 6f  rd [list $passwo
3c50: 72 64 4e 61 6d 65 5d 5d 20 7b 2c 20 7d 5d 22 0a  rdName]] {, }]".
3c60: 09 7d 0a 0a 09 73 65 74 20 3a 3a 73 61 76 65 52  .}...set ::saveR
3c70: 65 71 75 69 72 65 64 20 30 0a 7d 0a 0a 70 72 6f  equired 0.}..pro
3c80: 63 20 6c 69 73 74 50 61 73 73 77 6f 72 64 73 20  c listPasswords 
3c90: 7b 7d 20 7b 0a 09 64 62 20 65 76 61 6c 20 7b 53  {} {..db eval {S
3ca0: 45 4c 45 43 54 20 44 49 53 54 49 4e 43 54 20 6e  ELECT DISTINCT n
3cb0: 61 6d 65 20 46 52 4f 4d 20 70 61 73 73 77 6f 72  ame FROM passwor
3cc0: 64 73 3b 7d 20 72 6f 77 20 7b 0a 09 09 70 75 74  ds;} row {...put
3cd0: 73 20 22 24 72 6f 77 28 6e 61 6d 65 29 20 2d 20  s "$row(name) - 
3ce0: 5b 6a 6f 69 6e 20 5b 5f 67 65 74 55 73 65 72 73  [join [_getUsers
3cf0: 46 6f 72 50 61 73 73 77 6f 72 64 20 5b 6c 69 73  ForPassword [lis
3d00: 74 20 24 72 6f 77 28 6e 61 6d 65 29 5d 5d 20 7b  t $row(name)]] {
3d10: 2c 20 7d 5d 22 0a 09 7d 0a 0a 09 73 65 74 20 3a  , }]"..}...set :
3d20: 3a 73 61 76 65 52 65 71 75 69 72 65 64 20 30 0a  :saveRequired 0.
3d30: 7d 0a 0a 70 72 6f 63 20 6c 69 73 74 55 73 65 72  }..proc listUser
3d40: 73 20 7b 7d 20 7b 0a 09 64 62 20 65 76 61 6c 20  s {} {..db eval 
3d50: 7b 53 45 4c 45 43 54 20 44 49 53 54 49 4e 43 54  {SELECT DISTINCT
3d60: 20 6e 61 6d 65 20 46 52 4f 4d 20 75 73 65 72 73   name FROM users
3d70: 3b 7d 20 72 6f 77 20 7b 0a 09 09 70 75 74 73 20  ;} row {...puts 
3d80: 22 24 72 6f 77 28 6e 61 6d 65 29 20 2d 20 5b 6a  "$row(name) - [j
3d90: 6f 69 6e 20 5b 5f 67 65 74 50 61 73 73 77 6f 72  oin [_getPasswor
3da0: 64 73 46 6f 72 55 73 65 72 20 5b 6c 69 73 74 20  dsForUser [list 
3db0: 24 72 6f 77 28 6e 61 6d 65 29 5d 5d 20 7b 2c 20  $row(name)]] {, 
3dc0: 7d 5d 22 0a 09 7d 0a 0a 09 73 65 74 20 3a 3a 73  }]"..}...set ::s
3dd0: 61 76 65 52 65 71 75 69 72 65 64 20 30 0a 7d 0a  aveRequired 0.}.
3de0: 0a 70 72 6f 63 20 61 64 64 55 73 65 72 20 7b 75  .proc addUser {u
3df0: 73 65 72 4e 61 6d 65 20 6b 65 79 7d 20 7b 0a 09  serName key} {..
3e00: 73 65 74 20 6b 65 79 52 61 77 20 5b 62 69 6e 61  set keyRaw [bina
3e10: 72 79 20 64 65 63 6f 64 65 20 62 61 73 65 36 34  ry decode base64
3e20: 20 24 6b 65 79 5d 0a 09 73 65 74 20 6b 65 79 56   $key]..set keyV
3e30: 65 72 69 66 79 20 5b 3a 3a 70 6b 69 3a 3a 70 6b  erify [::pki::pk
3e40: 63 73 3a 3a 70 61 72 73 65 5f 70 75 62 6c 69 63  cs::parse_public
3e50: 5f 6b 65 79 20 24 6b 65 79 52 61 77 5d 0a 0a 09  _key $keyRaw]...
3e60: 64 62 20 65 76 61 6c 20 7b 49 4e 53 45 52 54 20  db eval {INSERT 
3e70: 49 4e 54 4f 20 75 73 65 72 73 20 28 6e 61 6d 65  INTO users (name
3e80: 2c 20 70 75 62 6c 69 63 4b 65 79 29 20 56 41 4c  , publicKey) VAL
3e90: 55 45 53 20 28 24 75 73 65 72 4e 61 6d 65 2c 20  UES ($userName, 
3ea0: 40 6b 65 79 29 3b 7d 0a 0a 09 23 20 58 58 58 3a  @key);}...# XXX:
3eb0: 54 4f 44 4f 3a 47 6f 20 74 68 72 6f 75 67 68 20  TODO:Go through 
3ec0: 61 6e 64 20 72 65 2d 61 75 74 68 6f 72 69 7a 65  and re-authorize
3ed0: 20 69 66 20 70 6f 73 73 69 62 6c 65 0a 7d 0a 0a   if possible.}..
3ee0: 70 72 6f 63 20 64 65 6c 65 74 65 55 73 65 72 20  proc deleteUser 
3ef0: 7b 75 73 65 72 4e 61 6d 65 7d 20 7b 0a 09 23 20  {userName} {..# 
3f00: 58 58 58 3a 54 4f 44 4f 3a 20 47 6f 20 74 68 72  XXX:TODO: Go thr
3f10: 6f 75 67 68 20 61 6e 64 20 64 65 2d 61 75 74 68  ough and de-auth
3f20: 6f 72 69 7a 65 0a 7d 0a 0a 70 72 6f 63 20 61 64  orize.}..proc ad
3f30: 64 50 61 73 73 77 6f 72 64 20 7b 70 61 73 73 77  dPassword {passw
3f40: 6f 72 64 4e 61 6d 65 20 70 61 73 73 77 6f 72 64  ordName password
3f50: 20 61 72 67 73 7d 20 7b 0a 09 73 65 74 20 69 6e   args} {..set in
3f60: 69 74 69 61 6c 55 73 65 72 73 20 24 61 72 67 73  itialUsers $args
3f70: 0a 0a 09 69 66 20 7b 24 70 61 73 73 77 6f 72 64  ...if {$password
3f80: 20 65 71 20 22 22 7d 20 7b 0a 09 09 73 65 74 20   eq ""} {...set 
3f90: 70 61 73 73 77 6f 72 64 20 5b 5f 70 72 6f 6d 70  password [_promp
3fa0: 74 20 22 50 6c 65 61 73 65 20 65 6e 74 65 72 20  t "Please enter 
3fb0: 74 68 65 20 6e 65 77 20 70 61 73 73 77 6f 72 64  the new password
3fc0: 3a 20 22 5d 0a 09 7d 0a 0a 09 23 20 56 65 72 69  : "]..}...# Veri
3fd0: 66 79 20 74 68 61 74 20 74 68 69 73 20 70 61 73  fy that this pas
3fe0: 73 77 6f 72 64 20 64 6f 65 73 20 6e 6f 74 20 61  sword does not a
3ff0: 6c 72 65 61 64 79 20 65 78 69 73 74 0a 09 73 65  lready exist..se
4000: 74 20 65 78 69 73 74 73 20 5b 64 62 20 65 76 61  t exists [db eva
4010: 6c 20 7b 53 45 4c 45 43 54 20 31 20 46 52 4f 4d  l {SELECT 1 FROM
4020: 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45   passwords WHERE
4030: 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77 6f 72   name = $passwor
4040: 64 4e 61 6d 65 20 4c 49 4d 49 54 20 31 3b 7d 5d  dName LIMIT 1;}]
4050: 0a 09 69 66 20 7b 24 65 78 69 73 74 73 20 3d 3d  ..if {$exists ==
4060: 20 22 31 22 7d 20 7b 0a 09 09 72 65 74 75 72 6e   "1"} {...return
4070: 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 50 61   -code error "Pa
4080: 73 73 77 6f 72 64 20 5c 22 24 70 61 73 73 77 6f  ssword \"$passwo
4090: 72 64 4e 61 6d 65 5c 22 20 61 6c 72 65 61 64 79  rdName\" already
40a0: 20 65 78 69 73 74 73 2c 20 63 61 6e 6e 6f 74 20   exists, cannot 
40b0: 61 64 64 2e 22 0a 09 7d 0a 0a 09 23 20 47 65 74  add."..}...# Get
40c0: 20 6b 65 79 73 20 66 6f 72 20 69 6e 69 74 69 61   keys for initia
40d0: 6c 20 75 73 65 72 73 0a 09 73 65 74 20 70 75 62  l users..set pub
40e0: 6c 69 63 4b 65 79 73 20 5b 6c 69 73 74 5d 0a 09  licKeys [list]..
40f0: 66 6f 72 65 61 63 68 20 75 73 65 72 20 24 69 6e  foreach user $in
4100: 69 74 69 61 6c 55 73 65 72 73 20 7b 0a 09 09 75  itialUsers {...u
4110: 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69 6e  nset -nocomplain
4120: 20 72 6f 77 0a 09 09 64 62 20 65 76 61 6c 20 7b   row...db eval {
4130: 53 45 4c 45 43 54 20 70 75 62 6c 69 63 4b 65 79  SELECT publicKey
4140: 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48 45 52   FROM users WHER
4150: 45 20 6e 61 6d 65 20 3d 20 24 75 73 65 72 3b 7d  E name = $user;}
4160: 20 72 6f 77 20 7b 0a 09 09 09 6c 61 70 70 65 6e   row {....lappen
4170: 64 20 70 75 62 6c 69 63 4b 65 79 73 20 24 72 6f  d publicKeys $ro
4180: 77 28 70 75 62 6c 69 63 4b 65 79 29 0a 09 09 7d  w(publicKey)...}
4190: 0a 09 7d 0a 0a 09 5f 61 64 64 50 61 73 73 77 6f  ..}..._addPasswo
41a0: 72 64 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65  rd $passwordName
41b0: 20 24 70 61 73 73 77 6f 72 64 20 24 70 75 62 6c   $password $publ
41c0: 69 63 4b 65 79 73 0a 7d 0a 0a 70 72 6f 63 20 67  icKeys.}..proc g
41d0: 65 74 50 61 73 73 77 6f 72 64 20 7b 70 61 73 73  etPassword {pass
41e0: 77 6f 72 64 4e 61 6d 65 7d 20 7b 0a 09 70 75 74  wordName} {..put
41f0: 73 20 5b 5f 67 65 74 50 61 73 73 77 6f 72 64 20  s [_getPassword 
4200: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5d 0a 0a  $passwordName]..
4210: 09 73 65 74 20 3a 3a 73 61 76 65 52 65 71 75 69  .set ::saveRequi
4220: 72 65 64 20 30 0a 7d 0a 0a 70 72 6f 63 20 75 70  red 0.}..proc up
4230: 64 61 74 65 50 61 73 73 77 6f 72 64 20 7b 70 61  datePassword {pa
4240: 73 73 77 6f 72 64 4e 61 6d 65 20 70 61 73 73 77  sswordName passw
4250: 6f 72 64 7d 20 7b 0a 09 69 66 20 7b 24 70 61 73  ord} {..if {$pas
4260: 73 77 6f 72 64 20 65 71 20 22 22 7d 20 7b 0a 09  sword eq ""} {..
4270: 09 73 65 74 20 70 61 73 73 77 6f 72 64 20 5b 5f  .set password [_
4280: 70 72 6f 6d 70 74 20 22 50 6c 65 61 73 65 20 65  prompt "Please e
4290: 6e 74 65 72 20 74 68 65 20 6e 65 77 20 70 61 73  nter the new pas
42a0: 73 77 6f 72 64 3a 20 22 5d 0a 09 7d 0a 0a 09 73  sword: "]..}...s
42b0: 65 74 20 6f 6c 64 50 61 73 73 77 6f 72 64 20 5b  et oldPassword [
42c0: 5f 67 65 74 50 61 73 73 77 6f 72 64 20 24 70 61  _getPassword $pa
42d0: 73 73 77 6f 72 64 4e 61 6d 65 5d 0a 0a 09 73 65  sswordName]...se
42e0: 74 20 70 75 62 6c 69 63 4b 65 79 73 20 5b 5f 76  t publicKeys [_v
42f0: 65 72 69 66 79 50 61 73 73 77 6f 72 64 20 24 70  erifyPassword $p
4300: 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 6f 6c 64  asswordName $old
4310: 50 61 73 73 77 6f 72 64 5d 0a 0a 09 69 66 20 7b  Password]...if {
4320: 5b 6c 6c 65 6e 67 74 68 20 24 70 75 62 6c 69 63  [llength $public
4330: 4b 65 79 73 5d 20 3d 3d 20 30 7d 20 7b 0a 09 09  Keys] == 0} {...
4340: 70 75 74 73 20 73 74 64 65 72 72 20 22 57 61 72  puts stderr "War
4350: 6e 69 6e 67 3a 20 54 68 69 73 20 77 69 6c 6c 20  ning: This will 
4360: 64 65 6c 65 74 65 20 74 68 65 20 70 61 73 73 77  delete the passw
4370: 6f 72 64 20 73 69 6e 63 65 20 74 68 65 72 65 20  ord since there 
4380: 61 72 65 20 6e 6f 20 76 61 6c 69 64 20 70 75 62  are no valid pub
4390: 6c 69 63 20 6b 65 79 73 2e 22 0a 09 7d 0a 0a 09  lic keys."..}...
43a0: 5f 61 64 64 50 61 73 73 77 6f 72 64 20 24 70 61  _addPassword $pa
43b0: 73 73 77 6f 72 64 4e 61 6d 65 20 24 70 61 73 73  sswordName $pass
43c0: 77 6f 72 64 20 24 70 75 62 6c 69 63 4b 65 79 73  word $publicKeys
43d0: 0a 7d 0a 0a 70 72 6f 63 20 64 65 6c 65 74 65 50  .}..proc deleteP
43e0: 61 73 73 77 6f 72 64 20 7b 70 61 73 73 77 6f 72  assword {passwor
43f0: 64 4e 61 6d 65 7d 20 7b 0a 09 64 62 20 65 76 61  dName} {..db eva
4400: 6c 20 7b 44 45 4c 45 54 45 20 46 52 4f 4d 20 70  l {DELETE FROM p
4410: 61 73 73 77 6f 72 64 73 20 57 48 45 52 45 20 6e  asswords WHERE n
4420: 61 6d 65 20 3d 20 24 70 61 73 73 77 6f 72 64 4e  ame = $passwordN
4430: 61 6d 65 3b 7d 0a 7d 0a 0a 70 72 6f 63 20 61 75  ame;}.}..proc au
4440: 74 68 6f 72 69 7a 65 55 73 65 72 73 20 7b 70 61  thorizeUsers {pa
4450: 73 73 77 6f 72 64 4e 61 6d 65 20 61 72 67 73 7d  sswordName args}
4460: 20 7b 0a 09 73 65 74 20 75 73 65 72 73 20 24 61   {..set users $a
4470: 72 67 73 0a 0a 09 5f 6d 6f 64 69 66 79 50 75 62  rgs..._modifyPub
4480: 6c 69 63 4b 65 79 73 20 24 70 61 73 73 77 6f 72  licKeys $passwor
4490: 64 4e 61 6d 65 20 24 75 73 65 72 73 20 7b 0a 09  dName $users {..
44a0: 09 69 66 20 7b 24 72 6f 77 28 70 75 62 6c 69 63  .if {$row(public
44b0: 4b 65 79 29 20 69 6e 20 24 70 75 62 6c 69 63 4b  Key) in $publicK
44c0: 65 79 73 7d 20 7b 0a 09 09 09 63 6f 6e 74 69 6e  eys} {....contin
44d0: 75 65 0a 09 09 7d 0a 0a 09 09 6c 61 70 70 65 6e  ue...}....lappen
44e0: 64 20 70 75 62 6c 69 63 4b 65 79 73 20 24 72 6f  d publicKeys $ro
44f0: 77 28 70 75 62 6c 69 63 4b 65 79 29 0a 0a 09 09  w(publicKey)....
4500: 73 65 74 20 63 68 61 6e 67 65 52 65 71 75 69 72  set changeRequir
4510: 65 64 20 31 0a 09 7d 0a 7d 0a 0a 70 72 6f 63 20  ed 1..}.}..proc 
4520: 61 75 74 68 6f 72 69 7a 65 55 73 65 72 20 7b 70  authorizeUser {p
4530: 61 73 73 77 6f 72 64 4e 61 6d 65 20 75 73 65 72  asswordName user
4540: 4e 61 6d 65 7d 20 7b 0a 09 72 65 74 75 72 6e 20  Name} {..return 
4550: 5b 61 75 74 68 6f 72 69 7a 65 55 73 65 72 73 20  [authorizeUsers 
4560: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 75  $passwordName $u
4570: 73 65 72 4e 61 6d 65 5d 0a 7d 0a 0a 70 72 6f 63  serName].}..proc
4580: 20 64 65 61 75 74 68 6f 72 69 7a 65 55 73 65 72   deauthorizeUser
4590: 73 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 20  s {passwordName 
45a0: 61 72 67 73 7d 20 7b 0a 09 73 65 74 20 75 73 65  args} {..set use
45b0: 72 73 20 24 61 72 67 73 0a 0a 09 5f 6d 6f 64 69  rs $args..._modi
45c0: 66 79 50 75 62 6c 69 63 4b 65 79 73 20 24 70 61  fyPublicKeys $pa
45d0: 73 73 77 6f 72 64 4e 61 6d 65 20 24 75 73 65 72  sswordName $user
45e0: 73 20 7b 0a 09 09 73 65 74 20 69 64 78 20 5b 6c  s {...set idx [l
45f0: 73 65 61 72 63 68 20 2d 65 78 61 63 74 20 24 70  search -exact $p
4600: 75 62 6c 69 63 4b 65 79 73 20 24 72 6f 77 28 70  ublicKeys $row(p
4610: 75 62 6c 69 63 4b 65 79 29 5d 0a 09 09 69 66 20  ublicKey)]...if 
4620: 7b 24 69 64 78 20 3d 3d 20 2d 31 7d 20 7b 0a 09  {$idx == -1} {..
4630: 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 7d 0a 0a  ..continue...}..
4640: 09 09 73 65 74 20 70 75 62 6c 69 63 4b 65 79 73  ..set publicKeys
4650: 20 5b 6c 72 65 70 6c 61 63 65 20 24 70 75 62 6c   [lreplace $publ
4660: 69 63 4b 65 79 73 20 24 69 64 78 20 24 69 64 78  icKeys $idx $idx
4670: 5d 0a 0a 09 09 73 65 74 20 63 68 61 6e 67 65 52  ]....set changeR
4680: 65 71 75 69 72 65 64 20 31 0a 09 7d 0a 7d 0a 0a  equired 1..}.}..
4690: 70 72 6f 63 20 64 65 61 75 74 68 6f 72 69 7a 65  proc deauthorize
46a0: 55 73 65 72 20 7b 70 61 73 73 77 6f 72 64 4e 61  User {passwordNa
46b0: 6d 65 20 75 73 65 72 4e 61 6d 65 7d 20 7b 0a 09  me userName} {..
46c0: 72 65 74 75 72 6e 20 5b 64 65 61 75 74 68 6f 72  return [deauthor
46d0: 69 7a 65 55 73 65 72 73 20 24 70 61 73 73 77 6f  izeUsers $passwo
46e0: 72 64 4e 61 6d 65 20 24 75 73 65 72 4e 61 6d 65  rdName $userName
46f0: 5d 0a 7d 0a 0a 70 72 6f 63 20 77 68 6f 61 6d 69  ].}..proc whoami
4700: 20 7b 7d 20 7b 0a 09 66 6f 72 65 61 63 68 20 73   {} {..foreach s
4710: 6c 6f 74 49 6e 66 6f 44 69 63 74 20 5b 5f 6c 69  lotInfoDict [_li
4720: 73 74 43 65 72 74 69 66 69 63 61 74 65 73 5d 20  stCertificates] 
4730: 7b 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d  {...unset -nocom
4740: 70 6c 61 69 6e 20 73 6c 6f 74 49 6e 66 6f 0a 09  plain slotInfo..
4750: 09 61 72 72 61 79 20 73 65 74 20 73 6c 6f 74 49  .array set slotI
4760: 6e 66 6f 20 24 73 6c 6f 74 49 6e 66 6f 44 69 63  nfo $slotInfoDic
4770: 74 0a 0a 09 09 73 65 74 20 70 75 62 6b 65 79 20  t....set pubkey 
4780: 24 73 6c 6f 74 49 6e 66 6f 28 70 75 62 6b 65 79  $slotInfo(pubkey
4790: 29 0a 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63 6f  )....unset -noco
47a0: 6d 70 6c 61 69 6e 20 72 6f 77 0a 09 09 64 62 20  mplain row...db 
47b0: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 6e 61 6d  eval {SELECT nam
47c0: 65 20 46 52 4f 4d 20 75 73 65 72 73 20 57 48 45  e FROM users WHE
47d0: 52 45 20 70 75 62 6c 69 63 4b 65 79 20 3d 20 24  RE publicKey = $
47e0: 70 75 62 6b 65 79 3b 7d 20 72 6f 77 20 7b 0a 09  pubkey;} row {..
47f0: 09 09 73 65 74 20 75 73 65 72 73 28 24 72 6f 77  ..set users($row
4800: 28 6e 61 6d 65 29 29 20 31 0a 09 09 7d 0a 09 7d  (name)) 1...}..}
4810: 0a 0a 09 70 75 74 73 20 5b 6a 6f 69 6e 20 5b 61  ...puts [join [a
4820: 72 72 61 79 20 6e 61 6d 65 73 20 75 73 65 72 73  rray names users
4830: 5d 20 7b 2c 20 7d 5d 0a 0a 09 73 65 74 20 3a 3a  ] {, }]...set ::
4840: 73 61 76 65 52 65 71 75 69 72 65 64 20 30 0a 7d  saveRequired 0.}
4850: 0a 0a 70 72 6f 63 20 68 65 6c 70 20 7b 7b 61 63  ..proc help {{ac
4860: 74 69 6f 6e 20 22 22 7d 7d 20 7b 0a 09 5f 70 72  tion ""}} {.._pr
4870: 69 6e 74 48 65 6c 70 20 73 74 64 6f 75 74 20 24  intHelp stdout $
4880: 61 63 74 69 6f 6e 0a 0a 09 73 65 74 20 3a 3a 73  action...set ::s
4890: 61 76 65 52 65 71 75 69 72 65 64 20 30 0a 7d 0a  aveRequired 0.}.
48a0: 23 20 45 6e 64 20 75 73 65 72 20 43 4c 49 20 66  # End user CLI f
48b0: 75 6e 63 74 69 6f 6e 73 0a 0a 23 23 23 20 4d 41  unctions..### MA
48c0: 49 4e 0a 0a 5f 6c 6f 61 64 44 42 20 64 62 20 24  IN.._loadDB db $
48d0: 70 61 73 73 77 6f 72 64 46 69 6c 65 0a 0a 69 66  passwordFile..if
48e0: 20 7b 24 61 63 74 69 6f 6e 20 69 6e 20 24 76 61   {$action in $va
48f0: 6c 69 64 43 6f 6d 6d 61 6e 64 73 7d 20 7b 0a 09  lidCommands} {..
4900: 69 66 20 7b 5b 63 61 74 63 68 20 7b 0a 09 09 24  if {[catch {...$
4910: 61 63 74 69 6f 6e 20 7b 2a 7d 24 61 72 67 76 0a  action {*}$argv.
4920: 09 7d 20 65 72 72 6f 72 5d 7d 20 7b 0a 09 09 70  .} error]} {...p
4930: 75 74 73 20 73 74 64 65 72 72 20 22 45 72 72 6f  uts stderr "Erro
4940: 72 3a 20 24 65 72 72 6f 72 22 0a 0a 09 09 65 78  r: $error"....ex
4950: 69 74 20 31 0a 09 7d 0a 7d 20 65 6c 73 65 20 7b  it 1..}.} else {
4960: 0a 09 70 75 74 73 20 73 74 64 65 72 72 20 22 49  ..puts stderr "I
4970: 6e 76 61 6c 69 64 20 61 63 74 69 6f 6e 22 0a 0a  nvalid action"..
4980: 09 65 78 69 74 20 31 0a 7d 0a 0a 69 66 20 7b 24  .exit 1.}..if {$
4990: 3a 3a 73 61 76 65 52 65 71 75 69 72 65 64 7d 20  ::saveRequired} 
49a0: 7b 0a 09 5f 73 61 76 65 44 42 20 64 62 20 24 70  {.._saveDB db $p
49b0: 61 73 73 77 6f 72 64 46 69 6c 65 0a 7d 0a 0a 64  asswordFile.}..d
49c0: 62 20 63 6c 6f 73 65 0a 0a 65 78 69 74 20 30 0a  b close..exit 0.