1 /* dbconverter-2.c -- convert libsasl v1 sasldb's to SASLv2 format
2 * $Id: dbconverter-2.c,v 1.8 2003/02/13 19:56:17 rjs3 Exp $
4 * based on SASLv1 sasldblistusers
7 * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
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
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
28 * Pittsburgh, PA 15213-3890
29 * (412) 268-4387, fax: (412) 268-7395
30 * tech-transfer@andrew.cmu.edu
32 * 4. Redistributions of any form whatsoever must retain the following
34 * "This product includes software developed by Computing Services
35 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
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.
53 #include "../sasldb/sasldb.h"
55 /* Cheating to make the utils work out right */
56 extern const sasl_utils_t *sasl_global_utils;
57 sasl_conn_t *globalconn;
59 typedef void *listcb_t(const char *, const char *, const char *,
60 const char *, unsigned);
62 void listusers_cb(const char *authid, const char *realm,
63 const char *mechanism, const char *secret,
66 char newPropBuffer[8192];
68 if (!authid || !mechanism || !realm) {
69 fprintf(stderr,"userlist callback has bad param");
73 /* the entries that just say the mechanism exists */
74 if (strlen(authid)==0) return;
76 printf("Converting: %s@%s (%s)...",authid,realm,mechanism);
78 /* Maybe we have a plaintext password? */
79 if(!strcmp(mechanism,"PLAIN-APOP")) {
80 sprintf(newPropBuffer, "userPassword");
81 /* Skip salt + NULL */
85 sprintf(newPropBuffer, "cmusaslsecret%s", mechanism);
88 _sasldb_putdata(sasl_global_utils, globalconn,
89 authid, realm, newPropBuffer,
96 * List all users in database
99 #if defined(SASL_GDBM)
103 #include <sys/stat.h>
105 int listusers(const char *path, listcb_t *cb)
108 datum dkey, nextkey, dvalue;
110 indb = gdbm_open((char *)path, 0, GDBM_READER, S_IRUSR | S_IWUSR, NULL);
113 fprintf(stderr, "can't open %s\n", path);
117 memset(&dkey, 0, sizeof(datum));
119 dkey = gdbm_firstkey(indb);
121 while (dkey.dptr != NULL) {
122 char *authid = dkey.dptr;
123 char *realm = dkey.dptr+strlen(authid)+1;
124 char *tmp = realm + strlen(realm)+1;
126 int len = dkey.dsize - (tmp - ((char *)dkey.dptr));
128 if (len >= (int) sizeof mech) {
129 fprintf(stderr, "malformed database entry\n");
132 memcpy(mech, tmp, len);
133 mech[dkey.dsize - (tmp - dkey.dptr)] = '\0';
135 dvalue = gdbm_fetch(indb, dkey);
137 if (*authid && dvalue.dptr) {
138 /* don't check return values */
139 cb(authid,realm,mech,dvalue.dptr,dvalue.dsize);
142 nextkey=gdbm_nextkey(indb, dkey);
150 #elif defined(SASL_NDBM)
154 #include <sys/stat.h>
156 int listusers(const char *path, listcb_t *cb)
159 datum dkey, nextkey, dvalue;
161 indb = dbm_open(path, O_RDONLY, S_IRUSR | S_IWUSR);
164 fprintf(stderr, "can't open %s\n", path);
168 dkey = dbm_firstkey(indb);
170 while (dkey.dptr != NULL) {
171 char *authid = dkey.dptr;
172 char *realm = dkey.dptr+strlen(authid)+1;
173 char *tmp = realm + strlen(realm)+1;
175 int len = dkey.dsize - (tmp - ((char *)dkey.dptr));
177 if (len >= (int) sizeof mech) {
178 fprintf(stderr, "malformed database entry\n");
181 memcpy(mech, tmp, len);
182 mech[dkey.dsize - (tmp - ((char *)dkey.dptr))] = '\0';
184 dvalue = dbm_fetch(indb, dkey);
186 if (*authid && dvalue.dptr) {
187 /* don't check return values */
188 cb(authid,realm,mech,dvalue.dptr,dvalue.dsize);
191 nextkey=dbm_nextkey(indb);
199 #elif defined(SASL_BERKELEYDB)
207 static int berkeleydb_open(const char *path,DB **mbdb)
211 #if DB_VERSION_MAJOR < 3
212 ret = db_open(path, DB_HASH, DB_CREATE, 0664, NULL, NULL, mbdb);
213 #else /* DB_VERSION_MAJOR < 3 */
214 ret = db_create(mbdb, NULL, 0);
215 if (ret == 0 && *mbdb != NULL)
217 #if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1
218 ret = (*mbdb)->open(*mbdb, NULL, path, NULL, DB_HASH, DB_CREATE, 0664);
220 ret = (*mbdb)->open(*mbdb, path, NULL, DB_HASH, DB_CREATE, 0664);
224 (void) (*mbdb)->close(*mbdb, 0);
228 #endif /* DB_VERSION_MAJOR < 3 */
231 fprintf(stderr,"Error opening password file %s\n", path);
243 static void berkeleydb_close(DB *mbdb)
247 ret = mbdb->close(mbdb, 0);
249 fprintf(stderr,"error closing sasldb: %s",
254 int listusers(const char *path, listcb_t *cb)
262 result=berkeleydb_open(path, &mbdb);
263 if (result!=SASL_OK) goto cleanup;
266 #if DB_VERSION_MAJOR < 3
267 #if DB_VERSION_MINOR < 6
268 result = mbdb->cursor(mbdb, NULL,&cursor);
270 result = mbdb->cursor(mbdb, NULL,&cursor, 0);
271 #endif /* DB_VERSION_MINOR < 7 */
272 #else /* DB_VERSION_MAJOR < 3 */
273 result = mbdb->cursor(mbdb, NULL,&cursor, 0);
274 #endif /* DB_VERSION_MAJOR < 3 */
277 fprintf(stderr,"Making cursor failure: %s\n",db_strerror(result));
282 memset(&key,0, sizeof(key));
283 memset(&data,0,sizeof(data));
286 result = cursor->c_get(cursor, &key, &data,
289 while (result != DB_NOTFOUND)
299 /* make sure there are exactly 2 null's */
300 for (lup=0;lup<key.size;lup++)
301 if (((char *)key.data)[lup]=='\0')
305 fprintf(stderr,"warning: probable database corruption\n");
306 result = cursor->c_get(cursor, &key, &data, DB_NEXT);
311 realm = authid + strlen(authid)+1;
312 tmp = realm + strlen(realm)+1;
313 len = key.size - (tmp - authid);
315 /* make sure we have enough space of mech */
316 if (len >=sizeof(mech)) {
317 fprintf(stderr,"warning: absurdly long mech name\n");
318 result = cursor->c_get(cursor, &key, &data, DB_NEXT);
322 memcpy(mech, tmp, key.size - (tmp - ((char *)key.data)));
323 mech[key.size - (tmp - ((char *)key.data))] = '\0';
326 /* don't check return values */
327 cb(authid,realm,mech,data.data,data.size);
330 result = cursor->c_get(cursor, &key, &data, DB_NEXT);
333 if (result != DB_NOTFOUND) {
334 fprintf(stderr,"failure: %s\n",db_strerror(result));
339 result = cursor->c_close(cursor);
340 if (result!=0) result = SASL_FAIL;
346 if (mbdb != NULL) berkeleydb_close(mbdb);
354 int listusers(const char *path __attribute__((unused)),
355 listcb_t *cb __attribute__((unused)))
357 fprintf(stderr,"Unsupported DB format");
363 char *db_new=SASL_DB_PATH;
365 int good_getopt(void *context __attribute__((unused)),
366 const char *plugin_name __attribute__((unused)),
371 if (db_new && !strcmp(option, "sasldb_path")) {
374 *len = strlen(db_new);
381 static struct sasl_callback goodsasl_cb[] = {
382 { SASL_CB_GETOPT, &good_getopt, NULL },
383 { SASL_CB_LIST_END, NULL, NULL }
386 int main(int argc, char **argv)
388 const char *db="/etc/sasldb";
398 result = sasl_server_init(goodsasl_cb, "dbconverter");
399 if (result != SASL_OK) {
400 printf("couldn't init saslv2\n");
404 result = sasl_server_new("sasldb",
412 if (result != SASL_OK) {
413 printf("couldn't create globalconn\n");
417 if(_sasl_check_db(sasl_global_utils,globalconn) != SASL_OK) {
418 printf("target DB %s is not OK\n", db_new);
422 printf("\nThis program will take the sasldb file specified on the\n"
423 "command line and convert it to a new sasldb file in the default\n"
424 "location (usually /etc/sasldb). It is STRONGLY RECOMMENDED that you\n"
425 "backup sasldb before allowing this program to run\n\n"
426 "We are going to convert %s and our output will be in %s\n\n"
427 "Press return to continue\n", db, db_new);
431 listusers(db, (listcb_t *) &listusers_cb);
433 sasl_dispose(&globalconn);