chiark / gitweb /
Fixed removal code based on suggestions made by Jonas Meurer
[developers-reference.git] / developers-reference.sgml
index c941fbdd7755e3ecb181daa7c88d92994b3a3784..ffd88a593d2847320cbcf7f2a7540db718c4affb 100644 (file)
@@ -7,7 +7,7 @@
   <!ENTITY % dynamicdata  SYSTEM "dynamic.ent" > %dynamicdata;
 
   <!-- CVS revision of this document -->
-  <!ENTITY cvs-rev "$Revision: 1.272 $">
+  <!ENTITY cvs-rev "$Revision: 1.280 $">
 
   <!-- if you are translating this document, please notate the CVS
        revision of the original developer's reference in cvs-en-rev -->
@@ -4163,9 +4163,11 @@ to system users.
 <package>base-passwd</package>, and a proper versioned depends to the
 <package>base-passwd</package> package that provides the user.
 
-<p>In the second case, you need to create the system user either in
-the <em>preinst</em> or in the <em>postinst</em> and make the package
-depend on <tt>adduser (>= 3.11)</tt>.
+<p>In the second case, you need to create the system user through maintainer
+scripts. <url id="http://www.debian.org/doc/debian-policy/ch-files.html#s10.9"
+name="policy"> requires you discuss an appropiate user and group name on
+<em>debian-devel</em> and make sure it is unique and does not overlap
+with other packages.
 
 <p>Running programs with a user with limited privileges makes sure
 that any security issue with the program makes limited damaged to the
@@ -4179,6 +4181,10 @@ Linux and Unix HOWTO</em> book.
        <sect2 id="bpp-create-sysuser">
          <heading>Creating system users and groups
 
+<p>If you want to create system groups on package installation you
+need to create it in either the <em>preinst</em> or in the <em>postinst</em>
+and have the package depend on <tt>adduser (>= 3.11)</tt>.
+
 <p>The following example code creates the user and group the daemon
 will run as when the package is installed or upgraded:
 
@@ -4213,9 +4219,13 @@ case "$1" in
        # create user to avoid running server as root
        # 1. create group if not existing
        if ! getent group | grep -q "^$SERVER_GROUP:" ; then
-             echo -n "Adding group $SERVER_GROUP.."
-             addgroup --quiet --system $SERVER_GROUP 2>/dev/null ||true
-            echo "..done"
+             echo -n "Adding system group $SERVER_GROUP.."
+             addgroup --quiet --system $SERVER_GROUP 
+             if ! getent group | grep -q "^$SERVER_GROUP:"; then
+               echo "..ERROR creating system group. Aborting installation."
+              exit 1
+            fi
+           echo "..done"
        fi
        # 2. create homedir if it does not exist
        test -d $SERVER_HOME || mkdir $SERVER_HOME
@@ -4227,24 +4237,30 @@ case "$1" in
                --ingroup $SERVER_GROUP \
                --no-create-home \
                --disabled-password \
-               $SERVER_USER 2>/dev/null || true
+               $SERVER_USER 
+           if ! getent passwd | grep -q "^$SERVER_USER:"; then
+             echo "..ERROR creating system user. Aborting installation."
+             exit 1
+          fi
            echo "..done"
            # 4. adjust passwd entry, only do this if the package
-          # creates the user
+           # creates the user
            usermod -c "$SERVER_NAME" \
                -d $SERVER_HOME \
                -g $SERVER_GROUP \
                $SERVER_USER
        else
        # The package might want to check if the user already exists
-       # and it is *not* a system user, in this case it should abort
-       # the installation (like in this example) or ask the administrator
-       # since otherwrise it might have unexpected consequences.
-       # Some packages try to prevent collision by using a prefix such as 'Debian-'
+       # and it is *not* a system user, in this case it could abort
+       # the installation (like in this example) or ask the administrator.
+       # Using a non-system user as the one in our package could 
+       # have unexpected consequences.
+       # Some packages try to prevent this kind of collision by using
+       # a prefix such as 'Debian-'
          for LINE in `grep SYSTEM_UID /etc/adduser.conf | grep -v "^#"`; do
             case $LINE in
                FIRST_SYSTEM_UID*)
