Hex Artifact Content

Artifact 05208b6e4e79640cc5a1a87d6e6677a70d03179f:


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 70 61 63 6b 61 67 65 20 72 65 71 75  d]..package requ
0c00: 69 72 65 20 73 71 6c 69 74 65 33 0a 70 61 63 6b  ire sqlite3.pack
0c10: 61 67 65 20 72 65 71 75 69 72 65 20 70 6c 61 74  age require plat
0c20: 66 6f 72 6d 0a 0a 6c 61 70 70 65 6e 64 20 3a 3a  form..lappend ::
0c30: 61 75 74 6f 5f 70 61 74 68 20 5b 66 69 6c 65 20  auto_path [file 
0c40: 6a 6f 69 6e 20 5b 66 69 6c 65 20 64 69 72 6e 61  join [file dirna
0c50: 6d 65 20 5b 69 6e 66 6f 20 73 63 72 69 70 74 5d  me [info script]
0c60: 5d 20 6c 69 62 20 5b 70 6c 61 74 66 6f 72 6d 3a  ] lib [platform:
0c70: 3a 69 64 65 6e 74 69 66 79 5d 5d 0a 6c 61 70 70  :identify]].lapp
0c80: 65 6e 64 20 3a 3a 61 75 74 6f 5f 70 61 74 68 20  end ::auto_path 
0c90: 5b 66 69 6c 65 20 6a 6f 69 6e 20 5b 66 69 6c 65  [file join [file
0ca0: 20 64 69 72 6e 61 6d 65 20 5b 69 6e 66 6f 20 73   dirname [info s
0cb0: 63 72 69 70 74 5d 5d 20 6c 69 62 20 5b 70 6c 61  cript]] lib [pla
0cc0: 74 66 6f 72 6d 3a 3a 67 65 6e 65 72 69 63 5d 5d  tform::generic]]
0cd0: 0a 6c 61 70 70 65 6e 64 20 3a 3a 61 75 74 6f 5f  .lappend ::auto_
0ce0: 70 61 74 68 20 5b 66 69 6c 65 20 6a 6f 69 6e 20  path [file join 
0cf0: 5b 66 69 6c 65 20 64 69 72 6e 61 6d 65 20 5b 69  [file dirname [i
0d00: 6e 66 6f 20 73 63 72 69 70 74 5d 5d 20 6c 69 62  nfo script]] lib
0d10: 5d 0a 0a 70 61 63 6b 61 67 65 20 72 65 71 75 69  ]..package requi
0d20: 72 65 20 70 6b 69 0a 70 61 63 6b 61 67 65 20 72  re pki.package r
0d30: 65 71 75 69 72 65 20 70 6b 69 3a 3a 70 6b 63 73  equire pki::pkcs
0d40: 31 31 0a 70 61 63 6b 61 67 65 20 72 65 71 75 69  11.package requi
0d50: 72 65 20 61 65 73 0a 70 61 63 6b 61 67 65 20 72  re aes.package r
0d60: 65 71 75 69 72 65 20 73 68 61 32 35 36 0a 0a 23  equire sha256..#
0d70: 20 42 61 63 6b 70 6f 72 74 73 20 66 6f 72 20 6f   Backports for o
0d80: 6c 64 65 72 20 76 65 72 73 69 6f 6e 73 20 6f 66  lder versions of
0d90: 20 22 70 6b 69 22 0a 70 72 6f 63 20 3a 3a 70 6b   "pki".proc ::pk
0da0: 69 3a 3a 70 6b 63 73 3a 3a 70 61 72 73 65 5f 70  i::pkcs::parse_p
0db0: 75 62 6c 69 63 5f 6b 65 79 20 7b 6b 65 79 20 7b  ublic_key {key {
0dc0: 70 61 73 73 77 6f 72 64 20 22 22 7d 7d 20 7b 0a  password ""}} {.
0dd0: 20 20 20 20 20 20 20 20 61 72 72 61 79 20 73 65          array se
0de0: 74 20 70 61 72 73 65 64 5f 6b 65 79 20 5b 3a 3a  t parsed_key [::
0df0: 70 6b 69 3a 3a 5f 70 61 72 73 65 5f 70 65 6d 20  pki::_parse_pem 
0e00: 24 6b 65 79 20 22 2d 2d 2d 2d 2d 42 45 47 49 4e  $key "-----BEGIN
0e10: 20 50 55 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d   PUBLIC KEY-----
0e20: 22 20 22 2d 2d 2d 2d 2d 45 4e 44 20 50 55 42 4c  " "-----END PUBL
0e30: 49 43 20 4b 45 59 2d 2d 2d 2d 2d 22 20 24 70 61  IC KEY-----" $pa
0e40: 73 73 77 6f 72 64 5d 0a 0a 20 20 20 20 20 20 20  ssword]..       
0e50: 20 73 65 74 20 6b 65 79 5f 73 65 71 20 24 70 61   set key_seq $pa
0e60: 72 73 65 64 5f 6b 65 79 28 64 61 74 61 29 0a 0a  rsed_key(data)..
0e70: 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61          ::asn::a
0e80: 73 6e 47 65 74 53 65 71 75 65 6e 63 65 20 6b 65  snGetSequence ke
0e90: 79 5f 73 65 71 20 70 75 62 6b 65 79 69 6e 66 6f  y_seq pubkeyinfo
0ea0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
0eb0: 20 3a 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 53 65   ::asn::asnGetSe
0ec0: 71 75 65 6e 63 65 20 70 75 62 6b 65 79 69 6e 66  quence pubkeyinf
0ed0: 6f 20 70 75 62 6b 65 79 5f 61 6c 67 6f 69 64 0a  o pubkey_algoid.
0ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ef0: 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61          ::asn::a
0f00: 73 6e 47 65 74 4f 62 6a 65 63 74 49 64 65 6e 74  snGetObjectIdent
0f10: 69 66 69 65 72 20 70 75 62 6b 65 79 5f 61 6c 67  ifier pubkey_alg
0f20: 6f 69 64 20 6f 69 64 0a 20 20 20 20 20 20 20 20  oid oid.        
0f30: 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61          ::asn::a
0f40: 73 6e 47 65 74 42 69 74 53 74 72 69 6e 67 20 70  snGetBitString p
0f50: 75 62 6b 65 79 69 6e 66 6f 20 70 75 62 6b 65 79  ubkeyinfo pubkey
0f60: 0a 20 20 20 20 20 20 20 20 73 65 74 20 72 65 74  .        set ret
0f70: 28 70 75 62 6b 65 79 5f 61 6c 67 6f 29 20 5b 3a  (pubkey_algo) [:
0f80: 3a 70 6b 69 3a 3a 5f 6f 69 64 5f 6e 75 6d 62 65  :pki::_oid_numbe
0f90: 72 5f 74 6f 5f 6e 61 6d 65 20 24 6f 69 64 5d 0a  r_to_name $oid].
0fa0: 0a 20 20 20 20 20 20 20 20 73 77 69 74 63 68 20  .        switch 
0fb0: 2d 2d 20 24 72 65 74 28 70 75 62 6b 65 79 5f 61  -- $ret(pubkey_a
0fc0: 6c 67 6f 29 20 7b 0a 20 20 20 20 20 20 20 20 20  lgo) {.         
0fd0: 20 20 20 20 20 20 20 22 72 73 61 45 6e 63 72 79         "rsaEncry
0fe0: 70 74 69 6f 6e 22 20 7b 0a 20 20 20 20 20 20 20  ption" {.       
0ff0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1000: 20 73 65 74 20 70 75 62 6b 65 79 20 5b 62 69 6e   set pubkey [bin
1010: 61 72 79 20 66 6f 72 6d 61 74 20 42 2a 20 24 70  ary format B* $p
1020: 75 62 6b 65 79 5d 0a 0a 20 20 20 20 20 20 20 20  ubkey]..        
1030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1040: 3a 3a 61 73 6e 3a 3a 61 73 6e 47 65 74 53 65 71  ::asn::asnGetSeq
1050: 75 65 6e 63 65 20 70 75 62 6b 65 79 20 70 75 62  uence pubkey pub
1060: 6b 65 79 5f 70 61 72 74 73 0a 20 20 20 20 20 20  key_parts.      
1070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1080: 20 20 20 20 20 20 20 20 20 20 3a 3a 61 73 6e 3a            ::asn:
1090: 3a 61 73 6e 47 65 74 42 69 67 49 6e 74 65 67 65  :asnGetBigIntege
10a0: 72 20 70 75 62 6b 65 79 5f 70 61 72 74 73 20 72  r pubkey_parts r
10b0: 65 74 28 6e 29 0a 20 20 20 20 20 20 20 20 20 20  et(n).          
10c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
10d0: 20 20 20 20 20 20 3a 3a 61 73 6e 3a 3a 61 73 6e        ::asn::asn
10e0: 47 65 74 42 69 67 49 6e 74 65 67 65 72 20 70 75  GetBigInteger pu
10f0: 62 6b 65 79 5f 70 61 72 74 73 20 72 65 74 28 65  bkey_parts ret(e
1100: 29 0a 0a 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 73 65 74 20 72             set r
1120: 65 74 28 6e 29 20 5b 3a 3a 6d 61 74 68 3a 3a 62  et(n) [::math::b
1130: 69 67 6e 75 6d 3a 3a 74 6f 73 74 72 20 24 72 65  ignum::tostr $re
1140: 74 28 6e 29 5d 0a 20 20 20 20 20 20 20 20 20 20  t(n)].          
1150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
1160: 74 20 72 65 74 28 65 29 20 5b 3a 3a 6d 61 74 68  t ret(e) [::math
1170: 3a 3a 62 69 67 6e 75 6d 3a 3a 74 6f 73 74 72 20  ::bignum::tostr 
1180: 24 72 65 74 28 65 29 5d 0a 20 20 20 20 20 20 20  $ret(e)].       
1190: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
11a0: 20 73 65 74 20 72 65 74 28 6c 29 20 5b 65 78 70   set ret(l) [exp
11b0: 72 20 7b 69 6e 74 28 5b 3a 3a 70 6b 69 3a 3a 5f  r {int([::pki::_
11c0: 62 69 74 73 20 24 72 65 74 28 6e 29 5d 20 2f 20  bits $ret(n)] / 
11d0: 38 2e 30 30 30 30 20 2b 20 30 2e 35 29 20 2a 20  8.0000 + 0.5) * 
11e0: 38 7d 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  8}].            
11f0: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 74 20              set 
1200: 72 65 74 28 74 79 70 65 29 20 72 73 61 0a 20 20  ret(type) rsa.  
1210: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7d 0a                }.
1220: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1230: 64 65 66 61 75 6c 74 20 7b 0a 20 20 20 20 20 20  default {.      
1240: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1250: 20 20 65 72 72 6f 72 20 22 55 6e 6b 6e 6f 77 6e    error "Unknown
1260: 20 61 6c 67 6f 72 69 74 68 6d 22 0a 20 20 20 20   algorithm".    
1270: 20 20 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20              }.  
1280: 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 20        }..       
1290: 20 72 65 74 75 72 6e 20 5b 61 72 72 61 79 20 67   return [array g
12a0: 65 74 20 72 65 74 5d 0a 7d 0a 0a 70 72 6f 63 20  et ret].}..proc 
12b0: 3a 3a 70 6b 69 3a 3a 72 73 61 3a 3a 73 65 72 69  ::pki::rsa::seri
12c0: 61 6c 69 7a 65 5f 70 75 62 6c 69 63 5f 6b 65 79  alize_public_key
12d0: 20 7b 6b 65 79 6c 69 73 74 7d 20 7b 0a 20 20 20   {keylist} {.   
12e0: 20 20 20 20 20 61 72 72 61 79 20 73 65 74 20 6b       array set k
12f0: 65 79 20 24 6b 65 79 6c 69 73 74 0a 0a 20 20 20  ey $keylist..   
1300: 20 20 20 20 20 66 6f 72 65 61 63 68 20 65 6e 74       foreach ent
1310: 72 79 20 5b 6c 69 73 74 20 6e 20 65 5d 20 7b 0a  ry [list n e] {.
1320: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1330: 69 66 20 7b 21 5b 69 6e 66 6f 20 65 78 69 73 74  if {![info exist
1340: 73 20 6b 65 79 28 24 65 6e 74 72 79 29 5d 7d 20  s key($entry)]} 
1350: 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  {.              
1360: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
1370: 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 4b 65   -code error "Ke
1380: 79 20 64 6f 65 73 20 6e 6f 74 20 63 6f 6e 74 61  y does not conta
1390: 69 6e 20 61 6e 20 65 6c 65 6d 65 6e 74 20 24 65  in an element $e
13a0: 6e 74 72 79 22 0a 20 20 20 20 20 20 20 20 20 20  ntry".          
13b0: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20        }.        
13c0: 7d 0a 0a 20 20 20 20 20 20 20 20 73 65 74 20 70  }..        set p
13d0: 75 62 6b 65 79 20 5b 3a 3a 61 73 6e 3a 3a 61 73  ubkey [::asn::as
13e0: 6e 53 65 71 75 65 6e 63 65 20 5c 0a 20 20 20 20  nSequence \.    
13f0: 20 20 20 20 20 20 20 20 20 20 20 20 5b 3a 3a 61              [::a
1400: 73 6e 3a 3a 61 73 6e 42 69 67 49 6e 74 65 67 65  sn::asnBigIntege
1410: 72 20 5b 3a 3a 6d 61 74 68 3a 3a 62 69 67 6e 75  r [::math::bignu
1420: 6d 3a 3a 66 72 6f 6d 73 74 72 20 24 6b 65 79 28  m::fromstr $key(
1430: 6e 29 5d 5d 20 5c 0a 20 20 20 20 20 20 20 20 20  n)]] \.         
1440: 20 20 20 20 20 20 20 5b 3a 3a 61 73 6e 3a 3a 61         [::asn::a
1450: 73 6e 42 69 67 49 6e 74 65 67 65 72 20 5b 3a 3a  snBigInteger [::
1460: 6d 61 74 68 3a 3a 62 69 67 6e 75 6d 3a 3a 66 72  math::bignum::fr
1470: 6f 6d 73 74 72 20 24 6b 65 79 28 65 29 5d 5d 20  omstr $key(e)]] 
1480: 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  \.              
1490: 20 20 5d 20 20 0a 20 20 20 20 20 20 20 20 73 65    ]  .        se
14a0: 74 20 70 75 62 6b 65 79 5f 61 6c 67 6f 5f 70 61  t pubkey_algo_pa
14b0: 72 61 6d 73 20 5b 3a 3a 61 73 6e 3a 3a 61 73 6e  rams [::asn::asn
14c0: 4e 75 6c 6c 5d 0a 0a 20 20 20 20 20 20 20 20 62  Null]..        b
14d0: 69 6e 61 72 79 20 73 63 61 6e 20 24 70 75 62 6b  inary scan $pubk
14e0: 65 79 20 42 2a 20 70 75 62 6b 65 79 5f 62 69 74  ey B* pubkey_bit
14f0: 73 74 72 69 6e 67 0a 0a 20 20 20 20 20 20 20 20  string..        
1500: 73 65 74 20 72 65 74 20 5b 3a 3a 61 73 6e 3a 3a  set ret [::asn::
1510: 61 73 6e 53 65 71 75 65 6e 63 65 20 5c 0a 20 20  asnSequence \.  
1520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 5b 3a                [:
1530: 3a 61 73 6e 3a 3a 61 73 6e 53 65 71 75 65 6e 63  :asn::asnSequenc
1540: 65 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20  e \.            
1550: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1560: 20 20 20 20 5b 3a 3a 61 73 6e 3a 3a 61 73 6e 4f      [::asn::asnO
1570: 62 6a 65 63 74 49 64 65 6e 74 69 66 69 65 72 20  bjectIdentifier 
1580: 5b 3a 3a 70 6b 69 3a 3a 5f 6f 69 64 5f 6e 61 6d  [::pki::_oid_nam
1590: 65 5f 74 6f 5f 6e 75 6d 62 65 72 20 72 73 61 45  e_to_number rsaE
15a0: 6e 63 72 79 70 74 69 6f 6e 5d 5d 20 5c 0a 20 20  ncryption]] \.  
15b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 24 70                $p
15d0: 75 62 6b 65 79 5f 61 6c 67 6f 5f 70 61 72 61 6d  ubkey_algo_param
15e0: 73 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20  s \.            
15f0: 20 20 20 20 20 20 20 20 20 20 20 20 5d 20 5c 0a              ] \.
1600: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1610: 20 20 20 20 20 20 20 20 5b 3a 3a 61 73 6e 3a 3a          [::asn::
1620: 61 73 6e 42 69 74 53 74 72 69 6e 67 20 24 70 75  asnBitString $pu
1630: 62 6b 65 79 5f 62 69 74 73 74 72 69 6e 67 5d 20  bkey_bitstring] 
1640: 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  \.              
1650: 20 20 20 20 20 20 20 20 20 20 5d 0a 0a 20 20 20            ]..   
1660: 20 20 20 20 20 72 65 74 75 72 6e 20 5b 6c 69 73       return [lis
1670: 74 20 64 61 74 61 20 24 72 65 74 20 62 65 67 69  t data $ret begi
1680: 6e 20 22 2d 2d 2d 2d 2d 42 45 47 49 4e 20 50 55  n "-----BEGIN PU
1690: 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d 22 20 65  BLIC KEY-----" e
16a0: 6e 64 20 22 2d 2d 2d 2d 2d 45 4e 44 20 50 55 42  nd "-----END PUB
16b0: 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d 22 5d 0a 7d  LIC KEY-----"].}
16c0: 0a 23 20 45 6e 64 20 62 61 63 6b 70 6f 72 74 73  .# End backports
16d0: 0a 0a 23 20 53 74 61 72 74 20 69 6e 74 65 72 6e  ..# Start intern
16e0: 61 6c 20 66 75 6e 63 74 69 6f 6e 73 0a 70 72 6f  al functions.pro
16f0: 63 20 5f 6c 69 73 74 43 65 72 74 69 66 69 63 61  c _listCertifica
1700: 74 65 73 20 7b 7d 20 7b 0a 09 69 66 20 7b 21 5b  tes {} {..if {![
1710: 69 6e 66 6f 20 65 78 69 73 74 73 20 3a 3a 65 6e  info exists ::en
1720: 76 28 50 4b 43 53 31 31 4d 4f 44 55 4c 45 29 5d  v(PKCS11MODULE)]
1730: 7d 20 7b 0a 09 09 72 65 74 75 72 6e 20 5b 6c 69  } {...return [li
1740: 73 74 5d 0a 09 7d 0a 0a 09 73 65 74 20 3a 3a 65  st]..}...set ::e
1750: 6e 76 28 43 41 43 4b 45 59 5f 4e 4f 5f 45 58 54  nv(CACKEY_NO_EXT
1760: 52 41 5f 43 45 52 54 53 29 20 31 0a 0a 09 73 65  RA_CERTS) 1...se
1770: 74 20 68 61 6e 64 6c 65 20 5b 3a 3a 70 6b 69 3a  t handle [::pki:
1780: 3a 70 6b 63 73 31 31 3a 3a 6c 6f 61 64 6d 6f 64  :pkcs11::loadmod
1790: 75 6c 65 20 24 3a 3a 65 6e 76 28 50 4b 43 53 31  ule $::env(PKCS1
17a0: 31 4d 4f 44 55 4c 45 29 5d 0a 0a 09 73 65 74 20  1MODULE)]...set 
17b0: 73 6c 6f 74 49 6e 66 6f 20 5b 6c 69 73 74 5d 0a  slotInfo [list].
17c0: 09 66 6f 72 65 61 63 68 20 73 6c 6f 74 20 5b 3a  .foreach slot [:
17d0: 3a 70 6b 69 3a 3a 70 6b 63 73 31 31 3a 3a 6c 69  :pki::pkcs11::li
17e0: 73 74 73 6c 6f 74 73 20 24 68 61 6e 64 6c 65 5d  stslots $handle]
17f0: 20 7b 0a 09 09 73 65 74 20 73 6c 6f 74 49 44 20   {...set slotID 
1800: 5b 6c 69 6e 64 65 78 20 24 73 6c 6f 74 20 30 5d  [lindex $slot 0]
1810: 0a 09 09 73 65 74 20 73 6c 6f 74 4c 61 62 65 6c  ...set slotLabel
1820: 20 5b 6c 69 6e 64 65 78 20 24 73 6c 6f 74 20 31   [lindex $slot 1
1830: 5d 0a 09 09 73 65 74 20 73 6c 6f 74 46 6c 61 67  ]...set slotFlag
1840: 73 20 5b 6c 69 6e 64 65 78 20 24 73 6c 6f 74 20  s [lindex $slot 
1850: 32 5d 0a 0a 09 09 69 66 20 7b 22 54 4f 4b 45 4e  2]....if {"TOKEN
1860: 5f 50 52 45 53 45 4e 54 22 20 6e 69 20 24 73 6c  _PRESENT" ni $sl
1870: 6f 74 46 6c 61 67 73 7d 20 7b 0a 09 09 09 63 6f  otFlags} {....co
1880: 6e 74 69 6e 75 65 0a 09 09 7d 0a 0a 09 09 69 66  ntinue...}....if
1890: 20 7b 22 54 4f 4b 45 4e 5f 49 4e 49 54 49 41 4c   {"TOKEN_INITIAL
18a0: 49 5a 45 44 22 20 6e 69 20 24 73 6c 6f 74 46 6c  IZED" ni $slotFl
18b0: 61 67 73 7d 20 7b 0a 09 09 09 63 6f 6e 74 69 6e  ags} {....contin
18c0: 75 65 0a 09 09 7d 0a 0a 09 09 73 65 74 20 73 6c  ue...}....set sl
18d0: 6f 74 50 72 6f 6d 70 74 46 6f 72 50 49 4e 20 66  otPromptForPIN f
18e0: 61 6c 73 65 0a 09 09 69 66 20 7b 22 50 52 4f 54  alse...if {"PROT
18f0: 45 43 54 45 44 5f 41 55 54 48 45 4e 54 49 43 41  ECTED_AUTHENTICA
1900: 54 49 4f 4e 5f 50 41 54 48 22 20 6e 69 20 24 73  TION_PATH" ni $s
1910: 6c 6f 74 46 6c 61 67 73 7d 20 7b 0a 09 09 09 69  lotFlags} {....i
1920: 66 20 7b 22 4c 4f 47 49 4e 5f 52 45 51 55 49 52  f {"LOGIN_REQUIR
1930: 45 44 22 20 69 6e 20 24 73 6c 6f 74 46 6c 61 67  ED" in $slotFlag
1940: 73 7d 20 7b 0a 09 09 09 09 73 65 74 20 73 6c 6f  s} {.....set slo
1950: 74 50 72 6f 6d 70 74 46 6f 72 50 49 4e 20 74 72  tPromptForPIN tr
1960: 75 65 0a 09 09 09 7d 0a 09 09 7d 0a 0a 09 09 66  ue....}...}....f
1970: 6f 72 65 61 63 68 20 63 65 72 74 20 5b 3a 3a 70  oreach cert [::p
1980: 6b 69 3a 3a 70 6b 63 73 31 31 3a 3a 6c 69 73 74  ki::pkcs11::list
1990: 63 65 72 74 73 20 24 68 61 6e 64 6c 65 20 24 73  certs $handle $s
19a0: 6c 6f 74 49 44 5d 20 7b 0a 09 09 09 73 65 74 20  lotID] {....set 
19b0: 70 75 62 6b 65 79 20 5b 62 69 6e 61 72 79 20 65  pubkey [binary e
19c0: 6e 63 6f 64 65 20 62 61 73 65 36 34 20 5b 64 69  ncode base64 [di
19d0: 63 74 20 67 65 74 20 5b 3a 3a 70 6b 69 3a 3a 72  ct get [::pki::r
19e0: 73 61 3a 3a 73 65 72 69 61 6c 69 7a 65 5f 70 75  sa::serialize_pu
19f0: 62 6c 69 63 5f 6b 65 79 20 24 63 65 72 74 5d 20  blic_key $cert] 
1a00: 64 61 74 61 5d 5d 0a 0a 09 09 09 6c 61 70 70 65  data]].....lappe
1a10: 6e 64 20 73 6c 6f 74 49 6e 66 6f 20 5b 6c 69 73  nd slotInfo [lis
1a20: 74 20 68 61 6e 64 6c 65 20 24 68 61 6e 64 6c 65  t handle $handle
1a30: 20 69 64 20 24 73 6c 6f 74 49 44 20 70 72 6f 6d   id $slotID prom
1a40: 70 74 20 24 73 6c 6f 74 50 72 6f 6d 70 74 46 6f  pt $slotPromptFo
1a50: 72 50 49 4e 20 63 65 72 74 20 24 63 65 72 74 20  rPIN cert $cert 
1a60: 70 75 62 6b 65 79 20 24 70 75 62 6b 65 79 5d 0a  pubkey $pubkey].
1a70: 09 09 7d 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 20  ..}..}...return 
1a80: 24 73 6c 6f 74 49 6e 66 6f 0a 7d 0a 0a 70 72 6f  $slotInfo.}..pro
1a90: 63 20 5f 76 65 72 69 66 79 50 61 73 73 77 6f 72  c _verifyPasswor
1aa0: 64 20 7b 6e 61 6d 65 20 70 61 73 73 77 6f 72 64  d {name password
1ab0: 7d 20 7b 0a 09 73 65 74 20 70 75 62 6c 69 63 4b  } {..set publicK
1ac0: 65 79 73 20 5b 6c 69 73 74 5d 0a 0a 09 64 62 20  eys [list]...db 
1ad0: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 70 75 62  eval {SELECT pub
1ae0: 6c 69 63 4b 65 79 2c 20 76 65 72 69 66 69 63 61  licKey, verifica
1af0: 74 69 6f 6e 20 46 52 4f 4d 20 70 61 73 73 77 6f  tion FROM passwo
1b00: 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d  rds WHERE name =
1b10: 20 24 6e 61 6d 65 7d 20 72 6f 77 20 7b 0a 09 09   $name} row {...
1b20: 73 65 74 20 73 61 6c 74 20 5b 64 69 63 74 20 67  set salt [dict g
1b30: 65 74 20 24 72 6f 77 28 76 65 72 69 66 69 63 61  et $row(verifica
1b40: 74 69 6f 6e 29 20 73 61 6c 74 5d 0a 09 09 73 65  tion) salt]...se
1b50: 74 20 68 61 73 68 41 6c 67 6f 72 69 74 68 6d 20  t hashAlgorithm 
1b60: 5b 64 69 63 74 20 67 65 74 20 24 72 6f 77 28 76  [dict get $row(v
1b70: 65 72 69 66 69 63 61 74 69 6f 6e 29 20 68 61 73  erification) has
1b80: 68 41 6c 67 6f 72 69 74 68 6d 5d 0a 09 09 73 65  hAlgorithm]...se
1b90: 74 20 70 75 62 6c 69 63 4b 65 79 20 24 72 6f 77  t publicKey $row
1ba0: 28 70 75 62 6c 69 63 4b 65 79 29 0a 0a 09 09 73  (publicKey)....s
1bb0: 65 74 20 70 6c 61 69 6e 74 65 78 74 20 22 24 7b  et plaintext "${
1bc0: 73 61 6c 74 7d 7c 24 7b 70 75 62 6c 69 63 4b 65  salt}|${publicKe
1bd0: 79 7d 7c 24 7b 70 61 73 73 77 6f 72 64 7d 22 0a  y}|${password}".
1be0: 0a 09 09 73 77 69 74 63 68 20 2d 2d 20 24 68 61  ...switch -- $ha
1bf0: 73 68 41 6c 67 6f 72 69 74 68 6d 20 7b 0a 09 09  shAlgorithm {...
1c00: 09 22 73 68 61 32 35 36 22 20 7b 0a 09 09 09 09  ."sha256" {.....
1c10: 73 65 74 20 76 65 72 69 66 69 63 61 74 69 6f 6e  set verification
1c20: 48 61 73 68 20 5b 73 68 61 32 3a 3a 73 68 61 32  Hash [sha2::sha2
1c30: 35 36 20 2d 68 65 78 20 2d 2d 20 24 70 6c 61 69  56 -hex -- $plai
1c40: 6e 74 65 78 74 5d 0a 09 09 09 7d 0a 09 09 09 64  ntext]....}....d
1c50: 65 66 61 75 6c 74 20 7b 0a 09 09 09 09 72 65 74  efault {.....ret
1c60: 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20  urn -code error 
1c70: 22 55 6e 6b 6e 6f 77 6e 20 68 61 73 68 69 6e 67  "Unknown hashing
1c80: 20 61 6c 67 6f 72 69 74 68 6d 3a 20 24 68 61 73   algorithm: $has
1c90: 68 41 6c 67 6f 72 69 74 68 6d 22 0a 09 09 09 7d  hAlgorithm"....}
1ca0: 0a 09 09 7d 0a 0a 09 09 73 65 74 20 72 6f 77 28  ...}....set row(
1cb0: 76 65 72 69 66 69 63 61 74 69 6f 6e 48 61 73 68  verificationHash
1cc0: 29 20 5b 64 69 63 74 20 67 65 74 20 24 72 6f 77  ) [dict get $row
1cd0: 28 76 65 72 69 66 69 63 61 74 69 6f 6e 29 20 68  (verification) h
1ce0: 61 73 68 5d 0a 0a 09 09 69 66 20 7b 24 76 65 72  ash]....if {$ver
1cf0: 69 66 69 63 61 74 69 6f 6e 48 61 73 68 20 6e 65  ificationHash ne
1d00: 20 24 72 6f 77 28 76 65 72 69 66 69 63 61 74 69   $row(verificati
1d10: 6f 6e 48 61 73 68 29 7d 20 7b 0a 09 09 09 72 65  onHash)} {....re
1d20: 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72  turn -code error
1d30: 20 22 46 41 49 4c 45 44 3a 20 76 65 72 69 66 69   "FAILED: verifi
1d40: 63 61 74 69 6f 6e 20 66 61 69 6c 65 64 20 66 6f  cation failed fo
1d50: 72 20 24 6e 61 6d 65 20 77 69 74 68 20 70 75 62  r $name with pub
1d60: 6c 69 63 20 6b 65 79 20 24 70 75 62 6c 69 63 4b  lic key $publicK
1d70: 65 79 20 2d 2d 20 69 74 20 77 69 6c 6c 20 6e 6f  ey -- it will no
1d80: 74 20 67 65 74 20 74 68 65 20 6e 65 77 20 70 61  t get the new pa
1d90: 73 73 77 6f 72 64 2e 22 0a 0a 09 09 09 63 6f 6e  ssword.".....con
1da0: 74 69 6e 75 65 0a 09 09 7d 0a 0a 09 09 6c 61 70  tinue...}....lap
1db0: 70 65 6e 64 20 70 75 62 6c 69 63 4b 65 79 73 20  pend publicKeys 
1dc0: 24 70 75 62 6c 69 63 4b 65 79 0a 09 7d 0a 0a 09  $publicKey..}...
1dd0: 72 65 74 75 72 6e 20 24 70 75 62 6c 69 63 4b 65  return $publicKe
1de0: 79 73 0a 7d 0a 0a 70 72 6f 63 20 5f 61 64 64 50  ys.}..proc _addP
1df0: 61 73 73 77 6f 72 64 20 7b 6e 61 6d 65 20 70 61  assword {name pa
1e00: 73 73 77 6f 72 64 20 70 75 62 6c 69 63 4b 65 79  ssword publicKey
1e10: 73 7d 20 7b 0a 09 73 65 74 20 66 64 20 5b 6f 70  s} {..set fd [op
1e20: 65 6e 20 22 2f 64 65 76 2f 75 72 61 6e 64 6f 6d  en "/dev/urandom
1e30: 22 20 72 5d 0a 09 66 63 6f 6e 66 69 67 75 72 65  " r]..fconfigure
1e40: 20 24 66 64 20 2d 74 72 61 6e 73 6c 61 74 69 6f   $fd -translatio
1e50: 6e 20 62 69 6e 61 72 79 0a 0a 09 73 65 74 20 6b  n binary...set k
1e60: 65 79 53 69 7a 65 20 31 36 0a 0a 09 23 20 50 61  eySize 16...# Pa
1e70: 64 20 74 68 65 20 70 61 73 73 77 6f 72 64 20 77  d the password w
1e80: 69 74 68 20 30 20 62 79 74 65 73 20 75 6e 74 69  ith 0 bytes unti
1e90: 6c 20 69 74 20 69 73 20 61 20 6d 75 6c 74 69 70  l it is a multip
1ea0: 6c 65 20 6f 66 20 74 68 65 20 6b 65 79 20 73 69  le of the key si
1eb0: 7a 65 0a 09 73 65 74 20 62 6c 6f 63 6b 50 61 73  ze..set blockPas
1ec0: 73 77 6f 72 64 20 24 70 61 73 73 77 6f 72 64 0a  sword $password.
1ed0: 09 61 70 70 65 6e 64 20 62 6c 6f 63 6b 50 61 73  .append blockPas
1ee0: 73 77 6f 72 64 20 5b 73 74 72 69 6e 67 20 72 65  sword [string re
1ef0: 70 65 61 74 20 22 5c 78 30 30 22 20 5b 65 78 70  peat "\x00" [exp
1f00: 72 20 7b 2d 5b 73 74 72 69 6e 67 20 6c 65 6e 67  r {-[string leng
1f10: 74 68 20 24 70 61 73 73 77 6f 72 64 5d 20 25 20  th $password] % 
1f20: 24 6b 65 79 53 69 7a 65 7d 5d 5d 0a 0a 09 64 62  $keySize}]]...db
1f30: 20 74 72 61 6e 73 61 63 74 69 6f 6e 20 7b 0a 09   transaction {..
1f40: 09 64 62 20 65 76 61 6c 20 7b 44 45 4c 45 54 45  .db eval {DELETE
1f50: 20 46 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20   FROM passwords 
1f60: 57 48 45 52 45 20 6e 61 6d 65 20 3d 20 24 6e 61  WHERE name = $na
1f70: 6d 65 3b 7d 0a 0a 09 09 66 6f 72 65 61 63 68 20  me;}....foreach 
1f80: 70 75 62 6c 69 63 4b 65 79 20 24 70 75 62 6c 69  publicKey $publi
1f90: 63 4b 65 79 73 20 7b 0a 09 09 09 73 65 74 20 6b  cKeys {....set k
1fa0: 65 79 20 5b 72 65 61 64 20 24 66 64 20 24 6b 65  ey [read $fd $ke
1fb0: 79 53 69 7a 65 5d 0a 09 09 09 69 66 20 7b 5b 73  ySize]....if {[s
1fc0: 74 72 69 6e 67 20 6c 65 6e 67 74 68 20 24 6b 65  tring length $ke
1fd0: 79 5d 20 21 3d 20 24 6b 65 79 53 69 7a 65 7d 20  y] != $keySize} 
1fe0: 7b 0a 09 09 09 09 63 6c 6f 73 65 20 24 66 64 0a  {.....close $fd.
1ff0: 0a 09 09 09 09 72 65 74 75 72 6e 20 2d 63 6f 64  .....return -cod
2000: 65 20 65 72 72 6f 72 20 22 45 52 52 4f 52 3a 20  e error "ERROR: 
2010: 53 68 6f 72 74 20 72 65 61 64 20 66 72 6f 6d 20  Short read from 
2020: 72 61 6e 64 6f 6d 20 64 65 76 69 63 65 22 0a 09  random device"..
2030: 09 09 7d 0a 0a 09 09 09 73 65 74 20 73 61 6c 74  ..}.....set salt
2040: 20 5b 72 65 61 64 20 24 66 64 20 24 6b 65 79 53   [read $fd $keyS
2050: 69 7a 65 5d 0a 09 09 09 73 65 74 20 73 61 6c 74  ize]....set salt
2060: 20 5b 62 69 6e 61 72 79 20 65 6e 63 6f 64 65 20   [binary encode 
2070: 62 61 73 65 36 34 20 24 73 61 6c 74 5d 0a 0a 09  base64 $salt]...
2080: 09 09 73 65 74 20 70 75 62 6c 69 63 4b 65 79 49  ..set publicKeyI
2090: 74 65 6d 20 5b 3a 3a 70 6b 69 3a 3a 70 6b 63 73  tem [::pki::pkcs
20a0: 3a 3a 70 61 72 73 65 5f 70 75 62 6c 69 63 5f 6b  ::parse_public_k
20b0: 65 79 20 5b 62 69 6e 61 72 79 20 64 65 63 6f 64  ey [binary decod
20c0: 65 20 62 61 73 65 36 34 20 24 70 75 62 6c 69 63  e base64 $public
20d0: 4b 65 79 5d 5d 0a 0a 09 09 09 73 65 74 20 65 6e  Key]].....set en
20e0: 63 72 79 70 74 65 64 4b 65 79 20 5b 62 69 6e 61  cryptedKey [bina
20f0: 72 79 20 65 6e 63 6f 64 65 20 62 61 73 65 36 34  ry encode base64
2100: 20 5b 3a 3a 70 6b 69 3a 3a 65 6e 63 72 79 70 74   [::pki::encrypt
2110: 20 2d 70 75 62 20 2d 62 69 6e 61 72 79 20 2d 2d   -pub -binary --
2120: 20 24 6b 65 79 20 24 70 75 62 6c 69 63 4b 65 79   $key $publicKey
2130: 49 74 65 6d 5d 5d 0a 0a 09 09 09 73 65 74 20 65  Item]].....set e
2140: 6e 63 72 79 70 74 65 64 50 61 73 73 20 5b 62 69  ncryptedPass [bi
2150: 6e 61 72 79 20 65 6e 63 6f 64 65 20 62 61 73 65  nary encode base
2160: 36 34 20 5b 3a 3a 61 65 73 3a 3a 61 65 73 20 2d  64 [::aes::aes -
2170: 64 69 72 20 65 6e 63 72 79 70 74 20 2d 6b 65 79  dir encrypt -key
2180: 20 24 6b 65 79 20 2d 2d 20 24 62 6c 6f 63 6b 50   $key -- $blockP
2190: 61 73 73 77 6f 72 64 5d 5d 0a 0a 09 09 09 73 65  assword]].....se
21a0: 74 20 76 65 72 69 66 69 63 61 74 69 6f 6e 48 61  t verificationHa
21b0: 73 68 20 5b 73 68 61 32 3a 3a 73 68 61 32 35 36  sh [sha2::sha256
21c0: 20 2d 68 65 78 20 2d 2d 20 22 24 7b 73 61 6c 74   -hex -- "${salt
21d0: 7d 7c 24 7b 70 75 62 6c 69 63 4b 65 79 7d 7c 24  }|${publicKey}|$
21e0: 7b 70 61 73 73 77 6f 72 64 7d 22 5d 0a 09 09 09  {password}"]....
21f0: 73 65 74 20 76 65 72 69 66 69 63 61 74 69 6f 6e  set verification
2200: 20 5b 6c 69 73 74 20 73 61 6c 74 20 24 73 61 6c   [list salt $sal
2210: 74 20 68 61 73 68 41 6c 67 6f 72 69 74 68 6d 20  t hashAlgorithm 
2220: 73 68 61 32 35 36 20 68 61 73 68 20 24 76 65 72  sha256 hash $ver
2230: 69 66 69 63 61 74 69 6f 6e 48 61 73 68 5d 0a 0a  ificationHash]..
2240: 09 09 09 64 62 20 65 76 61 6c 20 7b 49 4e 53 45  ...db eval {INSE
2250: 52 54 20 49 4e 54 4f 20 70 61 73 73 77 6f 72 64  RT INTO password
2260: 73 20 28 6e 61 6d 65 2c 20 65 6e 63 72 79 70 74  s (name, encrypt
2270: 65 64 50 61 73 73 2c 20 65 6e 63 72 79 70 74 65  edPass, encrypte
2280: 64 4b 65 79 2c 20 70 75 62 6c 69 63 4b 65 79 2c  dKey, publicKey,
2290: 20 76 65 72 69 66 69 63 61 74 69 6f 6e 29 20 56   verification) V
22a0: 41 4c 55 45 53 20 28 24 6e 61 6d 65 2c 20 40 65  ALUES ($name, @e
22b0: 6e 63 72 79 70 74 65 64 50 61 73 73 2c 20 40 65  ncryptedPass, @e
22c0: 6e 63 72 79 70 74 65 64 4b 65 79 2c 20 40 70 75  ncryptedKey, @pu
22d0: 62 6c 69 63 4b 65 79 2c 20 40 76 65 72 69 66 69  blicKey, @verifi
22e0: 63 61 74 69 6f 6e 29 3b 7d 0a 09 09 7d 0a 09 7d  cation);}...}..}
22f0: 0a 0a 09 63 6c 6f 73 65 20 24 66 64 0a 7d 0a 0a  ...close $fd.}..
2300: 70 72 6f 63 20 5f 70 72 6f 6d 70 74 20 7b 70 72  proc _prompt {pr
2310: 6f 6d 70 74 7d 20 7b 0a 09 70 75 74 73 20 2d 6e  ompt} {..puts -n
2320: 6f 6e 65 77 6c 69 6e 65 20 24 70 72 6f 6d 70 74  onewline $prompt
2330: 0a 09 66 6c 75 73 68 20 73 74 64 6f 75 74 0a 0a  ..flush stdout..
2340: 09 70 75 74 73 20 2d 6e 6f 6e 65 77 6c 69 6e 65  .puts -nonewline
2350: 20 5b 65 78 65 63 20 73 74 74 79 20 2d 65 63 68   [exec stty -ech
2360: 6f 5d 0a 09 66 6c 75 73 68 20 73 74 64 6f 75 74  o]..flush stdout
2370: 0a 0a 09 73 65 74 20 70 61 73 73 77 6f 72 64 20  ...set password 
2380: 5b 67 65 74 73 20 73 74 64 69 6e 5d 0a 0a 09 70  [gets stdin]...p
2390: 75 74 73 20 2d 6e 6f 6e 65 77 6c 69 6e 65 20 5b  uts -nonewline [
23a0: 65 78 65 63 20 73 74 74 79 20 65 63 68 6f 5d 0a  exec stty echo].
23b0: 09 70 75 74 73 20 22 22 0a 09 66 6c 75 73 68 20  .puts ""..flush 
23c0: 73 74 64 6f 75 74 0a 0a 09 72 65 74 75 72 6e 20  stdout...return 
23d0: 24 70 61 73 73 77 6f 72 64 0a 7d 0a 0a 70 72 6f  $password.}..pro
23e0: 63 20 5f 67 65 74 50 61 73 73 77 6f 72 64 20 7b  c _getPassword {
23f0: 6e 61 6d 65 7d 20 7b 0a 09 73 65 74 20 65 78 69  name} {..set exi
2400: 73 74 73 20 5b 64 62 20 65 76 61 6c 20 7b 53 45  sts [db eval {SE
2410: 4c 45 43 54 20 31 20 46 52 4f 4d 20 70 61 73 73  LECT 1 FROM pass
2420: 77 6f 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65  words WHERE name
2430: 20 3d 20 24 6e 61 6d 65 20 4c 49 4d 49 54 20 31   = $name LIMIT 1
2440: 3b 7d 5d 0a 09 69 66 20 7b 24 65 78 69 73 74 73  ;}]..if {$exists
2450: 20 21 3d 20 22 31 22 7d 20 7b 0a 09 09 72 65 74   != "1"} {...ret
2460: 75 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20  urn -code error 
2470: 22 50 61 73 73 77 6f 72 64 20 5c 22 24 6e 61 6d  "Password \"$nam
2480: 65 5c 22 20 64 6f 65 73 20 6e 6f 74 20 65 78 69  e\" does not exi
2490: 73 74 73 2e 22 0a 09 7d 0a 0a 09 66 6f 72 65 61  sts."..}...forea
24a0: 63 68 20 73 6c 6f 74 49 6e 66 6f 44 69 63 74 20  ch slotInfoDict 
24b0: 5b 5f 6c 69 73 74 43 65 72 74 69 66 69 63 61 74  [_listCertificat
24c0: 65 73 5d 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e  es] {...unset -n
24d0: 6f 63 6f 6d 70 6c 61 69 6e 20 73 6c 6f 74 49 6e  ocomplain slotIn
24e0: 66 6f 0a 09 09 61 72 72 61 79 20 73 65 74 20 73  fo...array set s
24f0: 6c 6f 74 49 6e 66 6f 20 24 73 6c 6f 74 49 6e 66  lotInfo $slotInf
2500: 6f 44 69 63 74 0a 0a 09 09 73 65 74 20 70 75 62  oDict....set pub
2510: 6b 65 79 20 24 73 6c 6f 74 49 6e 66 6f 28 70 75  key $slotInfo(pu
2520: 62 6b 65 79 29 0a 09 09 73 65 74 20 70 72 6f 6d  bkey)...set prom
2530: 70 74 20 24 73 6c 6f 74 49 6e 66 6f 28 70 72 6f  pt $slotInfo(pro
2540: 6d 70 74 29 0a 0a 09 09 69 66 20 7b 5b 69 6e 66  mpt)....if {[inf
2550: 6f 20 65 78 69 73 74 73 20 70 72 6f 6d 70 74 65  o exists prompte
2560: 64 28 24 73 6c 6f 74 49 6e 66 6f 28 69 64 29 29  d($slotInfo(id))
2570: 5d 7d 20 7b 0a 09 09 09 73 65 74 20 70 72 6f 6d  ]} {....set prom
2580: 70 74 20 66 61 6c 73 65 0a 09 09 7d 0a 0a 09 09  pt false...}....
2590: 69 66 20 7b 24 70 72 6f 6d 70 74 7d 20 7b 0a 09  if {$prompt} {..
25a0: 09 09 73 65 74 20 50 49 4e 20 5b 5f 70 72 6f 6d  ..set PIN [_prom
25b0: 70 74 20 22 50 6c 65 61 73 65 20 65 6e 74 65 72  pt "Please enter
25c0: 20 74 68 65 20 50 49 4e 20 66 6f 72 20 5b 64 69   the PIN for [di
25d0: 63 74 20 67 65 74 20 24 73 6c 6f 74 49 6e 66 6f  ct get $slotInfo
25e0: 28 63 65 72 74 29 20 73 75 62 6a 65 63 74 5d 3a  (cert) subject]:
25f0: 20 22 5d 0a 0a 09 09 09 69 66 20 7b 21 5b 3a 3a   "].....if {![::
2600: 70 6b 69 3a 3a 70 6b 63 73 31 31 3a 3a 6c 6f 67  pki::pkcs11::log
2610: 69 6e 20 24 73 6c 6f 74 49 6e 66 6f 28 68 61 6e  in $slotInfo(han
2620: 64 6c 65 29 20 24 73 6c 6f 74 49 6e 66 6f 28 69  dle) $slotInfo(i
2630: 64 29 20 24 50 49 4e 5d 7d 20 7b 0a 09 09 09 09  d) $PIN]} {.....
2640: 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72 72  return -code err
2650: 6f 72 20 22 55 6e 61 62 6c 65 20 74 6f 20 61 75  or "Unable to au
2660: 74 68 65 6e 74 69 63 61 74 65 22 0a 09 09 09 7d  thenticate"....}
2670: 0a 0a 09 09 09 73 65 74 20 70 72 6f 6d 70 74 65  .....set prompte
2680: 64 28 24 73 6c 6f 74 49 6e 66 6f 28 69 64 29 29  d($slotInfo(id))
2690: 20 31 0a 09 09 7d 0a 0a 09 09 64 62 20 65 76 61   1...}....db eva
26a0: 6c 20 7b 53 45 4c 45 43 54 20 65 6e 63 72 79 70  l {SELECT encryp
26b0: 74 65 64 50 61 73 73 2c 20 65 6e 63 72 79 70 74  tedPass, encrypt
26c0: 65 64 4b 65 79 20 46 52 4f 4d 20 70 61 73 73 77  edKey FROM passw
26d0: 6f 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20  ords WHERE name 
26e0: 3d 20 24 6e 61 6d 65 20 41 4e 44 20 70 75 62 6c  = $name AND publ
26f0: 69 63 4b 65 79 20 3d 20 24 70 75 62 6b 65 79 3b  icKey = $pubkey;
2700: 7d 20 72 6f 77 20 7b 0a 09 09 09 73 65 74 20 6b  } row {....set k
2710: 65 79 20 5b 3a 3a 70 6b 69 3a 3a 64 65 63 72 79  ey [::pki::decry
2720: 70 74 20 2d 62 69 6e 61 72 79 20 2d 70 72 69 76  pt -binary -priv
2730: 20 2d 2d 20 5b 62 69 6e 61 72 79 20 64 65 63 6f   -- [binary deco
2740: 64 65 20 62 61 73 65 36 34 20 24 72 6f 77 28 65  de base64 $row(e
2750: 6e 63 72 79 70 74 65 64 4b 65 79 29 5d 20 24 73  ncryptedKey)] $s
2760: 6c 6f 74 49 6e 66 6f 28 63 65 72 74 29 5d 0a 09  lotInfo(cert)]..
2770: 09 09 73 65 74 20 70 61 73 73 77 6f 72 64 20 5b  ..set password [
2780: 3a 3a 61 65 73 3a 3a 61 65 73 20 2d 64 69 72 20  ::aes::aes -dir 
2790: 64 65 63 72 79 70 74 20 2d 6b 65 79 20 24 6b 65  decrypt -key $ke
27a0: 79 20 2d 2d 20 5b 62 69 6e 61 72 79 20 64 65 63  y -- [binary dec
27b0: 6f 64 65 20 62 61 73 65 36 34 20 24 72 6f 77 28  ode base64 $row(
27c0: 65 6e 63 72 79 70 74 65 64 50 61 73 73 29 5d 5d  encryptedPass)]]
27d0: 0a 0a 09 09 09 72 65 74 75 72 6e 20 5b 73 74 72  .....return [str
27e0: 69 6e 67 20 74 72 69 6d 72 69 67 68 74 20 24 70  ing trimright $p
27f0: 61 73 73 77 6f 72 64 20 22 5c 78 30 30 22 5d 0a  assword "\x00"].
2800: 09 09 7d 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 20  ..}..}...return 
2810: 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 4e 6f 20  -code error "No 
2820: 76 61 6c 69 64 20 6b 65 79 73 22 0a 7d 0a 0a 70  valid keys".}..p
2830: 72 6f 63 20 5f 6d 6f 64 69 66 79 50 75 62 6c 69  roc _modifyPubli
2840: 63 4b 65 79 73 20 7b 70 61 73 73 77 6f 72 64 4e  cKeys {passwordN
2850: 61 6d 65 20 75 73 65 72 4e 61 6d 65 73 20 73 71  ame userNames sq
2860: 6c 7d 20 7b 0a 09 73 65 74 20 65 78 69 73 74 73  l} {..set exists
2870: 20 5b 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43   [db eval {SELEC
2880: 54 20 31 20 46 52 4f 4d 20 70 61 73 73 77 6f 72  T 1 FROM passwor
2890: 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20  ds WHERE name = 
28a0: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 4c 49  $passwordName LI
28b0: 4d 49 54 20 31 3b 7d 5d 0a 09 69 66 20 7b 24 65  MIT 1;}]..if {$e
28c0: 78 69 73 74 73 20 21 3d 20 22 31 22 7d 20 7b 0a  xists != "1"} {.
28d0: 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65  ..return -code e
28e0: 72 72 6f 72 20 22 50 61 73 73 77 6f 72 64 20 5c  rror "Password \
28f0: 22 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5c 22  "$passwordName\"
2900: 20 64 6f 65 73 20 6e 6f 74 20 65 78 69 73 74 73   does not exists
2910: 2e 22 0a 09 7d 0a 0a 09 73 65 74 20 70 75 62 6c  ."..}...set publ
2920: 69 63 4b 65 79 73 20 5b 6c 69 73 74 5d 0a 0a 09  icKeys [list]...
2930: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20  db eval {SELECT 
2940: 70 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d 20 70  publicKey FROM p
2950: 61 73 73 77 6f 72 64 73 20 57 48 45 52 45 20 6e  asswords WHERE n
2960: 61 6d 65 20 3d 20 24 70 61 73 73 77 6f 72 64 4e  ame = $passwordN
2970: 61 6d 65 3b 7d 20 72 6f 77 20 7b 0a 09 09 6c 61  ame;} row {...la
2980: 70 70 65 6e 64 20 70 75 62 6c 69 63 4b 65 79 73  ppend publicKeys
2990: 20 24 72 6f 77 28 70 75 62 6c 69 63 4b 65 79 29   $row(publicKey)
29a0: 0a 09 7d 0a 0a 09 73 65 74 20 63 68 61 6e 67 65  ..}...set change
29b0: 52 65 71 75 69 72 65 64 20 30 0a 09 66 6f 72 65  Required 0..fore
29c0: 61 63 68 20 75 73 65 72 20 24 75 73 65 72 4e 61  ach user $userNa
29d0: 6d 65 73 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e  mes {...unset -n
29e0: 6f 63 6f 6d 70 6c 61 69 6e 20 72 6f 77 0a 09 09  ocomplain row...
29f0: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20  db eval {SELECT 
2a00: 70 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d 20 75  publicKey FROM u
2a10: 73 65 72 73 20 57 48 45 52 45 20 6e 61 6d 65 20  sers WHERE name 
2a20: 3d 20 24 75 73 65 72 3b 7d 20 72 6f 77 20 24 73  = $user;} row $s
2a30: 71 6c 0a 09 7d 0a 0a 09 69 66 20 7b 21 24 63 68  ql..}...if {!$ch
2a40: 61 6e 67 65 52 65 71 75 69 72 65 64 7d 20 7b 0a  angeRequired} {.
2a50: 09 09 72 65 74 75 72 6e 0a 09 7d 0a 0a 09 73 65  ..return..}...se
2a60: 74 20 70 61 73 73 77 6f 72 64 20 5b 5f 67 65 74  t password [_get
2a70: 50 61 73 73 77 6f 72 64 20 24 70 61 73 73 77 6f  Password $passwo
2a80: 72 64 4e 61 6d 65 5d 0a 0a 09 5f 61 64 64 50 61  rdName]..._addPa
2a90: 73 73 77 6f 72 64 20 24 70 61 73 73 77 6f 72 64  ssword $password
2aa0: 4e 61 6d 65 20 24 70 61 73 73 77 6f 72 64 20 24  Name $password $
2ab0: 70 75 62 6c 69 63 4b 65 79 73 0a 7d 0a 0a 70 72  publicKeys.}..pr
2ac0: 6f 63 20 5f 67 65 74 55 73 65 72 73 46 6f 72 50  oc _getUsersForP
2ad0: 61 73 73 77 6f 72 64 20 7b 70 61 73 73 77 6f 72  assword {passwor
2ae0: 64 4e 61 6d 65 73 7d 20 7b 0a 09 73 65 74 20 75  dNames} {..set u
2af0: 73 65 72 4e 61 6d 65 73 20 5b 6c 69 73 74 5d 0a  serNames [list].
2b00: 0a 09 66 6f 72 65 61 63 68 20 70 61 73 73 77 6f  ..foreach passwo
2b10: 72 64 4e 61 6d 65 20 24 70 61 73 73 77 6f 72 64  rdName $password
2b20: 4e 61 6d 65 73 20 7b 0a 09 09 64 62 20 65 76 61  Names {...db eva
2b30: 6c 20 7b 53 45 4c 45 43 54 20 70 75 62 6c 69 63  l {SELECT public
2b40: 4b 65 79 20 46 52 4f 4d 20 70 61 73 73 77 6f 72  Key FROM passwor
2b50: 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d 20  ds WHERE name = 
2b60: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 3b 7d 20  $passwordName;} 
2b70: 70 61 73 73 77 6f 72 64 52 6f 77 20 7b 0a 09 09  passwordRow {...
2b80: 09 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54  .db eval {SELECT
2b90: 20 6e 61 6d 65 20 46 52 4f 4d 20 75 73 65 72 73   name FROM users
2ba0: 20 57 48 45 52 45 20 70 75 62 6c 69 63 4b 65 79   WHERE publicKey
2bb0: 20 3d 20 24 70 61 73 73 77 6f 72 64 52 6f 77 28   = $passwordRow(
2bc0: 70 75 62 6c 69 63 4b 65 79 29 7d 20 75 73 65 72  publicKey)} user
2bd0: 52 6f 77 20 7b 0a 09 09 09 09 69 66 20 7b 24 75  Row {.....if {$u
2be0: 73 65 72 52 6f 77 28 6e 61 6d 65 29 20 69 6e 20  serRow(name) in 
2bf0: 24 75 73 65 72 4e 61 6d 65 73 7d 20 7b 0a 09 09  $userNames} {...
2c00: 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 09 09  ...continue.....
2c10: 7d 0a 0a 09 09 09 09 6c 61 70 70 65 6e 64 20 75  }......lappend u
2c20: 73 65 72 4e 61 6d 65 73 20 24 75 73 65 72 52 6f  serNames $userRo
2c30: 77 28 6e 61 6d 65 29 0a 09 09 09 7d 0a 09 09 7d  w(name)....}...}
2c40: 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 20 24 75 73  ..}...return $us
2c50: 65 72 4e 61 6d 65 73 0a 7d 0a 0a 70 72 6f 63 20  erNames.}..proc 
2c60: 5f 67 65 74 50 61 73 73 77 6f 72 64 73 46 6f 72  _getPasswordsFor
2c70: 55 73 65 72 20 7b 75 73 65 72 4e 61 6d 65 73 7d  User {userNames}
2c80: 20 7b 0a 09 73 65 74 20 70 61 73 73 77 6f 72 64   {..set password
2c90: 4e 61 6d 65 73 20 5b 6c 69 73 74 5d 0a 0a 09 66  Names [list]...f
2ca0: 6f 72 65 61 63 68 20 75 73 65 72 4e 61 6d 65 20  oreach userName 
2cb0: 24 75 73 65 72 4e 61 6d 65 73 20 7b 0a 09 09 64  $userNames {...d
2cc0: 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 70  b eval {SELECT p
2cd0: 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d 20 75 73  ublicKey FROM us
2ce0: 65 72 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d  ers WHERE name =
2cf0: 20 24 75 73 65 72 4e 61 6d 65 3b 7d 20 75 73 65   $userName;} use
2d00: 72 52 6f 77 20 7b 0a 09 09 09 64 62 20 65 76 61  rRow {....db eva
2d10: 6c 20 7b 53 45 4c 45 43 54 20 6e 61 6d 65 20 46  l {SELECT name F
2d20: 52 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48  ROM passwords WH
2d30: 45 52 45 20 70 75 62 6c 69 63 4b 65 79 20 3d 20  ERE publicKey = 
2d40: 24 75 73 65 72 52 6f 77 28 70 75 62 6c 69 63 4b  $userRow(publicK
2d50: 65 79 29 7d 20 70 61 73 73 77 6f 72 64 52 6f 77  ey)} passwordRow
2d60: 20 7b 0a 09 09 09 09 69 66 20 7b 24 70 61 73 73   {.....if {$pass
2d70: 77 6f 72 64 52 6f 77 28 6e 61 6d 65 29 20 69 6e  wordRow(name) in
2d80: 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 73 7d   $passwordNames}
2d90: 20 7b 0a 09 09 09 09 09 63 6f 6e 74 69 6e 75 65   {......continue
2da0: 0a 09 09 09 09 7d 0a 0a 09 09 09 09 6c 61 70 70  .....}......lapp
2db0: 65 6e 64 20 70 61 73 73 77 6f 72 64 4e 61 6d 65  end passwordName
2dc0: 73 20 24 70 61 73 73 77 6f 72 64 52 6f 77 28 6e  s $passwordRow(n
2dd0: 61 6d 65 29 0a 09 09 09 7d 0a 09 09 7d 0a 09 7d  ame)....}...}..}
2de0: 0a 0a 09 72 65 74 75 72 6e 20 24 70 61 73 73 77  ...return $passw
2df0: 6f 72 64 4e 61 6d 65 73 0a 7d 0a 23 20 45 6e 64  ordNames.}.# End
2e00: 20 69 6e 74 65 72 6e 61 6c 20 66 75 6e 63 74 69   internal functi
2e10: 6f 6e 73 0a 0a 23 20 53 74 61 72 74 20 75 73 65  ons..# Start use
2e20: 72 20 43 4c 49 20 66 75 6e 63 74 69 6f 6e 73 0a  r CLI functions.
2e30: 70 72 6f 63 20 6c 69 73 74 4c 6f 63 61 6c 4b 65  proc listLocalKe
2e40: 79 73 20 7b 7d 20 7b 0a 09 66 6f 72 65 61 63 68  ys {} {..foreach
2e50: 20 73 6c 6f 74 49 6e 66 6f 44 69 63 74 20 5b 5f   slotInfoDict [_
2e60: 6c 69 73 74 43 65 72 74 69 66 69 63 61 74 65 73  listCertificates
2e70: 5d 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63  ] {...unset -noc
2e80: 6f 6d 70 6c 61 69 6e 20 73 6c 6f 74 49 6e 66 6f  omplain slotInfo
2e90: 0a 09 09 61 72 72 61 79 20 73 65 74 20 73 6c 6f  ...array set slo
2ea0: 74 49 6e 66 6f 20 24 73 6c 6f 74 49 6e 66 6f 44  tInfo $slotInfoD
2eb0: 69 63 74 0a 0a 09 09 73 65 74 20 73 75 62 6a 65  ict....set subje
2ec0: 63 74 20 5b 64 69 63 74 20 67 65 74 20 24 73 6c  ct [dict get $sl
2ed0: 6f 74 49 6e 66 6f 28 63 65 72 74 29 20 73 75 62  otInfo(cert) sub
2ee0: 6a 65 63 74 5d 0a 09 09 73 65 74 20 70 75 62 6b  ject]...set pubk
2ef0: 65 79 20 20 24 73 6c 6f 74 49 6e 66 6f 28 70 75  ey  $slotInfo(pu
2f00: 62 6b 65 79 29 0a 0a 09 09 6c 61 70 70 65 6e 64  bkey)....lappend
2f10: 20 70 75 62 6c 69 63 4b 65 79 73 28 24 73 75 62   publicKeys($sub
2f20: 6a 65 63 74 29 20 24 70 75 62 6b 65 79 0a 09 7d  ject) $pubkey..}
2f30: 0a 0a 09 66 6f 72 65 61 63 68 20 7b 73 75 62 6a  ...foreach {subj
2f40: 65 63 74 20 70 75 62 6b 65 79 73 7d 20 5b 61 72  ect pubkeys} [ar
2f50: 72 61 79 20 67 65 74 20 70 75 62 6c 69 63 4b 65  ray get publicKe
2f60: 79 73 5d 20 7b 0a 09 09 70 75 74 73 20 22 24 73  ys] {...puts "$s
2f70: 75 62 6a 65 63 74 22 0a 0a 09 09 66 6f 72 65 61  ubject"....forea
2f80: 63 68 20 70 75 62 6b 65 79 20 24 70 75 62 6b 65  ch pubkey $pubke
2f90: 79 73 20 7b 0a 09 09 09 70 75 74 73 20 22 20 20  ys {....puts "  
2fa0: 7c 2d 3e 20 24 70 75 62 6b 65 79 22 0a 09 09 7d  |-> $pubkey"...}
2fb0: 0a 09 7d 0a 7d 0a 0a 70 72 6f 63 20 6c 69 73 74  ..}.}..proc list
2fc0: 41 76 61 69 6c 61 62 6c 65 50 61 73 73 77 6f 72  AvailablePasswor
2fd0: 64 73 20 7b 7d 20 7b 0a 09 73 65 74 20 70 61 73  ds {} {..set pas
2fe0: 73 77 6f 72 64 4e 61 6d 65 73 20 5b 6c 69 73 74  swordNames [list
2ff0: 5d 0a 09 66 6f 72 65 61 63 68 20 73 6c 6f 74 49  ]..foreach slotI
3000: 6e 66 6f 44 69 63 74 20 5b 5f 6c 69 73 74 43 65  nfoDict [_listCe
3010: 72 74 69 66 69 63 61 74 65 73 5d 20 7b 0a 09 09  rtificates] {...
3020: 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61 69  unset -nocomplai
3030: 6e 20 73 6c 6f 74 49 6e 66 6f 0a 09 09 61 72 72  n slotInfo...arr
3040: 61 79 20 73 65 74 20 73 6c 6f 74 49 6e 66 6f 20  ay set slotInfo 
3050: 24 73 6c 6f 74 49 6e 66 6f 44 69 63 74 0a 0a 09  $slotInfoDict...
3060: 09 73 65 74 20 70 75 62 6b 65 79 20 24 73 6c 6f  .set pubkey $slo
3070: 74 49 6e 66 6f 28 70 75 62 6b 65 79 29 0a 0a 09  tInfo(pubkey)...
3080: 09 75 6e 73 65 74 20 2d 6e 6f 63 6f 6d 70 6c 61  .unset -nocompla
3090: 69 6e 20 72 6f 77 0a 09 09 64 62 20 65 76 61 6c  in row...db eval
30a0: 20 7b 53 45 4c 45 43 54 20 6e 61 6d 65 20 46 52   {SELECT name FR
30b0: 4f 4d 20 70 61 73 73 77 6f 72 64 73 20 57 48 45  OM passwords WHE
30c0: 52 45 20 70 75 62 6c 69 63 4b 65 79 20 3d 20 24  RE publicKey = $
30d0: 70 75 62 6b 65 79 3b 7d 20 72 6f 77 20 7b 0a 09  pubkey;} row {..
30e0: 09 09 69 66 20 7b 24 72 6f 77 28 6e 61 6d 65 29  ..if {$row(name)
30f0: 20 69 6e 20 24 70 61 73 73 77 6f 72 64 4e 61 6d   in $passwordNam
3100: 65 73 7d 20 7b 0a 09 09 09 09 63 6f 6e 74 69 6e  es} {.....contin
3110: 75 65 0a 09 09 09 7d 0a 0a 09 09 09 6c 61 70 70  ue....}.....lapp
3120: 65 6e 64 20 70 61 73 73 77 6f 72 64 4e 61 6d 65  end passwordName
3130: 73 20 24 72 6f 77 28 6e 61 6d 65 29 0a 09 09 7d  s $row(name)...}
3140: 0a 09 7d 0a 0a 0a 09 66 6f 72 65 61 63 68 20 70  ..}....foreach p
3150: 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 70 61 73  asswordName $pas
3160: 73 77 6f 72 64 4e 61 6d 65 73 20 7b 0a 09 09 70  swordNames {...p
3170: 75 74 73 20 22 24 70 61 73 73 77 6f 72 64 4e 61  uts "$passwordNa
3180: 6d 65 20 2d 20 5b 6a 6f 69 6e 20 5b 5f 67 65 74  me - [join [_get
3190: 55 73 65 72 73 46 6f 72 50 61 73 73 77 6f 72 64  UsersForPassword
31a0: 20 5b 6c 69 73 74 20 24 70 61 73 73 77 6f 72 64   [list $password
31b0: 4e 61 6d 65 5d 5d 20 7b 2c 20 7d 5d 22 0a 09 7d  Name]] {, }]"..}
31c0: 0a 7d 0a 0a 70 72 6f 63 20 6c 69 73 74 50 61 73  .}..proc listPas
31d0: 73 77 6f 72 64 73 20 7b 7d 20 7b 0a 09 64 62 20  swords {} {..db 
31e0: 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 44 49 53  eval {SELECT DIS
31f0: 54 49 4e 43 54 20 6e 61 6d 65 20 46 52 4f 4d 20  TINCT name FROM 
3200: 70 61 73 73 77 6f 72 64 73 3b 7d 20 72 6f 77 20  passwords;} row 
3210: 7b 0a 09 09 70 75 74 73 20 22 24 72 6f 77 28 6e  {...puts "$row(n
3220: 61 6d 65 29 20 2d 20 5b 6a 6f 69 6e 20 5b 5f 67  ame) - [join [_g
3230: 65 74 55 73 65 72 73 46 6f 72 50 61 73 73 77 6f  etUsersForPasswo
3240: 72 64 20 5b 6c 69 73 74 20 24 72 6f 77 28 6e 61  rd [list $row(na
3250: 6d 65 29 5d 5d 20 7b 2c 20 7d 5d 22 0a 09 7d 0a  me)]] {, }]"..}.
3260: 7d 0a 0a 70 72 6f 63 20 6c 69 73 74 55 73 65 72  }..proc listUser
3270: 73 20 7b 7d 20 7b 0a 09 64 62 20 65 76 61 6c 20  s {} {..db eval 
3280: 7b 53 45 4c 45 43 54 20 44 49 53 54 49 4e 43 54  {SELECT DISTINCT
3290: 20 6e 61 6d 65 20 46 52 4f 4d 20 75 73 65 72 73   name FROM users
32a0: 3b 7d 20 72 6f 77 20 7b 0a 09 09 70 75 74 73 20  ;} row {...puts 
32b0: 22 24 72 6f 77 28 6e 61 6d 65 29 20 2d 20 5b 6a  "$row(name) - [j
32c0: 6f 69 6e 20 5b 5f 67 65 74 50 61 73 73 77 6f 72  oin [_getPasswor
32d0: 64 73 46 6f 72 55 73 65 72 20 5b 6c 69 73 74 20  dsForUser [list 
32e0: 24 72 6f 77 28 6e 61 6d 65 29 5d 5d 20 7b 2c 20  $row(name)]] {, 
32f0: 7d 5d 22 0a 09 7d 0a 7d 0a 0a 70 72 6f 63 20 61  }]"..}.}..proc a
3300: 64 64 55 73 65 72 20 7b 75 73 65 72 4e 61 6d 65  ddUser {userName
3310: 20 6b 65 79 7d 20 7b 0a 09 73 65 74 20 6b 65 79   key} {..set key
3320: 52 61 77 20 5b 62 69 6e 61 72 79 20 64 65 63 6f  Raw [binary deco
3330: 64 65 20 62 61 73 65 36 34 20 24 6b 65 79 5d 0a  de base64 $key].
3340: 09 73 65 74 20 6b 65 79 56 65 72 69 66 79 20 5b  .set keyVerify [
3350: 3a 3a 70 6b 69 3a 3a 70 6b 63 73 3a 3a 70 61 72  ::pki::pkcs::par
3360: 73 65 5f 70 75 62 6c 69 63 5f 6b 65 79 20 24 6b  se_public_key $k
3370: 65 79 52 61 77 5d 0a 0a 09 64 62 20 65 76 61 6c  eyRaw]...db eval
3380: 20 7b 49 4e 53 45 52 54 20 49 4e 54 4f 20 75 73   {INSERT INTO us
3390: 65 72 73 20 28 6e 61 6d 65 2c 20 70 75 62 6c 69  ers (name, publi
33a0: 63 4b 65 79 29 20 56 41 4c 55 45 53 20 28 24 75  cKey) VALUES ($u
33b0: 73 65 72 4e 61 6d 65 2c 20 40 6b 65 79 29 3b 7d  serName, @key);}
33c0: 0a 0a 09 23 20 58 58 58 3a 54 4f 44 4f 3a 47 6f  ...# XXX:TODO:Go
33d0: 20 74 68 72 6f 75 67 68 20 61 6e 64 20 72 65 2d   through and re-
33e0: 61 75 74 68 6f 72 69 7a 65 20 69 66 20 70 6f 73  authorize if pos
33f0: 73 69 62 6c 65 0a 7d 0a 0a 70 72 6f 63 20 64 65  sible.}..proc de
3400: 6c 65 74 65 55 73 65 72 20 7b 75 73 65 72 4e 61  leteUser {userNa
3410: 6d 65 7d 20 7b 0a 09 23 20 58 58 58 3a 54 4f 44  me} {..# XXX:TOD
3420: 4f 3a 20 47 6f 20 74 68 72 6f 75 67 68 20 61 6e  O: Go through an
3430: 64 20 64 65 2d 61 75 74 68 6f 72 69 7a 65 0a 7d  d de-authorize.}
3440: 0a 0a 70 72 6f 63 20 61 64 64 50 61 73 73 77 6f  ..proc addPasswo
3450: 72 64 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65  rd {passwordName
3460: 20 70 61 73 73 77 6f 72 64 20 61 72 67 73 7d 20   password args} 
3470: 7b 0a 09 73 65 74 20 69 6e 69 74 69 61 6c 55 73  {..set initialUs
3480: 65 72 73 20 24 61 72 67 73 0a 0a 09 69 66 20 7b  ers $args...if {
3490: 24 70 61 73 73 77 6f 72 64 20 65 71 20 22 22 7d  $password eq ""}
34a0: 20 7b 0a 09 09 73 65 74 20 70 61 73 73 77 6f 72   {...set passwor
34b0: 64 20 5b 5f 70 72 6f 6d 70 74 20 22 50 6c 65 61  d [_prompt "Plea
34c0: 73 65 20 65 6e 74 65 72 20 74 68 65 20 6e 65 77  se enter the new
34d0: 20 70 61 73 73 77 6f 72 64 3a 20 22 5d 0a 09 7d   password: "]..}
34e0: 0a 0a 09 23 20 56 65 72 69 66 79 20 74 68 61 74  ...# Verify that
34f0: 20 74 68 69 73 20 70 61 73 73 77 6f 72 64 20 64   this password d
3500: 6f 65 73 20 6e 6f 74 20 61 6c 72 65 61 64 79 20  oes not already 
3510: 65 78 69 73 74 0a 09 73 65 74 20 65 78 69 73 74  exist..set exist
3520: 73 20 5b 64 62 20 65 76 61 6c 20 7b 53 45 4c 45  s [db eval {SELE
3530: 43 54 20 31 20 46 52 4f 4d 20 70 61 73 73 77 6f  CT 1 FROM passwo
3540: 72 64 73 20 57 48 45 52 45 20 6e 61 6d 65 20 3d  rds WHERE name =
3550: 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 4c   $passwordName L
3560: 49 4d 49 54 20 31 3b 7d 5d 0a 09 69 66 20 7b 24  IMIT 1;}]..if {$
3570: 65 78 69 73 74 73 20 3d 3d 20 22 31 22 7d 20 7b  exists == "1"} {
3580: 0a 09 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20  ...return -code 
3590: 65 72 72 6f 72 20 22 50 61 73 73 77 6f 72 64 20  error "Password 
35a0: 5c 22 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 5c  \"$passwordName\
35b0: 22 20 61 6c 72 65 61 64 79 20 65 78 69 73 74 73  " already exists
35c0: 2c 20 63 61 6e 6e 6f 74 20 61 64 64 2e 22 0a 09  , cannot add."..
35d0: 7d 0a 0a 09 23 20 47 65 74 20 6b 65 79 73 20 66  }...# Get keys f
35e0: 6f 72 20 69 6e 69 74 69 61 6c 20 75 73 65 72 73  or initial users
35f0: 0a 09 73 65 74 20 70 75 62 6c 69 63 4b 65 79 73  ..set publicKeys
3600: 20 5b 6c 69 73 74 5d 0a 09 66 6f 72 65 61 63 68   [list]..foreach
3610: 20 75 73 65 72 20 24 69 6e 69 74 69 61 6c 55 73   user $initialUs
3620: 65 72 73 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e  ers {...unset -n
3630: 6f 63 6f 6d 70 6c 61 69 6e 20 72 6f 77 0a 09 09  ocomplain row...
3640: 64 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20  db eval {SELECT 
3650: 70 75 62 6c 69 63 4b 65 79 20 46 52 4f 4d 20 75  publicKey FROM u
3660: 73 65 72 73 20 57 48 45 52 45 20 6e 61 6d 65 20  sers WHERE name 
3670: 3d 20 24 75 73 65 72 3b 7d 20 72 6f 77 20 7b 0a  = $user;} row {.
3680: 09 09 09 6c 61 70 70 65 6e 64 20 70 75 62 6c 69  ...lappend publi
3690: 63 4b 65 79 73 20 24 72 6f 77 28 70 75 62 6c 69  cKeys $row(publi
36a0: 63 4b 65 79 29 0a 09 09 7d 0a 09 7d 0a 0a 09 5f  cKey)...}..}..._
36b0: 61 64 64 50 61 73 73 77 6f 72 64 20 24 70 61 73  addPassword $pas
36c0: 73 77 6f 72 64 4e 61 6d 65 20 24 70 61 73 73 77  swordName $passw
36d0: 6f 72 64 20 24 70 75 62 6c 69 63 4b 65 79 73 0a  ord $publicKeys.
36e0: 7d 0a 0a 70 72 6f 63 20 67 65 74 50 61 73 73 77  }..proc getPassw
36f0: 6f 72 64 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d  ord {passwordNam
3700: 65 7d 20 7b 0a 09 70 75 74 73 20 5b 5f 67 65 74  e} {..puts [_get
3710: 50 61 73 73 77 6f 72 64 20 24 70 61 73 73 77 6f  Password $passwo
3720: 72 64 4e 61 6d 65 5d 0a 7d 0a 0a 70 72 6f 63 20  rdName].}..proc 
3730: 75 70 64 61 74 65 50 61 73 73 77 6f 72 64 20 7b  updatePassword {
3740: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 70 61 73  passwordName pas
3750: 73 77 6f 72 64 7d 20 7b 0a 09 69 66 20 7b 24 70  sword} {..if {$p
3760: 61 73 73 77 6f 72 64 20 65 71 20 22 22 7d 20 7b  assword eq ""} {
3770: 0a 09 09 73 65 74 20 70 61 73 73 77 6f 72 64 20  ...set password 
3780: 5b 5f 70 72 6f 6d 70 74 20 22 50 6c 65 61 73 65  [_prompt "Please
3790: 20 65 6e 74 65 72 20 74 68 65 20 6e 65 77 20 70   enter the new p
37a0: 61 73 73 77 6f 72 64 3a 20 22 5d 0a 09 7d 0a 0a  assword: "]..}..
37b0: 09 73 65 74 20 6f 6c 64 50 61 73 73 77 6f 72 64  .set oldPassword
37c0: 20 5b 5f 67 65 74 50 61 73 73 77 6f 72 64 20 24   [_getPassword $
37d0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 5d 0a 0a 09  passwordName]...
37e0: 73 65 74 20 70 75 62 6c 69 63 4b 65 79 73 20 5b  set publicKeys [
37f0: 5f 76 65 72 69 66 79 50 61 73 73 77 6f 72 64 20  _verifyPassword 
3800: 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 6f  $passwordName $o
3810: 6c 64 50 61 73 73 77 6f 72 64 5d 0a 0a 09 69 66  ldPassword]...if
3820: 20 7b 5b 6c 6c 65 6e 67 74 68 20 24 70 75 62 6c   {[llength $publ
3830: 69 63 4b 65 79 73 5d 20 3d 3d 20 30 7d 20 7b 0a  icKeys] == 0} {.
3840: 09 09 70 75 74 73 20 73 74 64 65 72 72 20 22 57  ..puts stderr "W
3850: 61 72 6e 69 6e 67 3a 20 54 68 69 73 20 77 69 6c  arning: This wil
3860: 6c 20 64 65 6c 65 74 65 20 74 68 65 20 70 61 73  l delete the pas
3870: 73 77 6f 72 64 20 73 69 6e 63 65 20 74 68 65 72  sword since ther
3880: 65 20 61 72 65 20 6e 6f 20 76 61 6c 69 64 20 70  e are no valid p
3890: 75 62 6c 69 63 20 6b 65 79 73 2e 22 0a 09 7d 0a  ublic keys."..}.
38a0: 0a 09 5f 61 64 64 50 61 73 73 77 6f 72 64 20 24  .._addPassword $
38b0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 70 61  passwordName $pa
38c0: 73 73 77 6f 72 64 20 24 70 75 62 6c 69 63 4b 65  ssword $publicKe
38d0: 79 73 0a 7d 0a 0a 70 72 6f 63 20 64 65 6c 65 74  ys.}..proc delet
38e0: 65 50 61 73 73 77 6f 72 64 20 7b 70 61 73 73 77  ePassword {passw
38f0: 6f 72 64 4e 61 6d 65 7d 20 7b 0a 09 64 62 20 65  ordName} {..db e
3900: 76 61 6c 20 7b 44 45 4c 45 54 45 20 46 52 4f 4d  val {DELETE FROM
3910: 20 70 61 73 73 77 6f 72 64 73 20 57 48 45 52 45   passwords WHERE
3920: 20 6e 61 6d 65 20 3d 20 24 70 61 73 73 77 6f 72   name = $passwor
3930: 64 4e 61 6d 65 3b 7d 0a 7d 0a 0a 70 72 6f 63 20  dName;}.}..proc 
3940: 61 75 74 68 6f 72 69 7a 65 55 73 65 72 73 20 7b  authorizeUsers {
3950: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 61 72 67  passwordName arg
3960: 73 7d 20 7b 0a 09 73 65 74 20 75 73 65 72 73 20  s} {..set users 
3970: 24 61 72 67 73 0a 0a 09 5f 6d 6f 64 69 66 79 50  $args..._modifyP
3980: 75 62 6c 69 63 4b 65 79 73 20 24 70 61 73 73 77  ublicKeys $passw
3990: 6f 72 64 4e 61 6d 65 20 24 75 73 65 72 73 20 7b  ordName $users {
39a0: 0a 09 09 69 66 20 7b 24 72 6f 77 28 70 75 62 6c  ...if {$row(publ
39b0: 69 63 4b 65 79 29 20 69 6e 20 24 70 75 62 6c 69  icKey) in $publi
39c0: 63 4b 65 79 73 7d 20 7b 0a 09 09 09 63 6f 6e 74  cKeys} {....cont
39d0: 69 6e 75 65 0a 09 09 7d 0a 0a 09 09 6c 61 70 70  inue...}....lapp
39e0: 65 6e 64 20 70 75 62 6c 69 63 4b 65 79 73 20 24  end publicKeys $
39f0: 72 6f 77 28 70 75 62 6c 69 63 4b 65 79 29 0a 0a  row(publicKey)..
3a00: 09 09 73 65 74 20 63 68 61 6e 67 65 52 65 71 75  ..set changeRequ
3a10: 69 72 65 64 20 31 0a 09 7d 0a 7d 0a 0a 70 72 6f  ired 1..}.}..pro
3a20: 63 20 61 75 74 68 6f 72 69 7a 65 55 73 65 72 20  c authorizeUser 
3a30: 7b 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 75 73  {passwordName us
3a40: 65 72 4e 61 6d 65 7d 20 7b 0a 09 72 65 74 75 72  erName} {..retur
3a50: 6e 20 5b 61 75 74 68 6f 72 69 7a 65 55 73 65 72  n [authorizeUser
3a60: 73 20 24 70 61 73 73 77 6f 72 64 4e 61 6d 65 20  s $passwordName 
3a70: 24 75 73 65 72 4e 61 6d 65 5d 0a 7d 0a 0a 70 72  $userName].}..pr
3a80: 6f 63 20 64 65 61 75 74 68 6f 72 69 7a 65 55 73  oc deauthorizeUs
3a90: 65 72 73 20 7b 70 61 73 73 77 6f 72 64 4e 61 6d  ers {passwordNam
3aa0: 65 20 61 72 67 73 7d 20 7b 0a 09 73 65 74 20 75  e args} {..set u
3ab0: 73 65 72 73 20 24 61 72 67 73 0a 0a 09 5f 6d 6f  sers $args..._mo
3ac0: 64 69 66 79 50 75 62 6c 69 63 4b 65 79 73 20 24  difyPublicKeys $
3ad0: 70 61 73 73 77 6f 72 64 4e 61 6d 65 20 24 75 73  passwordName $us
3ae0: 65 72 73 20 7b 0a 09 09 73 65 74 20 69 64 78 20  ers {...set idx 
3af0: 5b 6c 73 65 61 72 63 68 20 2d 65 78 61 63 74 20  [lsearch -exact 
3b00: 24 70 75 62 6c 69 63 4b 65 79 73 20 24 72 6f 77  $publicKeys $row
3b10: 28 70 75 62 6c 69 63 4b 65 79 29 5d 0a 09 09 69  (publicKey)]...i
3b20: 66 20 7b 24 69 64 78 20 3d 3d 20 2d 31 7d 20 7b  f {$idx == -1} {
3b30: 0a 09 09 09 63 6f 6e 74 69 6e 75 65 0a 09 09 7d  ....continue...}
3b40: 0a 0a 09 09 73 65 74 20 70 75 62 6c 69 63 4b 65  ....set publicKe
3b50: 79 73 20 5b 6c 72 65 70 6c 61 63 65 20 24 70 75  ys [lreplace $pu
3b60: 62 6c 69 63 4b 65 79 73 20 24 69 64 78 20 24 69  blicKeys $idx $i
3b70: 64 78 5d 0a 0a 09 09 73 65 74 20 63 68 61 6e 67  dx]....set chang
3b80: 65 52 65 71 75 69 72 65 64 20 31 0a 09 7d 0a 7d  eRequired 1..}.}
3b90: 0a 0a 70 72 6f 63 20 64 65 61 75 74 68 6f 72 69  ..proc deauthori
3ba0: 7a 65 55 73 65 72 20 7b 70 61 73 73 77 6f 72 64  zeUser {password
3bb0: 4e 61 6d 65 20 75 73 65 72 4e 61 6d 65 7d 20 7b  Name userName} {
3bc0: 0a 09 72 65 74 75 72 6e 20 5b 64 65 61 75 74 68  ..return [deauth
3bd0: 6f 72 69 7a 65 55 73 65 72 73 20 24 70 61 73 73  orizeUsers $pass
3be0: 77 6f 72 64 4e 61 6d 65 20 24 75 73 65 72 4e 61  wordName $userNa
3bf0: 6d 65 5d 0a 7d 0a 0a 70 72 6f 63 20 77 68 6f 61  me].}..proc whoa
3c00: 6d 69 20 7b 7d 20 7b 0a 09 66 6f 72 65 61 63 68  mi {} {..foreach
3c10: 20 73 6c 6f 74 49 6e 66 6f 44 69 63 74 20 5b 5f   slotInfoDict [_
3c20: 6c 69 73 74 43 65 72 74 69 66 69 63 61 74 65 73  listCertificates
3c30: 5d 20 7b 0a 09 09 75 6e 73 65 74 20 2d 6e 6f 63  ] {...unset -noc
3c40: 6f 6d 70 6c 61 69 6e 20 73 6c 6f 74 49 6e 66 6f  omplain slotInfo
3c50: 0a 09 09 61 72 72 61 79 20 73 65 74 20 73 6c 6f  ...array set slo
3c60: 74 49 6e 66 6f 20 24 73 6c 6f 74 49 6e 66 6f 44  tInfo $slotInfoD
3c70: 69 63 74 0a 0a 09 09 73 65 74 20 70 75 62 6b 65  ict....set pubke
3c80: 79 20 24 73 6c 6f 74 49 6e 66 6f 28 70 75 62 6b  y $slotInfo(pubk
3c90: 65 79 29 0a 0a 09 09 75 6e 73 65 74 20 2d 6e 6f  ey)....unset -no
3ca0: 63 6f 6d 70 6c 61 69 6e 20 72 6f 77 0a 09 09 64  complain row...d
3cb0: 62 20 65 76 61 6c 20 7b 53 45 4c 45 43 54 20 6e  b eval {SELECT n
3cc0: 61 6d 65 20 46 52 4f 4d 20 75 73 65 72 73 20 57  ame FROM users W
3cd0: 48 45 52 45 20 70 75 62 6c 69 63 4b 65 79 20 3d  HERE publicKey =
3ce0: 20 24 70 75 62 6b 65 79 3b 7d 20 72 6f 77 20 7b   $pubkey;} row {
3cf0: 0a 09 09 09 73 65 74 20 75 73 65 72 73 28 24 72  ....set users($r
3d00: 6f 77 28 6e 61 6d 65 29 29 20 31 0a 09 09 7d 0a  ow(name)) 1...}.
3d10: 09 7d 0a 0a 09 70 75 74 73 20 5b 6a 6f 69 6e 20  .}...puts [join 
3d20: 5b 61 72 72 61 79 20 6e 61 6d 65 73 20 75 73 65  [array names use
3d30: 72 73 5d 20 7b 2c 20 7d 5d 0a 7d 0a 0a 70 72 6f  rs] {, }].}..pro
3d40: 63 20 68 65 6c 70 20 7b 7b 61 63 74 69 6f 6e 20  c help {{action 
3d50: 22 22 7d 7d 20 7b 0a 09 5f 70 72 69 6e 74 48 65  ""}} {.._printHe
3d60: 6c 70 20 73 74 64 6f 75 74 20 24 61 63 74 69 6f  lp stdout $actio
3d70: 6e 0a 7d 0a 23 20 45 6e 64 20 75 73 65 72 20 43  n.}.# End user C
3d80: 4c 49 20 66 75 6e 63 74 69 6f 6e 73 0a 0a 23 23  LI functions..##
3d90: 23 20 4d 41 49 4e 0a 0a 73 71 6c 69 74 65 33 20  # MAIN..sqlite3 
3da0: 64 62 20 24 70 61 73 73 77 6f 72 64 46 69 6c 65  db $passwordFile
3db0: 0a 0a 64 62 20 65 76 61 6c 20 7b 0a 09 43 52 45  ..db eval {..CRE
3dc0: 41 54 45 20 54 41 42 4c 45 20 49 46 20 4e 4f 54  ATE TABLE IF NOT
3dd0: 20 45 58 49 53 54 53 20 75 73 65 72 73 28 6e 61   EXISTS users(na
3de0: 6d 65 2c 20 70 75 62 6c 69 63 4b 65 79 20 42 4c  me, publicKey BL
3df0: 4f 42 29 3b 0a 09 43 52 45 41 54 45 20 54 41 42  OB);..CREATE TAB
3e00: 4c 45 20 49 46 20 4e 4f 54 20 45 58 49 53 54 53  LE IF NOT EXISTS
3e10: 20 70 61 73 73 77 6f 72 64 73 28 6e 61 6d 65 2c   passwords(name,
3e20: 20 65 6e 63 72 79 70 74 65 64 50 61 73 73 20 42   encryptedPass B
3e30: 4c 4f 42 2c 20 65 6e 63 72 79 70 74 65 64 4b 65  LOB, encryptedKe
3e40: 79 20 42 4c 4f 42 2c 20 70 75 62 6c 69 63 4b 65  y BLOB, publicKe
3e50: 79 20 42 4c 4f 42 2c 20 76 65 72 69 66 69 63 61  y BLOB, verifica
3e60: 74 69 6f 6e 20 42 4c 4f 42 29 3b 0a 7d 0a 0a 69  tion BLOB);.}..i
3e70: 66 20 7b 24 61 63 74 69 6f 6e 20 69 6e 20 24 76  f {$action in $v
3e80: 61 6c 69 64 43 6f 6d 6d 61 6e 64 73 7d 20 7b 0a  alidCommands} {.
3e90: 09 69 66 20 7b 5b 63 61 74 63 68 20 7b 0a 09 09  .if {[catch {...
3ea0: 24 61 63 74 69 6f 6e 20 7b 2a 7d 24 61 72 67 76  $action {*}$argv
3eb0: 0a 09 7d 20 65 72 72 6f 72 5d 7d 20 7b 0a 09 09  ..} error]} {...
3ec0: 70 75 74 73 20 73 74 64 65 72 72 20 22 45 72 72  puts stderr "Err
3ed0: 6f 72 3a 20 24 65 72 72 6f 72 22 0a 0a 09 09 65  or: $error"....e
3ee0: 78 69 74 20 31 0a 09 7d 0a 7d 20 65 6c 73 65 20  xit 1..}.} else 
3ef0: 7b 0a 09 70 75 74 73 20 73 74 64 65 72 72 20 22  {..puts stderr "
3f00: 49 6e 76 61 6c 69 64 20 61 63 74 69 6f 6e 22 0a  Invalid action".
3f10: 0a 09 65 78 69 74 20 31 0a 7d 0a 0a 65 78 69 74  ..exit 1.}..exit
3f20: 20 30 0a 0a                                       0..