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
150
151
152
153
154
155
156
157
|
# 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
from portage.exception import CommandNotFound, \
DirectoryNotFound, FileNotFound, \
InvalidData, InvalidDataType, InvalidSignature, MissingParameter, \
MissingSignature, PortageException, SecurityViolation
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(object):
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 InvalidDataType(
"keydir argument: %s" % keydir)
if not os.path.isdir(keydir):
raise 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 InvalidDataType("keyring argument: %s" % keyring)
if keyring.find("/") != -1:
raise InvalidData("keyring: %s" % keyring)
pathname = ""
if keydir:
pathname = keydir + "/" + keyring
if not os.path.isfile(pathname):
raise FileNotFound(
"keyring missing: %s (dev.gentoo.org/~carpaski/gpg/)" % \
pathname)
keyringPath = keydir+"/"+keyring
if not keyring or not keyringPath and requireSignedRing:
raise MissingParameter((keyring, keyringPath))
self.keyringStats = fileStats(keyringPath)
self.minimumTrust = TRUSTED
if not self.verify(keyringPath, keyringPath+".asc"):
self.keyringIsTrusted = False
if requireSignedRing:
raise 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 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 FileNotFound, filename
if sigfile and not os.path.isfile(sigfile):
raise FileNotFound, sigfile
if self.keydir and not os.path.isdir(self.keydir):
raise DirectoryNotFound, filename
if self.keyringPath:
if not os.path.isfile(self.keyringPath):
raise FileNotFound, self.keyringPath
if not os.path.isfile(filename):
raise 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 PortageException("Signal: %d" % (signal))
trustLevel = UNTRUSTED
if result == 0:
trustLevel = TRUSTED
#if portage.output.find("WARNING") != -1:
# trustLevel = MARGINAL
if portage.output.find("BAD") != -1:
raise InvalidSignature(filename)
elif result == 1:
trustLevel = EXISTS
if portage.output.find("BAD") != -1:
raise InvalidSignature(filename)
elif result == 2:
trustLevel = UNTRUSTED
if portage.output.find("could not be verified") != -1:
raise MissingSignature(filename)
if portage.output.find("public key not found") != -1:
if self.keyringIsTrusted: # We trust the ring, but not the key specifically.
trustLevel = MARGINAL
else:
raise InvalidSignature(filename+"(Unknown Signature)")
else:
raise PortageException("GPG returned unknown result: %d" % (result))
if trustLevel >= self.minimumTrust:
return True
return False
|