]> granicus.if.org Git - sudo/commitdiff
Merged in LDAP Support
authorAaron Spangler <aaron777@gmail.com>
Fri, 13 Feb 2004 02:08:27 +0000 (02:08 +0000)
committerAaron Spangler <aaron777@gmail.com>
Fri, 13 Feb 2004 02:08:27 +0000 (02:08 +0000)
CHANGES
Makefile.in
README.LDAP [new file with mode: 0644]
config.h.in
configure.in

diff --git a/CHANGES b/CHANGES
index 0f5bce92dc33f7581d763142a31314ecd744f2ec..a750be7eb7d41571250d73314a156fd6af5fcc00 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1670,3 +1670,5 @@ Sudo 1.6.7p6 released.
      be logged as run by the user specified by the SUDO_USER environment
      variable.  In -e mode (sudoedit), SUDO_USER is used to determine
      what user to run the editor when the real uid is 0.
+
+524) Merged in LDAP support from Aaron Spangler.
index 8e06986ee868820bc18d7ed7aefc17504ba43105..2b70099250194217009f0c0a29aa039c813994c0 100644 (file)
@@ -118,7 +118,7 @@ PROGS = @PROGS@
 
 SRCS = alloc.c alloca.c check.c closefrom.c def_data.c defaults.c env.c err.c \
        fileops.c find_path.c fnmatch.c getcwd.c getprogname.c getspwuid.c \
-       goodpath.c interfaces.c lex.yy.c lsearch.c logging.c parse.c parse.lex \
+       goodpath.c interfaces.c ldap.c lex.yy.c lsearch.c logging.c parse.c parse.lex \
        parse.yacc set_perms.c sigaction.c snprintf.c strcasecmp.c strerror.c \
        strlcat.c strlcpy.c sudo.c sudo.tab.c sudo_edit.c testsudoers.c \
        tgetpass.c utime.c visudo.c zero_bytes.c $(AUTH_SRCS)
@@ -139,7 +139,7 @@ PARSEOBJS = sudo.tab.o lex.yy.o alloc.o defaults.o
 
 SUDOBJS = check.o env.o getspwuid.o goodpath.o fileops.o find_path.o \
          interfaces.o logging.o parse.o set_perms.o sudo.o sudo_edit.o \
-         tgetpass.o zero_bytes.o $(AUTH_OBJS) $(PARSEOBJS)
+         tgetpass.o zero_bytes.o @SUDO_OBJS@ $(AUTH_OBJS) $(PARSEOBJS)
 
 VISUDOBJS = visudo.o fileops.o goodpath.o find_path.o $(PARSEOBJS)
 
@@ -247,6 +247,7 @@ strlcat.o: strlcat.c config.h
 strlcpy.o: strlcpy.c config.h
 strerror.o: strerror.c config.h
 utime.o: utime.c config.h pathnames.h compat.h emul/utime.h
+ldap.o: ldap.c $(SUDODEP) parse.h
 
 # Authentication functions live in "auth" dir and so need extra care
 sudo_auth.o: $(authdir)/sudo_auth.c $(AUTHDEP) $(INSDEP)
