python-apt-binary 2.2.1__cp39-cp39-manylinux_2_31_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
apt/__init__.py ADDED
@@ -0,0 +1,38 @@
1
+ # Copyright (c) 2005-2009 Canonical
2
+ #
3
+ # Author: Michael Vogt <michael.vogt@ubuntu.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU General Public License as
7
+ # published by the Free Software Foundation; either version 2 of the
8
+ # License, or (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18
+ # USA
19
+ # import the core of apt_pkg
20
+ """High-Level Interface for working with apt."""
21
+ from __future__ import print_function
22
+
23
+ import apt_pkg
24
+
25
+ # import some fancy classes
26
+ from apt.package import Package as Package, Version as Version
27
+ from apt.cache import Cache as Cache, ProblemResolver as ProblemResolver
28
+ Cache # pyflakes
29
+ ProblemResolver # pyflakes
30
+ Version # pyflakes
31
+ from apt.cdrom import Cdrom as Cdrom
32
+
33
+ # init the package system, but do not re-initialize config
34
+ if "APT" not in apt_pkg.config:
35
+ apt_pkg.init_config()
36
+ apt_pkg.init_system()
37
+
38
+ __all__ = ['Cache', 'Cdrom', 'Package']
apt/auth.py ADDED
@@ -0,0 +1,309 @@
1
+ #!/usr/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ # auth - authentication key management
4
+ #
5
+ # Copyright (c) 2004 Canonical
6
+ # Copyright (c) 2012 Sebastian Heinlein
7
+ #
8
+ # Author: Michael Vogt <mvo@debian.org>
9
+ # Sebastian Heinlein <devel@glatzor.de>
10
+ #
11
+ # This program is free software; you can redistribute it and/or
12
+ # modify it under the terms of the GNU General Public License as
13
+ # published by the Free Software Foundation; either version 2 of the
14
+ # License, or (at your option) any later version.
15
+ #
16
+ # This program is distributed in the hope that it will be useful,
17
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ # GNU General Public License for more details.
20
+ #
21
+ # You should have received a copy of the GNU General Public License
22
+ # along with this program; if not, write to the Free Software
23
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24
+ # USA
25
+ """Handle GnuPG keys used to trust signed repositories."""
26
+
27
+ from __future__ import print_function
28
+
29
+ import errno
30
+ import os
31
+ import os.path
32
+ import shutil
33
+ import subprocess
34
+ import sys
35
+ import tempfile
36
+
37
+ import apt_pkg
38
+ from apt_pkg import gettext as _
39
+
40
+ from typing import List, Optional, Tuple
41
+
42
+
43
+ class AptKeyError(Exception):
44
+ pass
45
+
46
+
47
+ class AptKeyIDTooShortError(AptKeyError):
48
+ """Internal class do not rely on it."""
49
+
50
+
51
+ class TrustedKey(object):
52
+
53
+ """Represents a trusted key."""
54
+
55
+ def __init__(self, name, keyid, date):
56
+ # type: (str, str, str) -> None
57
+ self.raw_name = name
58
+ # Allow to translated some known keys
59
+ self.name = _(name)
60
+ self.keyid = keyid
61
+ self.date = date
62
+
63
+ def __str__(self):
64
+ # type: () -> str
65
+ return "%s\n%s %s" % (self.name, self.keyid, self.date)
66
+
67
+
68
+ def _call_apt_key_script(*args, **kwargs):
69
+ # type: (str, Optional[str]) -> str
70
+ """Run the apt-key script with the given arguments."""
71
+ conf = None
72
+ cmd = [apt_pkg.config.find_file("Dir::Bin::Apt-Key", "/usr/bin/apt-key")]
73
+ cmd.extend(args)
74
+ env = os.environ.copy()
75
+ env["LANG"] = "C"
76
+ env["APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE"] = "1"
77
+ try:
78
+ if apt_pkg.config.find_dir("Dir") != "/":
79
+ # If the key is to be installed into a chroot we have to export the
80
+ # configuration from the chroot to the apt-key script by using
81
+ # a temporary APT_CONFIG file. The apt-key script uses apt-config
82
+ # shell internally
83
+ conf = tempfile.NamedTemporaryFile(
84
+ prefix="apt-key", suffix=".conf")
85
+ conf.write(apt_pkg.config.dump().encode("UTF-8"))
86
+ conf.flush()
87
+ env["APT_CONFIG"] = conf.name
88
+ proc = subprocess.Popen(cmd, env=env, universal_newlines=True,
89
+ stdin=subprocess.PIPE,
90
+ stdout=subprocess.PIPE,
91
+ stderr=subprocess.PIPE)
92
+
93
+ stdin = kwargs.get("stdin", None)
94
+
95
+ output, stderr = proc.communicate(stdin) # type: str, str
96
+
97
+ if proc.returncode:
98
+ raise AptKeyError(
99
+ "The apt-key script failed with return code %s:\n"
100
+ "%s\n"
101
+ "stdout: %s\n"
102
+ "stderr: %s" % (
103
+ proc.returncode, " ".join(cmd), output, stderr))
104
+ elif stderr:
105
+ sys.stderr.write(stderr) # Forward stderr
106
+
107
+ return output.strip()
108
+ finally:
109
+ if conf is not None:
110
+ conf.close()
111
+
112
+
113
+ def add_key_from_file(filename):
114
+ # type: (str) -> None
115
+ """Import a GnuPG key file to trust repositores signed by it.
116
+
117
+ Keyword arguments:
118
+ filename -- the absolute path to the public GnuPG key file
119
+ """
120
+ if not os.path.abspath(filename):
121
+ raise AptKeyError("An absolute path is required: %s" % filename)
122
+ if not os.access(filename, os.R_OK):
123
+ raise AptKeyError("Key file cannot be accessed: %s" % filename)
124
+ _call_apt_key_script("add", filename)
125
+
126
+
127
+ def add_key_from_keyserver(keyid, keyserver):
128
+ # type: (str, str) -> None
129
+ """Import a GnuPG key file to trust repositores signed by it.
130
+
131
+ Keyword arguments:
132
+ keyid -- the long keyid (fingerprint) of the key, e.g.
133
+ A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553
134
+ keyserver -- the URL or hostname of the key server
135
+ """
136
+ tmp_keyring_dir = tempfile.mkdtemp()
137
+ try:
138
+ _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir)
139
+ except Exception:
140
+ raise
141
+ finally:
142
+ # We are racing with gpg when removing sockets, so ignore
143
+ # failure to delete non-existing files.
144
+ def onerror(func, path, exc_info):
145
+ # type: (object, str, Tuple[type, Exception, object]) -> None
146
+ if (isinstance(exc_info[1], OSError) and
147
+ exc_info[1].errno == errno.ENOENT):
148
+ return
149
+ raise
150
+
151
+ shutil.rmtree(tmp_keyring_dir, onerror=onerror)
152
+
153
+
154
+ def _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir):
155
+ # type: (str, str, str) -> None
156
+ if len(keyid.replace(" ", "").replace("0x", "")) < (160 / 4):
157
+ raise AptKeyIDTooShortError(
158
+ "Only fingerprints (v4, 160bit) are supported")
159
+ # create a temp keyring dir
160
+ tmp_secret_keyring = os.path.join(tmp_keyring_dir, "secring.gpg")
161
+ tmp_keyring = os.path.join(tmp_keyring_dir, "pubring.gpg")
162
+ # default options for gpg
163
+ gpg_default_options = [
164
+ "gpg",
165
+ "--no-default-keyring", "--no-options",
166
+ "--homedir", tmp_keyring_dir,
167
+ ]
168
+ # download the key to a temp keyring first
169
+ res = subprocess.call(gpg_default_options + [
170
+ "--secret-keyring", tmp_secret_keyring,
171
+ "--keyring", tmp_keyring,
172
+ "--keyserver", keyserver,
173
+ "--recv", keyid,
174
+ ])
175
+ if res != 0:
176
+ raise AptKeyError("recv from '%s' failed for '%s'" % (
177
+ keyserver, keyid))
178
+ # FIXME:
179
+ # - with gnupg 1.4.18 the downloaded key is actually checked(!),
180
+ # i.e. gnupg will not import anything that the server sends
181
+ # into the keyring, so the below checks are now redundant *if*
182
+ # gnupg 1.4.18 is used
183
+
184
+ # now export again using the long key id (to ensure that there is
185
+ # really only this one key in our keyring) and not someone MITM us
186
+ tmp_export_keyring = os.path.join(tmp_keyring_dir, "export-keyring.gpg")
187
+ res = subprocess.call(gpg_default_options + [
188
+ "--keyring", tmp_keyring,
189
+ "--output", tmp_export_keyring,
190
+ "--export", keyid,
191
+ ])
192
+ if res != 0:
193
+ raise AptKeyError("export of '%s' failed", keyid)
194
+ # now verify the fingerprint, this is probably redundant as we
195
+ # exported by the fingerprint in the previous command but its
196
+ # still good paranoia
197
+ output = subprocess.Popen(
198
+ gpg_default_options + [
199
+ "--keyring", tmp_export_keyring,
200
+ "--fingerprint",
201
+ "--batch",
202
+ "--fixed-list-mode",
203
+ "--with-colons",
204
+ ],
205
+ stdout=subprocess.PIPE,
206
+ universal_newlines=True).communicate()[0]
207
+ got_fingerprint = None
208
+ for line in output.splitlines():
209
+ if line.startswith("fpr:"):
210
+ got_fingerprint = line.split(":")[9]
211
+ # stop after the first to ensure no subkey trickery
212
+ break
213
+ # strip the leading "0x" is there is one and uppercase (as this is
214
+ # what gnupg is using)
215
+ signing_key_fingerprint = keyid.replace("0x", "").upper()
216
+ if got_fingerprint != signing_key_fingerprint:
217
+ # make the error match what gnupg >= 1.4.18 will output when
218
+ # it checks the key itself before importing it
219
+ raise AptKeyError(
220
+ "recv from '%s' failed for '%s'" % (
221
+ keyserver, signing_key_fingerprint))
222
+ # finally add it
223
+ add_key_from_file(tmp_export_keyring)
224
+
225
+
226
+ def add_key(content):
227
+ # type: (str) -> None
228
+ """Import a GnuPG key to trust repositores signed by it.
229
+
230
+ Keyword arguments:
231
+ content -- the content of the GnuPG public key
232
+ """
233
+ _call_apt_key_script("adv", "--quiet", "--batch",
234
+ "--import", "-", stdin=content)
235
+
236
+
237
+ def remove_key(fingerprint):
238
+ # type: (str) -> None
239
+ """Remove a GnuPG key to no longer trust repositores signed by it.
240
+
241
+ Keyword arguments:
242
+ fingerprint -- the fingerprint identifying the key
243
+ """
244
+ _call_apt_key_script("rm", fingerprint)
245
+
246
+
247
+ def export_key(fingerprint):
248
+ # type: (str) -> str
249
+ """Return the GnuPG key in text format.
250
+
251
+ Keyword arguments:
252
+ fingerprint -- the fingerprint identifying the key
253
+ """
254
+ return _call_apt_key_script("export", fingerprint)
255
+
256
+
257
+ def update():
258
+ # type: () -> str
259
+ """Update the local keyring with the archive keyring and remove from
260
+ the local keyring the archive keys which are no longer valid. The
261
+ archive keyring is shipped in the archive-keyring package of your
262
+ distribution, e.g. the debian-archive-keyring package in Debian.
263
+ """
264
+ return _call_apt_key_script("update")
265
+
266
+
267
+ def net_update():
268
+ # type: () -> str
269
+ """Work similar to the update command above, but get the archive
270
+ keyring from an URI instead and validate it against a master key.
271
+ This requires an installed wget(1) and an APT build configured to
272
+ have a server to fetch from and a master keyring to validate. APT
273
+ in Debian does not support this command and relies on update
274
+ instead, but Ubuntu's APT does.
275
+ """
276
+ return _call_apt_key_script("net-update")
277
+
278
+
279
+ def list_keys():
280
+ # type: () -> List[TrustedKey]
281
+ """Returns a list of TrustedKey instances for each key which is
282
+ used to trust repositories.
283
+ """
284
+ # The output of `apt-key list` is difficult to parse since the
285
+ # --with-colons parameter isn't user
286
+ output = _call_apt_key_script("adv", "--with-colons", "--batch",
287
+ "--fixed-list-mode", "--list-keys")
288
+ res = []
289
+ for line in output.split("\n"):
290
+ fields = line.split(":")
291
+ if fields[0] == "pub":
292
+ keyid = fields[4]
293
+ if fields[0] == "uid":
294
+ uid = fields[9]
295
+ creation_date = fields[5]
296
+ key = TrustedKey(uid, keyid, creation_date)
297
+ res.append(key)
298
+ return res
299
+
300
+
301
+ if __name__ == "__main__":
302
+ # Add some known keys we would like to see translated so that they get
303
+ # picked up by gettext
304
+ lambda: _("Ubuntu Archive Automatic Signing Key <ftpmaster@ubuntu.com>")
305
+ lambda: _("Ubuntu CD Image Automatic Signing Key <cdimage@ubuntu.com>")
306
+
307
+ apt_pkg.init()
308
+ for trusted_key in list_keys():
309
+ print(trusted_key)