ud-mailgate: remove exception for münchen.debian.net
[mirror/userdir-ldap.git] / ud-host
diff --git a/ud-host b/ud-host
index 92dda0c..438e272 100755 (executable)
--- a/ud-host
+++ b/ud-host
@@ -1,5 +1,26 @@
 #!/usr/bin/env python
 # -*- mode: python -*-
+
+#   Copyright (c) 2000-2001  Jason Gunthorpe <jgg@debian.org>
+#   Copyright (c) 2001       Ryan Murray <rmurray@debian.org>
+#   Copyright (c) 2003       James Troup <troup@debian.org>
+#   Copyright (c) 2004-2005  Joey Schulze <joey@infodrom.org>
+#   Copyright (c) 2008,2009  Peter Palfrader <peter@palfrader.org>
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
 # This script is an interactive way to manipulate fields in the LDAP directory.
 # When run it connects to the directory using the current users ID and fetches
 # all the attributes for the first machine. It then formats them nicely and
@@ -9,8 +30,12 @@
 #    -a    Set the authentication user (the user whose password you are
 #          going to enter)
 #    -h    Set the host to display
+#    -l    list all hosts and their status
+#    -f    list all SSH fingerprints
 
-import string, time, os, pwd, sys, getopt, ldap, crypt, whrandom, readline, copy;
+import time, os, pwd, sys, getopt, ldap, crypt, readline, copy;
+from tempfile import mktemp
+from os import O_CREAT, O_EXCL, O_WRONLY
 from userdir_ldap import *;
 
 RootMode = 0;
@@ -26,8 +51,17 @@ AttrInfo = {"description": ["Machine Descr.", 1],
             "machine": ["Machine Hardware", 10],
             "memory": ["Memory", 11],
             "disk": ["Disk", 12],
-            "sshrsahostkey": ["SSH Host Keys", 14],
-            "bandwidth": ["Bandwidth", 15]};
+            "physicalHost": ["Physical Host", 13],
+            "sshRSAHostKey": ["SSH Host Keys", 14],
+            "bandwidth": ["Bandwidth", 15],
+            "purpose": ["Purposes", 16],
+            "allowedGroups": ["Groups", 17],
+            "exportOptions": ["Export-Opts", 18],
+            "ipHostNumber": ["IP Address", 19],
+            "mXRecord": ["MXRecord", 20],
+            "dnsTTL": ["dnsTTL", 21],
+            "sshdistAuthKeysHost": ["extra authkeys ip", 22],
+            }
 
 AttrPrompt = {"description": ["Purpose of the machine"],
               "hostname": ["The hostnames for the box (ipv4/ipv6)"],
@@ -37,12 +71,21 @@ AttrPrompt = {"description": ["Purpose of the machine"],
               "distribution": ["The distribution version"],
               "access": ["all, developer only, restricted"],
               "admin": ["Admin email address"],
-              "architecture": ["Debian Arhitecture string"],
+              "architecture": ["Debian Architecture string"],
               "machine": ["Hardware description"],
               "memory": ["Installed RAM"],
               "disk": ["Disk Space, RAID levels, etc"],
-             "sshrsahostkey": ["A copy of /etc/ssh/ssh_*host_key.pub"],
-              "bandwidth": ["Available outbound"]};
+              "physicalHost": ["The box hosting this virtual server"],
+              "sshRSAHostKey": ["A copy of /etc/ssh/ssh_*host_key.pub"],
+              "bandwidth": ["Available outbound"],
+              "purpose": ["The purposes of this host"],
+              "allowedGroups": ["allowed Groups on this host"],
+              "exportOptions": ["additional export options"],
+              "ipHostNumber": ["IP Addresses(es) of the machine"],
+              "mXRecord": ["Mail Exchanger for this machine"],
+              "dnsTTL": ["dns TTL value"],
+              "sshdistAuthKeysHost": ["additional hosts for sshdist's authkeys file"],
+              };
 
 # Create a map of IDs to desc,value,attr
 OrderedIndex = {};
@@ -53,14 +96,14 @@ OrigOrderedIndex = copy.deepcopy(OrderedIndex);
 
 # Print out the automatic time stamp information
 def PrintModTime(Attrs):
