File: dpkg_verify.py

package info (click to toggle)
dpkg-scriptlib 0.1-2hamm1
  • links: PTS
  • area: main
  • in suites: hamm, slink
  • size: 188 kB
  • ctags: 230
  • sloc: python: 1,685; perl: 534; makefile: 41; sh: 18
file content (127 lines) | stat: -rw-r--r-- 4,159 bytes parent folder | download | duplicates (2)
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
# $Id$
#
# Copyright (C) 1997  Klee Dienes <klee@mit.edu>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import sys, string, regex, os, pwd, grp, posix, stat
import dpkg_debsums, dpkg_certificate, dpkg_util

def parse_stat (s):
	r = {}
	r['mode'], r['ino'], r['dev'], r['nlink'], r['uid'], r['gid'], r['size'], r['atime'], r['mtime'], r['ctime'] = s
	return r

def parse_passwd (s):
	r = {}
	try:
		p = pwd.getpwuid (s['uid'])
		r['name'], r['passwd'], r['uid'], r['gid'], r['gecos'], r['dir'], r['shell'] = p
	except KeyError:
		r['uid'] = s['uid']
		r['name'] = str (s['uid'])
	return r

def parse_group (s):
	r = {}
	try:
		g = grp.getgrgid (s['gid'])
		r['name'], r['passwd'], r['gid'], r['mem'] = g
	except KeyError:
		r['gid'] = s['gid']
		r['name'] = str (s['gid'])
	return r

VerificationError = 'verification-error'

def gen_errstr (r, s):
	return 'file "%s" %s (should be %s)' % (r['name'], s, dpkg_certificate.verification_entry (r))

def verify (r):

	if (r['type'] not in ['f', 'l', 'c', 'b', 'd', 's']):
		raise ValueError, "unknown type code '%s'" % r['type']

	if (r['type'] in ['f', 'l', 'c', 'b', 'd']):
		try:
			s = parse_stat (os.lstat (r['name']))
			p = parse_passwd (s)
			g = parse_group (s)
		except posix.error, v:
			if (v[0] == 2):
				raise VerificationError, gen_errstr (r, 'does not exist')
			elif (v[0] == 13):
				raise VerificationError, gen_errstr (r, 'permission denied on stat')
			else:
				raise sys.exc_type, sys.exc_value, sys.exc_traceback

	if (r['type'] in ['f', 'l', 'c', 'b', 'd']):
		if (stat.S_IMODE (r['mode']) != stat.S_IMODE (s['mode'])):
			raise VerificationError, gen_errstr (r, 'has permissions %04o' % stat.S_IMODE (s['mode']))
		if (r['uname'] != p['name']):
			raise VerificationError, gen_errstr (r, 'has wrong owner %s' % (p['name']))
		if (r['gname'] != g['name']):
			raise VerificationError, gen_errstr (r, 'has wrong group %s' % (g['name']))

	if (r['type'] in ['f']):

		try:
			fd = open (r['name'], 'r')
			md5 = dpkg_util.md5_file (fd)
		except IOError, v:
			if (v[0] == 13):
				raise VerificationError, gen_errstr (r, 'unable to compute MD5 (permission denied)')
			else:
				raise sys.exc_type, sys.exc_value, sys.exc_traceback
		
		if (r['md5'] != md5):
			raise VerificationError, gen_errstr (r, 'has bad MD5 %s' % md5)

	if (r['type'] in ['s']):
		try:
			link = posix.readlink (r['name'])
		except posix.error, v:
			if (v[0] == 2):
				raise VerificationError, gen_errstr (r, 'does not exist')
			elif (v[0] == 22):
				raise VerificationError, gen_errstr (r, 'is not a symbolic link')
			else:
				raise sys.exc_type, sys.exc_value, sys.exc_traceback
		if (link != r['link']):
			raise VerificationError, gen_errstr (r, 'has incorrect destination "%s")' % link)

	if (r['type'] == 'l'):
		try:
			s_to = parse_stat (os.stat (r['link']))
		except posix.error, v:
			if (v[0] == 2):
				raise VerificationError,  'destination for hard link "%s" does not exist (should be -> "%s")' % (r['name'], r['link'])
			else:
				raise sys.exc_type, sys.exc_value, sys.exc_traceback
		if (s['ino'] != s_to['ino']):
			raise VerificationError, 'hard link "%s" should point to "%s" (inode %d)' % (r['name'], r['link'], s_to['ino'])

	return
		
def verify_certificate (entry, logger):
	for r in entry['data-files']:
		if (entry.has_key ('configuration-files')):
			try:
				verify (r)
			except VerificationError, s:
				if (r['name'] in entry['configuration-files']):
					logger ('warning', 'configuration file ' + s)
				else:
					logger ('error', s)