source: trunk/third/cyrus-sasl/sasldb/db_gdbm.c @ 17977

Revision 17977, 9.1 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17976, which included commits to RCS files with non-trunk default branches.
Line 
1/* db_gdbm.c--SASL gdbm interface
2 * Rob Siemborski
3 * Rob Earhart
4 * $Id: db_gdbm.c,v 1.1.1.1 2002-10-13 18:00:39 ghudson Exp $
5 */
6/*
7 * Copyright (c) 2001 Carnegie Mellon University.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. The name "Carnegie Mellon University" must not be used to
22 *    endorse or promote products derived from this software without
23 *    prior written permission. For permission or any other legal
24 *    details, please contact 
25 *      Office of Technology Transfer
26 *      Carnegie Mellon University
27 *      5000 Forbes Avenue
28 *      Pittsburgh, PA  15213-3890
29 *      (412) 268-4387, fax: (412) 268-7395
30 *      tech-transfer@andrew.cmu.edu
31 *
32 * 4. Redistributions of any form whatsoever must retain the following
33 *    acknowledgment:
34 *    "This product includes software developed by Computing Services
35 *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
36 *
37 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
38 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
39 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
40 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
42 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
43 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 */
45
46#include <config.h>
47#include <gdbm.h>
48#include <sys/stat.h>
49#include <stdlib.h>
50#include <assert.h>
51#include "sasldb.h"
52
53static int db_ok = 0;
54
55int _sasldb_getdata(const sasl_utils_t *utils,
56                    sasl_conn_t *conn,
57                    const char *authid,
58                    const char *realm,
59                    const char *propName,
60                    char *out, const size_t max_out, size_t *out_len)
61{
62  int result = SASL_OK;
63  char *key;
64  size_t key_len;
65  GDBM_FILE db;
66  datum gkey, gvalue; 
67  void *cntxt;
68  sasl_getopt_t *getopt;
69  const char *path = SASL_DB_PATH;
70
71  if (!utils) return SASL_BADPARAM;
72  if (!authid || !propName || !realm || !out || !max_out) {
73      utils->seterror(conn, 0,
74                      "Bad parameter in db_gdbm.c: _sasldb_getdata");
75      return SASL_BADPARAM;
76  }
77
78  if (!db_ok) {
79      utils->seterror(conn, 0,
80                      "Database not checked");
81      return SASL_FAIL;
82  }
83
84  result = _sasldb_alloc_key(utils, authid, realm, propName,
85                             &key, &key_len);
86  if (result != SASL_OK) {
87      utils->seterror(conn, 0,
88                      "Could not allocate key in _sasldb_getdata");
89      return result;
90  }
91
92  if (utils->getcallback(conn, SASL_CB_GETOPT,
93                        &getopt, &cntxt) == SASL_OK) {
94      const char *p;
95      if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK
96          && p != NULL && *p != 0) {
97          path = p;
98      }
99  }
100  db = gdbm_open((char *)path, 0, GDBM_READER, S_IRUSR | S_IWUSR, NULL);
101  if (! db) {
102      utils->seterror(cntxt, 0, "Could not open %s: gdbm_errno=%d",
103                      path, gdbm_errno);
104      result = SASL_FAIL;
105      goto cleanup;
106  }
107  gkey.dptr = key;
108  gkey.dsize = key_len;
109  gvalue = gdbm_fetch(db, gkey);
110  gdbm_close(db);
111  if (! gvalue.dptr) {
112      if (gdbm_errno == GDBM_ITEM_NOT_FOUND) {
113          utils->seterror(conn, SASL_NOLOG,
114                          "user: %s@%s property: %s not found in %s",
115                          authid, realm, propName, path);
116          result = SASL_NOUSER;
117      } else {
118          utils->seterror(conn, 0,
119                          "Couldn't fetch entry from %s: gdbm_errno=%d",
120                          path, gdbm_errno);
121          result = SASL_FAIL;
122      }
123      goto cleanup;
124  }
125
126  if((size_t)gvalue.dsize > max_out + 1) {
127      utils->seterror(cntxt, 0, "buffer overflow");
128      return SASL_BUFOVER;
129  }
130 
131  if(out_len) *out_len = gvalue.dsize;
132  memcpy(out, gvalue.dptr, gvalue.dsize);
133  out[gvalue.dsize] = '\0';
134
135  /* Note: not sasl_FREE!  This is memory allocated by gdbm,
136   * which is using libc malloc/free. */
137  free(gvalue.dptr);
138
139 cleanup:
140  utils->free(key);
141
142  return result;
143}
144
145int _sasldb_putdata(const sasl_utils_t *utils,
146                    sasl_conn_t *conn,
147                    const char *authid,
148                    const char *realm,
149                    const char *propName,
150                    const char *data, size_t data_len)
151{
152  int result = SASL_OK;
153  char *key;
154  size_t key_len;
155  GDBM_FILE db;
156  datum gkey;
157  void *cntxt;
158  sasl_getopt_t *getopt;
159  const char *path = SASL_DB_PATH;
160
161  if (!utils) return SASL_BADPARAM;
162
163  if (!authid || !realm || !propName) {
164      utils->seterror(conn, 0,
165                      "Bad parameter in db_gdbm.c: _sasldb_putdata");
166      return SASL_BADPARAM;
167  }
168
169  result = _sasldb_alloc_key(utils, authid, realm, propName,
170                             &key, &key_len);
171  if (result != SASL_OK) {
172      utils->seterror(conn, 0,
173                      "Could not allocate key in _sasldb_putdata");
174      return result;
175  }
176
177  if (utils->getcallback(conn, SASL_CB_GETOPT,
178                         &getopt, &cntxt) == SASL_OK) {
179      const char *p;
180      if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK
181          && p != NULL && *p != 0) {
182          path = p;
183      }
184  }
185  db = gdbm_open((char *)path, 0, GDBM_WRCREAT, S_IRUSR | S_IWUSR, NULL);
186  if (! db) {
187      utils->log(conn, SASL_LOG_ERR,
188                 "SASL error opening password file. "
189                 "Do you have write permissions?\n");
190      utils->seterror(conn, 0, "Could not open %s for write: gdbm_errno=%d",
191                     path, gdbm_errno);
192      result = SASL_FAIL;
193      goto cleanup;
194  }
195  gkey.dptr = key;
196  gkey.dsize = key_len;
197  if (data) {
198    datum gvalue;
199    gvalue.dptr = (char *)data;
200    if(!data_len) data_len = strlen(data);
201    gvalue.dsize = data_len;
202    if (gdbm_store(db, gkey, gvalue, GDBM_REPLACE)) {
203        utils->seterror(conn, 0,
204                        "Couldn't replace entry in %s: gdbm_errno=%d",
205                        path, gdbm_errno);
206        result = SASL_FAIL;
207    }
208  } else {
209      if (gdbm_delete(db, gkey)) {
210          utils->seterror(conn, 0,
211                          "Couldn't delete entry in %s: gdbm_errno=%d",
212                          path, gdbm_errno);
213          result = SASL_NOUSER;
214      }
215  }
216  gdbm_close(db);
217
218 cleanup:
219  utils->free(key);
220
221  return result;
222}
223
224int _sasl_check_db(const sasl_utils_t *utils,
225                   sasl_conn_t *conn)
226{
227    const char *path = SASL_DB_PATH;
228    int ret;
229    void *cntxt;
230    sasl_getopt_t *getopt;
231    sasl_verifyfile_t *vf;
232
233    if(!utils) return SASL_BADPARAM;
234
235    if (utils->getcallback(conn, SASL_CB_GETOPT,
236                           &getopt, &cntxt) == SASL_OK) {
237        const char *p;
238        if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK
239            && p != NULL && *p != 0) {
240            path = p;
241        }
242    }
243
244    ret = utils->getcallback(NULL, SASL_CB_VERIFYFILE,
245                             &vf, &cntxt);
246    if(ret != SASL_OK) {
247        utils->seterror(conn, 0,
248                        "No verifyfile callback");
249        return ret;
250    }
251
252    ret = vf(cntxt, path, SASL_VRFY_PASSWD);
253    if (ret == SASL_OK) {
254        db_ok = 1;
255    }
256
257    if (ret == SASL_OK || ret == SASL_CONTINUE) {
258        return SASL_OK;
259    } else {
260        utils->seterror(conn, 0,
261                        "Verifyfile failed");
262        return ret;
263    }
264}
265
266typedef struct gdbm_handle
267{
268    GDBM_FILE db;
269    datum dkey;
270    int first;
271} handle_t;
272
273sasldb_handle _sasldb_getkeyhandle(const sasl_utils_t *utils,
274                                   sasl_conn_t *conn)
275{
276    const char *path = SASL_DB_PATH;
277    sasl_getopt_t *getopt;
278    void *cntxt;
279    GDBM_FILE db;
280    handle_t *handle;
281   
282    if(!utils || !conn) return NULL;
283
284    if(!db_ok) {
285        utils->seterror(conn, 0, "Database not OK in _sasldb_getkeyhandle");
286        return NULL;
287    }
288
289    if (utils->getcallback(conn, SASL_CB_GETOPT,
290                           &getopt, &cntxt) == SASL_OK) {
291        const char *p;
292        if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK
293            && p != NULL && *p != 0) {
294            path = p;
295        }
296    }
297
298    db = gdbm_open((char *)path, 0, GDBM_READER, S_IRUSR | S_IWUSR, NULL);
299
300    if(!db) {
301        utils->seterror(conn, 0, "Could not open %s: gdbm_errno=%d",
302                         path, gdbm_errno);
303        return NULL;
304    }
305
306    handle = utils->malloc(sizeof(handle_t));
307    if(!handle) {
308        utils->seterror(conn, 0, "no memory in _sasldb_getkeyhandle");
309        gdbm_close(db);
310        return NULL;
311    }
312   
313    handle->db = db;
314    handle->first = 1;
315
316    return (sasldb_handle)handle;
317}
318
319int _sasldb_getnextkey(const sasl_utils_t *utils __attribute__((unused)),
320                       sasldb_handle handle, char *out,
321                       const size_t max_out, size_t *out_len)
322{
323    handle_t *dbh = (handle_t *)handle;
324    datum nextkey;
325
326    if(!utils || !handle || !out || !max_out)
327        return SASL_BADPARAM;
328
329    if(dbh->first) {
330        dbh->dkey = gdbm_firstkey(dbh->db);
331        dbh->first = 0;
332    } else {
333        nextkey = gdbm_nextkey(dbh->db, dbh->dkey);
334        dbh->dkey = nextkey;
335    }
336
337    if(dbh->dkey.dptr == NULL)
338        return SASL_OK;
339   
340    if((unsigned)dbh->dkey.dsize > max_out)
341        return SASL_BUFOVER;
342   
343    memcpy(out, dbh->dkey.dptr, dbh->dkey.dsize);
344    if(out_len) *out_len = dbh->dkey.dsize;
345   
346    return SASL_CONTINUE;
347}
348
349int _sasldb_releasekeyhandle(const sasl_utils_t *utils,
350                             sasldb_handle handle)
351{
352    handle_t *dbh = (handle_t *)handle;
353   
354    if(!utils || !dbh) return SASL_BADPARAM;
355
356    if(dbh->db) gdbm_close(dbh->db);
357
358    utils->free(dbh);
359   
360    return SASL_OK;
361}
362
Note: See TracBrowser for help on using the repository browser.