1/* $NetBSD$ */ 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$"); 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 49void * 50otp_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 79void 80otp_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 91int 92otp_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 107static int 108otp_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 160int 161otp_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 170int 171otp_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 180int 181otp_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