Project

General

Profile

Docs ModAuth » History » Revision 41

Revision 40 (gstrauss, 2017-05-30 03:47) → Revision 41/52 (gstrauss, 2017-09-23 18:08)

h1. Module mod_auth - Using Authentication 

 {{>toc}} 

 h2. Warning 

 @mod_rewrite@ rules (@url.rewrite*@, not @url.rewrite-if-not-file@) are always executed before everything else, and the request gets restarted. *So your @mod_auth@ configuration must match the rewritten urls!* 

 h2. Supported Methods 

 lighttpd supports both authentication methods described by  
 RFC 2617:  

 h3. basic 

 The Basic method transfers the username and the password in  
 cleartext over the network (base64 encoded) and might result  
 in security problems if not used in conjunction with a crypted  
 channel between client and server. 

 h3. digest 

 The Digest method only transfers a hashed value over the  
 network which performs a lot of work to harden the  
 authentication process in insecure networks. 

 h2. Backends 

 Depending on the method lighttpd provides various way to store  
 the credentials used for the authentication. 

 For basic auth: 
 * plain_ 
 * htpasswd_  
 * htdigest_ 
 * ldap_ 
 * gssapi_ 
 * mysql_ 

 For digest auth: 
 * plain_ 
 * htdigest_ 

 h3. plain (mod_authn_file) 

 A file which contains username and the cleartext password  
 seperated by a colon. Each entry is terminated by a single  
 newline. 

 e.g.: 
 <pre> 
 agent007:secret 
 </pre> 

 h3. htpasswd (mod_authn_file) 

 A file which contains username and the crypt()'ed password  
 seperated by a colon. Each entry is terminated by a single  
 newline. 

 e.g.: 
 <pre> 
 agent007:XWY5JwrAVBXsQ 
 </pre> 

 You can use htpasswd from the apache distribution to manage  
 those files. 

 <pre> 
 $ htpasswd lighttpd.user.htpasswd agent007 
 </pre> 

 Keep in mind that not all versions of htpasswd default to use 
 Apache's modified MD5 algorithm for passwords, which is 
 required by lighttpd. You can force most to use MD5 with: 

 <pre> 
 $ htpasswd -m <pwfile> <username> 
 </pre> 

 h3. htdigest (mod_authn_file) 

 A file which contains a line per user identification. Each line contains the username, realm and a MD5 value separated by colons. 

 e.g.: 
 <pre> 
 agent007:download area:8364d0044ef57b3defcfa141e8f77b65 
 </pre> 

 The MD5 value is the checksum of a string concatenating the username, realm and password, separated by colons.  
 That way, there is a sort of recursion. An example consecuent with the previous one is: 

 e.g.: 
 <pre> 
 agent007:download area:secret 
 </pre> 

 You can use htdigest from the apache distribution to manage  
 that kind of files. 

 <pre> 
 $ htdigest lighttpd.user.htdigest 'download area' agent007 
 </pre> 
  
 Using md5sum can also generate the password-hash: 
 <pre> 
 #!/bin/sh 
 user=$1 
 realm=$2 
 pass=$3 

 hash=`echo -n "$user:$realm:$pass" | md5sum | cut -b -32` 

 echo "$user:$realm:$hash" 
 </pre> 

 To use it (spaces between arguments!): 

 <pre> 
 $ htdigest.sh 'agent007' 'download area' 'secret' 
 agent007:download area:8364d0044ef57b3defcfa141e8f77b65 
 </pre> 

 follow code is improved when you use for service: 
 <pre> 
 #!/bin/sh 

 export PATH="/bin:/usr/bin:/usr/sbin:$PATH" 

 # when input ctrl-c, remove lockfile and exit 
 trap '[ $lockstart -eq 1 ] && unlock $pfile && exit 0 || exit 0' INT 

 pfile="/etc/lighttpd/conf.d/lighttpd.user" 
 lockstart=0  
 remove=0 

 errmsg() { 
     echo "$1" > /dev/stderr 
 } 

 user_check() { 
     check_user=$1 
     grep "^${check_user}:" ${pfile} >& /dev/null 
     return $? 
 } 

 lock() { 
     lockfile="$1" 
     lockfile="${lockfile}.lock" 

     [ -f "${lockfile}" ] && { 
         errmsg "WARNING: lock file ${lockfile} is already exists" 
         errmsg "           Wait minites for end of previous working ..." 
     } 

     while [ -f "${lockfile}" ]; do echo >& /dev/null ; done 
     touch ${lockfile}  
     lockstart=1 
 } 

 unlock() { 
     lockfile="$1" 
     lockfile="${lockfile}.lock" 

     [ -f "${lockfile}" ] && rm -f ${lockfile} && lockstart=0 
 } 

 usage() { 
     errmsg 
     errmsg "lightdigest: lighttpd htdigest password generation program" 
     errmsg "Scripted by JoungKyun.Kim <http://oops.org>" 
     errmsg 
     errmsg "Usage: $0 -[hd] -u user -p pass -r realm [-f password_file]" 
     errmsg "Options:" 
     errmsg "      -h            print this help messages" 
     errmsg "      -u user       username" 
     errmsg "      -p pass       password" 
     errmsg "      -r realm      realm name" 
     errmsg "      -f filename password file [default: /etc/lighttpd/conf.d/lighttpd.user" 
     errmsg "      -d            remove user" 
     errmsg 

     [ $lockstart -eq 1 ] && rm -f ${pfile}.lock 

     exit 1 
 }    

 opts=$(getopt df:hp:r:u: $*) 
 [ $? != 0 ] && usage 

 set -- ${opts} 
 for i 
 do 
     case "$i" in 
         -d) remove=1; shift;; 
         -f) pfile="$2"; shift; shift;; 
         -p) pass="$2"; shift; shift;; 
         -r) realm="$2"; shift; shift;; 
         -u) user="$2"; shift; shift;; 
         --) shift; break; 
     esac 
 done 

 #echo $user 
 #echo $realm 
 #echo $pass 
 #echo $pfile 
 #echo $remove 

 [ -z "$user" ] && errmsg "ERROR: User is none!!" && usage 
 [ ${remove} -eq 0 -a -z "${realm}" ] && errmsg "ERROR: Realm is none!!" && usage 

 if [ -z "${pass}" -a ${remove} -eq 0 ]; then 
     echo -n "Input new password : " 
     read newpass 
     echo -n "Reinput password for confirm : " 
     read renewpass 

     if [ "${newpass}" != "${renewpass}" ]; then 
         errmsg "ERROR: Password is not match" 
         exit 1 
     fi 

     pass=${newpass} 
 fi 

 lock ${pfile} 

 if [ ${remove} -eq 0 ]; then 
     # User Add Mode 
     hash=$(echo -n "${user}:${realm}:${pass}" | md5sum | cut -b -32) 
     user_check ${user} 
     already=$? 

     [ -f "${pfile}" ] && cp -af ${pfile} ${pfile}.bak 
     if [ ${already} -eq 0 ]; then 
         # already exists 
         perl -pi -e "s/^${user}:.*$/${user}:${realm}:${hash}/g" ${pfile} 
     else 
         # add new user 
         echo "${user}:${realm}:${hash}" >> ${pfile} 
     fi 
 else 
     # User Remove Mode 
     tmp_htdigest="/tmp/lighttpd-htdiges.tmp.$$" 
     cp -af ${pfile} ${pfile}.bak 
     grep -v "^${user}:" ${pfile} > ${tmp_htdigest} 
     mv -f ${tmp_htdigest} ${pfile} 
 fi 

 unlock ${pfile} 

 exit 0 
 </pre> 

 To use it (don't use realm value! getopt of some bash version has bug.) : 

 <pre> 
   # if you add or change 
   $ lightdigest -u USERNAME -r REALM_NAME -f PASSWORD_FILE_PATH 
   # if you want to remove use   
   $ lightdigest -d -u USERNAME 
 </pre> 

 h3. ldap (mod_authn_ldap) 

 The ldap backend performs the following steps to authenticate a user 

 # Init the LDAP connection 
 # Set Protocol version to LDAPv3 
 # If StartTLS if configured -> Configure CA certificate if supplied 
 # If StartTLS if configured -> Activate TLS using StartTLS 
 # If Bind DN is included -> Simple bind with Bind-DN and Bind-Password 
 # If there is no Bind-DN -> Simple bind anonymously 
 # Try up to two times a SUBTREE search of the base-DN with the filter applied. 
 # Retrieve the DN of the user matching the filter. 
 # Finally, re-init the connection (following the steps above), this time using the DN found using the filter and the password supplied by the user. 

 If all 9 steps are performed without any error the user is authenticated. 

 h3. gssapi (mod_authn_gssapi) (kerberos5) 

 The gssapi backend authenticates the user against Kerberos5 infrastructure 

 h3. mysql (mod_authn_mysql) 

 The mysql backend authenticates the user against MySQL/MariaDB infrastructure 

 h2. Configuration template 

 After setup the backend, edit the authentication configuration file to reflect your backend selected.    The following is a configuration template. 

 <pre> 
 ################ 

 ## type of backend  
 # plain, htpasswd, htdigest (mod_authn_file); ldap (mod_authn_ldap); gssapi (mod_authn_gssapi); mysql (mod_authn_mysql) 
 server.modules += ( "mod_authn_file" ) 
 auth.backend                 = "htpasswd" 

 # filename of the password storage for plain 
 auth.backend.plain.userfile = "lighttpd-plain.user" 

 ## for htpasswd 
 auth.backend.htpasswd.userfile = "/full/path/to/lighttpd-htpasswd.user" 

 ## for htdigest 
 auth.backend.htdigest.userfile = "lighttpd-htdigest.user" 

 ################ 

 ## for ldap 
 # the $ in auth.backend.ldap.filter is replaced by the  
 # 'username' from the login dialog 
 # since lighttpd 1.4.46, '?' can be used as placeholder 
 # instead of '$', e.g. "(uid=?)" 
 server.modules += ( "mod_authn_ldap" ) 
 auth.backend = "ldap" 
 auth.backend.ldap.hostname = "localhost" 
 auth.backend.ldap.base-dn    = "dc=my-domain,dc=com" 
 auth.backend.ldap.filter     = "(uid=$)" 
 # if enabled, startTLS needs a valid (base64-encoded) CA  
 # certificate unless the certificate has been stored 
 # in a c_hashed directory and referenced in ldap.conf 
 auth.backend.ldap.starttls     = "enable" 
 auth.backend.ldap.ca-file     = "/etc/CAcertificate.pem" 
 # If you need to use a custom bind to access the server 
 auth.backend.ldap.bind-dn    = "uid=admin,dc=my-domain,dc=com" 
 auth.backend.ldap.bind-pw    = "mysecret" 
 # If you want to allow empty passwords 
 # "disable" for requiring passwords, "enable" for allowing empty passwords 
 auth.backend.ldap.allow-empty-pw = "disable" 
 # LDAP group (https://redmine.lighttpd.net/issues/1817) 
 #auth.backend.ldap.groupmember = "mygroup" 


 

 ################ 

 ## for gssapi 
 server.modules += ( "mod_authn_gssapi" ) 
 auth.backend = "gssapi" 
 auth.backend.gssapi.keytab = "/path/to/lighttpd.keytab" 
 auth.backend.gssapi.principal = "myhost" 

 ################ 

 ## for mysql 
 server.modules += ( "mod_authn_mysql" ) 
 auth.backend = "mysql" 
 #auth.backend.mysql.host = "" 
 #auth.backend.mysql.user = "" 
 #auth.backend.mysql.pass = "" 
 #auth.backend.mysql.db = "" 
 #auth.backend.mysql.port = "" 
 #auth.backend.mysql.socket = "" 
 auth.backend.mysql.users_table = "mysql_users_table" 
 #auth.backend.mysql.col_user = "user" 
 #auth.backend.mysql.col_pass = "password" 
 #auth.backend.mysql.col_realm = "realm" 
 # defaults above result in query: SELECT password FROM mysql_users_table WHERE user='%s' AND realm='%s' 

 ################ 

 # check REMOTE_USER (if set) against require rules prior to applying auth.backend 
 # REMOTE_USER might be set by another module, e.g. mod_openssl client cert verification 
 # and REMOTE_USER configured with ssl.verifyclient.username) 
 # (since lighttpd 1.4.46) 
 #auth.extern-authn = "enable" 

 ################ 
 ################ 

 ## restrictions 
 # set restrictions: 
 # 
 # ( <left-part-of-the-url> => 
 #     ( "method" => "digest"/"basic", 
 #       "realm" => <realm>, 
 #       "require" => "user=<username>" ) 
 # ) 
 # 
 # <realm> is a string to display in the dialog  
 #           presented to the user and is also used for the  
 #           digest-algorithm and has to match the realm in the  
 #           htdigest file (if used) 
 # 

 auth.require = ( "/download/" => 
                  ( 
                  # method must be either basic or digest 
                    "method"    => "digest", 
                    "realm"     => "download archiv", 
                    "require" => "user=agent007|user=agent008" 
                  ), 
                  "/server-info" => 
                  ( 
                  # limit access to server information 
                    "method"    => "digest", 
                    "realm"     => "download archiv", 
                    "require" => "valid-user" 
                  ) 
                  "/protected-folder/" => 
                  ( 
                  #  
                    "method"    => "digest", 
                    "realm"     => "download archiv", 
                    "require" => "valid-user" 
                  ) 
                ) 

 # Or, using regular expressions: 
 $HTTP["url"] =~ "^/download|^/server-info" { 
   auth.require = ( "" => 
                    ( 
                      "method"    => "digest", 
                      "realm"     => "download archiv", 
                      "require" => "user=agent007|user=agent008" 
                    ) 
                  ) 
 } 
 </pre> 

 When completed, enable the authentication configuration module.    The way to enable the module varies from different distributions.  

 h2. Limitations 

 * The implementation of digest method is not compliant with the standard as it still allows a replay attack. (i.e. *not* secure) (*Fixed in lighttpd 1.4.41* (#1844)) 
 * Digest algorithm="md5-sess" is not correctly implemented in lighttpd, and probably never will be, and so its use is not recommend. (#806)    Apache mod_auth_digest also does not implement algorithm="md5-sess". 
 * LDAP authentication only allows alphanumeric uid's that do not contain punctuations. i.e.) john.doe will come up as "ldap: invalid character (a-zA-Z0-9 allowed) in username: john.doe" (This issue appears to be solved since r2526. See issue #1941) (*Fixed in lighttpd 1.4.46*) 
 * As of 1.4.19 the group field inside the require directive is not yet implemented. So auth.backend.plain.groupfile is of no use at this moment. (Note: group support for LDAP is available since lighttpd 1.4.46 (#1817))  
 * When loaded together with @mod_fastcgi@, @mod_auth@ *must* be loaded *before* @mod_fastcgi@. Or else users will experience long delays when login in and sysadmins will probably not find out the source of the problem due to the lack of meaningful error messages. 

 h2. See Also 

 * [[HowToAuthenticationFromMultipleFiles|Authenticate from Multiple Password Files]]