1/* db_berkeley.c--SASL berkeley db interface 2 * Rob Siemborski 3 * Tim Martin 4 * $Id: allockey.c,v 1.9 2008/10/30 14:17:08 mel Exp $ 5 */ 6/* 7 * Copyright (c) 1998-2003 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 48#include <stdio.h> 49 50#include <sys/stat.h> 51#include <stdlib.h> 52#include "sasldb.h" 53 54/* 55 * Construct a key 56 * 57 */ 58int _sasldb_alloc_key(const sasl_utils_t *utils, 59 const char *auth_identity, 60 const char *realm, 61 const char *propName, 62 char **key, 63 size_t *key_len) 64{ 65 size_t auth_id_len, realm_len, prop_len; 66 67 if(!utils || !auth_identity || !realm || !propName || !key || !key_len) 68 return SASL_BADPARAM; 69 70 auth_id_len = strlen(auth_identity); 71 realm_len = strlen(realm); 72 prop_len = strlen(propName); 73 74 *key_len = auth_id_len + realm_len + prop_len + 2; 75 *key = utils->malloc(*key_len); 76 if (! *key) 77 return SASL_NOMEM; 78 memcpy(*key, auth_identity, auth_id_len); 79 (*key)[auth_id_len] = '\0'; 80 memcpy(*key + auth_id_len + 1, realm, realm_len); 81 (*key)[auth_id_len + realm_len + 1] = '\0'; 82 memcpy(*key + auth_id_len + realm_len + 2, propName, prop_len); 83 84 return SASL_OK; 85} 86 87/* 88 * decode a key 89 */ 90int _sasldb_parse_key(const char *key, const size_t key_len, 91 char *authid, const size_t max_authid, 92 char *realm, const size_t max_realm, 93 char *propName, const size_t max_propname) 94{ 95 unsigned i = 0; 96 unsigned numnulls = 0; 97 size_t alen = 0, rlen = 0, pnlen = 0; 98 99 if(!key || !key_len 100 || (authid && !max_authid) 101 || (realm && !max_realm) 102 || (propName && !max_propname)) 103 return SASL_BADPARAM; 104 105 for(i=0; i<key_len; i++) { 106 if(key[i] == '\0') numnulls++; 107 } 108 109 if(numnulls != 2) return SASL_BADPARAM; 110 111 alen = strlen(key); 112 rlen = strlen(key + alen + 1); 113 pnlen = key_len - alen - rlen - 2; 114 115 116 if(authid) { 117 if(alen >= max_authid) 118 return SASL_BUFOVER; 119 strncpy(authid, key, max_authid); 120 } 121 122 if(realm) { 123 if(rlen >= max_realm) 124 return SASL_BUFOVER; 125 strncpy(realm, key + alen + 1, max_realm); 126 } 127 128 if(propName) { 129 if(pnlen >= max_propname) 130 return SASL_BUFOVER; 131 strncpy(propName, key + alen + rlen + 2, pnlen); 132 133 /* Have to add the missing NULL */ 134 propName[pnlen] = '\0'; 135 } 136 137 return SASL_OK; 138} 139 140/* These are more or less aliases to the correct functions */ 141int _sasldb_getsecret(const sasl_utils_t *utils, 142 sasl_conn_t *context, 143 const char *authid, 144 const char *realm, 145 sasl_secret_t ** secret) 146{ 147 char buf[8192]; 148 size_t len; 149 sasl_secret_t *out; 150 int ret; 151 const char *param = SASL_AUX_PASSWORD; 152 param++; 153 154 if(!secret) { 155 utils->seterror(context, 0, "No secret pointer in _sasldb_getsecret"); 156 return SASL_BADPARAM; 157 } 158 159 ret = _sasldb_getdata(utils, context, authid, realm, param, 160 buf, 8192, &len); 161 162 if(ret != SASL_OK) { 163 return ret; 164 } 165 166 out = utils->malloc(sizeof(sasl_secret_t) + len); 167 if(!out) { 168 utils->seterror(context, 0, "Out of Memory in _sasldb_getsecret"); 169 return SASL_NOMEM; 170 } 171 172 out->len = (unsigned) len; 173 memcpy(out->data, buf, len); 174 out->data[len]='\0'; 175 176 *secret = out; 177 178 return SASL_OK; 179} 180 181int _sasldb_putsecret(const sasl_utils_t *utils, 182 sasl_conn_t *context, 183 const char *authid, 184 const char *realm, 185 const sasl_secret_t * secret) 186{ 187 const char *param = SASL_AUX_PASSWORD; 188 param++; /* skip leading * */ 189 return _sasldb_putdata(utils, context, authid, realm, param, 190 (const char *) (secret ? secret->data : NULL), 191 (secret ? secret->len : 0)); 192} 193 194int __sasldb_internal_list (const char *authid, 195 const char *realm, 196 const char *property, 197 void *rock __attribute__((unused))) 198{ 199 printf("%s@%s: %s\n", authid, realm, property); 200 201 return (SASL_OK); 202} 203 204/* List all users in database */ 205int _sasldb_listusers (const sasl_utils_t *utils, 206 sasl_conn_t *context, 207 sasldb_list_callback_t callback, 208 void *callback_rock) 209{ 210 int result; 211 char key_buf[32768]; 212 size_t key_len; 213 sasldb_handle dbh; 214 215 if (callback == NULL) { 216 callback = &__sasldb_internal_list; 217 callback_rock = NULL; 218 } 219 220 dbh = _sasldb_getkeyhandle(utils, context); 221 222 if(!dbh) { 223 utils->log (context, SASL_LOG_ERR, "_sasldb_getkeyhandle has failed"); 224 return SASL_FAIL; 225 } 226 227 result = _sasldb_getnextkey(utils, 228 dbh, 229 key_buf, 230 32768, 231 &key_len); 232 233 while (result == SASL_CONTINUE) 234 { 235 char authid_buf[16384]; 236 char realm_buf[16384]; 237 char property_buf[16384]; 238 int ret; 239 240 ret = _sasldb_parse_key(key_buf, key_len, 241 authid_buf, 16384, 242 realm_buf, 16384, 243 property_buf, 16384); 244 245 if(ret == SASL_BUFOVER) { 246 utils->log (context, SASL_LOG_ERR, "Key is too large in _sasldb_parse_key"); 247 continue; 248 } else if(ret != SASL_OK) { 249 utils->log (context, SASL_LOG_ERR, "Bad Key in _sasldb_parse_key"); 250 continue; 251 } 252 253 result = callback (authid_buf, 254 realm_buf, 255 property_buf, 256 callback_rock); 257 258 if (result != SASL_OK && result != SASL_CONTINUE) { 259 break; 260 } 261 262 result = _sasldb_getnextkey(utils, 263 dbh, 264 key_buf, 265 32768, 266 &key_len); 267 } 268 269 if (result == SASL_BUFOVER) { 270 utils->log (context, SASL_LOG_ERR, "Key is too large in _sasldb_getnextkey"); 271 } else if (result != SASL_OK) { 272 utils->log (context, SASL_LOG_ERR, "DB failure in _sasldb_getnextkey"); 273 } 274 275 return _sasldb_releasekeyhandle(utils, dbh); 276} 277