1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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
|
# portage_gpg.py -- core Portage functionality
# Copyright 2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
import os
import copy
import types
import commands
import portage_exception
import portage_checksum
GPG_BINARY = "/usr/bin/gpg"
GPG_OPTIONS = " --lock-never --no-random-seed-file --no-greeting --no-sig-cache "
GPG_VERIFY_FLAGS = " --verify "
GPG_KEYDIR = " --homedir '%s' "
GPG_KEYRING = " --keyring '%s' "
UNTRUSTED = 0
EXISTS = UNTRUSTED + 1
MARGINAL = EXISTS + 1
TRUSTED = MARGINAL + 1
def fileStats(filepath):
mya = []
for x in os.stat(filepath):
mya.append(x)
mya.append(portage_checksum.perform_checksum(filepath))
return mya
class FileChecker:
def __init__(self,keydir=None,keyring=None,requireSignedRing=False,minimumTrust=EXISTS):
self.minimumTrust = TRUSTED # Default we require trust. For rings.
self.keydir = None
self.keyring = None
self.keyringPath = None
self.keyringStats = None
self.keyringIsTrusted = False
if (keydir != None):
# Verify that the keydir is valid.
if type(keydir) != types.StringType:
raise portage_exception.InvalidDataType, "keydir argument: %s" % keydir
if not os.path.isdir(keydir):
raise portage_exception.DirectoryNotFound, "keydir: %s" % keydir
self.keydir = copy.deepcopy(keydir)
if (keyring != None):
# Verify that the keyring is a valid filename and exists.
if type(keyring) != types.StringType:
raise portage_exception.InvalidDataType, "keyring argument: %s" % keyring
if keyring.find("/") != -1:
raise portage_exception.InvalidData, "keyring: %s" % keyring
pathname = ""
if keydir:
pathname = keydir + "/" + keyring
if not os.path.isfile(pathname):
raise portage_exception.FileNotFound, "keyring missing: %s (dev.gentoo.org/~carpaski/gpg/)" % pathname
keyringPath = keydir+"/"+keyring
if not keyring or not keyringPath and requireSignedRing:
raise portage_exception.MissingParameter
self.keyringStats = fileStats(keyringPath)
self.minimumTrust = TRUSTED
if not self.verify(keyringPath, keyringPath+".asc"):
self.keyringIsTrusted = False
if requireSignedRing:
raise portage_exception.InvalidSignature, "Required keyring verification: "+keyringPath
else:
self.keyringIsTrusted = True
self.keyring = copy.deepcopy(keyring)
self.keyringPath = self.keydir+"/"+self.keyring
self.minimumTrust = minimumTrust
def _verifyKeyring(self):
if self.keyringStats and self.keyringPath:
new_stats = fileStats(self.keyringPath)
if new_stats != self.keyringStats:
raise portage_exception.SecurityViolation, "GPG keyring changed!"
def verify(self, filename, sigfile=None):
"""Uses minimumTrust to determine if it is Valid/True or Invalid/False"""
self._verifyKeyring()
if not os.path.isfile(filename):
raise portage_exception.FileNotFound, filename
if sigfile and not os.path.isfile(sigfile):
raise portage_exception.FileNotFound, sigfile
if self.keydir and not os.path.isdir(self.keydir):
raise portage_exception.DirectoryNotFound, filename
if self.keyringPath:
if not os.path.isfile(self.keyringPath):
raise portage_exception.FileNotFound, self.keyringPath
if not os.path.isfile(filename):
raise portage_exception.CommandNotFound, filename
command = GPG_BINARY + GPG_VERIFY_FLAGS + GPG_OPTIONS
if self.keydir:
command += GPG_KEYDIR % (self.keydir)
if self.keyring:
command += GPG_KEYRING % (self.keyring)
if sigfile:
command += " '"+sigfile+"'"
command += " '"+filename+"'"
result,output = commands.getstatusoutput(command)
signal = result & 0xff
result = (result >> 8)
if signal:
raise SignalCaught, "Signal: %d" % (signal)
trustLevel = UNTRUSTED
if result == 0:
trustLevel = TRUSTED
#if output.find("WARNING") != -1:
# trustLevel = MARGINAL
if output.find("BAD") != -1:
raise portage_exception.InvalidSignature, filename
elif result == 1:
trustLevel = EXISTS
if output.find("BAD") != -1:
raise portage_exception.InvalidSignature, filename
elif result == 2:
trustLevel = UNTRUSTED
if output.find("could not be verified") != -1:
raise portage_exception.MissingSignature, filename
if output.find("public key not found") != -1:
if self.keyringIsTrusted: # We trust the ring, but not the key specifically.
trustLevel = MARGINAL
else:
raise portage_exception.InvalidSignature, filename+" (Unknown Signature)"
else:
raise portage_exception.UnknownCondition, "GPG returned unknown result: %d" % (result)
if trustLevel >= self.minimumTrust:
return True
return False
|