1/* SASL server API implementation
2 * Rob Siemborski
3 * Tim Martin
4 * $Id: sasldb.c,v 1.6 2006/01/24 20:37:26 snsimon 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/* checkpw stuff */
49
50#include <stdio.h>
51
52#include "sasl.h"
53#include "saslutil.h"
54#include "saslplug.h"
55#include "../sasldb/sasldb.h"
56
57#include "plugin_common.h"
58
59static void sasldb_auxprop_lookup(void *glob_context __attribute__((unused)),
60				  sasl_server_params_t *sparams,
61				  unsigned flags,
62				  const char *user,
63				  unsigned ulen)
64{
65    char *userid = NULL;
66    char *realm = NULL;
67    const char *user_realm = NULL;
68    int ret;
69    const struct propval *to_fetch, *cur;
70    char value[8192];
71    size_t value_len;
72    char *user_buf;
73
74    if(!sparams || !user) return;
75
76    user_buf = sparams->utils->malloc(ulen + 1);
77    if(!user_buf)
78	goto done;
79
80    memcpy(user_buf, user, ulen);
81    user_buf[ulen] = '\0';
82
83    if(sparams->user_realm) {
84	user_realm = sparams->user_realm;
85    } else {
86	user_realm = sparams->serverFQDN;
87    }
88
89    ret = _plug_parseuser(sparams->utils, &userid, &realm, user_realm,
90			  sparams->serverFQDN, user_buf);
91    if(ret != SASL_OK) goto done;
92
93    to_fetch = sparams->utils->prop_get(sparams->propctx);
94    if(!to_fetch) goto done;
95
96    for(cur = to_fetch; cur->name; cur++) {
97	const char *realname = cur->name;
98
99	/* Only look up properties that apply to this lookup! */
100	if(cur->name[0] == '*' && (flags & SASL_AUXPROP_AUTHZID)) continue;
101	if(!(flags & SASL_AUXPROP_AUTHZID)) {
102	    if(cur->name[0] != '*') continue;
103	    else realname = cur->name + 1;
104	}
105
106	/* If it's there already, we want to see if it needs to be
107	 * overridden */
108	if(cur->values && !(flags & SASL_AUXPROP_OVERRIDE))
109	    continue;
110	else if(cur->values)
111	    sparams->utils->prop_erase(sparams->propctx, cur->name);
112
113	ret = _sasldb_getdata(sparams->utils,
114			      sparams->utils->conn, userid, realm,
115			      realname, value, 8192, &value_len);
116	if(ret != SASL_OK) {
117	    /* We didn't find it, leave it as not found */
118	    continue;
119	}
120
121	sparams->utils->prop_set(sparams->propctx, cur->name,
122				 value, (unsigned) value_len);
123    }
124
125 done:
126    if (userid) sparams->utils->free(userid);
127    if (realm)  sparams->utils->free(realm);
128    if (user_buf) sparams->utils->free(user_buf);
129}
130
131static int sasldb_auxprop_store(void *glob_context __attribute__((unused)),
132				sasl_server_params_t *sparams,
133				struct propctx *ctx,
134				const char *user,
135				unsigned ulen)
136{
137    char *userid = NULL;
138    char *realm = NULL;
139    const char *user_realm = NULL;
140    int ret = SASL_FAIL;
141    const struct propval *to_store, *cur;
142    char *user_buf;
143
144    /* just checking if we are enabled */
145    if(!ctx) return SASL_OK;
146
147    if(!sparams || !user) return SASL_BADPARAM;
148
149    user_buf = sparams->utils->malloc(ulen + 1);
150    if(!user_buf) {
151	ret = SASL_NOMEM;
152	goto done;
153    }
154
155    memcpy(user_buf, user, ulen);
156    user_buf[ulen] = '\0';
157
158    if(sparams->user_realm) {
159	user_realm = sparams->user_realm;
160    } else {
161	user_realm = sparams->serverFQDN;
162    }
163
164    ret = _plug_parseuser(sparams->utils, &userid, &realm, user_realm,
165			  sparams->serverFQDN, user_buf);
166    if(ret != SASL_OK) goto done;
167
168    to_store = sparams->utils->prop_get(ctx);
169    if(!to_store) {
170	ret = SASL_BADPARAM;
171	goto done;
172    }
173
174    for(cur = to_store; cur->name; cur++) {
175	/* We only support one value right now. */
176	ret = _sasldb_putdata(sparams->utils, sparams->utils->conn,
177			      userid, realm, cur->name,
178			      cur->values && cur->values[0] ?
179			      cur->values[0] : NULL,
180			      cur->values && cur->values[0] ?
181			      strlen(cur->values[0]) : 0);
182    }
183
184 done:
185    if (userid) sparams->utils->free(userid);
186    if (realm)  sparams->utils->free(realm);
187    if (user_buf) sparams->utils->free(user_buf);
188
189    return ret;
190}
191
192static sasl_auxprop_plug_t sasldb_auxprop_plugin = {
193    0,           		/* Features */
194    0,           		/* spare */
195    NULL,        		/* glob_context */
196    NULL,        		/* auxprop_free */
197    sasldb_auxprop_lookup,	/* auxprop_lookup */
198    "sasldb",			/* name */
199    sasldb_auxprop_store	/* auxprop_store */
200};
201
202int sasldb_auxprop_plug_init(const sasl_utils_t *utils,
203                             int max_version,
204                             int *out_version,
205                             sasl_auxprop_plug_t **plug,
206                             const char *plugname __attribute__((unused)))
207{
208    if(!out_version || !plug) return SASL_BADPARAM;
209
210    /* Do we have database support? */
211    /* Note that we can use a NULL sasl_conn_t because our
212     * sasl_utils_t is "blessed" with the global callbacks */
213    if(_sasl_check_db(utils, NULL) != SASL_OK)
214	return SASL_NOMECH;
215
216    if(max_version < SASL_AUXPROP_PLUG_VERSION) return SASL_BADVERS;
217
218    *out_version = SASL_AUXPROP_PLUG_VERSION;
219
220    *plug = &sasldb_auxprop_plugin;
221
222    return SASL_OK;
223}
224