-   Stamp = GetAttr(Attrs,"modifytimestamp","");
+   Stamp = GetAttr(Attrs,"modifyTimestamp","");
    if len(Stamp) >= 13:
       Time = (int(Stamp[0:4]),int(Stamp[4:6]),int(Stamp[6:8]),
               int(Stamp[8:10]),int(Stamp[10:12]),int(Stamp[12:14]),0,0,-1);
       print "%-24s:" % ("Record last modified on"), time.strftime("%a %d/%m/%Y %X UTC",Time),
-      print "by",ldap.explode_dn(GetAttr(Attrs,"modifiersname"),1)[0];
+      print "by",ldap.explode_dn(GetAttr(Attrs,"modifiersName"),1)[0];
 
-   Stamp = GetAttr(Attrs,"createtimestamp","");
+   Stamp = GetAttr(Attrs,"createTimestamp","");
    if len(Stamp) >= 13:
       Time = (int(Stamp[0:4]),int(Stamp[4:6]),int(Stamp[6:8]),
               int(Stamp[8:10]),int(Stamp[10:12]),int(Stamp[12:14]),0,0,-1);
@@ -90,9 +133,21 @@ def ShowAttrs(Attrs):
             print "'%s'" % (re.sub('[\n\r]','?',x)),
          print;
 
+def Overview(Attrs):
+   """Display a one-line overview for a given host"""
+   for i in ['host','architecture','distribution','access','status']:
+      if i not in Attrs[1].keys():
+         Attrs[1][i] = ['']
+   print "%-12s  %-10s  %-38s  %-25s %s" % (\
+      Attrs[1]['host'][0], \
+      Attrs[1]['architecture'][0], \
+      Attrs[1]['distribution'][0], \
+      Attrs[1]['access'][0], \
+      Attrs[1]['status'][0])
+
 # Change a single attribute
 def ChangeAttr(Attrs,Attr):
-   if (Attr == "sponsor" or Attr == "hostname" or Attr == "sshrsahostkey"):
+   if (Attr in ["sponsor", "sshRSAHostKey", "purpose", "allowedGroups", "exportOptions", "ipHostNumber", "mXRecord", "sshdistAuthKeysHost"]):
       return MultiChangeAttr(Attrs,Attr);
 
    print "Old value: '%s'" % (GetAttr(Attrs,Attr,""));
@@ -130,7 +185,7 @@ def MultiChangeAttr(Attrs,Attr):
    Attrs[1][Attr].sort();
    print "Old values: ",Attrs[1][Attr];
 
-   Mode = string.upper(raw_input("[D]elete or [A]dd? "));
+   Mode = raw_input("[D]elete or [A]dd? ").upper()
    if (Mode != 'D' and Mode != 'A'):
       return;
 
@@ -158,11 +213,32 @@ def MultiChangeAttr(Attrs,Attr):
    Attrs[1][Attr].append(NewValue);
    print;
 
+def CalcTempFile():
+   unique = 0
+   while unique == 0:
+      name = mktemp()
+      try:
+         fd = os.open(name, O_CREAT | O_EXCL | O_WRONLY, 0600)
+      except OSError:
+         continue
+      os.close(fd)
+      unique = 1
+   return name
+
+
 # Main program starts here
 User = pwd.getpwuid(os.getuid())[0];
 BindUser = User;
+ListMode = 0
+FingerPrints = 0
+Host = None
 # Process options
-(options, arguments) = getopt.getopt(sys.argv[1:], "nh:a:r")
+try:
+   (options, arguments) = getopt.getopt(sys.argv[1:], "nh:a:rlf")
+except getopt.GetoptError, data:
+   print data
+   sys.exit(1)
+
 for (switch, val) in options:
    if (switch == '-h'):
       Host = val;
@@ -172,30 +248,64 @@ for (switch, val) in options:
       RootMode = 1;
    elif (switch == '-n'):
       BindUser = "";
+   elif (switch == '-l'):
+      BindUser = "";
+      ListMode = 1
+   elif (switch == '-f'):
+      BindUser = "";
+      FingerPrints = 1
 
 if (BindUser != ""):
-   print "Accessing LDAP entry",
-if (BindUser != User):
-   if (BindUser != ""):
-      print "as '" + BindUser + "'";
-else:
-   print;
-if (BindUser != ""):
-   Password = getpass(BindUser + "'s password: ");
-
-# Connect to the ldap server
-l = ldap.open(LDAPServer);
-UserDn = "uid=" + BindUser + "," + BaseDn;
-if (BindUser != ""):
-   l.simple_bind_s(UserDn,Password);
+   l = passwdAccessLDAP(BaseDn, BindUser)
 else:
