]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - debian/guest-account.sh
Use standards-version 3.9.8
[sojka/lightdm.git] / debian / guest-account.sh
1 #!/bin/sh -e
2 # (C) 2008 Canonical Ltd.
3 # Author: Martin Pitt <martin.pitt@ubuntu.com>
4 # License: GPL v2 or later
5 # modified by David D Lowe and Thomas Detoux
6 #
7 # Setup user and temporary home directory for guest session.
8 # If this succeeds, this script needs to print the username as the last line to
9 # stdout.
10
11 export TEXTDOMAINDIR=/usr/share/locale-langpack
12 export TEXTDOMAIN=lightdm
13
14 # set the system wide locale for gettext calls
15 if [ -f /etc/default/locale ]; then
16   . /etc/default/locale
17   LANGUAGE=
18   export LANG LANGUAGE
19 fi
20
21 is_system_user ()
22 {
23   UID_MIN=$(cat /etc/login.defs | grep UID_MIN | awk '{print $2}')
24   SYS_UID_MIN=$(cat /etc/login.defs | grep SYS_UID_MIN | awk '{print $2}')
25   SYS_UID_MAX=$(cat /etc/login.defs | grep SYS_UID_MAX | awk '{print $2}')
26
27   SYS_UID_MIN=${SYS_UID_MIN:-101}
28   SYS_UID_MAX=${SYS_UID_MAX:-$(( UID_MIN - 1 ))}
29
30   [ ${1} -ge ${SYS_UID_MIN} ] && [ ${1} -le ${SYS_UID_MAX} ]
31 }
32
33 add_account ()
34 {
35   temp_home=$(mktemp -td guest-XXXXXX)
36   GUEST_HOME=$(echo ${temp_home} | tr '[:upper:]' '[:lower:]')
37   GUEST_USER=${GUEST_HOME#/tmp/}
38   [ ${GUEST_HOME} != ${temp_home} ] && mv ${temp_home} ${GUEST_HOME}
39
40   # if ${GUEST_USER} already exists, it must be a locked system account with no existing
41   # home directory
42   if PWSTAT=$(passwd -S ${GUEST_USER}) 2>/dev/null; then
43     if [ $(echo ${PWSTAT} | cut -f2 -d' ') != L ]; then
44       echo "User account ${GUEST_USER} already exists and is not locked"
45       exit 1
46     fi
47
48     PWENT=$(getent passwd ${GUEST_USER}) || {
49       echo "getent passwd ${GUEST_USER} failed"
50       exit 1
51     }
52
53     GUEST_UID=$(echo ${PWENT} | cut -f3 -d:)
54
55     if ! is_system_user ${GUEST_UID}; then
56       echo "Account ${GUEST_USER} is not a system user"
57       exit 1
58     fi
59
60     GUEST_HOME=$(echo ${PWENT} | cut -f6 -d:)
61
62     if [ ${GUEST_HOME} != / ] && [ ${GUEST_HOME#/tmp} = ${GUEST_HOME} ] && [ -d ${GUEST_HOME} ]; then
63       echo "Home directory of ${GUEST_USER} already exists"
64       exit 1
65     fi
66   else
67     # does not exist, so create it
68     useradd --system --home-dir ${GUEST_HOME} --comment $(gettext "Guest") --user-group --shell /bin/bash ${GUEST_USER} || {
69       rm -rf ${GUEST_HOME}
70       exit 1
71     }
72   fi
73
74   dist_gs=/usr/share/lightdm/guest-session
75   site_gs=/etc/guest-session
76
77   # create temporary home directory
78   mount -t tmpfs -o mode=700,uid=${GUEST_USER} none ${GUEST_HOME} || {
79     rm -rf ${GUEST_HOME}
80     exit 1
81   }
82
83   if [ -d ${site_gs}/skel ] && [ "$(ls -A ${site_gs}/skel)" ]; then
84     # Only perform union-mounting if BindFS is available
85     if [ -x /usr/bin/bindfs ]; then
86       bindfs_mount=true
87
88       # Try OverlayFS first
89       if modinfo -n overlay >/dev/null 2>&1; then
90         mkdir ${GUEST_HOME}/upper ${GUEST_HOME}/work
91         chown ${GUEST_USER}:${GUEST_USER} ${GUEST_HOME}/upper ${GUEST_HOME}/work
92
93         mount -t overlay -o lowerdir=${dist_gs}/skel:${site_gs}/skel,upperdir=${GUEST_HOME}/upper,workdir=${GUEST_HOME}/work overlay ${GUEST_HOME} || {
94           umount ${GUEST_HOME}
95           rm -rf ${GUEST_HOME}
96           exit 1
97         }
98       # If OverlayFS is not available, try AuFS
99       elif [ -x /sbin/mount.aufs ]; then
100         mount -t aufs -o br=${GUEST_HOME}:${dist_gs}/skel:${site_gs}/skel none ${GUEST_HOME} || {
101           umount ${GUEST_HOME}
102           rm -rf ${GUEST_HOME}
103           exit 1
104         }
105       # If none of them is available, fall back to copy over
106       else
107         cp -rT ${site_gs}/skel/ ${GUEST_HOME}
108         cp -rT ${dist_gs}/skel/ ${GUEST_HOME}
109         chown -R ${GUEST_USER}:${GUEST_USER} ${GUEST_HOME}
110         bindfs_mount=false
111       fi
112
113       if ${bindfs_mount}; then
114         # Wrap ${GUEST_HOME} in a BindFS mount, so that
115         # ${GUEST_USER} will be seen as the owner of ${GUEST_HOME}'s contents.
116         bindfs -u ${GUEST_USER} -g ${GUEST_USER} ${GUEST_HOME} ${GUEST_HOME} || {
117           umount ${GUEST_HOME} # union mount
118           umount ${GUEST_HOME} # tmpfs mount
119           rm -rf ${GUEST_HOME}
120           exit 1
121         }
122       fi
123     # If BindFS is not available, just fall back to copy over
124     else
125       cp -rT ${site_gs}/skel/ ${GUEST_HOME}
126       cp -rT ${dist_gs}/skel/ ${GUEST_HOME}
127       chown -R ${GUEST_USER}:${GUEST_USER} ${GUEST_HOME}
128     fi
129   else
130     cp -rT /etc/skel/ ${GUEST_HOME}
131     cp -rT ${dist_gs}/skel/ ${GUEST_HOME}
132     chown -R ${GUEST_USER}:${GUEST_USER} ${GUEST_HOME}
133   fi
134
135   # setup session
136   su ${GUEST_USER} -c "env HOME=${GUEST_HOME} site_gs=${site_gs} ${dist_gs}/setup.sh"
137
138   # set possible local guest session preferences
139   source_local_prefs() {
140     local USER=${GUEST_USER}
141     local HOME=${GUEST_HOME}
142     . ${site_gs}/prefs.sh
143     chown -R ${USER}:${USER} ${HOME}
144   }
145   if [ -f ${site_gs}/prefs.sh ]; then
146     source_local_prefs
147   fi
148
149   echo ${GUEST_USER}
150 }
151
152 remove_account ()
153 {
154   GUEST_USER=${1}
155
156   PWENT=$(getent passwd ${GUEST_USER}) || {
157     echo "Error: invalid user ${GUEST_USER}"
158     exit 1
159   }
160
161   GUEST_UID=$(echo ${PWENT} | cut -f3 -d:)
162
163   if ! is_system_user ${GUEST_UID}; then
164     echo "Error: user ${GUEST_USER} is not a system user."
165     exit 1
166   fi
167
168   GUEST_HOME=$(echo ${PWENT} | cut -f6 -d:)
169
170   # kill all remaining processes
171   if [ -x /bin/loginctl ] || [ -x /usr/bin/loginctl ]; then
172     loginctl --signal=9 kill-user ${GUEST_USER} >/dev/null || true
173   else
174     while ps h -u ${GUEST_USER} >/dev/null
175     do
176       killall -9 -u ${GUEST_USER} || true
177       sleep 0.2;
178     done
179   fi
180
181   if [ ${GUEST_HOME} = ${GUEST_HOME#/tmp/} ]; then
182     echo "Warning: home directory ${GUEST_HOME} is not in /tmp/. It won't be removed."
183   else
184     umount ${GUEST_HOME} || umount -l ${GUEST_HOME} || true # BindFS mount
185     umount ${GUEST_HOME} || umount -l ${GUEST_HOME} || true # union mount
186     umount ${GUEST_HOME} || umount -l ${GUEST_HOME} || true # tmpfs mount
187     rm -rf ${GUEST_HOME}
188   fi
189
190   # remove leftovers in /tmp
191   find /tmp -mindepth 1 -maxdepth 1 -uid ${GUEST_UID} -print0 | xargs -0 rm -rf || true
192
193   # remove possible {/run,}/media/guest-XXXXXX folder
194   for media_dir in /run/media/${GUEST_USER} /media/${GUEST_USER}; do
195     if [ -d ${media_dir} ]; then
196       for dir in $(find ${media_dir} -mindepth 1 -maxdepth 1); do
197         umount ${dir} || true
198       done
199
200       rmdir ${media_dir} || true
201     fi
202   done
203
204   userdel --force ${GUEST_USER}
205 }
206
207 case ${1} in
208   add)
209     add_account
210     ;;
211   remove)
212     if [ -z ${2} ] ; then
213       echo "Usage: ${0} remove [account]"
214       exit 1
215     fi
216
217     remove_account ${2}
218     ;;
219   *)
220     echo "Usage: ${0} add"
221     echo "       ${0} remove [account]"
222     exit 1
223 esac