python-apt-binary 2.6.0__cp311-cp311-manylinux_2_34_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,39 @@
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
+
29
+ Cache # pyflakes
30
+ ProblemResolver # pyflakes
31
+ Version # pyflakes
32
+ from apt.cdrom import Cdrom as Cdrom
33
+
34
+ # init the package system, but do not re-initialize config
35
+ if "APT" not in apt_pkg.config:
36
+ apt_pkg.init_config()
37
+ apt_pkg.init_system()
38
+
39
+ __all__ = ["Cache", "Cdrom", "Package"]
apt/auth.py ADDED
@@ -0,0 +1,327 @@
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(prefix="apt-key", suffix=".conf")
84
+ conf.write(apt_pkg.config.dump().encode("UTF-8"))
85
+ conf.flush()
86
+ env["APT_CONFIG"] = conf.name
87
+ proc = subprocess.Popen(
88
+ cmd,
89
+ env=env,
90
+ universal_newlines=True,
91
+ stdin=subprocess.PIPE,
92
+ stdout=subprocess.PIPE,
93
+ stderr=subprocess.PIPE,
94
+ )
95
+
96
+ stdin = kwargs.get("stdin", None)
97
+
98
+ output, stderr = proc.communicate(stdin) # type: str, str
99
+
100
+ if proc.returncode:
101
+ raise AptKeyError(
102
+ "The apt-key script failed with return code %s:\n"
103
+ "%s\n"
104
+ "stdout: %s\n"
105
+ "stderr: %s" % (proc.returncode, " ".join(cmd), output, stderr)
106
+ )
107
+ elif stderr:
108
+ sys.stderr.write(stderr) # Forward stderr
109
+
110
+ return output.strip()
111
+ finally:
112
+ if conf is not None:
113
+ conf.close()
114
+
115
+
116
+ def add_key_from_file(filename):
117
+ # type: (str) -> None
118
+ """Import a GnuPG key file to trust repositores signed by it.
119
+
120
+ Keyword arguments:
121
+ filename -- the absolute path to the public GnuPG key file
122
+ """
123
+ if not os.path.abspath(filename):
124
+ raise AptKeyError("An absolute path is required: %s" % filename)
125
+ if not os.access(filename, os.R_OK):
126
+ raise AptKeyError("Key file cannot be accessed: %s" % filename)
127
+ _call_apt_key_script("add", filename)
128
+
129
+
130
+ def add_key_from_keyserver(keyid, keyserver):
131
+ # type: (str, str) -> None
132
+ """Import a GnuPG key file to trust repositores signed by it.
133
+
134
+ Keyword arguments:
135
+ keyid -- the long keyid (fingerprint) of the key, e.g.
136
+ A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553
137
+ keyserver -- the URL or hostname of the key server
138
+ """
139
+ tmp_keyring_dir = tempfile.mkdtemp()
140
+ try:
141
+ _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir)
142
+ except Exception:
143
+ raise
144
+ finally:
145
+ # We are racing with gpg when removing sockets, so ignore
146
+ # failure to delete non-existing files.
147
+ def onerror(func, path, exc_info):
148
+ # type: (object, str, Tuple[type, Exception, object]) -> None
149
+ if isinstance(exc_info[1], OSError) and exc_info[1].errno == errno.ENOENT:
150
+ return
151
+ raise
152
+
153
+ shutil.rmtree(tmp_keyring_dir, onerror=onerror)
154
+
155
+
156
+ def _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir):
157
+ # type: (str, str, str) -> None
158
+ if len(keyid.replace(" ", "").replace("0x", "")) < (160 / 4):
159
+ raise AptKeyIDTooShortError("Only fingerprints (v4, 160bit) are supported")
160
+ # create a temp keyring dir
161
+ tmp_secret_keyring = os.path.join(tmp_keyring_dir, "secring.gpg")
162
+ tmp_keyring = os.path.join(tmp_keyring_dir, "pubring.gpg")
163
+ # default options for gpg
164
+ gpg_default_options = [
165
+ "gpg",
166
+ "--no-default-keyring",
167
+ "--no-options",
168
+ "--homedir",
169
+ tmp_keyring_dir,
170
+ ]
171
+ # download the key to a temp keyring first
172
+ res = subprocess.call(
173
+ gpg_default_options
174
+ + [
175
+ "--secret-keyring",
176
+ tmp_secret_keyring,
177
+ "--keyring",
178
+ tmp_keyring,
179
+ "--keyserver",
180
+ keyserver,
181
+ "--recv",
182
+ keyid,
183
+ ]
184
+ )
185
+ if res != 0:
186
+ raise AptKeyError("recv from '%s' failed for '%s'" % (keyserver, keyid))
187
+ # FIXME:
188
+ # - with gnupg 1.4.18 the downloaded key is actually checked(!),
189
+ # i.e. gnupg will not import anything that the server sends
190
+ # into the keyring, so the below checks are now redundant *if*
191
+ # gnupg 1.4.18 is used
192
+
193
+ # now export again using the long key id (to ensure that there is
194
+ # really only this one key in our keyring) and not someone MITM us
195
+ tmp_export_keyring = os.path.join(tmp_keyring_dir, "export-keyring.gpg")
196
+ res = subprocess.call(
197
+ gpg_default_options
198
+ + [
199
+ "--keyring",
200
+ tmp_keyring,
201
+ "--output",
202
+ tmp_export_keyring,
203
+ "--export",
204
+ keyid,
205
+ ]
206
+ )
207
+ if res != 0:
208
+ raise AptKeyError("export of '%s' failed", keyid)
209
+ # now verify the fingerprint, this is probably redundant as we
210
+ # exported by the fingerprint in the previous command but its
211
+ # still good paranoia
212
+ output = subprocess.Popen(
213
+ gpg_default_options
214
+ + [
215
+ "--keyring",
216
+ tmp_export_keyring,
217
+ "--fingerprint",
218
+ "--batch",
219
+ "--fixed-list-mode",
220
+ "--with-colons",
221
+ ],
222
+ stdout=subprocess.PIPE,
223
+ universal_newlines=True,
224
+ ).communicate()[0]
225
+ got_fingerprint = None
226
+ for line in output.splitlines():
227
+ if line.startswith("fpr:"):
228
+ got_fingerprint = line.split(":")[9]
229
+ # stop after the first to ensure no subkey trickery
230
+ break
231
+ # strip the leading "0x" is there is one and uppercase (as this is
232
+ # what gnupg is using)
233
+ signing_key_fingerprint = keyid.replace("0x", "").upper()
234
+ if got_fingerprint != signing_key_fingerprint:
235
+ # make the error match what gnupg >= 1.4.18 will output when
236
+ # it checks the key itself before importing it
237
+ raise AptKeyError(
238
+ "recv from '%s' failed for '%s'" % (keyserver, signing_key_fingerprint)
239
+ )
240
+ # finally add it
241
+ add_key_from_file(tmp_export_keyring)
242
+
243
+
244
+ def add_key(content):
245
+ # type: (str) -> None
246
+ """Import a GnuPG key to trust repositores signed by it.
247
+
248
+ Keyword arguments:
249
+ content -- the content of the GnuPG public key
250
+ """
251
+ _call_apt_key_script("adv", "--quiet", "--batch", "--import", "-", stdin=content)
252
+
253
+
254
+ def remove_key(fingerprint):
255
+ # type: (str) -> None
256
+ """Remove a GnuPG key to no longer trust repositores signed by it.
257
+
258
+ Keyword arguments:
259
+ fingerprint -- the fingerprint identifying the key
260
+ """
261
+ _call_apt_key_script("rm", fingerprint)
262
+
263
+
264
+ def export_key(fingerprint):
265
+ # type: (str) -> str
266
+ """Return the GnuPG key in text format.
267
+
268
+ Keyword arguments:
269
+ fingerprint -- the fingerprint identifying the key
270
+ """
271
+ return _call_apt_key_script("export", fingerprint)
272
+
273
+
274
+ def update():
275
+ # type: () -> str
276
+ """Update the local keyring with the archive keyring and remove from
277
+ the local keyring the archive keys which are no longer valid. The
278
+ archive keyring is shipped in the archive-keyring package of your
279
+ distribution, e.g. the debian-archive-keyring package in Debian.
280
+ """
281
+ return _call_apt_key_script("update")
282
+
283
+
284
+ def net_update():
285
+ # type: () -> str
286
+ """Work similar to the update command above, but get the archive
287
+ keyring from an URI instead and validate it against a master key.
288
+ This requires an installed wget(1) and an APT build configured to
289
+ have a server to fetch from and a master keyring to validate. APT
290
+ in Debian does not support this command and relies on update
291
+ instead, but Ubuntu's APT does.
292
+ """
293
+ return _call_apt_key_script("net-update")
294
+
295
+
296
+ def list_keys():
297
+ # type: () -> List[TrustedKey]
298
+ """Returns a list of TrustedKey instances for each key which is
299
+ used to trust repositories.
300
+ """
301
+ # The output of `apt-key list` is difficult to parse since the
302
+ # --with-colons parameter isn't user
303
+ output = _call_apt_key_script(
304
+ "adv", "--with-colons", "--batch", "--fixed-list-mode", "--list-keys"
305
+ )
306
+ res = []
307
+ for line in output.split("\n"):
308
+ fields = line.split(":")
309
+ if fields[0] == "pub":
310
+ keyid = fields[4]
311
+ if fields[0] == "uid":
312
+ uid = fields[9]
313
+ creation_date = fields[5]
314
+ key = TrustedKey(uid, keyid, creation_date)
315
+ res.append(key)
316
+ return res
317
+
318
+
319
+ if __name__ == "__main__":
320
+ # Add some known keys we would like to see translated so that they get
321
+ # picked up by gettext
322
+ lambda: _("Ubuntu Archive Automatic Signing Key <ftpmaster@ubuntu.com>")
323
+ lambda: _("Ubuntu CD Image Automatic Signing Key <cdimage@ubuntu.com>")
324
+
325
+ apt_pkg.init()
326
+ for trusted_key in list_keys():
327
+ print(trusted_key)