-   l.simple_bind_s("","");
-
-HBaseDn = "ou=hosts,dc=debian,dc=org";
-HostDn = "host=" + Host + "," + HBaseDn;
+   l = connectLDAP()
+   l.simple_bind_s("","")
+
+if ListMode == 1:
+   Attrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=*")
+   hosts = []
+   for hAttrs in Attrs:
+      hosts.append(hAttrs[1]['host'][0])
+   hosts.sort()
+
+   print "%-12s  %-10s  %-38s  %-25s %s" % ("Host name","Arch","Distribution","Access","Status")
+   print "-"*115
+   for host in hosts:
+      for hAttrs in Attrs:
+         if host == hAttrs[1]['host'][0]:
+            Overview(hAttrs)
+   sys.exit(0)
+elif FingerPrints == 1:
+   if Host is not None:
+      Attrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + Host)
+   else:
+      Attrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=*")
+   hosts = []
+   for hAttrs in Attrs:
+      hosts.append(hAttrs[1]['host'][0])
+   hosts.sort()
+
+   tmpfile = CalcTempFile()
+   for host in hosts:
+      for hAttrs in Attrs:
+         if host == hAttrs[1]['host'][0]:
+            if 'sshRSAHostKey' in hAttrs[1].keys():
+               for key in hAttrs[1]['sshRSAHostKey']:
+                  tmp = open(tmpfile, 'w')
+                  tmp.write(key + '\n')
+                  tmp.close()
+                  fp = os.popen('/usr/bin/ssh-keygen -l -f ' + tmpfile, "r")
+                  input = fp.readline()
+                  fp.close()
+                  fingerprint = input.split(' ')
+                  print "%s %s root@%s" % (fingerprint[0], fingerprint[1], host)
+   os.unlink(tmpfile)
+   sys.exit(0)
+
+HostDn = "host=" + Host + "," + HostBaseDn;
 
 # Query the server for all of the attributes
-Attrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + Host);
+Attrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + Host);
 if len(Attrs) == 0:
    print "Host",Host,"was not found.";
    sys.exit(0);
@@ -215,7 +325,7 @@ while(1):
 
    # Prompt
    Response = raw_input("Change? ");
-   if (Response == "x" or Response == "X" or Response == "q" or 
+   if (Response == "x" or Response == "X" or Response == "q" or
        Response == "quit" or Response == "exit"):
       break;
 
@@ -224,13 +334,13 @@ while(1):
       NewHost = raw_input("Host? ");
       if NewHost == "":
          continue;
-      NAttrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost);
+      NAttrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost);
       if len(NAttrs) == 0:
          print "Host",NewHost,"was not found.";
          continue;
       Attrs = NAttrs;
       Host = NewHost;
-      HostDn = "host=" + Host + "," + HBaseDn;
+      HostDn = "host=" + Host + "," + HostBaseDn;
       OrderedIndex = copy.deepcopy(OrigOrderedIndex);
       continue;
 
@@ -239,22 +349,26 @@ while(1):
       NewHost = raw_input("Host? ");
       if NewHost == "":
          continue;
-      NAttrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost);
+      NAttrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost);
       if len(NAttrs) != 0:
          print "Host",NewHost,"already exists.";
          continue;
-      Dn = "host=" + NewHost + "," + HBaseDn;
-      l.add_s(Dn,[("host",NewHost),
-                  ("objectclass","top")]);
+      NewHostName = raw_input("Hostname? ");
+      if NewHost == "":
+         continue;
+      Dn = "host=" + NewHost + "," + HostBaseDn;
+      l.add_s(Dn,[("host", NewHost),
+                  ("hostname", NewHostName),
+                  ("objectClass", ("top", "debianServer"))]);
 
       # Switch
-      NAttrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost);
+      NAttrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost);
       if len(NAttrs) == 0:
          print "Host",NewHost,"was not found.";
          continue;
       Attrs = NAttrs;
       Host = NewHost;
-      HostDn = "host=" + Host + "," + HBaseDn;
+      HostDn = "host=" + Host + "," + HostBaseDn;
       OrderedIndex = copy.deepcopy(OrigOrderedIndex);
       continue;