Project

General

Profile

Actions

Mod auth » History » Revision 28

« Previous | Revision 28/91 (diff) | Next »
Anonymous, 2008-06-10 11:05
Added a note about the absence of the "require group MyGroup" feature


TracNav(DocsToc)


#!rst
====================
Using Authentication
====================

----------------
Module: mod_auth
----------------

.. meta::
  :keywords: lighttpd, authentication

.. contents:: Table of Contents

Description
===========

Supported Methods
-----------------

lighttpd supports both authentication methods described by 
RFC 2617: 

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.

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.

Backends
--------

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

for basic auth:

- plain_
- htpasswd_ 
- htdigest_
- ldap_

for digest auth:

- plain_
- htdigest_

plain
`````

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

  e.g.:
  agent007:secret

htpasswd
````````

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

  e.g.:
  agent007:XWY5JwrAVBXsQ

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

  $ htpasswd lighttpd.user.htpasswd agent007

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:

  $htpasswd -m <pwfile> <username>

htdigest
````````

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

  e.g.:
  agent007:download area:8364d0044ef57b3defcfa141e8f77b65

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

  $ htdigest lighttpd.user.htdigest 'download area' agent007

Using md5sum can also generate the password-hash: ::

  #!/bin/sh
  user=$1
  realm=$2
  pass=$3

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

  echo "$user:$realm:$hash" 

To use it (spaces between arguments!) :

  $ htdigest.sh 'agent007' 'download area' 'secret'

  agent007:download area:8364d0044ef57b3defcfa141e8f77b65

follow code is improved when you use for service: ::

  #!/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

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

  # 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

ldap
````

the ldap backend is performing the following steps 
to authenticate a user

1. Init the LDAP connection
2. Set Protocol version to LDAPv3
3. If StartTLS if configured -> Configure CA certificate if supplied
4. If StartTLS if configured -> Activate TLS using StartTLS
5. If Bind DN is included -> Simple bind with Bind-DN and Bind-Password
6. If there is no Bind-DN -> Simple bind anonymously
7. Try up to two times a SUBTREE search of the base-DN with the filter applied.
8. Retrieve the DN of the user matching the filter.
9. 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

Configuration
=============

::

  ## debugging
  # 0 for off, 1 for 'auth-ok' messages, 2 for verbose debugging
  auth.debug                 = 0

  ## type of backend 
  # plain, htpasswd, ldap or htdigest
  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
  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" 

  ## 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" => 
                   ( 
             "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" 
                     )
        )
   }                        

Limitations
============

- The implementation of digest method is currently not 
  completely compliant with the standard as it still allows
  a replay attack.

- 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" 

- There seems to be no reasonable logging of failed login attempts yet

- 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. 

See Also
========

Updated by Anonymous almost 16 years ago · 28 revisions