xref: /illumos-gate/usr/src/lib/libsasl/lib/auxprop.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
6*7c478bd9Sstevel@tonic-gate 
7*7c478bd9Sstevel@tonic-gate /* auxprop.c - auxilliary property support
8*7c478bd9Sstevel@tonic-gate  * Rob Siemborski
9*7c478bd9Sstevel@tonic-gate  * $Id: auxprop.c,v 1.10 2003/03/19 18:25:27 rjs3 Exp $
10*7c478bd9Sstevel@tonic-gate  */
11*7c478bd9Sstevel@tonic-gate /*
12*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
15*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
16*7c478bd9Sstevel@tonic-gate  * are met:
17*7c478bd9Sstevel@tonic-gate  *
18*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
19*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
20*7c478bd9Sstevel@tonic-gate  *
21*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
22*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
23*7c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
24*7c478bd9Sstevel@tonic-gate  *    distribution.
25*7c478bd9Sstevel@tonic-gate  *
26*7c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
27*7c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
28*7c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
29*7c478bd9Sstevel@tonic-gate  *    details, please contact
30*7c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
31*7c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
32*7c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
33*7c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
34*7c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
35*7c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
36*7c478bd9Sstevel@tonic-gate  *
37*7c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
38*7c478bd9Sstevel@tonic-gate  *    acknowledgment:
39*7c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
40*7c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
41*7c478bd9Sstevel@tonic-gate  *
42*7c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
43*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
44*7c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
45*7c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46*7c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
47*7c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
48*7c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49*7c478bd9Sstevel@tonic-gate  */
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #include <config.h>
52*7c478bd9Sstevel@tonic-gate #include <sasl.h>
53*7c478bd9Sstevel@tonic-gate #include <prop.h>
54*7c478bd9Sstevel@tonic-gate #include <ctype.h>
55*7c478bd9Sstevel@tonic-gate #include "saslint.h"
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate struct proppool
58*7c478bd9Sstevel@tonic-gate {
59*7c478bd9Sstevel@tonic-gate     struct proppool *next;
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate     size_t size;          /* Size of Block */
62*7c478bd9Sstevel@tonic-gate     size_t unused;        /* Space unused in this pool between end
63*7c478bd9Sstevel@tonic-gate 			   * of char** area and beginning of char* area */
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate     char data[1];         /* Variable Sized */
66*7c478bd9Sstevel@tonic-gate };
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate struct propctx  {
69*7c478bd9Sstevel@tonic-gate     struct propval *values;
70*7c478bd9Sstevel@tonic-gate     struct propval *prev_val; /* Previous value used by set/setvalues */
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate     unsigned used_values, allocated_values;
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate     char *data_end; /* Bottom of string area in current pool */
75*7c478bd9Sstevel@tonic-gate     char **list_end; /* Top of list area in current pool */
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate     struct proppool *mem_base;
78*7c478bd9Sstevel@tonic-gate     struct proppool *mem_cur;
79*7c478bd9Sstevel@tonic-gate };
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate typedef struct auxprop_plug_list
82*7c478bd9Sstevel@tonic-gate {
83*7c478bd9Sstevel@tonic-gate     struct auxprop_plug_list *next;
84*7c478bd9Sstevel@tonic-gate     const sasl_auxprop_plug_t *plug;
85*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
86*7c478bd9Sstevel@tonic-gate     char *plugname;
87*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
88*7c478bd9Sstevel@tonic-gate } auxprop_plug_list_t;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
91*7c478bd9Sstevel@tonic-gate static auxprop_plug_list_t *auxprop_head = NULL;
92*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
93*7c478bd9Sstevel@tonic-gate 
alloc_proppool(size_t size)94*7c478bd9Sstevel@tonic-gate static struct proppool *alloc_proppool(size_t size)
95*7c478bd9Sstevel@tonic-gate {
96*7c478bd9Sstevel@tonic-gate     struct proppool *ret;
97*7c478bd9Sstevel@tonic-gate     /* minus 1 for the one that is already a part of the array
98*7c478bd9Sstevel@tonic-gate      * in the struct */
99*7c478bd9Sstevel@tonic-gate     size_t total_size = sizeof(struct proppool) + size - 1;
100*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
101*7c478bd9Sstevel@tonic-gate     ret = sasl_sun_ALLOC(total_size);
102*7c478bd9Sstevel@tonic-gate #else
103*7c478bd9Sstevel@tonic-gate     ret = sasl_ALLOC(total_size);
104*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_*/
105*7c478bd9Sstevel@tonic-gate     if(!ret) return NULL;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate     memset(ret, 0, total_size);
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate     ret->size = ret->unused = size;
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate     return ret;
112*7c478bd9Sstevel@tonic-gate }
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate /* Resize a proppool.  Invalidates the unused value for this pool */
resize_proppool(struct proppool * pool,size_t size)115*7c478bd9Sstevel@tonic-gate static struct proppool *resize_proppool(struct proppool *pool, size_t size)
116*7c478bd9Sstevel@tonic-gate {
117*7c478bd9Sstevel@tonic-gate     struct proppool *ret;
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate     if(pool->size >= size) return pool;
120*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
121*7c478bd9Sstevel@tonic-gate     ret = sasl_sun_REALLOC(pool, sizeof(struct proppool) + size);
122*7c478bd9Sstevel@tonic-gate #else
123*7c478bd9Sstevel@tonic-gate     ret = sasl_REALLOC(pool, sizeof(struct proppool) + size);
124*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_*/
125*7c478bd9Sstevel@tonic-gate     if(!ret) return NULL;
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate     ret->size = size;
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate     return ret;
130*7c478bd9Sstevel@tonic-gate }
131*7c478bd9Sstevel@tonic-gate 
prop_init(struct propctx * ctx,unsigned estimate)132*7c478bd9Sstevel@tonic-gate static int prop_init(struct propctx *ctx, unsigned estimate)
133*7c478bd9Sstevel@tonic-gate {
134*7c478bd9Sstevel@tonic-gate     const unsigned VALUES_SIZE = PROP_DEFAULT * sizeof(struct propval);
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate     ctx->mem_base = alloc_proppool(VALUES_SIZE + estimate);
137*7c478bd9Sstevel@tonic-gate     if(!ctx->mem_base) return SASL_NOMEM;
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate     ctx->mem_cur = ctx->mem_base;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate     ctx->values = (struct propval *)ctx->mem_base->data;
142*7c478bd9Sstevel@tonic-gate     ctx->mem_base->unused = ctx->mem_base->size - VALUES_SIZE;
143*7c478bd9Sstevel@tonic-gate     ctx->allocated_values = PROP_DEFAULT;
144*7c478bd9Sstevel@tonic-gate     ctx->used_values = 0;
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate     ctx->data_end = ctx->mem_base->data + ctx->mem_base->size;
147*7c478bd9Sstevel@tonic-gate     ctx->list_end = (char **)(ctx->mem_base->data + VALUES_SIZE);
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate     ctx->prev_val = NULL;
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate     return SASL_OK;
152*7c478bd9Sstevel@tonic-gate }
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate /* create a property context
155*7c478bd9Sstevel@tonic-gate  *  estimate -- an estimate of the storage needed for requests & responses
156*7c478bd9Sstevel@tonic-gate  *              0 will use module default
157*7c478bd9Sstevel@tonic-gate  * returns NULL on error
158*7c478bd9Sstevel@tonic-gate  */
prop_new(unsigned estimate)159*7c478bd9Sstevel@tonic-gate struct propctx *prop_new(unsigned estimate)
160*7c478bd9Sstevel@tonic-gate {
161*7c478bd9Sstevel@tonic-gate     struct propctx *new_ctx;
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate     if(!estimate) estimate = PROP_DEFAULT * 255;
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
166*7c478bd9Sstevel@tonic-gate     new_ctx = sasl_sun_ALLOC(sizeof(struct propctx));
167*7c478bd9Sstevel@tonic-gate #else
168*7c478bd9Sstevel@tonic-gate     new_ctx = sasl_ALLOC(sizeof(struct propctx));
169*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_*/
170*7c478bd9Sstevel@tonic-gate     if(!new_ctx) return NULL;
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate     if(prop_init(new_ctx, estimate) != SASL_OK) {
173*7c478bd9Sstevel@tonic-gate 	prop_dispose(&new_ctx);
174*7c478bd9Sstevel@tonic-gate     }
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate     return new_ctx;
177*7c478bd9Sstevel@tonic-gate }
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate /* create new propctx which duplicates the contents of an existing propctx
180*7c478bd9Sstevel@tonic-gate  * returns -1 on error
181*7c478bd9Sstevel@tonic-gate  */
prop_dup(struct propctx * src_ctx,struct propctx ** dst_ctx)182*7c478bd9Sstevel@tonic-gate int prop_dup(struct propctx *src_ctx, struct propctx **dst_ctx)
183*7c478bd9Sstevel@tonic-gate {
184*7c478bd9Sstevel@tonic-gate     struct proppool *pool;
185*7c478bd9Sstevel@tonic-gate     struct propctx *retval = NULL;
186*7c478bd9Sstevel@tonic-gate     unsigned i;
187*7c478bd9Sstevel@tonic-gate     int result;
188*7c478bd9Sstevel@tonic-gate     size_t total_size = 0, values_size;
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate     if(!src_ctx || !dst_ctx) return SASL_BADPARAM;
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate     /* What is the total allocated size of src_ctx? */
193*7c478bd9Sstevel@tonic-gate     pool = src_ctx->mem_base;
194*7c478bd9Sstevel@tonic-gate     while(pool) {
195*7c478bd9Sstevel@tonic-gate 	total_size += pool->size;
196*7c478bd9Sstevel@tonic-gate 	pool = pool->next;
197*7c478bd9Sstevel@tonic-gate     }
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate     /* allocate the new context */
200*7c478bd9Sstevel@tonic-gate     retval = prop_new(total_size);
201*7c478bd9Sstevel@tonic-gate     if(!retval) return SASL_NOMEM;
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate     retval->used_values = src_ctx->used_values;
204*7c478bd9Sstevel@tonic-gate     retval->allocated_values = src_ctx->used_values + 1;
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate     values_size = (retval->allocated_values * sizeof(struct propval));
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate     retval->mem_base->unused = retval->mem_base->size - values_size;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate     retval->list_end = (char **)(retval->mem_base->data + values_size);
211*7c478bd9Sstevel@tonic-gate     /* data_end should still be OK */
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate     /* Now dup the values */
214*7c478bd9Sstevel@tonic-gate     for(i=0; i<src_ctx->used_values; i++) {
215*7c478bd9Sstevel@tonic-gate 	retval->values[i].name = src_ctx->values[i].name;
216*7c478bd9Sstevel@tonic-gate 	result = prop_setvals(retval, retval->values[i].name,
217*7c478bd9Sstevel@tonic-gate 			      src_ctx->values[i].values);
218*7c478bd9Sstevel@tonic-gate 	if(result != SASL_OK)
219*7c478bd9Sstevel@tonic-gate 	    goto fail;
220*7c478bd9Sstevel@tonic-gate     }
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate     retval->prev_val = src_ctx->prev_val;
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate     *dst_ctx = retval;
225*7c478bd9Sstevel@tonic-gate     return SASL_OK;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate     fail:
228*7c478bd9Sstevel@tonic-gate     if(retval) prop_dispose(&retval);
229*7c478bd9Sstevel@tonic-gate     return result;
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate /*
233*7c478bd9Sstevel@tonic-gate  * dispose of property context
234*7c478bd9Sstevel@tonic-gate  *  ctx      -- is disposed and set to NULL; noop if ctx or *ctx is NULL
235*7c478bd9Sstevel@tonic-gate  */
prop_dispose(struct propctx ** ctx)236*7c478bd9Sstevel@tonic-gate void prop_dispose(struct propctx **ctx)
237*7c478bd9Sstevel@tonic-gate {
238*7c478bd9Sstevel@tonic-gate     struct proppool *tmp;
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate     if(!ctx || !*ctx) return;
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate     while((*ctx)->mem_base) {
243*7c478bd9Sstevel@tonic-gate 	tmp = (*ctx)->mem_base;
244*7c478bd9Sstevel@tonic-gate 	(*ctx)->mem_base = tmp->next;
245*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
246*7c478bd9Sstevel@tonic-gate         sasl_sun_FREE(tmp);
247*7c478bd9Sstevel@tonic-gate #else
248*7c478bd9Sstevel@tonic-gate 	sasl_FREE(tmp);
249*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_*/
250*7c478bd9Sstevel@tonic-gate     }
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
253*7c478bd9Sstevel@tonic-gate     sasl_sun_FREE(*ctx);
254*7c478bd9Sstevel@tonic-gate #else
255*7c478bd9Sstevel@tonic-gate     sasl_FREE(*ctx);
256*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_*/
257*7c478bd9Sstevel@tonic-gate     *ctx = NULL;
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate     return;
260*7c478bd9Sstevel@tonic-gate }
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate /* Add property names to request
263*7c478bd9Sstevel@tonic-gate  *  ctx       -- context from prop_new()
264*7c478bd9Sstevel@tonic-gate  *  names     -- list of property names; must persist until context freed
265*7c478bd9Sstevel@tonic-gate  *               or requests cleared
266*7c478bd9Sstevel@tonic-gate  *
267*7c478bd9Sstevel@tonic-gate  * NOTE: may clear values from context as side-effect
268*7c478bd9Sstevel@tonic-gate  * returns -1 on error
269*7c478bd9Sstevel@tonic-gate  */
prop_request(struct propctx * ctx,const char ** names)270*7c478bd9Sstevel@tonic-gate int prop_request(struct propctx *ctx, const char **names)
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate     unsigned i, new_values, total_values;
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate     if(!ctx || !names) return SASL_BADPARAM;
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate     /* Count how many we need to add */
277*7c478bd9Sstevel@tonic-gate     for(new_values=0; names[new_values]; new_values++);
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate     /* Do we need to add ANY? */
280*7c478bd9Sstevel@tonic-gate     if(!new_values) return SASL_OK;
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate     /* We always want atleast on extra to mark the end of the array */
283*7c478bd9Sstevel@tonic-gate     total_values = new_values + ctx->used_values + 1;
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate     /* Do we need to increase the size of our propval table? */
286*7c478bd9Sstevel@tonic-gate     if(total_values > ctx->allocated_values) {
287*7c478bd9Sstevel@tonic-gate 	unsigned max_in_pool;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	/* Do we need a larger base pool? */
290*7c478bd9Sstevel@tonic-gate 	max_in_pool = ctx->mem_base->size / sizeof(struct propval);
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	if(total_values <= max_in_pool) {
293*7c478bd9Sstevel@tonic-gate 	    /* Don't increase the size of the base pool, just use what
294*7c478bd9Sstevel@tonic-gate 	       we need */
295*7c478bd9Sstevel@tonic-gate 	    ctx->allocated_values = total_values;
296*7c478bd9Sstevel@tonic-gate 	    ctx->mem_base->unused =
297*7c478bd9Sstevel@tonic-gate 		ctx->mem_base->size - (sizeof(struct propval)
298*7c478bd9Sstevel@tonic-gate 				       * ctx->allocated_values);
299*7c478bd9Sstevel@tonic-gate       	} else {
300*7c478bd9Sstevel@tonic-gate 	    /* We need to allocate more! */
301*7c478bd9Sstevel@tonic-gate 	    unsigned new_alloc_length;
302*7c478bd9Sstevel@tonic-gate 	    size_t new_size;
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	    new_alloc_length = 2 * ctx->allocated_values;
305*7c478bd9Sstevel@tonic-gate 	    while(total_values > new_alloc_length) {
306*7c478bd9Sstevel@tonic-gate 		new_alloc_length *= 2;
307*7c478bd9Sstevel@tonic-gate 	    }
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	    new_size = new_alloc_length * sizeof(struct propval);
310*7c478bd9Sstevel@tonic-gate 	    ctx->mem_base = resize_proppool(ctx->mem_base, new_size);
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	    if(!ctx->mem_base) {
313*7c478bd9Sstevel@tonic-gate 		ctx->values = NULL;
314*7c478bd9Sstevel@tonic-gate 		ctx->allocated_values = ctx->used_values = 0;
315*7c478bd9Sstevel@tonic-gate 		return SASL_NOMEM;
316*7c478bd9Sstevel@tonic-gate 	    }
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	    /* It worked! Update the structure! */
319*7c478bd9Sstevel@tonic-gate 	    ctx->values = (struct propval *)ctx->mem_base->data;
320*7c478bd9Sstevel@tonic-gate 	    ctx->allocated_values = new_alloc_length;
321*7c478bd9Sstevel@tonic-gate 	    ctx->mem_base->unused = ctx->mem_base->size
322*7c478bd9Sstevel@tonic-gate 		- sizeof(struct propval) * ctx->allocated_values;
323*7c478bd9Sstevel@tonic-gate 	}
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	/* Clear out new propvals */
326*7c478bd9Sstevel@tonic-gate 	memset(&(ctx->values[ctx->used_values]), 0,
327*7c478bd9Sstevel@tonic-gate 	       sizeof(struct propval) * (ctx->allocated_values - ctx->used_values));
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate         /* Finish updating the context -- we've extended the list! */
330*7c478bd9Sstevel@tonic-gate 	/* ctx->list_end = (char **)(ctx->values + ctx->allocated_values); */
331*7c478bd9Sstevel@tonic-gate 	/* xxx test here */
332*7c478bd9Sstevel@tonic-gate 	ctx->list_end = (char **)(ctx->values + total_values);
333*7c478bd9Sstevel@tonic-gate     }
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate     /* Now do the copy, or referencing rather */
336*7c478bd9Sstevel@tonic-gate     for(i=0;i<new_values;i++) {
337*7c478bd9Sstevel@tonic-gate 	unsigned j, flag;
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	flag = 0;
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	/* Check for dups */
342*7c478bd9Sstevel@tonic-gate 	for(j=0;j<ctx->used_values;j++) {
343*7c478bd9Sstevel@tonic-gate 	    if(!strcmp(ctx->values[j].name, names[i])) {
344*7c478bd9Sstevel@tonic-gate 		flag = 1;
345*7c478bd9Sstevel@tonic-gate 		break;
346*7c478bd9Sstevel@tonic-gate 	    }
347*7c478bd9Sstevel@tonic-gate 	}
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 	/* We already have it... skip! */
350*7c478bd9Sstevel@tonic-gate 	if(flag) continue;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	ctx->values[ctx->used_values++].name = names[i];
353*7c478bd9Sstevel@tonic-gate     }
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate     prop_clear(ctx, 0);
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate     return SASL_OK;
358*7c478bd9Sstevel@tonic-gate }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate /* return array of struct propval from the context
361*7c478bd9Sstevel@tonic-gate  *  return value persists until next call to
362*7c478bd9Sstevel@tonic-gate  *   prop_request, prop_clear or prop_dispose on context
363*7c478bd9Sstevel@tonic-gate  */
prop_get(struct propctx * ctx)364*7c478bd9Sstevel@tonic-gate const struct propval *prop_get(struct propctx *ctx)
365*7c478bd9Sstevel@tonic-gate {
366*7c478bd9Sstevel@tonic-gate     if(!ctx) return NULL;
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate     return ctx->values;
369*7c478bd9Sstevel@tonic-gate }
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate /* Fill in an array of struct propval based on a list of property names
372*7c478bd9Sstevel@tonic-gate  *  return value persists until next call to
373*7c478bd9Sstevel@tonic-gate  *   prop_request, prop_clear or prop_dispose on context
374*7c478bd9Sstevel@tonic-gate  *  returns -1 on error (no properties ever requested, ctx NULL, etc)
375*7c478bd9Sstevel@tonic-gate  *  returns number of matching properties which were found (values != NULL)
376*7c478bd9Sstevel@tonic-gate  *  if a name requested here was never requested by a prop_request, then
377*7c478bd9Sstevel@tonic-gate  *  the name field of the associated vals entry will be set to NULL
378*7c478bd9Sstevel@tonic-gate  */
prop_getnames(struct propctx * ctx,const char ** names,struct propval * vals)379*7c478bd9Sstevel@tonic-gate int prop_getnames(struct propctx *ctx, const char **names,
380*7c478bd9Sstevel@tonic-gate 		  struct propval *vals)
381*7c478bd9Sstevel@tonic-gate {
382*7c478bd9Sstevel@tonic-gate     int found_names = 0;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate     struct propval *cur = vals;
385*7c478bd9Sstevel@tonic-gate     const char **curname;
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate     if(!ctx || !names || !vals) return SASL_BADPARAM;
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate     for(curname = names; *curname; curname++) {
390*7c478bd9Sstevel@tonic-gate 	struct propval *val;
391*7c478bd9Sstevel@tonic-gate 	for(val = ctx->values; val->name; val++) {
392*7c478bd9Sstevel@tonic-gate 	    if(!strcmp(*curname,val->name)) {
393*7c478bd9Sstevel@tonic-gate 		found_names++;
394*7c478bd9Sstevel@tonic-gate 		memcpy(cur, val, sizeof(struct propval));
395*7c478bd9Sstevel@tonic-gate 		goto next;
396*7c478bd9Sstevel@tonic-gate 	    }
397*7c478bd9Sstevel@tonic-gate 	}
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 	/* If we are here, we didn't find it */
400*7c478bd9Sstevel@tonic-gate 	memset(cur, 0, sizeof(struct propval));
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	next:
403*7c478bd9Sstevel@tonic-gate 	cur++;
404*7c478bd9Sstevel@tonic-gate     }
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate     return found_names;
407*7c478bd9Sstevel@tonic-gate }
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate /* clear values and optionally requests from property context
411*7c478bd9Sstevel@tonic-gate  *  ctx      -- property context
412*7c478bd9Sstevel@tonic-gate  *  requests -- 0 = don't clear requests, 1 = clear requests
413*7c478bd9Sstevel@tonic-gate  */
prop_clear(struct propctx * ctx,int requests)414*7c478bd9Sstevel@tonic-gate void prop_clear(struct propctx *ctx, int requests)
415*7c478bd9Sstevel@tonic-gate {
416*7c478bd9Sstevel@tonic-gate     struct proppool *new_pool, *tmp;
417*7c478bd9Sstevel@tonic-gate     unsigned i;
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
420*7c478bd9Sstevel@tonic-gate     if(!ctx) return;
421*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate     /* We're going to need a new proppool once we reset things */
424*7c478bd9Sstevel@tonic-gate     new_pool = alloc_proppool(ctx->mem_base->size +
425*7c478bd9Sstevel@tonic-gate 			      (ctx->used_values+1) * sizeof(struct propval));
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate     if(requests) {
428*7c478bd9Sstevel@tonic-gate 	/* We're wiping the whole shebang */
429*7c478bd9Sstevel@tonic-gate 	ctx->used_values = 0;
430*7c478bd9Sstevel@tonic-gate     } else {
431*7c478bd9Sstevel@tonic-gate 	/* Need to keep around old requets */
432*7c478bd9Sstevel@tonic-gate 	struct propval *new_values = (struct propval *)new_pool->data;
433*7c478bd9Sstevel@tonic-gate 	for(i=0; i<ctx->used_values; i++) {
434*7c478bd9Sstevel@tonic-gate 	    new_values[i].name = ctx->values[i].name;
435*7c478bd9Sstevel@tonic-gate 	}
436*7c478bd9Sstevel@tonic-gate     }
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate     while(ctx->mem_base) {
439*7c478bd9Sstevel@tonic-gate 	tmp = ctx->mem_base;
440*7c478bd9Sstevel@tonic-gate 	ctx->mem_base = tmp->next;
441*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
442*7c478bd9Sstevel@tonic-gate 	sasl_sun_FREE(tmp);
443*7c478bd9Sstevel@tonic-gate #else
444*7c478bd9Sstevel@tonic-gate 	sasl_FREE(tmp);
445*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
446*7c478bd9Sstevel@tonic-gate     }
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate     /* Update allocation-related metadata */
449*7c478bd9Sstevel@tonic-gate     ctx->allocated_values = ctx->used_values+1;
450*7c478bd9Sstevel@tonic-gate     new_pool->unused =
451*7c478bd9Sstevel@tonic-gate 	new_pool->size - (ctx->allocated_values * sizeof(struct propval));
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate     /* Setup pointers for the values array */
454*7c478bd9Sstevel@tonic-gate     ctx->values = (struct propval *)new_pool->data;
455*7c478bd9Sstevel@tonic-gate     ctx->prev_val = NULL;
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate     /* Setup the pools */
458*7c478bd9Sstevel@tonic-gate     ctx->mem_base = ctx->mem_cur = new_pool;
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate     /* Reset list_end and data_end for the new memory pool */
461*7c478bd9Sstevel@tonic-gate     ctx->list_end =
462*7c478bd9Sstevel@tonic-gate 	(char **)((char *)ctx->mem_base->data + ctx->allocated_values * sizeof(struct propval));
463*7c478bd9Sstevel@tonic-gate     ctx->data_end = (char *)ctx->mem_base->data + ctx->mem_base->size;
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate     return;
466*7c478bd9Sstevel@tonic-gate }
467*7c478bd9Sstevel@tonic-gate 
468*7c478bd9Sstevel@tonic-gate /*
469*7c478bd9Sstevel@tonic-gate  * erase the value of a property
470*7c478bd9Sstevel@tonic-gate  */
prop_erase(struct propctx * ctx,const char * name)471*7c478bd9Sstevel@tonic-gate void prop_erase(struct propctx *ctx, const char *name)
472*7c478bd9Sstevel@tonic-gate {
473*7c478bd9Sstevel@tonic-gate     struct propval *val;
474*7c478bd9Sstevel@tonic-gate     int i;
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate     if(!ctx || !name) return;
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate     for(val = ctx->values; val->name; val++) {
479*7c478bd9Sstevel@tonic-gate 	if(!strcmp(name,val->name)) {
480*7c478bd9Sstevel@tonic-gate 	    if(!val->values) break;
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 	    /*
483*7c478bd9Sstevel@tonic-gate 	     * Yes, this is casting away the const, but
484*7c478bd9Sstevel@tonic-gate 	     * we should be okay because the only place this
485*7c478bd9Sstevel@tonic-gate 	     * memory should be is in the proppool's
486*7c478bd9Sstevel@tonic-gate 	     */
487*7c478bd9Sstevel@tonic-gate 	    for(i=0;val->values[i];i++) {
488*7c478bd9Sstevel@tonic-gate 		memset((void *)(val->values[i]),0,strlen(val->values[i]));
489*7c478bd9Sstevel@tonic-gate 		val->values[i] = NULL;
490*7c478bd9Sstevel@tonic-gate 	    }
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	    val->values = NULL;
493*7c478bd9Sstevel@tonic-gate 	    val->nvalues = 0;
494*7c478bd9Sstevel@tonic-gate 	    val->valsize = 0;
495*7c478bd9Sstevel@tonic-gate 	    break;
496*7c478bd9Sstevel@tonic-gate 	}
497*7c478bd9Sstevel@tonic-gate     }
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate     return;
500*7c478bd9Sstevel@tonic-gate }
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate /****fetcher interfaces****/
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate /* format the requested property names into a string
505*7c478bd9Sstevel@tonic-gate  *  ctx    -- context from prop_new()/prop_request()
506*7c478bd9Sstevel@tonic-gate  *  sep    -- separator between property names (unused if none requested)
507*7c478bd9Sstevel@tonic-gate  *  seplen -- length of separator, if < 0 then strlen(sep) will be used
508*7c478bd9Sstevel@tonic-gate  *  outbuf -- output buffer
509*7c478bd9Sstevel@tonic-gate  *  outmax -- maximum length of output buffer including NUL terminator
510*7c478bd9Sstevel@tonic-gate  *  outlen -- set to length of output string excluding NUL terminator
511*7c478bd9Sstevel@tonic-gate  * returns 0 on success and amount of additional space needed on failure
512*7c478bd9Sstevel@tonic-gate  */
prop_format(struct propctx * ctx,const char * sep,int seplen,char * outbuf,unsigned outmax,unsigned * outlen)513*7c478bd9Sstevel@tonic-gate int prop_format(struct propctx *ctx, const char *sep, int seplen,
514*7c478bd9Sstevel@tonic-gate 		char *outbuf, unsigned outmax, unsigned *outlen)
515*7c478bd9Sstevel@tonic-gate {
516*7c478bd9Sstevel@tonic-gate     unsigned needed, flag = 0;
517*7c478bd9Sstevel@tonic-gate     struct propval *val;
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate     if(!ctx || !outbuf) return SASL_BADPARAM;
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate     if(!sep) seplen = 0;
522*7c478bd9Sstevel@tonic-gate     if(seplen < 0) seplen = strlen(sep);
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate     needed = seplen * (ctx->used_values - 1);
525*7c478bd9Sstevel@tonic-gate     for(val = ctx->values; val->name; val++) {
526*7c478bd9Sstevel@tonic-gate 	needed += strlen(val->name);
527*7c478bd9Sstevel@tonic-gate     }
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate     if(!outmax) return (needed + 1); /* Because of unsigned funkiness */
530*7c478bd9Sstevel@tonic-gate     if(needed > (outmax - 1)) return (needed - (outmax - 1));
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate     *outbuf = '\0';
533*7c478bd9Sstevel@tonic-gate     if(outlen) *outlen = needed;
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate     if(needed == 0) return SASL_OK;
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate     for(val = ctx->values; val->name; val++) {
538*7c478bd9Sstevel@tonic-gate 	if(seplen && flag) {
539*7c478bd9Sstevel@tonic-gate 	    strncat(outbuf, sep, seplen);
540*7c478bd9Sstevel@tonic-gate 	} else {
541*7c478bd9Sstevel@tonic-gate 	    flag = 1;
542*7c478bd9Sstevel@tonic-gate 	}
543*7c478bd9Sstevel@tonic-gate 	strcat(outbuf, val->name);
544*7c478bd9Sstevel@tonic-gate     }
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate     return SASL_OK;
547*7c478bd9Sstevel@tonic-gate }
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate /* add a property value to the context
550*7c478bd9Sstevel@tonic-gate  *  ctx    -- context from prop_new()/prop_request()
551*7c478bd9Sstevel@tonic-gate  *  name   -- name of property to which value will be added
552*7c478bd9Sstevel@tonic-gate  *            if NULL, add to the same name as previous prop_set/setvals call
553*7c478bd9Sstevel@tonic-gate  *  value  -- a value for the property; will be copied into context
554*7c478bd9Sstevel@tonic-gate  *            if NULL, remove existing values
555*7c478bd9Sstevel@tonic-gate  *  vallen -- length of value, if <= 0 then strlen(value) will be used
556*7c478bd9Sstevel@tonic-gate  */
prop_set(struct propctx * ctx,const char * name,const char * value,int vallen)557*7c478bd9Sstevel@tonic-gate int prop_set(struct propctx *ctx, const char *name,
558*7c478bd9Sstevel@tonic-gate 	     const char *value, int vallen)
559*7c478bd9Sstevel@tonic-gate {
560*7c478bd9Sstevel@tonic-gate     struct propval *cur;
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate     if(!ctx) return SASL_BADPARAM;
563*7c478bd9Sstevel@tonic-gate     if(!name && !ctx->prev_val) return SASL_BADPARAM;
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate     if(name) {
566*7c478bd9Sstevel@tonic-gate 	struct propval *val;
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 	ctx->prev_val = NULL;
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	for(val = ctx->values; val->name; val++) {
571*7c478bd9Sstevel@tonic-gate 	    if(!strcmp(name,val->name)){
572*7c478bd9Sstevel@tonic-gate 		ctx->prev_val = val;
573*7c478bd9Sstevel@tonic-gate 		break;
574*7c478bd9Sstevel@tonic-gate 	    }
575*7c478bd9Sstevel@tonic-gate 	}
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 	/* Couldn't find it! */
578*7c478bd9Sstevel@tonic-gate 	if(!ctx->prev_val) return SASL_BADPARAM;
579*7c478bd9Sstevel@tonic-gate     }
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate     cur = ctx->prev_val;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate     if(name) /* New Entry */ {
584*7c478bd9Sstevel@tonic-gate 	unsigned nvalues = 1; /* 1 for NULL entry */
585*7c478bd9Sstevel@tonic-gate 	const char **old_values = NULL;
586*7c478bd9Sstevel@tonic-gate 	char **tmp, **tmp2;
587*7c478bd9Sstevel@tonic-gate 	size_t size;
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 	if(cur->values) {
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 	    if(!value) {
592*7c478bd9Sstevel@tonic-gate 		/* If we would be adding a null value, then we are done */
593*7c478bd9Sstevel@tonic-gate 		return SASL_OK;
594*7c478bd9Sstevel@tonic-gate 	    }
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 	    old_values = cur->values;
597*7c478bd9Sstevel@tonic-gate 	    tmp = (char **)cur->values;
598*7c478bd9Sstevel@tonic-gate 	    while(*tmp) {
599*7c478bd9Sstevel@tonic-gate 		nvalues++;
600*7c478bd9Sstevel@tonic-gate 		tmp++;
601*7c478bd9Sstevel@tonic-gate 	    }
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 	}
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 	if(value) {
606*7c478bd9Sstevel@tonic-gate 	    nvalues++; /* for the new value */
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	size = nvalues * sizeof(char*);
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate 	if(size > ctx->mem_cur->unused) {
612*7c478bd9Sstevel@tonic-gate 	    size_t needed;
613*7c478bd9Sstevel@tonic-gate 
614*7c478bd9Sstevel@tonic-gate 	    for(needed = ctx->mem_cur->size * 2; needed < size; needed *= 2);
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	    /* Allocate a new proppool */
617*7c478bd9Sstevel@tonic-gate 	    ctx->mem_cur->next = alloc_proppool(needed);
618*7c478bd9Sstevel@tonic-gate 	    if(!ctx->mem_cur->next) return SASL_NOMEM;
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 	    ctx->mem_cur = ctx->mem_cur->next;
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 	    ctx->list_end = (char **)ctx->mem_cur->data;
623*7c478bd9Sstevel@tonic-gate 	    ctx->data_end = ctx->mem_cur->data + needed;
624*7c478bd9Sstevel@tonic-gate 	}
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	/* Grab the memory */
627*7c478bd9Sstevel@tonic-gate 	ctx->mem_cur->unused -= size;
628*7c478bd9Sstevel@tonic-gate 	cur->values = (const char **)ctx->list_end;
629*7c478bd9Sstevel@tonic-gate 	cur->values[nvalues - 1] = NULL;
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 	/* Finish updating the context */
632*7c478bd9Sstevel@tonic-gate 	ctx->list_end = (char **)(cur->values + nvalues);
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 	/* If we don't have an actual value to fill in, we are done */
635*7c478bd9Sstevel@tonic-gate 	if(!value)
636*7c478bd9Sstevel@tonic-gate 	    return SASL_OK;
637*7c478bd9Sstevel@tonic-gate 
638*7c478bd9Sstevel@tonic-gate 	tmp2 = (char **)cur->values;
639*7c478bd9Sstevel@tonic-gate 	if(old_values) {
640*7c478bd9Sstevel@tonic-gate 	    tmp = (char **)old_values;
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate 	    while(*tmp) {
643*7c478bd9Sstevel@tonic-gate 		*tmp2 = *tmp;
644*7c478bd9Sstevel@tonic-gate 		tmp++; tmp2++;
645*7c478bd9Sstevel@tonic-gate 	    }
646*7c478bd9Sstevel@tonic-gate 	}
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 	/* Now allocate the last entry */
649*7c478bd9Sstevel@tonic-gate 	if(vallen <= 0)
650*7c478bd9Sstevel@tonic-gate 	    size = (size_t)(strlen(value) + 1);
651*7c478bd9Sstevel@tonic-gate 	else
652*7c478bd9Sstevel@tonic-gate 	    size = (size_t)(vallen + 1);
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate 	if(size > ctx->mem_cur->unused) {
655*7c478bd9Sstevel@tonic-gate 	    size_t needed;
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 	    needed = ctx->mem_cur->size * 2;
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	    while(needed < size) {
660*7c478bd9Sstevel@tonic-gate 		needed *= 2;
661*7c478bd9Sstevel@tonic-gate 	    }
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 	    /* Allocate a new proppool */
664*7c478bd9Sstevel@tonic-gate 	    ctx->mem_cur->next = alloc_proppool(needed);
665*7c478bd9Sstevel@tonic-gate 	    if(!ctx->mem_cur->next) return SASL_NOMEM;
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	    ctx->mem_cur = ctx->mem_cur->next;
668*7c478bd9Sstevel@tonic-gate 	    ctx->list_end = (char **)ctx->mem_cur->data;
669*7c478bd9Sstevel@tonic-gate 	    ctx->data_end = ctx->mem_cur->data + needed;
670*7c478bd9Sstevel@tonic-gate 	}
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate 	/* Update the data_end pointer */
673*7c478bd9Sstevel@tonic-gate 	ctx->data_end -= size;
674*7c478bd9Sstevel@tonic-gate 	ctx->mem_cur->unused -= size;
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 	/* Copy and setup the new value! */
677*7c478bd9Sstevel@tonic-gate 	memcpy(ctx->data_end, value, size-1);
678*7c478bd9Sstevel@tonic-gate 	ctx->data_end[size - 1] = '\0';
679*7c478bd9Sstevel@tonic-gate 	cur->values[nvalues - 2] = ctx->data_end;
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate 	cur->nvalues++;
682*7c478bd9Sstevel@tonic-gate 	cur->valsize += (size - 1);
683*7c478bd9Sstevel@tonic-gate     } else /* Appending an entry */ {
684*7c478bd9Sstevel@tonic-gate 	char **tmp;
685*7c478bd9Sstevel@tonic-gate 	size_t size;
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 	/* If we are setting it to be NULL, we are done */
688*7c478bd9Sstevel@tonic-gate 	if(!value) return SASL_OK;
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate 	size = sizeof(char*);
691*7c478bd9Sstevel@tonic-gate 
692*7c478bd9Sstevel@tonic-gate 	/* Is it in the current pool, and will it fit in the unused space? */
693*7c478bd9Sstevel@tonic-gate 	if(size > ctx->mem_cur->unused &&
694*7c478bd9Sstevel@tonic-gate 	    (void *)cur->values > (void *)(ctx->mem_cur->data) &&
695*7c478bd9Sstevel@tonic-gate 	    (void *)cur->values < (void *)(ctx->mem_cur->data + ctx->mem_cur->size)) {
696*7c478bd9Sstevel@tonic-gate 	    /* recursively call the not-fast way */
697*7c478bd9Sstevel@tonic-gate 	    return prop_set(ctx, cur->name, value, vallen);
698*7c478bd9Sstevel@tonic-gate 	}
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate 	/* Note the invariant: the previous value list must be
701*7c478bd9Sstevel@tonic-gate 	   at the top of the CURRENT pool at this point */
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 	/* Grab the memory */
704*7c478bd9Sstevel@tonic-gate 	ctx->mem_cur->unused -= size;
705*7c478bd9Sstevel@tonic-gate 	ctx->list_end++;
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate 	*(ctx->list_end - 1) = NULL;
708*7c478bd9Sstevel@tonic-gate 	tmp = (ctx->list_end - 2);
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate 	/* Now allocate the last entry */
711*7c478bd9Sstevel@tonic-gate 	if(vallen <= 0)
712*7c478bd9Sstevel@tonic-gate 	    size = strlen(value) + 1;
713*7c478bd9Sstevel@tonic-gate 	else
714*7c478bd9Sstevel@tonic-gate 	    size = vallen + 1;
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 	if(size > ctx->mem_cur->unused) {
717*7c478bd9Sstevel@tonic-gate 	    size_t needed;
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 	    needed = ctx->mem_cur->size * 2;
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 	    while(needed < size) {
722*7c478bd9Sstevel@tonic-gate 		needed *= 2;
723*7c478bd9Sstevel@tonic-gate 	    }
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 	    /* Allocate a new proppool */
726*7c478bd9Sstevel@tonic-gate 	    ctx->mem_cur->next = alloc_proppool(needed);
727*7c478bd9Sstevel@tonic-gate 	    if(!ctx->mem_cur->next) return SASL_NOMEM;
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate 	    ctx->mem_cur = ctx->mem_cur->next;
730*7c478bd9Sstevel@tonic-gate 	    ctx->list_end = (char **)ctx->mem_cur->data;
731*7c478bd9Sstevel@tonic-gate 	    ctx->data_end = ctx->mem_cur->data + needed;
732*7c478bd9Sstevel@tonic-gate 	}
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 	/* Update the data_end pointer */
735*7c478bd9Sstevel@tonic-gate 	ctx->data_end -= size;
736*7c478bd9Sstevel@tonic-gate 	ctx->mem_cur->unused -= size;
737*7c478bd9Sstevel@tonic-gate 
738*7c478bd9Sstevel@tonic-gate 	/* Copy and setup the new value! */
739*7c478bd9Sstevel@tonic-gate 	memcpy(ctx->data_end, value, size-1);
740*7c478bd9Sstevel@tonic-gate 	ctx->data_end[size - 1] = '\0';
741*7c478bd9Sstevel@tonic-gate 	*tmp = ctx->data_end;
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 	cur->nvalues++;
744*7c478bd9Sstevel@tonic-gate 	cur->valsize += (size - 1);
745*7c478bd9Sstevel@tonic-gate     }
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate     return SASL_OK;
748*7c478bd9Sstevel@tonic-gate }
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 
751*7c478bd9Sstevel@tonic-gate /* set the values for a property
752*7c478bd9Sstevel@tonic-gate  *  ctx    -- context from prop_new()/prop_request()
753*7c478bd9Sstevel@tonic-gate  *  name   -- name of property to which value will be added
754*7c478bd9Sstevel@tonic-gate  *            if NULL, add to the same name as previous prop_set/setvals call
755*7c478bd9Sstevel@tonic-gate  *  values -- array of values, ending in NULL.  Each value is a NUL terminated
756*7c478bd9Sstevel@tonic-gate  *            string
757*7c478bd9Sstevel@tonic-gate  */
prop_setvals(struct propctx * ctx,const char * name,const char ** values)758*7c478bd9Sstevel@tonic-gate int prop_setvals(struct propctx *ctx, const char *name,
759*7c478bd9Sstevel@tonic-gate 		 const char **values)
760*7c478bd9Sstevel@tonic-gate {
761*7c478bd9Sstevel@tonic-gate     const char **val = values;
762*7c478bd9Sstevel@tonic-gate     int result = SASL_OK;
763*7c478bd9Sstevel@tonic-gate 
764*7c478bd9Sstevel@tonic-gate     if(!ctx) return SASL_BADPARAM;
765*7c478bd9Sstevel@tonic-gate 
766*7c478bd9Sstevel@tonic-gate     /* If they want us to add no values, we can do that */
767*7c478bd9Sstevel@tonic-gate     if(!values) return SASL_OK;
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate     /* Basically, use prop_set to do all our dirty work for us */
770*7c478bd9Sstevel@tonic-gate     if(name) {
771*7c478bd9Sstevel@tonic-gate 	result = prop_set(ctx, name, *val, 0);
772*7c478bd9Sstevel@tonic-gate 	val++;
773*7c478bd9Sstevel@tonic-gate     }
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate     for(;*val;val++) {
776*7c478bd9Sstevel@tonic-gate 	if(result != SASL_OK) return result;
777*7c478bd9Sstevel@tonic-gate 	result = prop_set(ctx, NULL, *val,0);
778*7c478bd9Sstevel@tonic-gate     }
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate     return result;
781*7c478bd9Sstevel@tonic-gate }
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate /* Request a set of auxiliary properties
784*7c478bd9Sstevel@tonic-gate  *  conn         connection context
785*7c478bd9Sstevel@tonic-gate  *  propnames    list of auxiliary property names to request ending with
786*7c478bd9Sstevel@tonic-gate  *               NULL.
787*7c478bd9Sstevel@tonic-gate  *
788*7c478bd9Sstevel@tonic-gate  * Subsequent calls will add items to the request list.  Call with NULL
789*7c478bd9Sstevel@tonic-gate  * to clear the request list.
790*7c478bd9Sstevel@tonic-gate  *
791*7c478bd9Sstevel@tonic-gate  * errors
792*7c478bd9Sstevel@tonic-gate  *  SASL_OK       -- success
793*7c478bd9Sstevel@tonic-gate  *  SASL_BADPARAM -- bad count/conn parameter
794*7c478bd9Sstevel@tonic-gate  *  SASL_NOMEM    -- out of memory
795*7c478bd9Sstevel@tonic-gate  */
sasl_auxprop_request(sasl_conn_t * conn,const char ** propnames)796*7c478bd9Sstevel@tonic-gate int sasl_auxprop_request(sasl_conn_t *conn, const char **propnames)
797*7c478bd9Sstevel@tonic-gate {
798*7c478bd9Sstevel@tonic-gate     int result;
799*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *sconn;
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate     if(!conn) return SASL_BADPARAM;
802*7c478bd9Sstevel@tonic-gate     if(conn->type != SASL_CONN_SERVER)
803*7c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
804*7c478bd9Sstevel@tonic-gate 
805*7c478bd9Sstevel@tonic-gate     sconn = (sasl_server_conn_t *)conn;
806*7c478bd9Sstevel@tonic-gate 
807*7c478bd9Sstevel@tonic-gate     if(!propnames) {
808*7c478bd9Sstevel@tonic-gate 	prop_clear(sconn->sparams->propctx,1);
809*7c478bd9Sstevel@tonic-gate 	return SASL_OK;
810*7c478bd9Sstevel@tonic-gate     }
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate     result = prop_request(sconn->sparams->propctx, propnames);
813*7c478bd9Sstevel@tonic-gate     RETURN(conn, result);
814*7c478bd9Sstevel@tonic-gate }
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate /* Returns current auxiliary property context.
818*7c478bd9Sstevel@tonic-gate  * Use functions in prop.h to access content
819*7c478bd9Sstevel@tonic-gate  *
820*7c478bd9Sstevel@tonic-gate  *  if authentication hasn't completed, property values may be empty/NULL
821*7c478bd9Sstevel@tonic-gate  *
822*7c478bd9Sstevel@tonic-gate  *  properties not recognized by active plug-ins will be left empty/NULL
823*7c478bd9Sstevel@tonic-gate  *
824*7c478bd9Sstevel@tonic-gate  *  returns NULL if conn is invalid.
825*7c478bd9Sstevel@tonic-gate  */
sasl_auxprop_getctx(sasl_conn_t * conn)826*7c478bd9Sstevel@tonic-gate struct propctx *sasl_auxprop_getctx(sasl_conn_t *conn)
827*7c478bd9Sstevel@tonic-gate {
828*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *sconn;
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate     if(!conn || conn->type != SASL_CONN_SERVER) return NULL;
831*7c478bd9Sstevel@tonic-gate 
832*7c478bd9Sstevel@tonic-gate     sconn = (sasl_server_conn_t *)conn;
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate     return sconn->sparams->propctx;
835*7c478bd9Sstevel@tonic-gate }
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate /* add an auxiliary property plugin */
838*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
sasl_auxprop_add_plugin(const char * plugname,sasl_auxprop_init_t * auxpropfunc)839*7c478bd9Sstevel@tonic-gate int sasl_auxprop_add_plugin(const char *plugname,
840*7c478bd9Sstevel@tonic-gate                             sasl_auxprop_init_t *auxpropfunc)
841*7c478bd9Sstevel@tonic-gate {
842*7c478bd9Sstevel@tonic-gate     return (_sasl_auxprop_add_plugin(_sasl_gbl_ctx(), plugname, auxpropfunc));
843*7c478bd9Sstevel@tonic-gate }
844*7c478bd9Sstevel@tonic-gate 
_sasl_auxprop_add_plugin(void * ctx,const char * plugname,sasl_auxprop_init_t * auxpropfunc)845*7c478bd9Sstevel@tonic-gate int _sasl_auxprop_add_plugin(void *ctx,
846*7c478bd9Sstevel@tonic-gate                              const char *plugname,
847*7c478bd9Sstevel@tonic-gate                              sasl_auxprop_init_t *auxpropfunc)
848*7c478bd9Sstevel@tonic-gate #else
849*7c478bd9Sstevel@tonic-gate int sasl_auxprop_add_plugin(const char *plugname,
850*7c478bd9Sstevel@tonic-gate 			    sasl_auxprop_init_t *auxpropfunc)
851*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
852*7c478bd9Sstevel@tonic-gate {
853*7c478bd9Sstevel@tonic-gate     int result, out_version;
854*7c478bd9Sstevel@tonic-gate     auxprop_plug_list_t *new_item;
855*7c478bd9Sstevel@tonic-gate     sasl_auxprop_plug_t *plug;
856*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
857*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx;
858*7c478bd9Sstevel@tonic-gate     auxprop_plug_list_t *auxprop_head;
859*7c478bd9Sstevel@tonic-gate     const sasl_utils_t *sasl_global_utils;
860*7c478bd9Sstevel@tonic-gate     auxprop_plug_list_t *l;
861*7c478bd9Sstevel@tonic-gate 
862*7c478bd9Sstevel@tonic-gate     auxprop_head = gctx->auxprop_head;
863*7c478bd9Sstevel@tonic-gate     sasl_global_utils = gctx->sasl_server_global_utils;
864*7c478bd9Sstevel@tonic-gate 
865*7c478bd9Sstevel@tonic-gate   /* Check to see if this plugin has already been registered */
866*7c478bd9Sstevel@tonic-gate     for (l = auxprop_head; l != NULL; l = l->next) {
867*7c478bd9Sstevel@tonic-gate 	if (strcmp(plugname, l->plugname) == 0) {
868*7c478bd9Sstevel@tonic-gate 	    return SASL_OK;
869*7c478bd9Sstevel@tonic-gate 	}
870*7c478bd9Sstevel@tonic-gate     }
871*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
872*7c478bd9Sstevel@tonic-gate 
873*7c478bd9Sstevel@tonic-gate     result = auxpropfunc(sasl_global_utils, SASL_AUXPROP_PLUG_VERSION,
874*7c478bd9Sstevel@tonic-gate 			 &out_version, &plug, plugname);
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate     if(result != SASL_OK) {
877*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
878*7c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks,
879*7c478bd9Sstevel@tonic-gate 		SASL_LOG_ERR, "auxpropfunc error %i\n",result);
880*7c478bd9Sstevel@tonic-gate #else
881*7c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR, "auxpropfunc error %i\n",result);
882*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
883*7c478bd9Sstevel@tonic-gate 	return result;
884*7c478bd9Sstevel@tonic-gate     }
885*7c478bd9Sstevel@tonic-gate 
886*7c478bd9Sstevel@tonic-gate     /* We require that this function is implemented */
887*7c478bd9Sstevel@tonic-gate     if(!plug->auxprop_lookup) return SASL_BADPROT;
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
890*7c478bd9Sstevel@tonic-gate     /* Check plugin to make sure name is non-NULL */
891*7c478bd9Sstevel@tonic-gate     if (plug->name == NULL) {
892*7c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks,
893*7c478bd9Sstevel@tonic-gate 		SASL_LOG_ERR, "invalid auxprop plugin %s", plugname);
894*7c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
895*7c478bd9Sstevel@tonic-gate     }
896*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
897*7c478bd9Sstevel@tonic-gate 
898*7c478bd9Sstevel@tonic-gate     new_item = sasl_ALLOC(sizeof(auxprop_plug_list_t));
899*7c478bd9Sstevel@tonic-gate     if(!new_item) return SASL_NOMEM;
900*7c478bd9Sstevel@tonic-gate 
901*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
902*7c478bd9Sstevel@tonic-gate     if(_sasl_strdup(plugname, &new_item->plugname, NULL) != SASL_OK) {
903*7c478bd9Sstevel@tonic-gate 	sasl_FREE(new_item);
904*7c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
905*7c478bd9Sstevel@tonic-gate     }
906*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
907*7c478bd9Sstevel@tonic-gate     /* These will load from least-important to most important */
908*7c478bd9Sstevel@tonic-gate     new_item->plug = plug;
909*7c478bd9Sstevel@tonic-gate     new_item->next = auxprop_head;
910*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
911*7c478bd9Sstevel@tonic-gate     gctx->auxprop_head = new_item;
912*7c478bd9Sstevel@tonic-gate #else
913*7c478bd9Sstevel@tonic-gate     auxprop_head = new_item;
914*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate     return SASL_OK;
917*7c478bd9Sstevel@tonic-gate }
918*7c478bd9Sstevel@tonic-gate 
919*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
_sasl_auxprop_free(_sasl_global_context_t * gctx)920*7c478bd9Sstevel@tonic-gate void _sasl_auxprop_free(_sasl_global_context_t *gctx)
921*7c478bd9Sstevel@tonic-gate #else
922*7c478bd9Sstevel@tonic-gate void _sasl_auxprop_free()
923*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
924*7c478bd9Sstevel@tonic-gate {
925*7c478bd9Sstevel@tonic-gate     auxprop_plug_list_t *ptr, *ptr_next;
926*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
927*7c478bd9Sstevel@tonic-gate     const sasl_utils_t *sasl_global_utils = gctx->sasl_server_global_utils;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate     for(ptr = (auxprop_plug_list_t *)gctx->auxprop_head; ptr; ptr = ptr_next) {
930*7c478bd9Sstevel@tonic-gate #else
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate     for(ptr = auxprop_head; ptr; ptr = ptr_next) {
933*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
934*7c478bd9Sstevel@tonic-gate 	ptr_next = ptr->next;
935*7c478bd9Sstevel@tonic-gate 	if(ptr->plug->auxprop_free)
936*7c478bd9Sstevel@tonic-gate 	    ptr->plug->auxprop_free(ptr->plug->glob_context,
937*7c478bd9Sstevel@tonic-gate 				    sasl_global_utils);
938*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
939*7c478bd9Sstevel@tonic-gate 	sasl_FREE(ptr->plugname);
940*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
941*7c478bd9Sstevel@tonic-gate 	sasl_FREE(ptr);
942*7c478bd9Sstevel@tonic-gate     }
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
945*7c478bd9Sstevel@tonic-gate     gctx->auxprop_head = NULL;
946*7c478bd9Sstevel@tonic-gate #else
947*7c478bd9Sstevel@tonic-gate     auxprop_head = NULL;
948*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
949*7c478bd9Sstevel@tonic-gate }
950*7c478bd9Sstevel@tonic-gate 
951*7c478bd9Sstevel@tonic-gate 
952*7c478bd9Sstevel@tonic-gate /* Do the callbacks for auxprop lookups */
953*7c478bd9Sstevel@tonic-gate void _sasl_auxprop_lookup(sasl_server_params_t *sparams,
954*7c478bd9Sstevel@tonic-gate 			  unsigned flags,
955*7c478bd9Sstevel@tonic-gate 			  const char *user, unsigned ulen)
956*7c478bd9Sstevel@tonic-gate {
957*7c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
958*7c478bd9Sstevel@tonic-gate     int ret, found = 0;
959*7c478bd9Sstevel@tonic-gate     void *context;
960*7c478bd9Sstevel@tonic-gate     const char *plist = NULL;
961*7c478bd9Sstevel@tonic-gate     auxprop_plug_list_t *ptr;
962*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
963*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx = sparams->utils->conn->gctx;
964*7c478bd9Sstevel@tonic-gate     auxprop_plug_list_t *auxprop_head = gctx->auxprop_head;
965*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate     if(_sasl_getcallback(sparams->utils->conn,
968*7c478bd9Sstevel@tonic-gate 			 SASL_CB_GETOPT, &getopt, &context) == SASL_OK) {
969*7c478bd9Sstevel@tonic-gate 	ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL);
970*7c478bd9Sstevel@tonic-gate 	if(ret != SASL_OK) plist = NULL;
971*7c478bd9Sstevel@tonic-gate     }
972*7c478bd9Sstevel@tonic-gate 
973*7c478bd9Sstevel@tonic-gate     if(!plist) {
974*7c478bd9Sstevel@tonic-gate 	/* Do lookup in all plugins */
975*7c478bd9Sstevel@tonic-gate 	for(ptr = auxprop_head; ptr; ptr = ptr->next) {
976*7c478bd9Sstevel@tonic-gate 	    found=1;
977*7c478bd9Sstevel@tonic-gate 	    ptr->plug->auxprop_lookup(ptr->plug->glob_context,
978*7c478bd9Sstevel@tonic-gate 				      sparams, flags, user, ulen);
979*7c478bd9Sstevel@tonic-gate 	}
980*7c478bd9Sstevel@tonic-gate     } else {
981*7c478bd9Sstevel@tonic-gate 	char *pluginlist = NULL, *freeptr = NULL, *thisplugin = NULL;
982*7c478bd9Sstevel@tonic-gate 
983*7c478bd9Sstevel@tonic-gate 	if(_sasl_strdup(plist, &pluginlist, NULL) != SASL_OK) return;
984*7c478bd9Sstevel@tonic-gate 	thisplugin = freeptr = pluginlist;
985*7c478bd9Sstevel@tonic-gate 
986*7c478bd9Sstevel@tonic-gate 	/* Do lookup in all *specified* plugins, in order */
987*7c478bd9Sstevel@tonic-gate 	while(*thisplugin) {
988*7c478bd9Sstevel@tonic-gate 	    char *p;
989*7c478bd9Sstevel@tonic-gate 	    int last=0;
990*7c478bd9Sstevel@tonic-gate 
991*7c478bd9Sstevel@tonic-gate 	    while(*thisplugin && isspace((int)*thisplugin)) thisplugin++;
992*7c478bd9Sstevel@tonic-gate 	    if(!(*thisplugin)) break;
993*7c478bd9Sstevel@tonic-gate 
994*7c478bd9Sstevel@tonic-gate 	    for(p = thisplugin;*p != '\0' && !isspace((int)*p); p++);
995*7c478bd9Sstevel@tonic-gate 	    if(*p == '\0') last = 1;
996*7c478bd9Sstevel@tonic-gate 	    else *p='\0';
997*7c478bd9Sstevel@tonic-gate 
998*7c478bd9Sstevel@tonic-gate 	    for(ptr = auxprop_head; ptr; ptr = ptr->next) {
999*7c478bd9Sstevel@tonic-gate 		/* Skip non-matching plugins */
1000*7c478bd9Sstevel@tonic-gate 		if(!ptr->plug->name
1001*7c478bd9Sstevel@tonic-gate 		   || strcasecmp(ptr->plug->name, thisplugin))
1002*7c478bd9Sstevel@tonic-gate 		    continue;
1003*7c478bd9Sstevel@tonic-gate 
1004*7c478bd9Sstevel@tonic-gate 		found=1;
1005*7c478bd9Sstevel@tonic-gate 		ptr->plug->auxprop_lookup(ptr->plug->glob_context,
1006*7c478bd9Sstevel@tonic-gate 					  sparams, flags, user, ulen);
1007*7c478bd9Sstevel@tonic-gate 	    }
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate 	    if(last) break;
1010*7c478bd9Sstevel@tonic-gate 
1011*7c478bd9Sstevel@tonic-gate 	    thisplugin = p+1;
1012*7c478bd9Sstevel@tonic-gate 	}
1013*7c478bd9Sstevel@tonic-gate 
1014*7c478bd9Sstevel@tonic-gate 	sasl_FREE(freeptr);
1015*7c478bd9Sstevel@tonic-gate     }
1016*7c478bd9Sstevel@tonic-gate 
1017*7c478bd9Sstevel@tonic-gate     if(!found)
1018*7c478bd9Sstevel@tonic-gate 	_sasl_log(sparams->utils->conn, SASL_LOG_DEBUG,
1019*7c478bd9Sstevel@tonic-gate 		  "could not find auxprop plugin, was searching for '%s'",
1020*7c478bd9Sstevel@tonic-gate 		  plist ? plist : "[all]");
1021*7c478bd9Sstevel@tonic-gate }
1022