-                  FIST_SYSTEM_UID=`echo $LINE | cut -f2 -d '='`
+                  FIRST_SYSTEM_UID=`echo $LINE | cut -f2 -d '='`
                ;;
                LAST_SYSTEM_UID*)
                   LAST_SYSTEM_UID=`echo $LINE | cut -f2 -d '='`
@@ -4254,11 +4270,11 @@ case "$1" in
             esac
          done
          # Abort package installation if the user has not been created by
-        # us.
-         if [ -n "$FIST_SYSTEM_UID" ] && [ -n "$LAST_SYSTEM_UID" ]; then
+         # us.
+         if [ -n "$FIRST_SYSTEM_UID" ] && [ -n "$LAST_SYSTEM_UID" ]; then
             if USERID=`getent passwd $SERVER_USER | cut -f 3 -d ':'`; then
                if [ -n "$USERID" ]; then
-                  if [ "$FIST_SYSTEM_UID" -le "$USERID" ] && \
+                  if [ "$FIRST_SYSTEM_UID" -le "$USERID" ] && \
                      [ "$USERID" -le "$LAST_SYSTEM_UID" ]; then
                        echo "The user $SERVER_USER already exists as a non system user!" >&2
                        echo "Aborting package installation" >&2
@@ -4266,7 +4282,7 @@ case "$1" in
                   fi
                fi
             fi
-         fi
+          fi
         fi
 
        # 5. adjust file and directory permissions
@@ -4320,17 +4336,36 @@ for this.
 
 </list>
 
-<!-- TODO: write about ownership of files:
-     * configuration files: readable but not owned
-     * logfiles, writable, but not once rotated
--->
+<p>File ownerships of files shipped by the package will need to be adjusted:
+
+<list>
+<item>Configuration files should be readable by the system user, if they
+contain sensitive information the system user should not own them unless there
+is a need for it to write to its own configuration files. Typically this means
+that the configuration files are owned by root and by the system group created
+by the package and are mode 0640.
+
+<item>If the The system user generates state files (such as pidfiles) it will
+need to have a directory under <tt>/var/run</tt> owned by itself.  It can be
+created by the package maintainers script but, since it can be wiped after a
+system reboot, it should be be recreated by the init.d script since the state
+directory.
+
+<item>If the daemon logs directly to <tt>/var/log</tt> logfiles should be
+writable by the system user but, once rotated, they should not be either owned
+or writable by it to prevent it from overwritting old log entries if a security
+vulnerability in the software were to be used. If the daemon logs to a
+directory under <tt>/var/log/</tt> then the directory should be owned by the
+system user and rotated log files need not be changed ownership.
+
+</list>
 
        <sect2 id="bpp-removing-sysuser">
          <heading>Removing system users
 
 <p>If the package creates the system user it can remove it when it is
-purged in its <em>postrm</em>, this currently <em>not</em> recommended
-since it has a few known 
+purged in its <em>postrm</em> script. This currently <em>not</em> recommended
+for all situations since it has a few known 
 <footnote>
 Some relevant threads discussing these issues include:
 <url
@@ -4359,25 +4394,39 @@ uids and the gid is belongs to a system group:
 case "$1" in
     purge)
 [...]
-        # find first and last SYSTEM_UID numbers
-         for LINE in `grep SYSTEM_UID /etc/adduser.conf | grep -v "^#"`; do
+         # find first and last SYSTEM_UID numbers
+        if [ -r /etc/adduser.conf ] ; then
+          for LINE in `grep SYSTEM_UID /etc/adduser.conf | grep -v "^#"`; do
             case $LINE in
                FIRST_SYSTEM_UID*)
