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