Merged in LDAP Support
This commit is contained in:
2
CHANGES
2
CHANGES
@@ -1670,3 +1670,5 @@ Sudo 1.6.7p6 released.
|
|||||||
be logged as run by the user specified by the SUDO_USER environment
|
be logged as run by the user specified by the SUDO_USER environment
|
||||||
variable. In -e mode (sudoedit), SUDO_USER is used to determine
|
variable. In -e mode (sudoedit), SUDO_USER is used to determine
|
||||||
what user to run the editor when the real uid is 0.
|
what user to run the editor when the real uid is 0.
|
||||||
|
|
||||||
|
524) Merged in LDAP support from Aaron Spangler.
|
||||||
|
@@ -118,7 +118,7 @@ PROGS = @PROGS@
|
|||||||
|
|
||||||
SRCS = alloc.c alloca.c check.c closefrom.c def_data.c defaults.c env.c err.c \
|
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 \
|
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 \
|
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 \
|
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)
|
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 \
|
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 \
|
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)
|
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
|
strlcpy.o: strlcpy.c config.h
|
||||||
strerror.o: strerror.c config.h
|
strerror.o: strerror.c config.h
|
||||||
utime.o: utime.c config.h pathnames.h compat.h emul/utime.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
|
# Authentication functions live in "auth" dir and so need extra care
|
||||||
sudo_auth.o: $(authdir)/sudo_auth.c $(AUTHDEP) $(INSDEP)
|
sudo_auth.o: $(authdir)/sudo_auth.c $(AUTHDEP) $(INSDEP)
|
||||||
|
274
README.LDAP
Normal file
274
README.LDAP
Normal file
@@ -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
|
||||||
|
|
@@ -162,6 +162,15 @@
|
|||||||
/* Define if you use Kerberos V. */
|
/* Define if you use Kerberos V. */
|
||||||
#undef HAVE_KERB5
|
#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. */
|
/* Define to 1 if you have the `lockf' function. */
|
||||||
#undef HAVE_LOCKF
|
#undef HAVE_LOCKF
|
||||||
|
|
||||||
|
20
configure.in
20
configure.in
@@ -19,6 +19,7 @@ AC_SUBST(PROGS)dnl
|
|||||||
AC_SUBST(CPPFLAGS)dnl
|
AC_SUBST(CPPFLAGS)dnl
|
||||||
AC_SUBST(LDFLAGS)dnl
|
AC_SUBST(LDFLAGS)dnl
|
||||||
AC_SUBST(SUDO_LDFLAGS)dnl
|
AC_SUBST(SUDO_LDFLAGS)dnl
|
||||||
|
AC_SUBST(SUDO_OBJS)dnl
|
||||||
AC_SUBST(LIBS)dnl
|
AC_SUBST(LIBS)dnl
|
||||||
AC_SUBST(SUDO_LIBS)dnl
|
AC_SUBST(SUDO_LIBS)dnl
|
||||||
AC_SUBST(NET_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])
|
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],
|
AC_ARG_WITH(pc-insults, [ --with-pc-insults replace politically incorrect insults with less offensive ones],
|
||||||
[case $with_pc_insults in
|
[case $with_pc_insults in
|
||||||
yes) AC_DEFINE(PC_INSULTS, 1, [Define to replace politically incorrect insults with less offensive ones.])
|
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"
|
SUDO_LIBS="${SUDO_LIBS} -ls"
|
||||||
fi
|
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
|
||||||
dnl Add $blibpath to SUDO_LDFLAGS if specified by the user or if we
|
dnl Add $blibpath to SUDO_LDFLAGS if specified by the user or if we
|
||||||
dnl added -L dirpaths to SUDO_LDFLAGS.
|
dnl added -L dirpaths to SUDO_LDFLAGS.
|
||||||
|
Reference in New Issue
Block a user