afsconfig-and-rcsid-all-around-20010705
[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 <afs/param.h>
15 #include <afsconfig.h>
16
17 RCSID("$Header$");
18
19 #include <fcntl.h>
20 #ifdef AFS_NT40_ENV
21 #include <fcntl.h>
22 #include <io.h>
23 #else
24 #include <sys/file.h>
25 #endif
26 #include <rx/rxkad.h>
27 #include "ubik_int.h"
28 #include "kauth.h"
29 #include "kaserver.h"
30
31
32 static int fd = 0;
33
34 /* Open the auxiliary database file containing failed authentication
35  * counters, and the times at which the last failures occurred.
36  * Nothing fancy.
37  */
38 int kaux_opendb(char *path)
39 {
40     char dbpathname[1024];
41     static char dbname[] = "auxdb";
42
43     if (strlen(path) < 1024 - strlen(dbname)) {  /* bullet-proofing */
44
45         strcpy(dbpathname, path);
46         strcat(dbpathname, dbname);
47
48         fd = open (dbpathname, O_CREAT | O_RDWR, 0600);
49         if (fd <0) perror(dbpathname);
50     }
51
52     return fd;
53 }
54
55 /* close that auxiliary database.  Unneccessary, but here for symmetry.
56  */
57 void kaux_closedb(void)
58 {
59
60     if (fd > 0) close(fd);
61     return;
62 }
63
64
65 /* 
66  * The read and write routines take as a parameter, the offset into
67  * the main database at which a particular user's entry resides.  They
68  * then convert that into an offset into the auxiliary database.  This
69  * makes the main code a little simpler, though it obscures a small
70  * detail.
71  */
72 int kaux_read(
73   afs_int32 to,  /* this is the offset of the user id in the main database. 
74              * we do the conversion here - probably a bad idea. */
75   unsigned int *nfailures,
76   afs_uint32 *lasttime)
77 {
78     unsigned int offset;
79
80     *nfailures = *lasttime = 0;
81
82     if (fd <= 0 || !to) return 0;
83
84     offset = ((to - sizeof(struct kaheader))/ENTRYSIZE)*(sizeof(int)+sizeof(afs_int32));
85     /* can't get there from here */
86     if (offset > lseek(fd, offset, SEEK_SET)) return 0;
87
88     /* we should just end up with 0 for nfailures and lasttime if EOF is 
89     * encountered here, I hope */
90     if ((0 > read(fd, nfailures, sizeof(int))) || 
91     (0 > read(fd, lasttime, sizeof(afs_int32)))) {
92         *nfailures = *lasttime = 0;
93         perror("kaux_read()");
94     }
95
96     return 0;
97 }          
98
99 int kaux_write(
100   afs_int32 to,
101   unsigned int nfailures,
102   afs_uint32 lasttime)
103 {
104     unsigned int offset;
105
106     if (fd <= 0 || !to) return 0;
107
108     offset = ((to - sizeof(struct kaheader))/ENTRYSIZE)*(sizeof(int)+sizeof(afs_int32));
109     /* can't get there from here */
110     if (offset > lseek(fd, offset, SEEK_SET)) return 0;
111
112     if ((write (fd, &nfailures, sizeof(int)) != sizeof(int)) || 
113     (write (fd, &lasttime, sizeof(afs_int32)) != sizeof(afs_int32))) 
114         perror("kaux_write()");
115
116 }          
117
118
119 /* adjust this user's records to reflect a failure.
120  * locktime is the value stored in the main database that specifies
121  * how afs_int32 a user's ID should be locked once the attempts limit has
122  * been exceeded.  It also functions as the interval during which the
123  * permitted N-1 authentication failures plus the forbidden Nth
124  * failure must occur, in order for the ID to actually be locked.  Ie,
125  * all failures which occurred more than _locktime_ seconds ago are
126  * forgiven.
127  * locktime == 0 signifies that the ID should be locked indefinitely
128  */
129 void kaux_inc(
130     afs_int32 to,
131     afs_uint32 locktime)
132 {
133     int nfailures;
134     afs_uint32 lasttime, now;          
135
136     now = time(0);
137
138     kaux_read(to, &nfailures, &lasttime);
139
140     if (locktime && lasttime + locktime < now) 
141         nfailures = 1;
142     else
143         nfailures++;
144
145     kaux_write(to, nfailures, now);
146
147 }          
148
149 /* 
150  * report on whether a particular id is locked or not...
151  * has to get some dirt from ubik.
152  * We multiply the actual number of permitted attempts by two because
153  * klog tries to authenticate twice when the password is bogus: once
154  * with the ka_string_to_key, and once with des_string_to_key, for
155  * Kerberos compatibility.  It's easier to frob here than to explain
156  * to users/admins.
157  * RETURNS: time when the ID will be unlocked, or 0 if it's not locked. 
158  */
159 int kaux_islocked(
160   afs_int32 to,
161   u_int   attempts,
162   u_int   locktime)
163 {
164     extern int ubeacon_Debug(), ubeacon_AmSyncSite();
165     unsigned int nfailures, myshare;
166     afs_uint32 lasttime;
167     struct ubik_debug beaconinfo;
168     afs_uint32 now;
169
170     /* if attempts is 0, that means there's no limit, so the id
171     * can't ever be locked...
172     */
173     if (!attempts) return 0;  
174
175     kaux_read(to, &nfailures, &lasttime);
176
177     ubeacon_Debug(&beaconinfo);
178     attempts = attempts * 2;
179
180     myshare = attempts / beaconinfo.nServers;
181     if (ubeacon_AmSyncSite())
182      myshare += attempts % beaconinfo.nServers;
183
184     if (!myshare) {
185         return -1;
186     }
187     else if ((nfailures <  myshare) || (locktime && lasttime + locktime < time(0))) {
188         return 0;
189     }
190     else if (locktime == 0) { /* infinite */
191         return -1;
192     }
193     else {
194         return (lasttime + locktime);
195     }
196 }