From f3a9d113fd89db152db9cd2f061fc8f7367f0fc9 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sat, 22 Feb 2020 00:16:19 -0700 Subject: notmuch-slurp-debbug: use Mail::Box instead of shelling out Also some refactoring for readability. Signed-off-by: Sean Whitton --- debian/control | 1 - 1 file changed, 1 deletion(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 613335c..3ce1ac4 100644 --- a/debian/control +++ b/debian/control @@ -43,7 +43,6 @@ Depends: libipc-system-simple-perl, liblist-moreutils-perl, libmail-box-perl, - libmime-tools-perl, python3, ${misc:Depends}, ${perl:Depends}, -- cgit v1.2.3 From 51e0c8a488b7a8d195d32d0bc58e5ef24b38e626 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Tue, 10 Mar 2020 12:49:36 -0400 Subject: imap-dl: Kerberos support using python3-gssapi This is based off offlineimap's code rather than getmail's. getmail relied on pykerberos, which is considered deprecated in Fedora/RHEL/CentOS; offlineimap relied on python-gssapi, which is considered its replacement there. python3-gssapi doesn't yet have type annotations, but this is planned to change in the future. Signed-off-by: Robbie Harwood Acked-by: Daniel Kahn Gillmor --- debian/control | 1 + imap-dl | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- imap-dl.1.pod | 4 ++++ 3 files changed, 65 insertions(+), 2 deletions(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 3ce1ac4..ffe889d 100644 --- a/debian/control +++ b/debian/control @@ -51,6 +51,7 @@ Recommends: git, notmuch, python3-argcomplete, + python3-gssapi, python3-pgpy, Suggests: gnutls-bin, diff --git a/imap-dl b/imap-dl index f1259da..83ce84f 100755 --- a/imap-dl +++ b/imap-dl @@ -50,13 +50,19 @@ import argparse import statistics import configparser -from typing import Dict, List, Union, Tuple +from typing import Dict, List, Optional, Tuple, Union try: import argcomplete #type: ignore except ImportError: argcomplete = None +try: + import gssapi # type: ignore +except ModuleNotFoundError: + gssapi = None + + class Splitter(object): def __init__(self, name:str, match:bytes): self._splitter = re.compile(match) @@ -88,6 +94,52 @@ def auth_builtin(username:str, imap:imaplib.IMAP4_SSL, if resp[0] != 'OK': raise Exception(f'login failed with {resp} as user {username} on {server}') +# imaplib auth methods need to be in the form of callables, and they all +# requre both additional parameters and storage beyond what the function +# interface provides. +class GSSAPI_handler(): + gss_vc:gssapi.SecurityContext + username:str + + def __init__(self, server:str, username:str) -> None: + name = gssapi.Name(f'imap@{server}', gssapi.NameType.hostbased_service) + self.gss_vc = gssapi.SecurityContext(usage="initiate", name=name) + self.username = username + + def __call__(self, token:Optional[bytes]) -> bytes: + if token == b"": + token = None + if not self.gss_vc.complete: + response = self.gss_vc.step(token) + return response if response else b"" # type: ignore + elif token is None: + return b"" + + response = self.gss_vc.unwrap(token) + + # Preserve the "length" of the message we received, and set the first + # byte to one. If username is provided, it's next. + reply:List[int] = [] + reply[0:4] = response.message[0:4] + reply[0] = 1 + if self.username: + reply[5:] = self.username.encode("utf-8") + + response = self.gss_vc.wrap(bytes(reply), response.encrypted) + return response.message if response.message else b"" # type: ignore + +def auth_gssapi(username:str, imap:imaplib.IMAP4_SSL, + conf:configparser.ConfigParser, server:str) -> None: + if not gssapi: + raise Exception('Kerberos requested, but python3-gssapi not found') + + logging.info(f'Logging in as {username} with GSSAPI') + + callback = GSSAPI_handler(server, username) + resp = imap.authenticate("GSSAPI", callback) + if resp[0] != 'OK': + raise Exception(f'GSSAPI login failed with {resp} as user {username} on {server}') + def scan_msgs(configfile:str, verbose:bool) -> None: conf = configparser.ConfigParser() conf.read_file(open(configfile, 'r')) @@ -133,7 +185,13 @@ def scan_msgs(configfile:str, verbose:bool) -> None: port=int(conf.get('retriever', 'port', fallback=993)), ssl_context=ctx) as imap: username:str = conf.get('retriever', 'username') - auth_builtin(username, imap, conf, server) + use_kerberos = conf.getboolean('retriever', 'use_kerberos', + fallback=False) + if use_kerberos: + auth_gssapi(username, imap, conf, server) + else: + auth_builtin(username, imap, conf, server) + if verbose: # only enable debugging after login to avoid leaking credentials in the log imap.debug = 4 logging.info("capabilities reported: %s", ', '.join(imap.capabilities)) diff --git a/imap-dl.1.pod b/imap-dl.1.pod index 7998d3a..5864267 100644 --- a/imap-dl.1.pod +++ b/imap-dl.1.pod @@ -48,6 +48,10 @@ B is the username of the IMAP account. B is the password for the IMAP account when using plaintext passwords. +B (boolean) requests that Kerberos (through GSSAPI) is +to be used instead of password-based auth. There is no need to specify +password when using Kerberos. This requires the python3-gssapi module. + B is an OpenSSL cipher string to use instead of the defaults. (The defaults are good; this should be avoided except to work around bugs.) -- cgit v1.2.3