GSS_S_PROMPTING_NEEDED is a bit
[cyrus-sasl.git] / sasldb / allockey.c
1 /* db_berkeley.c--SASL berkeley db interface
2  * Rob Siemborski
3  * Tim Martin
4  * $Id: allockey.c,v 1.8 2006/04/10 13:26:51 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  */
58 int _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  */
90 int _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 */
141 int _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
181 int _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                            (secret ? secret->data : NULL),
191                            (secret ? secret->len : 0));
192 }
193
194 int __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 */
205 int _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 }