Nuke debug prints.
[dragonfly.git] / contrib / opie / libopie / lock.c
blobdb1fa01b1c81c0de4e953853ab44de16337b8bcd
1 /* lock.c: The opielock() library function.
3 %%% portions-copyright-cmetz-96
4 Portions of this software are Copyright 1996-1999 by Craig Metz, All Rights
5 Reserved. The Inner Net License Version 2 applies to these portions of
6 the software.
7 You should have received a copy of the license with this software. If
8 you didn't get a copy, you may request one from <license@inner.net>.
10 Portions of this software are Copyright 1995 by Randall Atkinson and Dan
11 McDonald, All Rights Reserved. All Rights under this copyright are assigned
12 to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
13 License Agreement applies to this software.
15 History:
17 Modified by cmetz for OPIE 2.4. Use snprintf.
18 Modified by cmetz for OPIE 2.31. Put locks in a separate dir.
19 Bug fixes.
20 Modified by cmetz for OPIE 2.3. Do refcounts whether or not we
21 actually lock. Fixed USER_LOCKING=0 case.
22 Modified by cmetz for OPIE 2.22. Added reference count for locks.
23 Changed lock filename/refcount symbol names to better indicate
24 that they're not user serviceable.
25 Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
26 Use "principal" instead of "name" to make it clearer.
27 Ifdef around some headers, be more careful about allowed
28 error return values. Check open() return value properly.
29 Avoid NULL.
30 Created at NRL for OPIE 2.2 from opiesubr2.c
32 $FreeBSD: src/contrib/opie/libopie/lock.c,v 1.1.1.2.6.2 2002/07/15 14:48:47 des Exp $
33 $DragonFly: src/contrib/opie/libopie/lock.c,v 1.2 2003/06/17 04:24:05 dillon Exp $
35 #include "opie_cfg.h"
36 #if HAVE_STRING_H
37 #include <string.h>
38 #endif /* HAVE_STRING_H */
39 #if HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif /* HAVE_UNISTD_H */
42 #include <sys/stat.h>
43 #include <syslog.h>
44 #include <fcntl.h>
45 #if HAVE_STDLIB_H
46 #include <stdlib.h>
47 #endif /* HAVE_STDLIB_H */
48 #include <errno.h>
49 #include "opie.h"
51 #if !HAVE_LSTAT
52 #define lstat(x, y) stat(x, y)
53 #endif /* !HAVE_LSTAT */
55 int __opie_lockrefcount = 0;
56 static int do_atexit = 1;
58 VOIDRET opiedisableaeh FUNCTION_NOARGS
60 do_atexit = 0;
62 #if USER_LOCKING
63 char *__opie_lockfilename = (char *)0;
65 /* atexit() handler for opielock() */
66 VOIDRET opieunlockaeh FUNCTION_NOARGS
68 if (__opie_lockfilename) {
69 __opie_lockrefcount = 0;
70 opieunlock();
73 #endif /* USER_LOCKING */
75 /*
76 Serialize (we hope) authentication of user to prevent race conditions.
77 Creates a lock file with a name of OPIE_LOCK_PREFIX with the user name
78 appended. This file contains the pid of the lock's owner and a time()
79 stamp. We use the former to check for dead owners and the latter to
80 provide an upper bound on the lock duration. If there are any problems,
81 we assume the lock is bogus.
83 The value of this locking and its security implications are still not
84 completely clear and require further study.
86 One could conceivably hack this facility to provide locking of user
87 accounts after several authentication failures.
89 Return -1 on low-level error, 0 if ok, 1 on locking failure.
91 int opielock FUNCTION((principal), char *principal)
93 #if USER_LOCKING
94 int fh, waits = 0, rval = -1, pid, t, i;
95 char buffer[128], buffer2[128], *c, *c2;
96 struct stat statbuf[2];
98 if (getuid() && geteuid()) {
99 #if DEBUG
100 syslog(LOG_DEBUG, "opielock: requires superuser priveleges");
101 #endif /* DEBUG */
102 return -1;
105 if (__opie_lockfilename) {
106 __opie_lockrefcount++;
107 return 0;
110 if (!(__opie_lockfilename = (char *)malloc(sizeof(OPIE_LOCK_DIR) + 1 + strlen(principal))))
111 return -1;
113 strcpy(__opie_lockfilename, OPIE_LOCK_DIR);
115 if (mkdir(__opie_lockfilename, 0700) < 0)
116 if (errno != EEXIST)
117 return -1;
119 if (lstat(__opie_lockfilename, &statbuf[0]) < 0)
120 return -1;
122 if (statbuf[0].st_uid) {
123 #if DEBUG
124 syslog(LOG_DEBUG, "opielock: %s isn't owned by the superuser.", __opie_lockfilename);
125 #endif /* DEBUG */
126 return -1;
129 if (!S_ISDIR(statbuf[0].st_mode)) {
130 #if DEBUG
131 syslog(LOG_DEBUG, "opielock: %s isn't a directory.", __opie_lockfilename);
132 #endif /* DEBUG */
133 return -1;
136 if ((statbuf[0].st_mode & 0777) != 00700) {
137 #if DEBUG
138 syslog(LOG_DEBUG, "opielock: permissions on %s are not correct.", __opie_lockfilename);
139 #endif /* DEBUG */
140 return -1;
143 strcat(__opie_lockfilename, "/");
144 strcat(__opie_lockfilename, principal);
146 fh = -1;
147 while (fh < 0) {
148 if (!lstat(__opie_lockfilename, &statbuf[0]))
149 if (!S_ISREG(statbuf[0].st_mode))
150 goto lockret;
152 if ((fh = open(__opie_lockfilename, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0) {
153 if (lstat(__opie_lockfilename, &statbuf[1]) < 0)
154 goto lockret;
155 if (statbuf[0].st_ino != statbuf[1].st_ino)
156 goto lockret;
157 if (statbuf[0].st_mode != statbuf[1].st_mode)
158 goto lockret;
159 if ((fh = open(__opie_lockfilename, O_RDONLY, 0600)) < 0)
160 goto lockret;
161 if ((i = read(fh, buffer, sizeof(buffer))) <= 0)
162 goto lockret;
164 buffer[sizeof(buffer) - 1] = 0;
165 buffer[i - 1] = 0;
167 if (!(c = strchr(buffer, '\n')))
168 break;
170 *(c++) = 0;
172 if (!(c2 = strchr(c, '\n')))
173 break;
175 *(c2++) = 0;
177 if (!(pid = atoi(buffer)))
178 break;
180 if (!(t = atoi(c)))
181 break;
183 if ((t + OPIE_LOCK_TIMEOUT) < time(0))
184 break;
186 if (kill(pid, 0))
187 break;
189 close(fh);
190 fh = 0;
191 sleep(1);
192 if (waits++ > 3) {
193 rval = 1;
194 goto lockret;
199 if (lstat(__opie_lockfilename, &statbuf[0]) < 0)
200 goto lockret;
201 if (fstat(fh, &statbuf[1]) < 0)
202 goto lockret;
203 if (!S_ISREG(statbuf[0].st_mode) || (statbuf[0].st_mode != statbuf[1].st_mode) || (statbuf[0].st_ino != statbuf[1].st_ino))
204 goto lockret;
206 if (snprintf(buffer, sizeof(buffer), "%d\n%d\n", getpid(), time(0)) >= sizeof(buffer))
207 goto lockret;
209 i = strlen(buffer) + 1;
210 if (lseek(fh, 0, SEEK_SET)) {
211 close(fh);
212 unlink(__opie_lockfilename);
213 fh = 0;
214 goto lockret;
216 if (write(fh, buffer, i) != i) {
217 close(fh);
218 unlink(__opie_lockfilename);
219 fh = 0;
220 goto lockret;
222 close(fh);
223 if ((fh = open(__opie_lockfilename, O_RDWR, 0600)) < 0) {
224 unlink(__opie_lockfilename);
225 goto lockret;
227 if (read(fh, buffer2, i) != i) {
228 close(fh);
229 unlink(__opie_lockfilename);
230 fh = 0;
231 goto lockret;
233 close(fh);
234 if (memcmp(buffer, buffer2, i)) {
235 unlink(__opie_lockfilename);
236 goto lockret;
239 __opie_lockrefcount++;
240 rval = 0;
241 if (do_atexit)
242 atexit(opieunlockaeh);
244 lockret:
245 if (fh >= 0)
246 close(fh);
247 if (!__opie_lockrefcount) {
248 free (__opie_lockfilename);
249 __opie_lockfilename = NULL;
251 return rval;
252 #else /* USER_LOCKING */
253 __opie_lockrefcount++;
254 return 0;
255 #endif /* USER_LOCKING */