Import Upstream version 1.8.5
[hcoop/debian/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 }