-                  FIST_SYSTEM_UID=`echo $LINE | cut -f2 -d '='`
+                  FIRST_SYSTEM_UID=`echo $LINE | cut -f2 -d '='`
                ;;
                LAST_SYSTEM_UID*)
                   LAST_SYSTEM_UID=`echo $LINE | cut -f2 -d '='`
                ;;
+               FIRST_SYSTEM_GID*)
+                  FIRST_SYSTEM_GID=`echo $LINE | cut -f2 -d '='`
+               ;;
+               LAST_SYSTEM_GID*)
+                  LAST_SYSTEM_GID=`echo $LINE | cut -f2 -d '='`
+               ;;
                *)
                ;;
             esac
-         done
-         # Remove system account if necessary
+          done
+         fi
+         # Sane defaults
+        [ -z "$FIRST_SYSTEM_UID" ] && FIRST_SYSTEM_UID=100
+        [ -z "$LAST_SYSTEM_UID" ] && LAST_SYSTEM_UID=999
+        [ -z "$FIRST_SYSTEM_GID" ] && FIRST_SYSTEM_GID=100
+        [ -z "$LAST_SYSTEM_GID" ] && LAST_SYSTEM_GID=999
+
+         # Remove system account if it is a system user
          CREATEDUSER="<var>server_user</var>"
-         if [ -n "$FIST_SYSTEM_UID" ] && [ -n "$LAST_SYSTEM_UID" ]; then
+         if [ -n "$FIRST_SYSTEM_UID" ] && [ -n "$LAST_SYSTEM_UID" ]; then
             if USERID=`getent passwd $CREATEDUSER | cut -f 3 -d ':'`; then
                if [ -n "$USERID" ]; then
-                  if [ "$FIST_SYSTEM_UID" -le "$USERID" ] && \
+                  if [ "$FIRST_SYSTEM_UID" -le "$USERID" ] && \
                      [ "$USERID" -le "$LAST_SYSTEM_UID" ]; then
                        echo -n "Removing $CREATEDUSER system user.."
                         deluser --quiet $CREATEDUSER || true
@@ -4386,13 +4435,13 @@ case "$1" in
                fi
             fi
          fi
-         # Remove system group if necessary
-        CREATEDGROUP=<var>server_group</var>
-         FIRST_USER_GID=`grep ^USERS_GID /etc/adduser.conf | cut -f2 -d '='`
-         if [ -n "$FIST_USER_GID" ] then
+         # Remove system group if it is a system group
+         CREATEDGROUP=<var>server_group</var>
+         if [ -n "$FIRST_SYSTEM_GID" ] && [ -n "$LAST_SYSTEM_GID" ]; then
             if GROUPGID=`getent group $CREATEDGROUP | cut -f 3 -d ':'`; then
                if [ -n "$GROUPGID" ]; then
-                  if [ "$FIST_USER_GID" -gt "$GROUPGID" ]; then
+                  if [ "$FIRST_SYSTEM_GID" -le "$GROUPID" ] && \
+                     [ "$GROUPID" -le "$LAST_SYSTEM_GID" ]; then
                        echo -n "Removing $CREATEDGROUP group.."
                        delgroup --only-if-empty $CREATEDGROUP || true
                        echo "..done"
@@ -4403,10 +4452,14 @@ case "$1" in
 [...]
 </example>
 
-<p>Other possibilities, are to make sure the account is locked (has an invalid
-password and <em>/bin/false</em> as a shell) and modify the GECOS field
+<p>Other possibilities, are making sure the account is locked (has an invalid
+password and <em>/bin/false</em> as a shell) and/or changing the GECOS field
 pointing out that the account is no longer used.
 
+<!-- There is currently no consensus as to how any of the above should be
+     done in a way that would make it easy for administrators to locate
+     unused (but not removed) accounts -->
+
 </sect1>
 
 </sect>