[27854] in Source-Commits
lert-compat commit: Initial revision
daemon@ATHENA.MIT.EDU (Victor Vasiliev)
Tue Mar 11 17:47:52 2014
Date: Tue, 11 Mar 2014 17:47:44 -0400
From: Victor Vasiliev <vasilvv@MIT.EDU>
Message-Id: <201403112147.s2BLlilH011350@drugstore.mit.edu>
To: source-commits@MIT.EDU
https://github.com/mit-athena/lert-compat/commit/8dab449450b87ce701a9d3a62d91b2b57b968554
commit 8dab449450b87ce701a9d3a62d91b2b57b968554
Author: Victor Vasiliev <vasilvv@mit.edu>
Date: Tue Mar 11 17:21:48 2014 -0400
Initial revision
lert | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
setup.py | 7 +++
2 files changed, 142 insertions(+), 0 deletions(-)
diff --git a/lert b/lert
new file mode 100755
index 0000000..2cf23ee
--- /dev/null
+++ b/lert
@@ -0,0 +1,135 @@
+#!/usr/bin/python
+
+"""
+Compatibility shim for lert.
+
+This is not a full lert implementation. It does only basic operations,
+like authenticating to lert server and printing response.
+"""
+
+import argparse
+import hesiod
+import krbV
+import random
+import socket
+import sys
+
+from struct import pack
+
+# =========== lert constants ===========
+
+LERT_VERSION = '2'
+LERT_TIMEOUT = 1
+LERT_SERVICE = 'daemon'
+LERT_PORT = 3717
+LERT_MAX_PACKET_SIZE = 2048
+
+LERT_BAD = '0'
+LERT_FREE = '1'
+LERT_MSG = '2'
+LERT_SICK = '3'
+
+# =========== Helper Athena functions ===========
+
+class LertError(Exception):
+ pass
+
+def locate_server():
+ """Locates the lert server through Hesiod."""
+
+ lookup = hesiod.Lookup("lert", "sloc")
+ if not lookup or not lookup.results:
+ raise LertError("Unable to locate lert server through Hesiod")
+
+ return random.choice(lookup.results)
+
+# =========== Actual lert client ===========
+
+def lert(server, acknowledge):
+ """Sends lert server a message and waits for response."""
+
+ _, _, addrs = socket.gethostbyaddr(server)
+ dest = (addrs[0], LERT_PORT)
+
+ # Initialize Kerberos variables
+ krb_ctx = krbV.default_context()
+ krb_ccache = krb_ctx.default_ccache()
+ krb_cprinc = krb_ccache.principal()
+ krb_sprinc = krbV.Principal(name='%s/%s' % (LERT_SERVICE, server.lower()), context=krb_ctx)
+ krb_authctx = krbV.AuthContext(context=krb_ctx)
+ krb_authctx.rcache = krb_ctx.default_rcache()
+
+ # Initialize the socket
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ sock.connect(dest)
+ sock.settimeout(LERT_TIMEOUT)
+
+ # Get the AP_REQ
+ krb_authctx.genaddrs(sock, krbV.KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR | krbV.KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR)
+ _, ap_req = krb_ctx.mk_req(client=krb_cprinc, server=krb_sprinc, ccache=krb_ccache, auth_context=krb_authctx)
+
+ # Send the request
+ packet = LERT_VERSION + pack('B', int(acknowledge)) + b"\0\0"
+ packet += ap_req
+ sock.sendall(packet)
+
+ # Receive the response
+ raw_response = sock.recv(LERT_MAX_PACKET_SIZE)
+ response = krb_authctx.rd_priv(raw_response)
+
+ # Parse the response
+ server_version = response[0]
+ response_code = response[1]
+ if server_version != LERT_VERSION:
+ raise LertError("Unrecognized lert server version")
+
+ if response_code == LERT_BAD:
+ raise LertError("lert server was unable to process the request")
+ if response_code == LERT_SICK:
+ raise LertError("lert server is malfunctioning")
+ if response_code == LERT_MSG:
+ return response[2:]
+ if response_code == LERT_FREE:
+ return ""
+ raise LertError("lert server returned invalid status code")
+
+# =========== Command-line interface ===========
+
+class DeprecatedAction(argparse.Action):
+ def __call__(self, parser, namespace, values, opt_str=None):
+ print >>sys.stderr, "WARNING: '%s' is obsolete and will be removed in future versions." % (opt_str)
+
+def deprecate_flag(parser, name):
+ """Adds an argument which is marked as deprecated."""
+
+ parser.add_argument(name, nargs=0, action=DeprecatedAction, help="[obsolete]")
+
+def main(args):
+ argparser = argparse.ArgumentParser(description="lert deactivation message client")
+
+ argparser.add_argument('-n', '--no', action="store_true",
+ help="Inform server that the message was read and should not be shown again")
+ argparser.add_argument('-q', '--quiet', action="store_true",
+ help="Do not display errors if operation fails")
+ argparser.add_argument('-s', '--server', help="lert server to use")
+
+ deprecate_flag(argparser, '-z')
+ deprecate_flag(argparser, '-m')
+
+ args = argparser.parse_args(args)
+
+ server = args.server if args.server else locate_server()
+
+ try:
+ message = lert(server, args.no)
+ if message:
+ print message
+ except Exception as err:
+ if not args.quiet:
+ if isinstance(err, krbV.Krb5Error):
+ _, err = err
+ print >>sys.stderr, "ERROR: %s" % err
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..08e389f
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,7 @@
+from distutils.core import setup
+
+setup(name='lert',
+ version='10.1',
+ author='Debathena Project',
+ author_email='debathena@mit.edu',
+ scripts=['lert'])