kauth-warning-cleanup-20011005
[openafs.git] / src / kauth / kaauxdb.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 /*
11  * ALL RIGHTS RESERVED
12  */
13
14 #include <afsconfig.h>
15 #include <afs/param.h>
16
17 RCSID("$Header$");
18
19 #ifdef AFS_NT40_ENV
20 #include <io.h>
21 #else
22 #include <sys/file.h>
23 #endif
24 #ifdef HAVE_FCNTL_H
25 #include <fcntl.h>
26 #endif
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #else
30 #ifdef HAVE_STRINGS_H
31 #include <strings.h>
32 #endif
33 #endif
34 #include <rx/rxkad.h>
35 #include "ubik_int.h"
36 #include "kauth.h"
37 #include "kaserver.h"
38
39
40 static int fd = 0;
41
42 /* Open the auxiliary database file containing failed authentication
43  * counters, and the times at which the last failures occurred.
44  * Nothing fancy.
45  */
46 int kaux_opendb(char *path)
47 {
48     char dbpathname[1024];
49     static char dbname[] = "auxdb";
50
51     if (strlen(path) < 1024 - strlen(dbname)) {  /* bullet-proofing */
52
53         strcpy(dbpathname, path);
54         strcat(dbpathname, dbname);
55
56         fd = open (dbpathname, O_CREAT | O_RDWR, 0600);
57         if (fd <0) perror(dbpathname);
58     }
59
60     return fd;
61 }
62
63 /* close that auxiliary database.  Unneccessary, but here for symmetry.
64  */
65 void kaux_closedb(void)
66 {
67
68     if (fd > 0) close(fd);
69     return;
70 }
71
72
73 /* 
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
78  * detail.
79  */
80 int kaux_read(
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,
84   afs_uint32 *lasttime)
85 {
86     unsigned int offset;
87
88     *nfailures = *lasttime = 0;
89
90     if (fd <= 0 || !to) return 0;
91
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;
95
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()");
102     }
103
104     return 0;
105 }          
106
107 int kaux_write(
108   afs_int32 to,
109   unsigned int nfailures,
110   afs_uint32 lasttime)
111 {
112     unsigned int offset;
113
114     if (fd <= 0 || !to) return 0;
115
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;
119
120     if ((write (fd, &nfailures, sizeof(int)) != sizeof(int)) || 
121     (write (fd, &lasttime, sizeof(afs_int32)) != sizeof(afs_int32))) 
122         perror("kaux_write()");
123
124 }          
125
126
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
134  * forgiven.
135  * locktime == 0 signifies that the ID should be locked indefinitely
136  */
137 void kaux_inc(
138     afs_int32 to,
139     afs_uint32 locktime)
140 {
141     int nfailures;
142     afs_uint32 lasttime, now;          
143
144     now = time(0);
145
146     kaux_read(to, &nfailures, &lasttime);
147
148     if (locktime && lasttime + locktime < now) 
149         nfailures = 1;
150     else
151         nfailures++;
152
153     kaux_write(to, nfailures, now);
154
155 }          
156
157 /* 
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
164  * to users/admins.
165  * RETURNS: time when the ID will be unlocked, or 0 if it's not locked. 
166  */
167 int kaux_islocked(
168   afs_int32 to,
169   u_int   attempts,
170   u_int   locktime)
171 {
172     extern int ubeacon_Debug(), ubeacon_AmSyncSite();
173     unsigned int nfailures, myshare;
174     afs_uint32 lasttime;
175     struct ubik_debug beaconinfo;
176
177     /* if attempts is 0, that means there's no limit, so the id
178     * can't ever be locked...
179     */
180     if (!attempts) return 0;  
181
182     kaux_read(to, &nfailures, &lasttime);
183
184     ubeacon_Debug(&beaconinfo);
185     attempts = attempts * 2;
186
187     myshare = attempts / beaconinfo.nServers;
188     if (ubeacon_AmSyncSite())
189      myshare += attempts % beaconinfo.nServers;
190
191     if (!myshare) {
192         return -1;
193     }
194     else if ((nfailures <  myshare) || (locktime && lasttime + locktime < time(0))) {
195         return 0;
196     }
197     else if (locktime == 0) { /* infinite */
198         return -1;
199     }
200     else {
201         return (lasttime + locktime);
202     }
203 }