From: Peter Palfrader Date: Fri, 10 Sep 2010 12:53:44 +0000 (+0200) Subject: Add ud-krb-reset, and make ud-mailgate call it when receiving a mail at chpasswd... X-Git-Tag: userdir-ldap-0.3.78~1 X-Git-Url: https://git.adam-barratt.org.uk/?p=mirror%2Fuserdir-ldap.git;a=commitdiff_plain;h=200c280e08a33e415aae8c7f0da289284d2c4504 Add ud-krb-reset, and make ud-mailgate call it when receiving a mail at chpasswd@ saying 'Please change my Kerberos password'. --- diff --git a/debian/changelog b/debian/changelog index a608a32..f5973c2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,8 +13,11 @@ userdir-ldap (0.3.7x) xnstable; urgency=low functions. * userdir-ldap-slapd.conf: Fix ACL rule for keyring maintainers (we want group=..., not dn=...). + * Add ud-krb-reset, and make ud-mailgate call it when + receiving a mail at chpasswd@ saying + 'Please change my Kerberos password'. - -- Peter Palfrader Wed, 11 Aug 2010 11:11:53 +0200 + -- Peter Palfrader Fri, 10 Sep 2010 14:52:43 +0200 userdir-ldap (0.3.77) unstable; urgency=low diff --git a/debian/install b/debian/install index 0a06f86..31d24f8 100644 --- a/debian/install +++ b/debian/install @@ -11,6 +11,7 @@ ud-lock usr/bin ud-ldapshow usr/bin ud-userimport usr/bin ud-mailgate usr/bin +ud-krb-reset usr/bin ud-generate usr/bin ud-passchk usr/bin ud-useradd usr/bin diff --git a/ud-krb-reset b/ud-krb-reset new file mode 100755 index 0000000..d7e2eff --- /dev/null +++ b/ud-krb-reset @@ -0,0 +1,68 @@ +#!/usr/bin/perl + +# Copyright (c) 2010 Peter Palfrader + +# Resets the password for a kerberos principal given on the command line. +# If the principal does not exist, try to create them. + +use strict; +use Heimdal::Kadm5; +use Getopt::Long; +use English; +use String::Random; + +my $USAGE = "Usage: $PROGRAM_NAME [--admin=] [--keytab=] \n"; + +sub getname() { + my $username = getpwuid($UID); + die "Cannot get current username\n" unless defined $username; + return $username; +}; + +my $params; +Getopt::Long::config('bundling'); +GetOptions ( + '--help' => \$params->{'help'}, + '--admin=s' => \$params->{'admin'}, + '--keytab=s' => \$params->{'keytab'}, +) or die ($USAGE); + +if ($params->{'help'}) { + print $USAGE; + exit (0); +}; + +die $USAGE if (scalar @ARGV != 1); +my $name = shift @ARGV; + +unless (defined $params->{'admin'}) { + $params->{'admin'} = getname().'/admin'; +}; +unless (defined $params->{'keytab'}) { + $params->{'keytab'} = '/etc/userdir-ldap/keytab.'.getname(); +}; + +my $client = Heimdal::Kadm5::Client->new( + Principal => $params->{'admin'}, + Keytab => $params->{'keytab'} + ); +die "Unable to get Heimdal Client object.\n" unless defined $client; + + +my $password = '844u6MrG0gTS'; + +my $rnd = new String::Random; +my $password = $rnd->randregex('[a-zA-Z0-9]{16}'); + +my $principal = $client->getPrincipal($name); +unless (defined $principal) { + print "Principal appears to not exist. Trying to add.\n"; + $principal = $client->makePrincipal($name); + my $ret = $client->createPrincipal($principal, $password, undef); + die "Failed to create principal $name.\n" unless ($ret); + print "Created principal $name with password '$password'.\n"; +} else { + my $ret = $client->changePassword($name, $password); + die "Failed to change password for $name.\n" unless ($ret); + print "Changed password of principal $name to '$password'.\n"; +}; diff --git a/ud-mailgate b/ud-mailgate index f3752ec..a37b047 100755 --- a/ud-mailgate +++ b/ud-mailgate @@ -9,6 +9,7 @@ import userdir_gpg, userdir_ldap, sys, traceback, time, ldap, os, commands import pwd, tempfile +import subprocess from userdir_gpg import * from userdir_ldap import * @@ -568,6 +569,8 @@ def connect_to_ldap_and_check_if_locked(DnRecord): or GetAttr(Attrs[0],"userPassword").startswith("!"): raise UDNotAllowedError, "This account is locked"; + return l + # Handle an [almost] arbitary change def HandleChange(Reply,DnRecord,Key): global PlainText; @@ -690,6 +693,44 @@ def HandleChPass(Reply,DnRecord,Key): return Reply; +def HandleChKrbPass(Reply,DnRecord,Key): + # Connect to the ldap server, will throw an exception if account locked. + l = connect_to_ldap_and_check_if_locked(DnRecord) + + user = GetAttr(DnRecord,"uid") + krb_proc = subprocess.Popen( ('ud-krb-reset', user), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + krb_proc.stdin.close() + out = krb_proc.stdout.readlines() + krb_proc.wait() + exitcode = krb_proc.returncode + + # Use GPG to encrypt it + m = "Tried to reset your kerberos principal's password.\n" + if exitcode == 0: + m += "The exitcode of the reset script was zero, indicating that everything\n" + m += "worked. However, this being software who knows. Script's output below." + else: + m += "The exitcode of the reset script was %d, indicating that something\n"%(exitcode) + m += "went terribly, terribly wrong. Please consult the script's output below\n" + m += "for more information. Contact the admins if you have any questions or\n" + m += "require assitance." + + m += "\n"+''.join( map(lambda x: "| "+x, out) ) + + Message = GPGEncrypt(m, "0x"+Key[1],Key[4]); + if Message == None: + raise UDFormatError, "Unable to generate the encrypted reply, gpg failed."; + + Subst = {}; + Subst["__FROM__"] = ChPassFrom; + Subst["__EMAIL__"] = EmailAddress(DnRecord); + Subst["__CRYPTTYPE__"] = get_crypttype_preamble(Key) + Subst["__PASSWORD__"] = Message; + Subst["__ADMIN__"] = ReplyTo; + Reply = Reply + TemplateSubst(Subst,open(TemplatesDir+"passwd-changed","r").read()); + + return Reply; + # Start of main program # Drop messages from a mailer daemon. @@ -787,8 +828,10 @@ try: if sys.argv[1] == "ping": Reply = HandlePing(Reply,Attrs[0],pgp.key_info); elif sys.argv[1] == "chpass": - if PlainText.strip().find("Please change my Debian password"): + if PlainText.strip().find("Please change my Debian password") >= 0: Reply = HandleChPass(Reply,Attrs[0],pgp.key_info); + elif PlainText.strip().find("Please change my Kerberos password") >= 0: + Reply = HandleChKrbPass(Reply,Attrs[0],pgp.key_info); else: raise UDFormatError,"Please send a signed message where the first line of text is the string 'Please change my Debian password' or some other string we accept here."; elif sys.argv[1] == "change":