diff --git a/en_US.ISO8859-1/articles/Makefile b/en_US.ISO8859-1/articles/Makefile index a2303fec11..0f24c0a771 100644 --- a/en_US.ISO8859-1/articles/Makefile +++ b/en_US.ISO8859-1/articles/Makefile @@ -1,63 +1,64 @@ # $FreeBSD$ SUBDIR = SUBDIR+= 5-roadmap SUBDIR+= bsdl-gpl SUBDIR+= building-products SUBDIR+= casestudy-argentina.com SUBDIR+= checkpoint SUBDIR+= committers-guide SUBDIR+= compiz-fusion SUBDIR+= console-server SUBDIR+= contributing SUBDIR+= contributing-ports SUBDIR+= contributors SUBDIR+= cvs-freebsd SUBDIR+= cvsup-advanced SUBDIR+= dialup-firewall SUBDIR+= diskless-x SUBDIR+= euro SUBDIR+= explaining-bsd SUBDIR+= fbsd-from-scratch SUBDIR+= filtering-bridges SUBDIR+= fonts SUBDIR+= formatting-media SUBDIR+= freebsd-questions SUBDIR+= geom-class SUBDIR+= gjournal-desktop SUBDIR+= hats SUBDIR+= hubs SUBDIR+= ipsec-must SUBDIR+= laptop +SUBDIR+= ldap-auth SUBDIR+= linux-comparison SUBDIR+= linux-emulation SUBDIR+= linux-users SUBDIR+= mailing-list-faq SUBDIR+= mh SUBDIR+= multi-os SUBDIR+= nanobsd SUBDIR+= new-users SUBDIR+= p4-primer SUBDIR+= pam SUBDIR+= portbuild SUBDIR+= pr-guidelines SUBDIR+= problem-reports SUBDIR+= pxe SUBDIR+= rc-scripting SUBDIR+= relaydelay SUBDIR+= releng SUBDIR+= releng-packages SUBDIR+= remote-install SUBDIR+= serial-uart SUBDIR+= solid-state SUBDIR+= storage-devices SUBDIR+= version-guide SUBDIR+= vinum SUBDIR+= vm-design SUBDIR+= wp-toolbox SUBDIR+= zip-drive # ROOT_SYMLINKS+= new-users DOC_PREFIX?= ${.CURDIR}/../.. .include "${DOC_PREFIX}/share/mk/doc.project.mk" diff --git a/en_US.ISO8859-1/articles/ldap-auth/Makefile b/en_US.ISO8859-1/articles/ldap-auth/Makefile new file mode 100644 index 0000000000..c0266a09d6 --- /dev/null +++ b/en_US.ISO8859-1/articles/ldap-auth/Makefile @@ -0,0 +1,21 @@ +# +# $FreeBSD$ +# +# Article: LDAP Authentication + +MAINTAINER= kurin@causa-sui.net + +DOC?= article + +FORMATS?= html-split html +WITH_ARTICLE_TOC?= YES + +INSTALL_COMPRESSED?= gz +INSTALL_ONLY_COMPRESSED?= + +SRCS= article.sgml + +URL_RELPREFIX?= ../../../.. +DOC_PREFIX?= ${.CURDIR}/../../.. + +.include "${DOC_PREFIX}/share/mk/doc.project.mk" diff --git a/en_US.ISO8859-1/articles/ldap-auth/article.sgml b/en_US.ISO8859-1/articles/ldap-auth/article.sgml new file mode 100644 index 0000000000..c37325e969 --- /dev/null +++ b/en_US.ISO8859-1/articles/ldap-auth/article.sgml @@ -0,0 +1,909 @@ + +%articles.ent; +]> + +
+ + LDAP Authentication + + + + Toby + Burress + +
kurin@causa-sui.net
+
+
+
+ + $FreeBSD$ + + + 2007 + 2008 + The FreeBSD Documentation Project + + + + &tm-attrib.freebsd; + &tm-attrib.general; + + + + This document is indended as a guide for the configuration + of an LDAP server (principally an OpenLDAP + server) for authentication on &os;. This is useful for situations + where many servers need the same user accounts, for example as a + replacement for NIS. + +
+ + + Preface + + This document is intended to give the reader enough of an + understanding of LDAP to configure an LDAP server. This document will + attempt to provide an + explanation of net/nss_ldap + and security/pam_ldap for use with + client machines services for use with the LDAP server. + + When finished, the reader should be able to configure and + deploy a &os; server that can host an LDAP directory, and to + configure and deploy a &os; server which can authenticate against + an LDAP directory. + + This article is not intended to be an exhaustive account of + the security, robustness, or best practice considerations for + configuring LDAP or the other services discussed herein. While the author + takes care to do everything correctly, he does not + address security issues beyond a general scope. This article should be + considered to lay the theoretical groundwork only, and any actual + implementation should be accompanied by careful requirement + analysis. + + + + Configuring LDAP + LDAP stands for Lightweight Directory Access + Protocol and is a subset of the X.500 Directory Access + Protocol. Its most recent specifications are in RFC4510 and + friends. Essentially it is a database that expects to be read from + more often than it is written to. + + The LDAP server OpenLDAP will be used in the + examples in this document; while the principles here should be + generally applicable to many different servers, most of the + concrete administration is + OpenLDAP-specific. There are several + server versions in ports, for example net/openldap23-server. Client servers + will need the corresponding net/openldap23-client libraries. + + There are (basically) two areas of the LDAP service which need + configuration. The first is setting up a server to receive + connections properly, and the second is adding entries to the + server's directory so that &os; tools know how to interact with it. + + + Setting Up the Server for Connections + + + This section is specific to + OpenLDAP. If you are using another + server, you will need to consult that server's + documentation. + + + + Installing <application>OpenLDAP</application> + + First, install OpenLDAP: + + + Installing <application>OpenLDAP</application> + + &prompt.root; cd /usr/ports/net/openldap24-server +&prompt.root; make install clean + + + This installs the slapd and + slurpd binaries, along with the required + OpenLDAP libraries. + + + + Configuring <application>OpenLDAP</application> + + Next we must configure + OpenLDAP. + + You will want to require encryption in your + connections to the LDAP server; otherwise your users' passwords + will be transferred in plain text, which is considered + insecure. The tools we will be using support two very similar kinds + of encryption, SSL and TLS. + + TLS stands for Transportation Layer Security. + Services that employ TLS tend to connect on the + same ports as the same services without + TLS; thus an SMTP server which supports TLS will listen for + connections on port 25, and an LDAP server will listen on 389. + + SSL stands for Secure Sockets Layer, and + services that implement SSL do not listen on + the same ports as their non-SSL counterparts. Thus SMTPS listens + on port 465 (not 45), HTTPS listens on 443, and LDAPS on + 636. + + The reason SSL uses a different port than TLS is because a + TLS connection begins as plain text, and switches to encrypted + traffic after the STARTTLS directive. SSL + connections are encrypted from the beginning. Other than that + there are no substantial differences between the two. + + + We will adjust + OpenLDAP to use TLS, as SSL is + considered deprecated. + + + Once OpenLDAP is installed via + ports, the following configuration parameters in + /usr/local/etc/openldap/slapd.conf will + enable TLS: + + security ssf=128 + +TLSCertificateFile /path/to/your/cert.crt +TLSCertificateKeyFile /path/to/your/cert.key +TLSCACertificateFile /path/to/your/cacert.crt + + + Here, ssf=128 tells + OpenLDAP to require 128-bit + encryption for all connections, both search and update. This + parameter may be configured based on the security needs of your + site, but rarely you need to weaken it, as most LDAP client + libraries support strong encryption. + + The cert.crt, + cert.key, and + cacert.crt files are necessary for clients + to authenticate you as the valid LDAP + server. If you simply want a server that runs, you can create a + self-signed certificate with OpenSSL: + + + Generating an RSA key + + &prompt.user; openssl genrsa -out cert.key 1024 +Generating RSA private key, 1024 bit long modulus +....................++++++ +...++++++ +e is 65537 (0x10001) +&prompt.user; openssl req -new -key cert.key -out cert.csr + + + At this point you should be prompted for some values. You + may enter whatever values you like; however, it is important the + Common Name value be the fully qualified domain + name of the OpenLDAPserver. + In our case, and the examples here, the server is + server.example.org. + Incorrectly setting this value will cause clients to fail when + making connections. This can the + cause of great frustration, so ensure that you follow these + steps closely. + + Finally, the certificate signing request needs to be + signed: + + + Self-signing the certificate + + &prompt.user; openssl x509 -req -in cert.csr -days 365 -signkey cert.key -out cert.crt +Signature ok +subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd +Getting Private key + + + This will create a self-signed certificate that can be + used for the directives in slapd.conf, + where cert.crt and + cacert.crt are the same file. If you are + going to use many OpenLDAP servers + (for replication via slurpd) you will want to + see to generate a CA key and use it to + sign individual server certificates. + + Once this is done, put the following in + /etc/rc.conf: + + slapd_enable="YES" + + Then run /usr/local/etc/rc.d/slapd + start. This should start + OpenLDAP. Confirm that it is + listening on 389 with + + &prompt.user; sockstat -4 -p 389 +ldap slapd 3261 7 tcp4 *:389 *:* + + + + Configuring the Client + + Install the net/openldap23-client port for the + OpenLDAP libraries. The client + machines will always have OpenLDAP + libraries since that is all security/pam_ldap and net/nss_ldap support, at least for the + moment. + + The configuration file for the + OpenLDAP libraries is + /usr/local/etc/openldap/ldap.conf. Edit + this file to contain the following values: + + base dc=example,dc=org +uri ldap://server.example.org/ +ssl start_tls +tls_cacert /path/to/your/cacert.crt + + + It is important that your clients have access to + cacert.crt, otherwise they will not be + able to connect. + + + + There are two files called + ldap.conf. The first is this file, which + is for the OpenLDAP libraries and + defines how to talk to the server. The second is + /usr/local/etc/ldap.conf, and is for + pam_ldap. + + + At this point you should be able to run + ldapsearch -Z on the client machine; + means use TLS. If you + encounter an error, then something is configured wrong; most + likely it is your certificates. Use &man.openssl.1;'s + s_client and s_server to + ensure you have them configured and signed properly. + + + + + Entries in the Database + + Authentication against an LDAP directory is generally + accomplished by attempting to bind to the directory as the connectin user. + This is done by establishing a simple + bind on the directory with the user name supplied. If there is an + entry with the uid equal to the user name and + that entry's userPassword attribute matches the + password supplied, then the bind is successful. + + The first thing we have to do is figure out is where in the + directory our users will live. + + The base entry for our database is + dc=example,dc=org. The default location for + users that most clients seem to expect is something like + ou=people,base, so + that is what will be used here. However keep in mind that this is + configurable. + + So the ldif entry for the people + organizational unit will look like: + + dn: ou=people,dc=example,dc=org +objectClass: top +objectClass: organizationalUnit +ou: people + + All users will be created as subentries of this + organizational unit. + + Some thought might be given to the object class your users + will belong to. Most tools by default will use + people, which is fine if you simply want to + provide entries against which to authenticate. However, if you + are going to store user information in the LDAP database as well, + you will probably want to use inetOrgPerson, + which has many useful attributes. In either case, the relevant + schemas need to be loaded in + slapd.conf. + + For this example we will use the person + object class. If you are using inetOrgPerson, + the steps are basically identical, except that the + sn attribute is required. + + To add a user testuser, the ldif would + be: + + dn: uid=tuser,ou=people,dc=example,dc=org +objectClass: person +objectClass: posixAccount +objectClass: shadowAccount +objectClass: top +uidNumber: 10000 +gidNumber: 10000 +homeDirectory: /home/tuser +loginShell: /bin/csh +uid: tuser +cn: tuser + + I start my LDAP users' UIDs at 10000 to avoid colisions with + system accounts; you can configure whatever number you wish here, + as long as it's less than 65536. + + We also need group entries. They are as configurable as + user entries, but we will use the defaults below: + + dn: ou=groups,dc=example,dc=org +objectClass: top +objectClass: organizationalUnit +ou: groups + +dn: cn=tuser,ou=groups,dc=example,dc=org +objectClass: posixGroup +objectClass: top +gidNumber: 10000 +cn: tuser + + To enter these into your database, you can use + slapadd or ldapadd + on a file containing these entries. Alternatively, you can use + sysutils/ldapvi. + + The ldapsearch utility on the client machine + should now return these entries. If it does, your database is + properly configured to be used as an LDAP authentication server. + + + + + Client Configuration + + The client should already have + OpenLDAP libraries from , but if you are installing several + client machines you will need to install net/openldap23-client on each of + them. + + &os; requires two ports to be installed to authenticate + against an LDAP server, security/pam_ldap and net/nss_ldap. + + + Authentication + + security/pam_ldap is + configured via /usr/local/etc/ldap.conf. + + + This is a different file than the + OpenLDAP library functions' + configuration file, + /usr/local/etc/openldap/ldap.conf; however, + it takes many of the same options; in fact it is a superset of + that file. For the rest of this section, references to + ldap.conf will mean + /usr/local/etc/ldap.conf. + + + Thus, we will want to copy all of our original + configuration parameters from + openldap/ldap.conf to the new + ldap.conf. Once this is done, we want to + tell security/pam_ldap what to + look for on the directory server. + + We are identifying our users with the uid + attribute. To configure this (though it is the default), set the + pam_login_attribute directive in + ldap.conf: + + + Setting <literal>pam_login_attribute</literal> + + pam_login_attribute uid + + + With this set, security/pam_ldap will search the entire + LDAP directory under base for the value + uid=username. If it + finds one and only one entry, it will attempt to bind as that user + with the password it was given. If it binds correctly, then it + will allow access. Otherwise it will fail. + + + PAM + + PAM, which stands for Pluggable Authentication + Modules, is the method by which &os; authenticates most + of its sessions. To tell &os; we wish to use an LDAP server, we + will have to add a line to the appropriate PAM file. + + Most of the time the appropriate PAM file is + /etc/pam.d/sshd, if you want to use + SSH (remember to set the relevant + options in /etc/ssh/sshd_config, otherwise + SSH will not use PAM). + + To use PAM for authentication, add the line + + auth sufficient /usr/local/lib/pam_ldap.so no_warn + + Exactly where this line shows up in the file and which + options appear in the fourth column determine the exact behavior + of the authentication mechanism; see &man.pam.d.5; + + With this configuration you should be able to authenticate + a user against an LDAP directory. + PAM will perform a bind with your + credentails, and if successful will tell + SSH to allow access. + + However it is not a good idea to allow + every user in the directory into + every client machine. With the + current configuration, all that a user needs to log into a + machine is an LDAP entry. Fortunately there are a few ways to + restrict user access. + + ldap.conf supports a + pam_groupdn directive; every account that + connects to this machine needs to be a member of the group + specified here. For example, if you have + + pam_groupdn cn=servername,ou=accessgroups,dc=example,dc=org + + in ldap.conf, then only members of + that group will be able to log in. There are a few things to + bear in mind, however. + + Members of this group are specified in one or more + memberUid attributes, and each attribute must + have the full distinguished name of the member. So + memberUid: someuser will not work; it must + be: + + memberUid: uid=someuser,ou=people,dc=example,dc=org + + Additionally, this directive is not checked in PAM during + authentication, it is checked during account management, so you + will need a second line in your PAM files under + account. This will require, in turn, + every user to be listed in the group, which + is not necessarily what we want. To avoid blocking users that + are not in LDAP, you should enable the + ignore_unknown_user attribute. Finally, you + should set the ignore_authinfo_unavail option + so that you are not locked out of every computer when the LDAP + server is unavailable. + + Your pam.d/sshd might then end up + looking like this: + + + Sample <filename>pam.d/sshd</filename> + + auth required pam_nologin.so no_warn +auth sufficient pam_opie.so no_warn no_fake_prompts +auth requisite pam_opieaccess.so no_warn allow_local +auth sufficient /usr/local/lib/pam_ldap.so no_warn +auth required pam_unix.so no_warn try_first_pass + +account required pam_login_access.so +account required /usr/local/lib/pam_ldap.so no_warn ignore_authinfo_unavail ignore_unknown_user + + + + Since we are adding these lines specifically to + pam.d/sshd, this will only have an effect + on SSH sessions. LDAP users will + be unable to log in at the console. To change this behavior, + examine the other files in /etc/pam.d and + modify them accordingly. + + + + + + Name Service Switch + + NSS is the service that maps + attributes to names. So, for example, if a file is owned by user + 1001, an application will query + NSS for the name of + 1001, and it might get bob + or ted or whatever the user's name is. + + Now that our user information is kept in LDAP, we need to + tell NSS to look there when + queried. + + The net/nss_ldap port + does this. It uses the same configuration file as security/pam_ldap, and should not need + any extra parameters once it is installed. Instead, what is left + is simply to edit /etc/nsswitch.conf to take + advantage of the directory. Simply replace the following + lines: + + group: compat +passwd: compat + + with + + group: files ldap +passwd: files ldap + + This will allow you to map usernames to UIDs and UIDs to + usernames. + + Congratulations! You should now have working LDAP + authentication. + + + + Caveats + + Unfortunately, as of the time this was written &os; did not + support changing user passwords with &man.passwd.1;. Because of + this, most administrators are left to implement a solution + themselves. I provide some examples here. Note that if you write + your own password change script, there are some security issues + you should be made aware of; see + + + Shell script for changing passwords + + + + + + This script does hardly any error checking, but more + important it is very cavalier about how it stores your + passwords. If you do anything like this, at least adjust + the security.bsd.see_other_uids + sysctl value: + + &prompt.root; sysctl security.bsd.see_other_uids=0. + + + A more flexible (and probably more secure) approach can be + used by writing a custom program, or even a web interface. The + following is part of a Ruby library + that can change LDAP passwords. It sees use both on the command + line, and on the web. + + + Ruby script for changing passwords + + + + + Although not guaranteed to be free of security holes (the + password is kept in memory, for example) this is cleaner and more + flexible than a simple sh script. + + + + + Security Considerations + + Now that your machines (and possibly other services) are + authenticating against your LDAP server, this server needs to be + protected at least as well as + /etc/master.passwd would be on a regular + server, and possibly even more so since a broken or cracked LDAP + server would break every client service. + + Remember, this section is not exhaustive. You should + continually review your configuration and procedures for + improvements. + + + Setting attributes read-only + + Several attributes in LDAP should be read-only. If left + writable by the user, for example, a user could change his + uidNumber attribute to 0 and + get root access! + + To begin with, the userPassword attribute + should not be world-readable. By default, anyone who can connect + to the LDAP server can read this attribute. To disable this, put + the following in slapd.conf: + + + Hide passwords + + access to dn.subtree="ou=people,dc=example,dc=org" + attrs=userPassword + by self write + by anonymous auth + by * none + +access to * + by self write + by * read + + + This will disallow reading of the + userPassword attribute, while still allowing + users to change their own passwords. + + Additionally, you'll want to keep users from changing some + of their own attributes. By default, users can change any + attribute (except for those which the LDAP schemas themselves deny + changes), such as uidNumber. To close this + hole, modify the above to + + + Read-only attributes + + access to dn.subtree="ou=people,dc=example,dc=org" + attrs=userPassword + by self write + by anonymous auth + by * none + +access to attrs=homeDirectory,uidNumber,gidNumber + by * read + +access to * + by self write + by * read + + + This will stop users from being able to masquerade as other + users. + + + + <username>Root</username> account definition + + Often the root or manager account for + the LDAP service will be defined in the configuration file. + OpenLDAP supports this, for example, + and it works, but it can lead to trouble if + slapd.conf is compromised. It may be better + to use this only to bootstrap yourself into LDAP, and then define + a root account there. + + Even better is to define accounts that have limited + permissions, and omit a root account entirely. + For example, users to can add or remove user accounts are added to + one group, but they cannot themselves change the membership of + this group. Such a security policy would help mitigate the effects + of a leaked password. + + + Creating a management group + + Say you want your IT department to be able to change home + directories for users, but you don't want all of them to be able + to add or remove users. The way to do this is to add a group + for these admins: + + + Creating a management group + + dn: cn=homemanagement,dc=example,dc=org +objectClass: top +objectClass: posixGroup +cn: homemanagement +gidNumber: 121 # required for posixGroup +memberUid: uid=tuser,ou=people,dc=example,dc=org +memberUid: uid=user2,ou=people,dc=example,dc=org + + + And then change the permissions attributes in + slapd.conf: + + + ACLs for a home directory management group + + access to dn.subtree="ou=people,dc=example,dc=org" + attr=homeDirectory + by dn="cn=homemanagement,dc=example,dc=org" + dnattr=memberUid write + + + Now tuser and user2 + can change other users' home directories. + + In this example we've given a subset of administrative + power to certain users without giving them power in other + domains. The idea is that soon no single user account has the + power of a root account, but every power + root had is had by at least one user. The root + account then becomes unnecessary and can be removed. + + + + + Password storage + + By default OpenLDAP will store + the value of the userPassword attribute as it + stores any other data: in the clear. Most of the time it is base + 64 encoded, which provides enough protection to keep an honest + administrator from knowing your password, but little else. + + It is a good idea, then, to store passwords in a more secure + format, such as SSHA (salted SHA). This is done by whatever + program you use to change users' passwords. + + + + + Useful Aids + + There are a few other programs that might be useful, + particularly if you have many users and do not want to configure + everything manually. + + security/pam_mkhomedir is + a PAM module that always succeeds; its purpose is to create home + directories for users which do not have them. If you have dozens of + client servers and hundreds of users, it is much easier to use this + and set up skeleton directories than to prepare every home + directory. + + sysutils/cpu is a + &man.pw.8;-like utility that can be used to manage users in the LDAP + directory. You can call it directly, or wrap scripts around it. It + can handle both TLS (with the flag) and + SSL (directly). + + sysutils/ldapvi is a great + utility for editing LDAP values in an LDIF-like syntax. The + directory (or subsection of the directory) is presented in the + editor chosen by the EDITOR environment variable. + This makes it easy to enable large-scale changes in the directory + without having to write a custom tool. + + security/openssh-portable + has the ability to contact an LDAP server to verify + SSH keys. This is extremely nice if you + have many servers and do not want to copy your public keys across + all of them. + + + + <application>OpenSSL</application> Certificates For LDAP + + If you are hosting two or more LDAP servers, you will probably + not want to use self-signed certificates, since each client will + have to be configured to work with each certificate. While this is + possible, it is not nearly as simple as creating your own + certificate authority, and signing your servers' certificates with + that. + + The steps here are presented as they are with very little + attempt at explaining what is going on—further explanation + can be found in &man.openssl.1; and its friends. + + To create a certificate authority, we simply need a + self-signed certificate and key. The steps for this again + are + + + Creating a certificate + + &prompt.user; openssl genrsa -out root.key 1024 +&prompt.user; openssl req -new -key root.key -out root.csr +&prompt.user; openssl x509 -req -days 1024 -in root.csr -signkey root.key -out root.crt + + + These will be your root CA key and certificate. You will + probably want to encrypt the key and store it in a cool, dry place; + anyone with access to it can masquerade as one of your LDAP + servers. + + Next, using the first two steps above create a key + ldap-server-one.key and certificate signing + request ldap-server-one.csr. Once you sign the + signing request with root.key, you will be able + to use ldap-server-one.* on your LDAP + servers. + + + Do not forget to use the fully qualified domain name for the + common name attribute when generating the + certificate signing request; otherwise clients will reject a + connection with you, and it can be very tricky to diagnose. + + + To sign the key, use and + instead of + : + + + Signing as a certificate authorty + + &prompt.user; openssl x509 -req -days 1024 \ +-in ldap-server-one.csr -CA root.crt -CAkey root.key \ +-out ldap-server-one.crt + + + The resulting file will be the certificate that you can use on + your LDAP servers. + + Finally, for clients to trust all your servers, distribute + root.crt (the certificate, + not the key!) to each client, and specify it in the + TLSCACertificateFile directive in + ldap.conf. + +