1 /*	$NetBSD: otp_db.c,v 1.1.1.1 2011/04/13 18:15:39 elric Exp $	*/
2 
3 /*
4  * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 __RCSID("$NetBSD: otp_db.c,v 1.1.1.1 2011/04/13 18:15:39 elric Exp $");
39 #endif
40 
41 #include "otp_locl.h"
42 
43 #if !defined(HAVE_NDBM) && !defined(HAVE_DB_NDBM)
44 #include "ndbm_wrap.h"
45 #endif
46 
47 #define RETRIES 5
48 
49 void *
50 otp_db_open (void)
51 {
52   int lock;
53   int i;
54   void *ret;
55 
56   for(i = 0; i < RETRIES; ++i) {
57     struct stat statbuf;
58 
59     lock = open (OTP_DB_LOCK, O_WRONLY | O_CREAT | O_EXCL, 0666);
60     if (lock >= 0) {
61       close(lock);
62       break;
63     }
64     if (stat (OTP_DB_LOCK, &statbuf) == 0) {
65       if (time(NULL) - statbuf.st_mtime > OTP_DB_TIMEOUT)
66 	unlink (OTP_DB_LOCK);
67       else
68 	sleep (1);
69     }
70   }
71   if (i == RETRIES)
72     return NULL;
73   ret = dbm_open (OTP_DB, O_RDWR | O_CREAT, 0600);
74   if (ret == NULL)
75     unlink (OTP_DB_LOCK);
76   return ret;
77 }
78 
79 void
80 otp_db_close (void *dbm)
81 {
82   dbm_close ((DBM *)dbm);
83   unlink (OTP_DB_LOCK);
84 }
85 
86 /*
87  * Remove this entry from the database.
88  * return 0 if ok.
89  */
90 
91 int
92 otp_delete (void *v, OtpContext *ctx)
93 {
94   DBM *dbm = (DBM *)v;
95   datum key;
96 
97   key.dsize = strlen(ctx->user);
98   key.dptr  = ctx->user;
99 
100   return dbm_delete(dbm, key);
101 }
102 
103 /*
104  * Read this entry from the database and lock it if lockp.
105  */
106 
107 static int
108 otp_get_internal (void *v, OtpContext *ctx, int lockp)
109 {
110   DBM *dbm = (DBM *)v;
111   datum dat, key;
112   char *p;
113   time_t now, then;
114 
115   key.dsize = strlen(ctx->user);
116   key.dptr  = ctx->user;
117 
118   dat = dbm_fetch (dbm, key);
119   if (dat.dptr == NULL) {
120     ctx->err = "Entry not found";
121     return -1;
122   }
123   p = dat.dptr;
124 
125   memcpy (&then, p, sizeof(then));
126   ctx->lock_time = then;
127   if (lockp) {
128     time(&now);
129     if (then && now - then < OTP_USER_TIMEOUT) {
130       ctx->err = "Entry locked";
131       return -1;
132     }
133     memcpy (p, &now, sizeof(now));
134   }
135   p += sizeof(now);
136   ctx->alg = otp_find_alg (p);
137   if (ctx->alg == NULL) {
138     ctx->err = "Bad algorithm";
139     return -1;
140   }
141   p += strlen(p) + 1;
142   {
143     unsigned char *up = (unsigned char *)p;
144     ctx->n = (up[0] << 24) | (up[1] << 16) | (up[2] << 8) | up[3];
145   }
146   p += 4;
147   memcpy (ctx->key, p, OTPKEYSIZE);
148   p += OTPKEYSIZE;
149   strlcpy (ctx->seed, p, sizeof(ctx->seed));
150   if (lockp)
151     return dbm_store (dbm, key, dat, DBM_REPLACE);
152   else
153     return 0;
154 }
155 
156 /*
157  * Get and lock.
158  */
159 
160 int
161 otp_get (void *v, OtpContext *ctx)
162 {
163   return otp_get_internal (v, ctx, 1);
164 }
165 
166 /*
167  * Get and don't lock.
168  */
169 
170 int
171 otp_simple_get (void *v, OtpContext *ctx)
172 {
173   return otp_get_internal (v, ctx, 0);
174 }
175 
176 /*
177  * Write this entry to the database.
178  */
179 
180 int
181 otp_put (void *v, OtpContext *ctx)
182 {
183   DBM *dbm = (DBM *)v;
184   datum dat, key;
185   char buf[1024], *p;
186   time_t zero = 0;
187   size_t len, rem;
188 
189   key.dsize = strlen(ctx->user);
190   key.dptr  = ctx->user;
191 
192   p = buf;
193   rem = sizeof(buf);
194 
195   if (rem < sizeof(zero))
196       return -1;
197   memcpy (p, &zero, sizeof(zero));
198   p += sizeof(zero);
199   rem -= sizeof(zero);
200   len = strlen(ctx->alg->name) + 1;
201 
202   if (rem < len)
203       return -1;
204   strlcpy (p, ctx->alg->name, rem);
205   p += len;
206   rem -= len;
207 
208   if (rem < 4)
209       return -1;
210   {
211     unsigned char *up = (unsigned char *)p;
212     *up++ = (ctx->n >> 24) & 0xFF;
213     *up++ = (ctx->n >> 16) & 0xFF;
214     *up++ = (ctx->n >>  8) & 0xFF;
215     *up++ = (ctx->n >>  0) & 0xFF;
216   }
217   p += 4;
218   rem -= 4;
219 
220   if (rem < OTPKEYSIZE)
221       return -1;
222   memcpy (p, ctx->key, OTPKEYSIZE);
223   p += OTPKEYSIZE;
224   rem -= OTPKEYSIZE;
225 
226   len = strlen(ctx->seed) + 1;
227   if (rem < len)
228       return -1;
229   strlcpy (p, ctx->seed, rem);
230   p += len;
231   rem -= len;
232   dat.dptr  = buf;
233   dat.dsize = p - buf;
234   return dbm_store (dbm, key, dat, DBM_REPLACE);
235 }
236