diff --git a/README.LDAP b/README.LDAP
new file mode 100644 (file)
index 0000000..8e83b8f
--- /dev/null
@@ -0,0 +1,274 @@
+This file explains how to use the optional LDAP functionality of SUDO to
+store /etc/sudoers information.  This feature is separate from LDAP passwords.
+
+LDAP philosophy
+===============
+As times change and servers become cheap, an enterprise can easily have 500+
+UNIX servers.  Using LDAP to synchronize Users, Groups, Hosts, Mounts, and
+others across an enterprise can greatly reduce the administrative overhead.
+
+Sudo in the past has only used a single local configuration file /etc/sudoers.
+Some have attempted to workaround this by synchronizing changes via
+RCS/CVS/RSYNC/RDIST/RCP/SCP and even NFS.  Many have asked for a Hesiod, NIS,
+or LDAP patch for sudo, so here is my attempt at LDAP'izing sudo.
+
+Definitions
+===========
+Many times the word 'Directory' is used in the document to refer to the LDAP
+server, structure and contents.
+
+Many times 'options' are used in this document to refer to sudoer 'defaults'.
+They are on in the same.
+
+Design Features
+===============
+
+  * Sudo no longer needs to read all sudoers.  Parsing of /etc/sudoers requires
+      the entire file to be read.  The LDAP feature of sudo uses two
+      (sometimes three) LDAP queries per invocation.  It never reads the
+      all the sudoer entries in the LDAP store.  This makes it
+      especially fast and particularly usable in LDAP environments.
+      The first query is to parse default options (see below).  The second
+      is to match against the username or groups a user belongs to.
+      (The special ALL tag is matched in this query too.)
+      If not match is against the username, the third query pulls the entries
+      that match against user netgroups to compare back to the user.
+
+  * Sudo no longer blows up if there is a typo.  Parsing of /etc/sudoers can
+      still blow up when sudo is invoked.  However when using the LDAP feature
+      of sudo, LDAP syntax rules are applied before the data is uploaded into
+      the LDAP server, so proper syntax is always guaranteed!
+      One can of course still insert a bogus hostname or username,
+      but sudo will not care.
+
+  * Options inside of entries now override global default options.
+      /etc/sudoers allowed for only default options and limited options
+      associated with user/host/command aliases.  The syntax can be difficult
+      for the newbie.  The LDAP feature attempts to simplify this and yet
+      still provide maximum flexibility.
+
+      Sudo first looks for an entry called 'cn=default' in the SUDOers
+      container.  If found, the multi-valued sudoOption attribute is parsed
+      the same way the global 'Defaults' line in /etc/sudoers is parsed.
+
+      If on the second or third query, a response containing a sudoRole
+      which matches against the user, host, and command, then the matched
+      object is scanned for a additional options to override the top-level
+      defaults.  See the Example LDAP content below for more information.
+
+  * Visudo is no longer needed.  Visudo provides locking and syntax checking
+      against the /etc/sudoers file.  Since LDAP updates are atomic, locking
+      is no longer necessary.  Because syntax is checked when the data is
+      inserted into LDAP, the sudoers syntax check becomes unnecessary.
+
+  * Aliases are no longer needed.  User, Host, and Command Aliases were setup
+      to allow simplification and readability of the sudoers files.  Since the
+      LDAP sudoer entry allows multiple values for each of its attributes and
+      since most LDAP browsers are graphical and easy to work with, original
+      aliases are no longer needed.
+
+      If you want to specify lots of users into an entry or want to have
+      similar entries with identical users, then use either groups or user
+      netgroups.  Thats what groups and netgroups are for and Sudo handles
+      this well.  Or just paste them all into the LDAP record.
+
+      If you want to specify lots of hosts into an entry, use netgroups or
+      IP address matches (10.2.3.4/255.255.0.0).  Thats what netgroups are
+      for and Sudo handles this well.  Or just past them all into the LDAP
+      record.
+
+      If you want to specify lots of commands, use directories or wildcards,
+      or just paste them all into LDAP.  That's what it's for.
+
+  * The /etc/sudoers file can be disabled.  Paranoid security administrators
+      can now disallow parsing of any local /etc/sudoers file by an LDAP
+      sudoOption '!local_sudoers'.  This way all sudoers can be controlled
+      and audited in one place because local entries are not allowed.
+      In the future, this file may not be present.
+      BUG: THIS OPTION IS NOT IMPLEMENTED YET.
+
+  * The sudo binary compiled with LDAP support should be totally
+      backward compatible and be syntactically and source code equivalent
+      to its non LDAP-enabled build.
+
+
+Build instructions
+==================
+The most simplest way to build sudo with LDAP support is to include the
+'--with-ldap' option.  I recommend including the '--with-pam' option on those
+system with PAM so that if you decide to use LDAP for authentication, you won't
+need to recompile sudo.
+
+  $ ./configure --with-ldap --with-pam
+
+If your ldap libraries and headers are in a non standard place, you will need
+to specify them at configure time.
+
+  $ CPPFLAGS="-I/usr/local/ldapsdk/include" \
+  > LDFLAGS="-L/usr/local/ldapsdk/lib" \
+  > ./configure --with-ldap --with-pam
+
+In early revs of sudo where the '--with-ldap' option is not available, you
+need to manually append '#define HAVE_LDAP 1' to config.h and set
+LIBS='-lldap' in Makefile.
+
+Sudo by default builds against OpenLDAP's libraries.  For others LDAP
+libraries such as Netscape, iPlanet, Mozilla, SecureWay, add these lines
+to config.h before running make:
+
+  #undef HAVE_LDAP_INITIALIZE
+  #define HAVE_LBER_H
+
+You might have to also include '-llber' or '-lldif' in your LIBS.
+
+Your Mileage may vary.  Please let Aaron Spangler <aaron@spangler.ods.org>
+know what combinations worked best for your OS & LDAP Combinations so
+we can improve sudo.
+
+Schema Changes
+==============
+Add the following schema to your LDAP server so that it may contain sudoer
+content.  In OpenLDAP, simply place this into a new file and 'include' it
+in your slapd.conf and restart slapd.  For other LDAP servers, provide this
+to your LDAP Administrator.  Make sure to index the attribute 'sudoUser'.
+
+
+  #
+  #  schema file for sudo
+  #
+
+  attributetype ( 1.3.6.1.4.1.15953.9.1.1
+        NAME 'sudoUser'
+        DESC 'User(s) who may  run sudo'
+        EQUALITY caseExactIA5Match
+        SUBSTR caseExactIA5SubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+  attributetype ( 1.3.6.1.4.1.15953.9.1.2
+        NAME 'sudoHost'
+        DESC 'Host(s) who may run sudo'
+        EQUALITY caseExactIA5Match
+        SUBSTR caseExactIA5SubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+  attributetype ( 1.3.6.1.4.1.15953.9.1.3
+        NAME 'sudoCommand'
+        DESC 'Command(s) to be executed by sudo'
+        EQUALITY caseExactIA5Match
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+  attributetype ( 1.3.6.1.4.1.15953.9.1.4
+        NAME 'sudoRunAs'
+        DESC 'User(s) impersonated by sudo'
+        EQUALITY caseExactIA5Match
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+  attributetype ( 1.3.6.1.4.1.15953.9.1.5
+        NAME 'sudoOption'
+        DESC 'Options(s) followed by sudo'
+        EQUALITY caseExactIA5Match
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+  objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+        DESC 'Sudoer Entries'
+        MUST ( cn )
+        MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoOption $
+              description )
+        )
+
+
+Importing /etc/sudoers to LDAP
+==============================
+Importing is a two step process.
+
+Step 1:
+Ask your LDAP Administrator where to create the ou=SUDOers container.
+(An example location is shown below).  Then use the provided script to convert
+your sudoers file into LDIF format.  The script will also convert any default
+options.
+
+  # SUDOERS_BASE=ou=SUDOers,dc=example,dc=com
+  # export SUDOERS_BASE
+  # ./sudoers2ldif /etc/sudoers > /tmp/sudoers.ldif
+
+Step 2:
+Import into your directory server.  If you are using OpenLDAP, do the following
+if you are using another directory, provide the LDIF file to your LDAP
+Administrator.  An example is shown below.
+
+  # ldapadd -f /tmp/sudoers.ldif -h ldapserver \
+  > -D cn=Manager,dc=example,dc=com -W -x
+
+Example sudoers Entries in LDAP
+===============================
+The equivalent of a sudoer in LDAP is a 'sudoRole'.  It contains sudoUser(s),
+sudoHost, sudoCommand and optional sudoOption(s) and sudoRunAs(s).
+<put an example here>
+
+Managing LDAP entries
+=====================
+Doing a one-time bulk load of your ldap entries is fine.  However what if you
+need to make minor changes on a daily basis?  It doesn't make sense to delete
+and re-add objects.  (You can, but this is tedious).
+
+I recommend using any of the following LDAP browsers to administer your SUDOers.
+  * GQ - The gentleman's LDAP client - Open Source - I use this a lot on
+         Linux and since it is Schema aware, I don't need to create a sudoRole
+      template.
+    http://biot.com/gq/
+
+  * LDAP Browser/Editor - by Jarek Gawor - I use this a lot on Windows
+    and Solaris.  It runs anywhere in a Java Virtual Machine including
+    web pages.  You have to make a template from an existing sudoRole entry.
+    http://www.iit.edu/~gawojar/ldap
+    http://www.mcs.anl.gov/~gawor/ldap
+    http://ldapmanager.com
+
+  There are dozens of others, some open source, some free, some not.
+
+
+Configure your /etc/ldap.conf
+=============================
+The /etc/ldap.conf file is meant to be shared between sudo, pam_ldap, nss_ldap
+and other ldap applications and modules.  IBM Secureway unfortunately uses
+the same filename but has a different syntax.  If you need to rename where
+this file is stored, recompile SUDO with the -DLDAP_CONFIG compile option.
+
+Make sure you sudoers_base matches exactly with the location you specified
+when you imported the sudoers.  Below is an example /etc/ldap.conf
+
+  # Either specify a uri or host & port
+  #host          ldapserver
+  #port          389
+  uri            ldap://ldapserver
+  #
+  # must be set or sudo will ignore LDAP
+  sudoers_base   ou=SUDOers,dc=example,dc=com
+  #
+  # verbose sudoers matching from ldap
+  #sudoers_debug 2
+  #
+  # optional proxy credentials
+  #binddn        <who to search as>
+  #bindpw        <password>
+  #
+  # LDAP Protocol Version defaults to 3
+  #ldap_version 3
+  #
+
+Debugging your LDAP configuration
+=================================
+Enable debugging if you think sudo is not parsing LDAP the way you think it
+it should.  A value of 1 shows moderate debugging.  A value of 2 shows the
+results of the matches themselves.  Make sure to set the value back to zero
+so that other users don't get confused by the debugging messages.  This value
+is 'sudoers_debug' in the /etc/ldap.conf.
+
+Configure your /etc/nsswitch.conf
+=================================
+At the time of this writing, sudo does not consult nsswitch.conf for the
+search order.  But if it did, it would look like this:
+This might be implemented in the future.  For now just skip this step.
+
+  sudoers: files ldap
+
index e0ce34d0436bc03bbc89d9441ea31830eb4b4145..66628c04bdacd755199557e4723497ce101d168b 100644 (file)
 /* Define if you use Kerberos V. */
 #undef HAVE_KERB5
 
+/* Define if you use LDAP. */
+#undef HAVE_LDAP
+
+/* Define if your LDAP needs <lber.h>. (OpenLDAP does not) */
+#undef HAVE_LBER_H
+
+/* Define if your LDAP Supports URLs. (OpenLDAP does) */
+#define HAVE_LDAP_INITIALIZE
+
 /* Define to 1 if you have the `lockf' function. */
 #undef HAVE_LOCKF
 
index 5619c6ac7757cf93a2a1171083754582a892e1ce..9c3ee5ab4a6c61260af49f5105b12c8df0ae1ea2 100644 (file)
@@ -19,6 +19,7 @@ AC_SUBST(PROGS)dnl
 AC_SUBST(CPPFLAGS)dnl
 AC_SUBST(LDFLAGS)dnl
 AC_SUBST(SUDO_LDFLAGS)dnl
+AC_SUBST(SUDO_OBJS)dnl
 AC_SUBST(LIBS)dnl
 AC_SUBST(SUDO_LIBS)dnl
 AC_SUBST(NET_LIBS)dnl
@@ -906,6 +907,17 @@ AC_ARG_WITH(goons-insults, [  --with-goons-insults    include the insults from t
                ;;
 esac])
 
+AC_ARG_WITH(ldap, [  --with-ldap             enable LDAP support],
+[case $with_ldap in
+    yes)       AC_DEFINE(HAVE_LDAP, 1, [Define if you use LDAP.])
+               AC_MSG_CHECKING(whether to use sudoers from LDAP)
+               AC_MSG_RESULT(yes)
+               ;;
+    no)                ;;
+    *)         AC_MSG_ERROR(["--with-ldap does not take an argument."])
+               ;;
+esac])
+
 AC_ARG_WITH(pc-insults, [  --with-pc-insults       replace politically incorrect insults with less offensive ones],
 [case $with_pc_insults in  
     yes)       AC_DEFINE(PC_INSULTS, 1, [Define to replace politically incorrect insults with less offensive ones.])
@@ -2064,6 +2076,14 @@ if test "$with_authenticate" = "yes"; then
     SUDO_LIBS="${SUDO_LIBS} -ls"
 fi
 
+dnl
+dnl extra lib and .o file for LDAP support
+dnl
+if test "$with_ldap" = "yes"; then
+    SUDO_LIBS="${SUDO_LIBS} -lldap"
+    SUDO_OBJS="${SUDO_OBJS} ldap.o"
+fi
+
 dnl
 dnl Add $blibpath to SUDO_LDFLAGS if specified by the user or if we
 dnl added -L dirpaths to SUDO_LDFLAGS.