Linux Server Security (2nd Edition( [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Linux Server Security (2nd Edition( [Electronic resources] - نسخه متنی

Michael D. Bauer

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







7.3. LDAP Database Management


Okay, we've installed OpenLDAP, configured
slapd, gotten TLS encryption working, and
created our first LDAP record. Now
it's time to add some users and start using our
servere.g., for authenticating IMAP sessions.


7.3.1. Database Structure


The first step in creating an LDAP user database is to decide on a
directory structure i.e., whether to group users and other
entities or whether to instead use a completely flat structure. If
your LDAP database will be used strictly as an online address book or
authentication server, a flat database may suffice; in that case,
your users' Distinguished Names (DNs) will look like
this: dn=Mick Bauer,dc=wiremonkeys,dc=org. We
discussed some of the issues surrounding LDAP database structure
earlier, in the section "Hierarchies and Naming
Conventions." As I mentioned then, LDAP is extremely flexible, and there are far
more ways to structure an LDAP database than I can do justice to
here. So to keep this discussion simple, I'm going
to use a flat database for the rest of this
chapter's examples; I leave it to you to determine
whether and how to structure an LDAP database that best meets your
particular LDAP needs. The documentation at http://www.openldap.org and included with
OpenLDAP software provides ample examples.

7.3.1.1 Schema and user records


A related decision you'll need to make is which
LDAP attributes to include for each
record. I've described how these are grouped and
interrelated in schemas; you may recall that the schemas you specify
(include) in /etc/openldap/slapd.conf determine
which attributes will be available for you to use in records.

In addition to including schema in
/etc/openldap/slapd.conf, in each record you
create you'll need to use
objectclass statements to associate the
appropriate schemas with each user. Again, the schema files in
/etc/openldap/schema determine which schema
support which attributes, and within a given schema, which object
classes those attributes apply to.

It may seem like a kluge to sort through and combine
objectclasses, trying to cobble together the right
combination of LDAP attributes to meet your particular needs:
wouldn't it make more sense to somehow pull all your
desired attributes into a single, custom
objectclass? It would, and you can, by creating
your own schema file. However, it turns out to be much less work, and
much less of a "reinventing the
wheel" exercise, to simply combine a few standard
objectclasses.

Suppose you intend to use your LDAP server to authenticate one of the
many protocols such as POP or IMAP, which request a username and a
password. The essential LDAP attributes for this purpose are
uid and
userPassword..

One way to determine which schema and object classes provide
uid and userPassword is to
grep the contents of
/etc/openldap/schema for the strings
uid and userPassword, note
which files contain them, and then manually parse those files to find
the object classes that contain those attributes in MUST() or MAY( ) statements. If I do this for
uid on Red Hat 7.3 system running OpenLDAP 2.0, I
find that the files
core.schema,
cosine.schema,
inetorgperson.schema,
nis.schema, and
openldap.schema contain references to the
uid attribute.

Quick scans of these files (using less) tell me
that:

core.schema's object
uidObject requires uid cosine.schema's only reference
to the attribute uid is commented out and can be
disregarded inetorgperson.schema contains an object class,
inetOrgPerson, which supports
uid as an optional attribute nis.schema contains two object classes,
posixAccount and shadowAccount,
both of which require uid openldap.schema's object class
OpenLDAPperson also requires
uid
Luckily, there's a much faster way to determine the
same information: the gq LDAP tool allows you to
browse all supported attributes in all supported schema on your LDAP
server. Figure 7-5 contains a screenshot
illustrating my LDAP server's support for
uid, according to gq.


Figure 7-5. Schema browsing with gq


Note the "Used in
objectclasses" box in Figure 7-5,
which tells us that the selected attribute, uid,
is used in the object classes uidObject,
posixAccount, shadowAccount,
and inetOrgPerson, all four of which we identified
earlier via grep. The object class
OpenLDAPperson does not appear in the
gq screen: this is because the LDAP server in
question doesn't have an include
statement in its /etc/openldap/slapd.conf file
for the file openldap.schema. When in doubt,
therefore, you should include even schemas you're
not sure you need: after you settle on an LDAP record format, you can
always uninclude schemas that don't contain object
classes you need.

All this probably sounds like a lot of trouble, and indeed it can be,
but it's extremely important for you to be able to
create records that contain the kinds of information pertinent to
your LDAP needs, and since LDAP is so flexible, figuring out
precisely how to assemble that information in the form of attributes
can take some tinkering.

7.3.2. Building and Adding Records


Just as schema-browsing can be done either
manually or via GUI, so can adding LDAP records. We used the manual
method to create our root-organization entry, and
we'll do so again to add our first user record. This
method has two steps: first create a special text file in LDIF
format, and then use the ldapadd command to
import it into the LDAP database. Consider the
LDIF file in
Example 7-6.

Example 7-6. LDIF file for a user record


dn: cn=Wong Fei Hung,dc=wiremonkeys,dc=org
cn: Wong Fei Hung
sn: Wong
givenname: Fei Hung
objectclass: person
objectclass: top
objectclass: inetOrgPerson
mail: wongfh@wiremonkeys.org
telephonenumber: 651-344-1043
o: Wiremonkeys
uid: wongfh Since they determine everything else, we'll begin by
examining Example 7-6s
objectclass statements: this user has been
associated with the object classes top (mandatory
for all records), person, and
inetorgperson. I chose person
because it supports the attributes userPassword
(which is not set in Example 7-6;
we'll set Mr. Wong's password
shortly) and telephonenumber, which I
don't need yet but may in the future. The object
class inetOrgPerson, as we've
seen, supports the uid attribute, plus a whole
slew of others that may also come in handy later.


One way around having to know and comply with the
MUST and MAY restrictions in schema is
to add the statement schemacheck
off to
/etc/openldap/slapd.conf. This will allow you to
use any attribute defined in any schema file included in
slapd.conf without needing to pay any attention
to object classes. However, it will also adversely affect your LDAP
server's interoperability with other LDAP servers,
and even with other applications (besides flouting LDAP RFCs), so
many LDAP experts consider it poor form to disable schema-checking in
this manner.

It isn't necessary to discuss each and every line in
Example 7-6; many of the attributes are
self-explanatory. Just know that:

You don't need to set every attribute you intend to
use, but some are mandatory (i.e., are contained in MUST() statements in their respective object class definitions).

Each attribute you do define must be specified in the
MUST( ) or MAY( ) statement of
at least one of the object classes defined in the record.

Some attributes, such as cn, may be defined
multiple times in the same record.


To add the record specified in Example 7-6, use the
ldapadd command:

ldapadd -x -D "cn=ldapguy,dc=wiremonkeys,dc=org" -W -f ./wong.ldif This is very similar to how we used ldapadd in
the previous section. For a complete explanation of this
command's syntax, see the
ldapadd(1)
manpage.

If you specified the attributes required by all object classes set in
the LDIF file and if all attributes you specified are supported by
those object classes and if, when prompted, you provide the correct
LDAP bind password, the record will be added to the database. If any
of those conditions is false, however, the action will fail and
ldapadd will tell you what went wrong. Thus, you
can use good old trial and error to craft a workable record format;
after all, once you've figured this out once, you
can use the same format for subsequent records without going through
all this schema-induced zaniness.

I offer one caveat: if your LDIF file contains multiple records,
which is permitted, keep in mind that if your LDAP server detects an
error, it will quit parsing the file and will not attempt to add any
records below the one that failed. Therefore, you should stick to
single-record LDIF files for the first couple of user-adds, until
you've finalized your record format.

That's the manual record-creation method:
it's a little clunky, but it easily accommodates
tinkering, which is especially useful in the early stages of LDAP
database construction.

Once you've got a user record or two in place, you
can use a GUI tool such as
gq or
ldapbrowser to create additional records. In
gq, for example, left-clicking on a record pops
up a menu containing the option "New
Use current
entry," which copies the selected record into a new
record. This is much faster and simpler than manually typing
everything into an LDIF file.

7.3.3. Creating Passwords


I mentioned in the description of Example 7-6 that
we generally don't specify user passwords in
LDIF
files: there's a separate mechanism for that, in the
form of the command
ldappasswd. By design, its syntax is very similar
to that of ldapadd:

ldappasswd -S -x -D "cn=hostmaster,dc=upstreamsolutions,dc=com" /
-W "cn=Phil Lesh,dc=upstreamsolutions,dc=com" (You'll be prompted for your existing and new
passwords after you enter this command.) You don't
need to be logged in to a shell session on the LDAP server to use the
ldappasswd command; you can use the
-H flag to specify the URL of a remote LDAP
server. For example:

ldappasswd -S -x -H ldaps://ldap.upstreamsolutions.com /
-D "cn=hostmaster,dc=upstreamsolutions,dc=com" -W
"cn=Phil Lesh,dc=upstreamsolutions,dc=com" This flag may also be used with
ldapadd.

Note the ldaps:// URL in the previous example:
since I've specified the -x flag
for simple cleartext authentication, I definitely need to connect to
the server with TLS encryption (again, ldaps is
ldap secure) rather than in the clear. (See the
previous section.) Having said all that, however, I must point out that password
management for end users is one of LDAP's problem
areas. On the one hand, if your users all have access to the
ldappasswd command (e.g., if they run Linux),
you can use a combination of local
/etc/ldap.conf files and scripts/frontends for
ldappasswd to make it reasonably simple for
users to change their own passwords.

But if users run some other OS (e.g., Windows), you must either
manage passwords centrally (i.e., have all users contact the email
administrator every time they need to change their password) or issue
users LDAP client software such as LDAP Browser/Editor and then teach
users how to use it. The former option needn't be as
distasteful as it may sound, so long as your email administrator is
trustworthy (this is necessary, regardless) and some common sense is
applied in how you go about it.


7.3.4. Access Controls


Technically, we've covered or touched on all the
tasks needed to build an LDAP server using OpenLDAP (excluding,
necessarily, the sometimes lengthy step of actually getting your
various server applications to successfully authenticate users
against it, which is covered by those respective
applications' own documentation). In the interest of
robust security, there's one more thing we should
discuss in detail:
OpenLDAP access-control lists (ACLs).

Like most other things affecting the slapd
daemon, these are set in
/etc/openldap/slapd.conf. And like most other
things involving LDAP, they can be confusing, to say the least, and
usually require some tinkering to get right.

Example 7-7 shows a sample set of ACLs.

Example 7-7. ACLs in /etc/slapd.conf


access to attrs=userPassword
by dn="cn=ldapguy,dc=wiremonkeys,dc=org" write
by self write
by * compare
access to *
by dn="cn=ldapguy,dc=wiremonkeys,dc=org" write
by users read
by * auth ACLs are described in detail in the
slapd.conf(5) manpage, but in Example 7-7, you can get the gist of how these work: for
each LDAP specification to which you wish to control access, you
specify who may access it and with what level of access. Technically,
an entire ACL may be listed on one line (e.g., access to *
by users read by * auth
), but by convention, we list each
by... statement on its own line;
slapd is smart enough to know that the string
access to marks the beginning of the next ACL.

While I'm not going to describe ACL syntax in great
detail, there are a few important points to note. First, ACLs are
parsed from top to bottom, and "first match
wins": they act like a stack of filters. Therefore,
it's crucial that you put specific ACLs and
by... statements above more general ones.

For example, in Example 7-7 we see an ACL
restricting access to the userPassword attribute,
followed by one applicable to *, meaning the
entire LDAP database. Putting the userPassword ACL
first means that the rule "allow users to change
their own passwords" (i.e., access to
attrs=userPassword by self write
) is an exception to the
more general rule "users may have only read-access
to anything" (i.e., access to
* by users read).

Another important point is that access levels are hierarchical.
Possible levels are none, auth,
compare, search,
read, and write, where
none is the lowest level of access and
write is the highest, and where each level
includes the rights of all levels lower than it. These two points,
the "first match wins" rule and the
inclusive nature of access levels, are crucial in understanding how
ACLs are parsed and in making sure yours don't lead
to either greater or lesser levels of access in a given situation
than you intend.


/ 94