1 |
#! /bin/sh |
2 |
# |
3 |
# @(#)$Id$ |
4 |
# |
5 |
# Copyright (c) Members of the EGEE Collaboration. 2008. |
6 |
# See http://eu-egee.org/partners/ for details on the copyright holders. |
7 |
# For license conditions see the license file or |
8 |
# http://eu-egee.org/license.html |
9 |
# |
10 |
glexec=glexec |
11 |
mktemp=mktemp |
12 |
chmod=chmod |
13 |
basename=basename |
14 |
id=id |
15 |
sed=sed |
16 |
awk=awk |
17 |
rm=rm |
18 |
|
19 |
error() { |
20 |
echo "$@" >&2 |
21 |
exit 1; |
22 |
} |
23 |
|
24 |
warn() { |
25 |
echo "$@" >&2 ; |
26 |
} |
27 |
|
28 |
help() { |
29 |
progname=`$basename $0` |
30 |
cat <<EOF |
31 |
Usage: $progname [-h] [-r [-f] gltmp_directory] |
32 |
[-t targetdir-mode] [-m parentmode] [directory] |
33 |
|
34 |
Create a directory owned by the glexec target user in a secure fashion. |
35 |
The path of the directory created is printed to stdout. |
36 |
|
37 |
-t targetdir-mode permissions of the target directory created |
38 |
(default: 0700, i.e. unreadable by the glexec invoker) |
39 |
-m parentmode permissions for the current user on the parent tree |
40 |
(default: 0755, and should traversable for target uid) |
41 |
-r gltmp_dir remove the target directory previously created by |
42 |
$progname. Directory must be empty, unless -f |
43 |
is also specified. |
44 |
|
45 |
directory base directory in which target directory is created |
46 |
(default: current $TMPDIR or if unset /tmp) |
47 |
|
48 |
Return value is 0 if directory was successfully created, non-zero otherwise. |
49 |
|
50 |
EOF |
51 |
exit 0; |
52 |
} |
53 |
|
54 |
###################################################################### |
55 |
# removal support |
56 |
forceremove=0 |
57 |
|
58 |
remove() { |
59 |
test -e "$1" || error "$0 (remove): $1: does not exist" |
60 |
test -d "$1" || error "$0 (remove): $1: not a directory" |
61 |
|
62 |
test `expr substr "$1" 1 1` != "/" && error \ |
63 |
"$0 (remove): $1: must be an absolute path" |
64 |
|
65 |
test `expr match "$1" '.*/\.\./'` -ne 0 && error \ |
66 |
"$0 (remove): $1: contains disallowed parent directory designator" |
67 |
|
68 |
# determine uid (name) in a portable way (-u and -n are gnu-isms) |
69 |
uid=`$id | $sed -e 's/uid=[0-9][0-9]*(\([a-zA-Z0-9]*\)).*/\1/'` |
70 |
|
71 |
# a gltmpdir directory is at least three levels deep and the two |
72 |
# upper directories are owned by this user and have only one entry |
73 |
|
74 |
gltmpdir="$1" |
75 |
stickydir=`dirname "$gltmpdir"` |
76 |
securedir=`dirname "$stickydir"` |
77 |
|
78 |
test "$securedir" = "/" && error \ |
79 |
"Path depth error: $gltmpdir not deep enough, not a mkgltmpdir result" |
80 |
test `ls -ld $gltmpdir | $awk '{print $3}'` = "$uid" && error \ |
81 |
"Directory $gltmpdir is already owned by $uid" |
82 |
test `ls -1 "$stickydir" | wc -l` -ne 1 && error \ |
83 |
"Compliance error: $stickydir has multiple entries" |
84 |
test `ls -ld $stickydir | $awk '{print $3}'` != "$uid" && error \ |
85 |
"Directory $stickydir not owner by $uid" |
86 |
test `ls -1 "$securedir" | wc -l` -ne 1 && error \ |
87 |
"Compliance error: $securedir has multiple entries" |
88 |
test `ls -ld $securedir | $awk '{print $3}'` != "$uid" && error \ |
89 |
"Directory $securedir not owner by $uid" |
90 |
|
91 |
$chmod 0700 $securedir || error \ |
92 |
"Cannot chmod $securedir to 0700" |
93 |
$chmod 01777 $stickydir || error \ |
94 |
"Cannot chmod $stickydir to 01777" |
95 |
|
96 |
if test "$forceremove" -eq 1 |
97 |
then |
98 |
( cd $stickydir && $glexec $rm -fr `basename $gltmpdir` ) |
99 |
else |
100 |
( cd $stickydir && $glexec rmdir `basename $gltmpdir` ) |
101 |
fi |
102 |
|
103 |
test -d $gltmpdir && error \ |
104 |
"Failed to remove $gltmpdir, sorry. Exiting." |
105 |
|
106 |
rmdir $stickydir || error "Cannot remove $stickydir, exiting." |
107 |
rmdir $securedir || error "Cannot remove $securedir, exiting." |
108 |
|
109 |
return 0; |
110 |
} |
111 |
|
112 |
###################################################################### |
113 |
# parse arguments |
114 |
# |
115 |
while :; do |
116 |
case "$1" in |
117 |
-h ) help ; exit 0 ;; |
118 |
-m ) MODE=0"$2"; shift 2 ;; |
119 |
-t ) tmode=0"$2"; shift 2 ;; |
120 |
-r ) remove="$2" ; shift 2 ;; |
121 |
-f ) forceremove=1 ; shift ;; |
122 |
-- ) shift ; break ;; |
123 |
-* ) error "Cannot parse option $1" ; break ;; |
124 |
* ) break ;; |
125 |
esac |
126 |
done |
127 |
|
128 |
# invoke removal of directory |
129 |
test "$remove" && { remove "$remove" ; exit $?; } |
130 |
|
131 |
case "$#" in |
132 |
1 ) TMPDIR="$1" ;; |
133 |
esac |
134 |
|
135 |
###################################################################### |
136 |
# creating a temporary directory owner by the target uid with |
137 |
# mask $tmode |
138 |
# |
139 |
|
140 |
# set defaults |
141 |
TMPDIR=${TMPDIR:-/tmp} |
142 |
MODE=${MODE:-0755} |
143 |
umask 0077 |
144 |
|
145 |
# create private temporary WD and return its name |
146 |
securedir=`$mktemp -d "$TMPDIR/gltmpdir.$$.XXXX"` || error \ |
147 |
"Cannot create secured directory at $TMPDIR" |
148 |
# this should be superfluous given the 0077 umask, but do it anyway |
149 |
$chmod 0700 "$securedir" |
150 |
|
151 |
# make world-writable sticky directory below this one for the target uid |
152 |
stickydir=`$mktemp -d "$securedir/XXXX"` || { |
153 |
rmdir -f "$securedir" |
154 |
error "Cannot create world-writable stikcy directory in the secure area" |
155 |
} |
156 |
$chmod 1777 "$stickydir" |
157 |
|
158 |
cd "$stickydir" || { |
159 |
rmdir "$stickydir" && rmdir "$securedir" |
160 |
error "Cannot enter sticky directory" |
161 |
} |
162 |
|
163 |
targetdir=`$glexec $mktemp -d XXXX` |
164 |
rc=$? |
165 |
|
166 |
cd ../.. |
167 |
|
168 |
test $rc -ne 0 && { |
169 |
warn "Cannot create target uid temporary directory: $rc" |
170 |
rmdir "$stickydir" |
171 |
rmdir "$securedir" |
172 |
exit "Cleanup attempted, exiting." |
173 |
} |
174 |
|
175 |
test "$tmode" && { |
176 |
cd "$stickydir" |
177 |
$glexec $chmod $tmode "$targetdir" |
178 |
rc=$? |
179 |
cd ../.. |
180 |
test $rc -ne 0 && { |
181 |
warn "Cannot set target mode $tmode for $targetdir: $rc" |
182 |
rmdir "$stickydir" |
183 |
rmdir "$securedir" |
184 |
exit "Cleanup attempted, exiting." |
185 |
} |
186 |
} |
187 |
|
188 |
$chmod $MODE "$stickydir" |
189 |
$chmod $MODE "$securedir" |
190 |
|
191 |
echo "$stickydir/$targetdir" |