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
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.
17 Modified by cmetz for OPIE 2.4. Use snprintf.
18 Modified by cmetz for OPIE 2.31. Put locks in a separate dir.
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.
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 $
38 #endif /* HAVE_STRING_H */
41 #endif /* HAVE_UNISTD_H */
47 #endif /* HAVE_STDLIB_H */
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
63 char *__opie_lockfilename
= (char *)0;
65 /* atexit() handler for opielock() */
66 VOIDRET opieunlockaeh FUNCTION_NOARGS
68 if (__opie_lockfilename
) {
69 __opie_lockrefcount
= 0;
73 #endif /* USER_LOCKING */
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
)
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()) {
100 syslog(LOG_DEBUG
, "opielock: requires superuser priveleges");
105 if (__opie_lockfilename
) {
106 __opie_lockrefcount
++;
110 if (!(__opie_lockfilename
= (char *)malloc(sizeof(OPIE_LOCK_DIR
) + 1 + strlen(principal
))))
113 strcpy(__opie_lockfilename
, OPIE_LOCK_DIR
);
115 if (mkdir(__opie_lockfilename
, 0700) < 0)
119 if (lstat(__opie_lockfilename
, &statbuf
[0]) < 0)
122 if (statbuf
[0].st_uid
) {
124 syslog(LOG_DEBUG
, "opielock: %s isn't owned by the superuser.", __opie_lockfilename
);
129 if (!S_ISDIR(statbuf
[0].st_mode
)) {
131 syslog(LOG_DEBUG
, "opielock: %s isn't a directory.", __opie_lockfilename
);
136 if ((statbuf
[0].st_mode
& 0777) != 00700) {
138 syslog(LOG_DEBUG
, "opielock: permissions on %s are not correct.", __opie_lockfilename
);
143 strcat(__opie_lockfilename
, "/");
144 strcat(__opie_lockfilename
, principal
);
148 if (!lstat(__opie_lockfilename
, &statbuf
[0]))
149 if (!S_ISREG(statbuf
[0].st_mode
))
152 if ((fh
= open(__opie_lockfilename
, O_WRONLY
| O_CREAT
| O_EXCL
, 0600)) < 0) {
153 if (lstat(__opie_lockfilename
, &statbuf
[1]) < 0)
155 if (statbuf
[0].st_ino
!= statbuf
[1].st_ino
)
157 if (statbuf
[0].st_mode
!= statbuf
[1].st_mode
)
159 if ((fh
= open(__opie_lockfilename
, O_RDONLY
, 0600)) < 0)
161 if ((i
= read(fh
, buffer
, sizeof(buffer
))) <= 0)
164 buffer
[sizeof(buffer
) - 1] = 0;
167 if (!(c
= strchr(buffer
, '\n')))
172 if (!(c2
= strchr(c
, '\n')))
177 if (!(pid
= atoi(buffer
)))
183 if ((t
+ OPIE_LOCK_TIMEOUT
) < time(0))
199 if (lstat(__opie_lockfilename
, &statbuf
[0]) < 0)
201 if (fstat(fh
, &statbuf
[1]) < 0)
203 if (!S_ISREG(statbuf
[0].st_mode
) || (statbuf
[0].st_mode
!= statbuf
[1].st_mode
) || (statbuf
[0].st_ino
!= statbuf
[1].st_ino
))
206 if (snprintf(buffer
, sizeof(buffer
), "%d\n%d\n", getpid(), time(0)) >= sizeof(buffer
))
209 i
= strlen(buffer
) + 1;
210 if (lseek(fh
, 0, SEEK_SET
)) {
212 unlink(__opie_lockfilename
);
216 if (write(fh
, buffer
, i
) != i
) {
218 unlink(__opie_lockfilename
);
223 if ((fh
= open(__opie_lockfilename
, O_RDWR
, 0600)) < 0) {
224 unlink(__opie_lockfilename
);
227 if (read(fh
, buffer2
, i
) != i
) {
229 unlink(__opie_lockfilename
);
234 if (memcmp(buffer
, buffer2
, i
)) {
235 unlink(__opie_lockfilename
);
239 __opie_lockrefcount
++;
242 atexit(opieunlockaeh
);
247 if (!__opie_lockrefcount
) {
248 free (__opie_lockfilename
);
249 __opie_lockfilename
= NULL
;
252 #else /* USER_LOCKING */
253 __opie_lockrefcount
++;
255 #endif /* USER_LOCKING */