2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
14 #include <afsconfig.h>
15 #include <afs/param.h>
42 /* Open the auxiliary database file containing failed authentication
43 * counters, and the times at which the last failures occurred.
46 int kaux_opendb(char *path)
48 char dbpathname[1024];
49 static char dbname[] = "auxdb";
51 if (strlen(path) < 1024 - strlen(dbname)) { /* bullet-proofing */
53 strcpy(dbpathname, path);
54 strcat(dbpathname, dbname);
56 fd = open (dbpathname, O_CREAT | O_RDWR, 0600);
57 if (fd <0) perror(dbpathname);
63 /* close that auxiliary database. Unneccessary, but here for symmetry.
65 void kaux_closedb(void)
68 if (fd > 0) close(fd);
74 * The read and write routines take as a parameter, the offset into
75 * the main database at which a particular user's entry resides. They
76 * then convert that into an offset into the auxiliary database. This
77 * makes the main code a little simpler, though it obscures a small
81 afs_int32 to, /* this is the offset of the user id in the main database.
82 * we do the conversion here - probably a bad idea. */
83 unsigned int *nfailures,
88 *nfailures = *lasttime = 0;
90 if (fd <= 0 || !to) return 0;
92 offset = ((to - sizeof(struct kaheader))/ENTRYSIZE)*(sizeof(int)+sizeof(afs_int32));
93 /* can't get there from here */
94 if (offset > lseek(fd, offset, SEEK_SET)) return 0;
96 /* we should just end up with 0 for nfailures and lasttime if EOF is
97 * encountered here, I hope */
98 if ((0 > read(fd, nfailures, sizeof(int))) ||
99 (0 > read(fd, lasttime, sizeof(afs_int32)))) {
100 *nfailures = *lasttime = 0;
101 perror("kaux_read()");
109 unsigned int nfailures,
114 if (fd <= 0 || !to) return 0;
116 offset = ((to - sizeof(struct kaheader))/ENTRYSIZE)*(sizeof(int)+sizeof(afs_int32));
117 /* can't get there from here */
118 if (offset > lseek(fd, offset, SEEK_SET)) return 0;
120 if ((write (fd, &nfailures, sizeof(int)) != sizeof(int)) ||
121 (write (fd, &lasttime, sizeof(afs_int32)) != sizeof(afs_int32)))
122 perror("kaux_write()");
127 /* adjust this user's records to reflect a failure.
128 * locktime is the value stored in the main database that specifies
129 * how long a user's ID should be locked once the attempts limit has
130 * been exceeded. It also functions as the interval during which the
131 * permitted N-1 authentication failures plus the forbidden Nth
132 * failure must occur, in order for the ID to actually be locked. Ie,
133 * all failures which occurred more than _locktime_ seconds ago are
135 * locktime == 0 signifies that the ID should be locked indefinitely
142 afs_uint32 lasttime, now;
146 kaux_read(to, &nfailures, &lasttime);
148 if (locktime && lasttime + locktime < now)
153 kaux_write(to, nfailures, now);
158 * report on whether a particular id is locked or not...
159 * has to get some dirt from ubik.
160 * We multiply the actual number of permitted attempts by two because
161 * klog tries to authenticate twice when the password is bogus: once
162 * with the ka_string_to_key, and once with des_string_to_key, for
163 * Kerberos compatibility. It's easier to frob here than to explain
165 * RETURNS: time when the ID will be unlocked, or 0 if it's not locked.
172 extern int ubeacon_Debug(), ubeacon_AmSyncSite();
173 unsigned int nfailures, myshare;
175 struct ubik_debug beaconinfo;
177 /* if attempts is 0, that means there's no limit, so the id
178 * can't ever be locked...
180 if (!attempts) return 0;
182 kaux_read(to, &nfailures, &lasttime);
184 ubeacon_Debug(&beaconinfo);
185 attempts = attempts * 2;
187 myshare = attempts / beaconinfo.nServers;
188 if (ubeacon_AmSyncSite())
189 myshare += attempts % beaconinfo.nServers;
194 else if ((nfailures < myshare) || (locktime && lasttime + locktime < time(0))) {
197 else if (locktime == 0) { /* infinite */
201 return (lasttime + locktime);