lock.c revision 59300
1155192Srwatson/* lock.c: The opielock() library function. 2188311Srwatson 3155192Srwatson%%% portions-copyright-cmetz-96 4155192SrwatsonPortions of this software are Copyright 1996-1998 by Craig Metz, All Rights 5155192SrwatsonReserved. The Inner Net License Version 2 applies to these portions of 6155192Srwatsonthe software. 7155192SrwatsonYou should have received a copy of the license with this software. If 8155192Srwatsonyou didn't get a copy, you may request one from <license@inner.net>. 9155192Srwatson 10155192SrwatsonPortions of this software are Copyright 1995 by Randall Atkinson and Dan 11155192SrwatsonMcDonald, All Rights Reserved. All Rights under this copyright are assigned 12155192Srwatsonto the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and 13180701SrwatsonLicense Agreement applies to this software. 14155192Srwatson 15155192Srwatson History: 16155192Srwatson 17155192Srwatson Modified by cmetz for OPIE 2.31. Put locks in a separate dir. 18155192Srwatson Bug fixes. 19155192Srwatson Modified by cmetz for OPIE 2.3. Do refcounts whether or not we 20155192Srwatson actually lock. Fixed USER_LOCKING=0 case. 21155192Srwatson Modified by cmetz for OPIE 2.22. Added reference count for locks. 22155192Srwatson Changed lock filename/refcount symbol names to better indicate 23155192Srwatson that they're not user serviceable. 24155192Srwatson Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. 25155192Srwatson Use "principal" instead of "name" to make it clearer. 26155192Srwatson Ifdef around some headers, be more careful about allowed 27155192Srwatson error return values. Check open() return value properly. 28155192Srwatson Avoid NULL. 29155192Srwatson Created at NRL for OPIE 2.2 from opiesubr2.c 30178186Srwatson 31178186Srwatson$FreeBSD: head/contrib/opie/libopie/lock.c 59300 2000-04-17 00:01:23Z kris $ 32178186Srwatson*/ 33155192Srwatson#include "opie_cfg.h" 34155192Srwatson#if HAVE_STRING_H 35155192Srwatson#include <string.h> 36155192Srwatson#endif /* HAVE_STRING_H */ 37155192Srwatson#if HAVE_UNISTD_H 38155192Srwatson#include <unistd.h> 39155192Srwatson#endif /* HAVE_UNISTD_H */ 40160136Swsalamon#include <sys/stat.h> 41155192Srwatson#include <syslog.h> 42155192Srwatson#include <fcntl.h> 43155192Srwatson#if HAVE_STDLIB_H 44155192Srwatson#include <stdlib.h> 45155192Srwatson#endif /* HAVE_STDLIB_H */ 46155192Srwatson#include <errno.h> 47155192Srwatson#include "opie.h" 48155192Srwatson 49155192Srwatson#if !HAVE_LSTAT 50155192Srwatson#define lstat(x, y) stat(x, y) 51155192Srwatson#endif /* !HAVE_LSTAT */ 52155192Srwatson 53155192Srwatsonint __opie_lockrefcount = 0; 54155192Srwatsonstatic int do_atexit = 1; 55155192Srwatson 56155192SrwatsonVOIDRET opiedisableaeh FUNCTION_NOARGS 57155192Srwatson{ 58155192Srwatson do_atexit = 0; 59155192Srwatson} 60155192Srwatson#if USER_LOCKING 61155192Srwatsonchar *__opie_lockfilename = (char *)0; 62155192Srwatson 63155192Srwatson/* atexit() handler for opielock() */ 64155192SrwatsonVOIDRET opieunlockaeh FUNCTION_NOARGS 65155192Srwatson{ 66155192Srwatson if (__opie_lockfilename) { 67155192Srwatson __opie_lockrefcount = 0; 68155192Srwatson opieunlock(); 69155192Srwatson } 70155192Srwatson} 71155192Srwatson#endif /* USER_LOCKING */ 72155192Srwatson 73156889Srwatson/* 74156889Srwatson Serialize (we hope) authentication of user to prevent race conditions. 75156889Srwatson Creates a lock file with a name of OPIE_LOCK_PREFIX with the user name 76180706Srwatson appended. This file contains the pid of the lock's owner and a time() 77156889Srwatson stamp. We use the former to check for dead owners and the latter to 78156889Srwatson provide an upper bound on the lock duration. If there are any problems, 79155192Srwatson we assume the lock is bogus. 80156889Srwatson 81155192Srwatson The value of this locking and its security implications are still not 82156889Srwatson completely clear and require further study. 83155192Srwatson 84162466Srwatson One could conceivably hack this facility to provide locking of user 85155192Srwatson accounts after several authentication failures. 86155192Srwatson 87155192Srwatson Return -1 on low-level error, 0 if ok, 1 on locking failure. 88155192Srwatson*/ 89155192Srwatsonint opielock FUNCTION((principal), char *principal) 90155192Srwatson{ 91155192Srwatson#if USER_LOCKING 92155192Srwatson int fh, waits = 0, rval = -1, pid, t, i; 93155192Srwatson char buffer[128], buffer2[128], *c, *c2; 94156889Srwatson struct stat statbuf[2]; 95155192Srwatson 96155192Srwatson if (getuid() && geteuid()) { 97155192Srwatson#if DEBUG 98155192Srwatson syslog(LOG_DEBUG, "opielock: requires superuser priveleges"); 99155192Srwatson#endif /* DEBUG */ 100155192Srwatson return -1; 101155192Srwatson }; 102155192Srwatson 103155192Srwatson if (__opie_lockfilename) { 104155192Srwatson __opie_lockrefcount++; 105155192Srwatson return 0; 106155192Srwatson } 107155192Srwatson 108155192Srwatson if (!(__opie_lockfilename = (char *)malloc(sizeof(OPIE_LOCK_DIR) + 1 + strlen(principal)))) 109155192Srwatson return -1; 110155192Srwatson 111155192Srwatson strcpy(__opie_lockfilename, OPIE_LOCK_DIR); 112155192Srwatson 113155192Srwatson if (mkdir(__opie_lockfilename, 0700) < 0) 114155192Srwatson if (errno != EEXIST) 115155192Srwatson return -1; 116184856Scsjp 117184856Scsjp if (lstat(__opie_lockfilename, &statbuf[0]) < 0) 118184856Scsjp return -1; 119156889Srwatson 120184856Scsjp if (statbuf[0].st_uid) { 121184856Scsjp#if DEBUG 122184856Scsjp syslog(LOG_DEBUG, "opielock: %s isn't owned by the superuser.", __opie_lockfilename); 123184856Scsjp#endif /* DEBUG */ 124184856Scsjp return -1; 125184856Scsjp }; 126184856Scsjp 127184856Scsjp if (!S_ISDIR(statbuf[0].st_mode)) { 128184856Scsjp#if DEBUG 129184856Scsjp syslog(LOG_DEBUG, "opielock: %s isn't a directory.", __opie_lockfilename); 130184856Scsjp#endif /* DEBUG */ 131184856Scsjp return -1; 132184856Scsjp }; 133184856Scsjp 134184856Scsjp if ((statbuf[0].st_mode & 0777) != 00700) { 135184856Scsjp#if DEBUG 136162466Srwatson syslog(LOG_DEBUG, "opielock: permissions on %s are not correct.", __opie_lockfilename); 137170196Srwatson#endif /* DEBUG */ 138162466Srwatson return -1; 139162466Srwatson }; 140184856Scsjp 141184856Scsjp strcat(__opie_lockfilename, "/"); 142184856Scsjp strcat(__opie_lockfilename, principal); 143184856Scsjp 144162466Srwatson fh = -1; 145155192Srwatson while (fh < 0) { 146162466Srwatson if (!lstat(__opie_lockfilename, &statbuf[0])) 147162466Srwatson if (!S_ISREG(statbuf[0].st_mode)) 148155192Srwatson goto lockret; 149162466Srwatson 150162466Srwatson if ((fh = open(__opie_lockfilename, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0) { 151162466Srwatson if (lstat(__opie_lockfilename, &statbuf[1]) < 0) 152162466Srwatson goto lockret; 153162466Srwatson if (statbuf[0].st_ino != statbuf[1].st_ino) 154155192Srwatson goto lockret; 155155192Srwatson if (statbuf[0].st_mode != statbuf[1].st_mode) 156155192Srwatson goto lockret; 157155192Srwatson if ((fh = open(__opie_lockfilename, O_RDONLY, 0600)) < 0) 158156889Srwatson goto lockret; 159156889Srwatson if ((i = read(fh, buffer, sizeof(buffer))) <= 0) 160155192Srwatson goto lockret; 161155192Srwatson 162155192Srwatson buffer[sizeof(buffer) - 1] = 0; 163155192Srwatson buffer[i - 1] = 0; 164155192Srwatson 165155192Srwatson if (!(c = strchr(buffer, '\n'))) 166156889Srwatson break; 167155192Srwatson 168155192Srwatson *(c++) = 0; 169155192Srwatson 170155192Srwatson if (!(c2 = strchr(c, '\n'))) 171156889Srwatson break; 172155192Srwatson 173155192Srwatson *(c2++) = 0; 174156889Srwatson 175155192Srwatson if (!(pid = atoi(buffer))) 176155192Srwatson break; 177155192Srwatson 178155192Srwatson if (!(t = atoi(c))) 179155192Srwatson break; 180170196Srwatson 181180704Srwatson if ((t + OPIE_LOCK_TIMEOUT) < time(0)) 182155192Srwatson break; 183155192Srwatson 184155192Srwatson if (kill(pid, 0)) 185155192Srwatson break; 186195925Srwatson 187195925Srwatson close(fh); 188195925Srwatson fh = 0; 189195925Srwatson sleep(1); 190195925Srwatson if (waits++ > 3) { 191195925Srwatson rval = 1; 192195925Srwatson goto lockret; 193195925Srwatson }; 194195925Srwatson }; 195195925Srwatson }; 196195925Srwatson 197195925Srwatson if (lstat(__opie_lockfilename, &statbuf[0]) < 0) 198195925Srwatson goto lockret; 199195925Srwatson if (fstat(fh, &statbuf[1]) < 0) 200180708Srwatson goto lockret; 201155192Srwatson if (!S_ISREG(statbuf[0].st_mode) || (statbuf[0].st_mode != statbuf[1].st_mode) || (statbuf[0].st_ino != statbuf[1].st_ino)) 202155192Srwatson goto lockret; 203155192Srwatson 204155192Srwatson sprintf(buffer, "%d\n%d\n", getpid(), time(0)); 205155192Srwatson i = strlen(buffer) + 1; 206155192Srwatson if (lseek(fh, 0, SEEK_SET)) { 207180708Srwatson close(fh); 208155192Srwatson unlink(__opie_lockfilename); 209155192Srwatson fh = 0; 210155192Srwatson goto lockret; 211155192Srwatson }; 212155192Srwatson if (write(fh, buffer, i) != i) { 213155192Srwatson close(fh); 214180708Srwatson unlink(__opie_lockfilename); 215195925Srwatson fh = 0; 216195925Srwatson goto lockret; 217195925Srwatson }; 218195925Srwatson close(fh); 219180709Srwatson if ((fh = open(__opie_lockfilename, O_RDWR, 0600)) < 0) { 220155192Srwatson unlink(__opie_lockfilename); 221155192Srwatson goto lockret; 222155192Srwatson }; 223155192Srwatson if (read(fh, buffer2, i) != i) { 224155192Srwatson close(fh); 225180708Srwatson unlink(__opie_lockfilename); 226246911Spjd fh = 0; 227180709Srwatson goto lockret; 228155192Srwatson }; 229155192Srwatson close(fh); 230155192Srwatson if (memcmp(buffer, buffer2, i)) { 231155192Srwatson unlink(__opie_lockfilename); 232155192Srwatson goto lockret; 233180708Srwatson }; 234180709Srwatson 235155192Srwatson __opie_lockrefcount++; 236155192Srwatson rval = 0; 237155192Srwatson if (do_atexit) 238155192Srwatson atexit(opieunlockaeh); 239155192Srwatson 240180711Srwatsonlockret: 241155192Srwatson if (fh >= 0) 242155192Srwatson close(fh); 243155192Srwatson if (!__opie_lockrefcount) { 244155192Srwatson free (__opie_lockfilename); 245155192Srwatson __opie_lockfilename = NULL; 246155192Srwatson }; 247155192Srwatson return rval; 248155192Srwatson#else /* USER_LOCKING */ 249155192Srwatson __opie_lockrefcount++; 250156889Srwatson return 0; 251156889Srwatson#endif /* USER_LOCKING */ 252155192Srwatson} 253155192Srwatson