Diff
Not logged in

Differences From Artifact [9dc3f0e9e9]:

To Artifact [5a0dd193f2]:


95
96
97
98
99
100
101
102



103
104

105
106
107
108
109
110
111
112
113
114


115
116
117
118
119
120

121
122
123
124
125






















126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168






169
170
171
172
173
174
175
95
96
97
98
99
100
101

102
103
104
105

106
107
108
109
110
111
112
113
114


115
116
117
118
119
120
121

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159








160




161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176





177
178
179
180
181
182
183
184
185
186
187
188
189







-
+
+
+

-
+








-
-
+
+





-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
-
-
-
-
-
-
-
+
-
-
-
-
















-
-
-
-
-
+
+
+
+
+
+







  #
  # NOTE: This procedure returns non-zero if the specified string value
  #       looks like a Harpy (script) certificate.  The value argument
  #       is the string to check.
  #
  # <public>
  proc isHarpyCertificate { value } {
    if {[string length $value] == 0 || [string first [string trim {
    if {[string length $value] == 0 || ([string first [string trim {
      <?xml version="1.0" encoding="utf-8"?>
    }] $value] == 0 && [string first [string trim {
      <Certificate xmlns="https://eagle.to/2011/harpy"
    }] $value] != -1} then {
    }] $value] != -1)} then {
      return true
    } else {
      return false
    }
  }

  #
  # NOTE: This procedure returns non-zero if the specified string value
  #       looks like a PGP signature.  The value argument is the string
  #       to check.
  #       looks like an OpenPGP signature.  The value argument is the
  #       string to check.
  #
  # <public>
  proc isPgpSignature { value } {
    if {[string length $value] == 0 || [string first [string trim {
      -----BEGIN PGP SIGNATURE-----
    }] $value] != -1} then {
    }] $value] == 0} then {
      return true
    } else {
      return false
    }
  }

  #
  # NOTE: This procedure returns the fully qualified name of the directory
  #       where temporary files should be written.  The envVarName argument
  #       is an optional extra environment variable to check (first).
  #
  proc getFileTempDirectory { {envVarName ""} } {
    global env

    if {[string length $envVarName] > 0 && \
        [info exists env($envVarName)]} then {
      return $env($envVarName)
    } elseif {[info exists env(TEMP)]} then {
      return $env(TEMP)
    } elseif {[info exists env(TMP)]} then {
      return $env(TMP)
    } else {
      error [appendArgs \
          "please set " $envVarName \
          " (via environment) to temporary directory"]
    }
  }

  #
  # NOTE: This procedure returns a unique temporary file name.  A script
  #       error is raised if this task cannot be accomplished.  There are
  #       no arguments.
  #
  proc getFileTempName {} {
    if {[isEagle]} then {
      return [file tempname]
    } else {
      global env

      if {[info exists env(PKGR_TEMP)]} then {
        set directory $env(PKGD_TEMP)
      } elseif {[info exists env(TEMP)]} then {
        set directory $env(TEMP)
      } elseif {[info exists env(TMP)]} then {
        set directory $env(TMP)
      set directory [getFileTempDirectory PKGR_TEMP]
      } else {
        error "please set PKGR_TEMP (via environment) to temporary directory"
      }

      set counter [expr {[pid] ^ int(rand() * 0xFFFF)}]

      while {1} {
        set fileNameOnly [format tcl%04X.tmp $counter]
        set fileName [file join $directory $fileNameOnly]

        if {![file exists $fileName]} then {
          return $fileName
        }

        incr counter
      }
    }
  }

  #
  # NOTE: This procedure attempts to verify the PGP signature contained in
  #       the specified (named) file.  Non-zero is only returned if the PGP
  #       signature is verified successfully.  A script error should not be
  #       raised by this procedure.  The fileName argument must be the fully
  #       qualified path and file name of the PGP signature file to verify.
  # NOTE: This procedure attempts to verify the OpenPGP signature contained
  #       in the specified (named) file.  Non-zero is only returned if the
  #       OpenPGP signature is verified successfully.  A script error should
  #       not be raised by this procedure.  The fileName argument must be
  #       the fully qualified path and file name of the OpenPGP signature
  #       file to verify.
  #
  # <public>
  proc verifyPgpSignature { fileName } {
    variable pgpCommand

    if {[isEagle]} then {
      set fileName [appendArgs \" $fileName \"]
630
631
632
633
634
635
636
637
638


639
640
641
642
643
644
645
644
645
646
647
648
649
650


651
652
653
654
655
656
657
658
659







-
-
+
+








    return false
  }

  #
  # NOTE: This procedure uses the package lookup metadata.  If the package
  #       script is properly signed, an attempt will be made to evaluate it
  #       in the target language.  If the script was signed using PGP, then
  #       a conforming implementation of the OpenPGP specification (e.g.
  #       in the target language.  If the script was signed using OpenPGP,
  #       then a conforming implementation of the OpenPGP specification (e.g.
  #       gpg2) must be installed locally.  If the script was signed using
  #       Harpy then Garuda, Eagle, and Harpy must be installed locally.
  #       This procedure is designed to work for both native Tcl and Eagle
  #       packages.  Additionally, it is designed to work when evaluated
  #       using either native Tcl or Eagle; however, it is up to the package
  #       script itself to either add the package or provide the package to
  #       the language(s) supported by that package.  The varName argument
892
893
894
895
896
897
898
899

900
901
902
903
904
905
906
907
908
909
910

911
912
913
914
915
916
917


918
919
920
921
922


923
924
925
926
927
928


929
930
931
932
933
934


935
936
937
938
939
940
941


942
943
944
945
946
947
948
906
907
908
909
910
911
912

913
914
915
916
917
918
919
920
921
922
923

924
925
926
927
928
929
930

931
932
933
934
935


936
937
938
939
940
941


942
943
944
945
946
947


948
949
950
951
952
953
954


955
956
957
958
959
960
961
962
963







-
+










-
+






-
+
+



-
-
+
+




-
-
+
+




-
-
+
+





-
-
+
+







      #
      # NOTE: If there is no package script, there is nothing we
      #       can do here.
      #
      if {[string length $metadata(script)] > 0} then {
        #
        # NOTE: Figure out temporary file name for the downloaded script
        #       and its associated PGP signature.
        #       and its associated OpenPGP signature.
        #
        set fileName(1) [getFileTempName]
        set fileName(2) [appendArgs $fileName(1) .asc]

        #
        # NOTE: Write downloaded script to a temporary file.
        #
        writeFile $fileName(1) $metadata(script)

        #
        # NOTE: Write downloaded script PGP signature a temporary file.
        # NOTE: Write downloaded script OpenPGP signature a temporary file.
        #
        if {[string length $metadata(certificate)] > 0} then {
          writeFile $fileName(2) $metadata(certificate)
        }

        #
        # NOTE: Attempt to verify the PGP signature for the package script.
        # NOTE: Attempt to verify the OpenPGP signature for the package
        #       script.
        #
        if {[verifyPgpSignature $fileName(2)]} then {
          #
          # NOTE: Delete the temporary files that we created for the PGP
          #       signature verification.
          # NOTE: Delete the temporary files that we created for the
          #       OpenPGP signature verification.
          #
          eval $script(cleanup)
        } else {
          #
          # NOTE: Delete the temporary files that we created for the PGP
          #       signature verification.
          # NOTE: Delete the temporary files that we created for the
          #       OpenPGP signature verification.
          #
          eval $script(cleanup)

          #
          # NOTE: PGP signature verification failed.  Raise an error and
          #       do not proceed with evaluating the package script.
          # NOTE: OpenPGP signature verification failed.  Raise an error
          #       and do not proceed with evaluating the package script.
          #
          error "bad PGP signature"
        }

        #
        # NOTE: The PGP signature was verified; use the downloaded package
        #       script verbatim.
        # NOTE: The OpenPGP signature was verified; use the downloaded
        #       package script verbatim.
        #
        set script(inner) $metadata(script)

        #
        # NOTE: Determine the target language for the package script, which
        #       may or may not be the language that is currently evaluating
        #       this script (Eagle).  The default language, when one was not