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