1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * Copyright 2004 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 /* SASL server API implementation
7*7c478bd9Sstevel@tonic-gate * Rob Siemborski
8*7c478bd9Sstevel@tonic-gate * Tim Martin
9*7c478bd9Sstevel@tonic-gate * $Id: client.c,v 1.61 2003/04/16 19:36:00 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 <stdio.h>
53*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
54*7c478bd9Sstevel@tonic-gate #include <limits.h>
55*7c478bd9Sstevel@tonic-gate #include <ctype.h>
56*7c478bd9Sstevel@tonic-gate #include <string.h>
57*7c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H
58*7c478bd9Sstevel@tonic-gate #include <unistd.h>
59*7c478bd9Sstevel@tonic-gate #endif
60*7c478bd9Sstevel@tonic-gate
61*7c478bd9Sstevel@tonic-gate /* SASL Headers */
62*7c478bd9Sstevel@tonic-gate #include "sasl.h"
63*7c478bd9Sstevel@tonic-gate #include "saslplug.h"
64*7c478bd9Sstevel@tonic-gate #include "saslutil.h"
65*7c478bd9Sstevel@tonic-gate #include "saslint.h"
66*7c478bd9Sstevel@tonic-gate
67*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
68*7c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(init_client_mutex);
69*7c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(client_active_mutex);
70*7c478bd9Sstevel@tonic-gate /*
71*7c478bd9Sstevel@tonic-gate * client_plug_mutex ensures only one client plugin is init'ed at a time
72*7c478bd9Sstevel@tonic-gate * If a plugin is loaded more than once, the glob_context may be overwritten
73*7c478bd9Sstevel@tonic-gate * which may lead to a memory leak. We keep glob_context with each mech
74*7c478bd9Sstevel@tonic-gate * to avoid this problem.
75*7c478bd9Sstevel@tonic-gate */
76*7c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(client_plug_mutex);
77*7c478bd9Sstevel@tonic-gate #else
78*7c478bd9Sstevel@tonic-gate static cmech_list_t *cmechlist; /* global var which holds the list */
79*7c478bd9Sstevel@tonic-gate
80*7c478bd9Sstevel@tonic-gate static sasl_global_callbacks_t global_callbacks;
81*7c478bd9Sstevel@tonic-gate
82*7c478bd9Sstevel@tonic-gate static int _sasl_client_active = 0;
83*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
84*7c478bd9Sstevel@tonic-gate
85*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
init_mechlist(_sasl_global_context_t * gctx)86*7c478bd9Sstevel@tonic-gate static int init_mechlist(_sasl_global_context_t *gctx)
87*7c478bd9Sstevel@tonic-gate {
88*7c478bd9Sstevel@tonic-gate cmech_list_t *cmechlist = gctx->cmechlist;
89*7c478bd9Sstevel@tonic-gate #else
90*7c478bd9Sstevel@tonic-gate static int init_mechlist()
91*7c478bd9Sstevel@tonic-gate {
92*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
93*7c478bd9Sstevel@tonic-gate
94*7c478bd9Sstevel@tonic-gate cmechlist->mutex = sasl_MUTEX_ALLOC();
95*7c478bd9Sstevel@tonic-gate if(!cmechlist->mutex) return SASL_FAIL;
96*7c478bd9Sstevel@tonic-gate
97*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
98*7c478bd9Sstevel@tonic-gate cmechlist->utils=
99*7c478bd9Sstevel@tonic-gate _sasl_alloc_utils(gctx, NULL, &gctx->client_global_callbacks);
100*7c478bd9Sstevel@tonic-gate #else
101*7c478bd9Sstevel@tonic-gate cmechlist->utils=_sasl_alloc_utils(NULL, &global_callbacks);
102*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
103*7c478bd9Sstevel@tonic-gate if (cmechlist->utils==NULL)
104*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
105*7c478bd9Sstevel@tonic-gate
106*7c478bd9Sstevel@tonic-gate cmechlist->mech_list=NULL;
107*7c478bd9Sstevel@tonic-gate cmechlist->mech_length=0;
108*7c478bd9Sstevel@tonic-gate
109*7c478bd9Sstevel@tonic-gate return SASL_OK;
110*7c478bd9Sstevel@tonic-gate }
111*7c478bd9Sstevel@tonic-gate
112*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
113*7c478bd9Sstevel@tonic-gate static int client_done(_sasl_global_context_t *gctx) {
114*7c478bd9Sstevel@tonic-gate cmech_list_t *cmechlist = gctx->cmechlist;
115*7c478bd9Sstevel@tonic-gate _sasl_path_info_t *path_info, *p;
116*7c478bd9Sstevel@tonic-gate #else
117*7c478bd9Sstevel@tonic-gate static int client_done(void) {
118*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
119*7c478bd9Sstevel@tonic-gate cmechanism_t *cm;
120*7c478bd9Sstevel@tonic-gate cmechanism_t *cprevm;
121*7c478bd9Sstevel@tonic-gate
122*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
123*7c478bd9Sstevel@tonic-gate if(!gctx->sasl_client_active)
124*7c478bd9Sstevel@tonic-gate return SASL_NOTINIT;
125*7c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&client_active_mutex) < 0) {
126*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
127*7c478bd9Sstevel@tonic-gate }
128*7c478bd9Sstevel@tonic-gate gctx->sasl_client_active--;
129*7c478bd9Sstevel@tonic-gate
130*7c478bd9Sstevel@tonic-gate if(gctx->sasl_client_active) {
131*7c478bd9Sstevel@tonic-gate /* Don't de-init yet! Our refcount is nonzero. */
132*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_active_mutex);
133*7c478bd9Sstevel@tonic-gate return SASL_CONTINUE;
134*7c478bd9Sstevel@tonic-gate }
135*7c478bd9Sstevel@tonic-gate #else
136*7c478bd9Sstevel@tonic-gate if(!_sasl_client_active)
137*7c478bd9Sstevel@tonic-gate return SASL_NOTINIT;
138*7c478bd9Sstevel@tonic-gate else
139*7c478bd9Sstevel@tonic-gate _sasl_client_active--;
140*7c478bd9Sstevel@tonic-gate
141*7c478bd9Sstevel@tonic-gate if(_sasl_client_active) {
142*7c478bd9Sstevel@tonic-gate /* Don't de-init yet! Our refcount is nonzero. */
143*7c478bd9Sstevel@tonic-gate return SASL_CONTINUE;
144*7c478bd9Sstevel@tonic-gate }
145*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
146*7c478bd9Sstevel@tonic-gate
147*7c478bd9Sstevel@tonic-gate cm=cmechlist->mech_list; /* m point to begging of the list */
148*7c478bd9Sstevel@tonic-gate while (cm!=NULL)
149*7c478bd9Sstevel@tonic-gate {
150*7c478bd9Sstevel@tonic-gate cprevm=cm;
151*7c478bd9Sstevel@tonic-gate cm=cm->next;
152*7c478bd9Sstevel@tonic-gate
153*7c478bd9Sstevel@tonic-gate if (cprevm->plug->mech_free) {
154*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
155*7c478bd9Sstevel@tonic-gate cprevm->plug->mech_free(cprevm->glob_context, cmechlist->utils);
156*7c478bd9Sstevel@tonic-gate #else
157*7c478bd9Sstevel@tonic-gate cprevm->plug->mech_free(cprevm->plug->glob_context,
158*7c478bd9Sstevel@tonic-gate cmechlist->utils);
159*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
160*7c478bd9Sstevel@tonic-gate }
161*7c478bd9Sstevel@tonic-gate
162*7c478bd9Sstevel@tonic-gate sasl_FREE(cprevm->plugname);
163*7c478bd9Sstevel@tonic-gate sasl_FREE(cprevm);
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate sasl_MUTEX_FREE(cmechlist->mutex);
166*7c478bd9Sstevel@tonic-gate _sasl_free_utils(&cmechlist->utils);
167*7c478bd9Sstevel@tonic-gate sasl_FREE(cmechlist);
168*7c478bd9Sstevel@tonic-gate
169*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
170*7c478bd9Sstevel@tonic-gate gctx->cmechlist = NULL;
171*7c478bd9Sstevel@tonic-gate p = gctx->cplug_path_info;
172*7c478bd9Sstevel@tonic-gate while((path_info = p) != NULL) {
173*7c478bd9Sstevel@tonic-gate sasl_FREE(path_info->path);
174*7c478bd9Sstevel@tonic-gate p = path_info->next;
175*7c478bd9Sstevel@tonic-gate sasl_FREE(path_info);
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate gctx->cplug_path_info = NULL;
178*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_active_mutex);
179*7c478bd9Sstevel@tonic-gate #else
180*7c478bd9Sstevel@tonic-gate cmechlist = NULL;
181*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
182*7c478bd9Sstevel@tonic-gate
183*7c478bd9Sstevel@tonic-gate return SASL_OK;
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate int sasl_client_add_plugin(const char *plugname,
187*7c478bd9Sstevel@tonic-gate sasl_client_plug_init_t *entry_point)
188*7c478bd9Sstevel@tonic-gate {
189*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
190*7c478bd9Sstevel@tonic-gate return (_sasl_client_add_plugin(_sasl_gbl_ctx(), plugname, entry_point));
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate
193*7c478bd9Sstevel@tonic-gate int _sasl_client_add_plugin(void *ctx,
194*7c478bd9Sstevel@tonic-gate const char *plugname,
195*7c478bd9Sstevel@tonic-gate sasl_client_plug_init_t *entry_point)
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate cmech_list_t *cmechlist;
198*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
199*7c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx;
200*7c478bd9Sstevel@tonic-gate int sun_reg;
201*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
202*7c478bd9Sstevel@tonic-gate int i;
203*7c478bd9Sstevel@tonic-gate cmechanism_t *m;
204*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
205*7c478bd9Sstevel@tonic-gate int plugcount;
206*7c478bd9Sstevel@tonic-gate sasl_client_plug_t *pluglist;
207*7c478bd9Sstevel@tonic-gate cmechanism_t *mech;
208*7c478bd9Sstevel@tonic-gate int result;
209*7c478bd9Sstevel@tonic-gate int version;
210*7c478bd9Sstevel@tonic-gate int lupe;
211*7c478bd9Sstevel@tonic-gate
212*7c478bd9Sstevel@tonic-gate if(!plugname || !entry_point) return SASL_BADPARAM;
213*7c478bd9Sstevel@tonic-gate
214*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
215*7c478bd9Sstevel@tonic-gate cmechlist = gctx->cmechlist;
216*7c478bd9Sstevel@tonic-gate
217*7c478bd9Sstevel@tonic-gate if (cmechlist == NULL) return SASL_BADPARAM;
218*7c478bd9Sstevel@tonic-gate
219*7c478bd9Sstevel@tonic-gate /* Check to see if this plugin has already been registered */
220*7c478bd9Sstevel@tonic-gate m = cmechlist->mech_list;
221*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmechlist->mech_length; i++) {
222*7c478bd9Sstevel@tonic-gate if (strcmp(plugname, m->plugname) == 0) {
223*7c478bd9Sstevel@tonic-gate return SASL_OK;
224*7c478bd9Sstevel@tonic-gate }
225*7c478bd9Sstevel@tonic-gate m = m->next;
226*7c478bd9Sstevel@tonic-gate }
227*7c478bd9Sstevel@tonic-gate
228*7c478bd9Sstevel@tonic-gate result = LOCK_MUTEX(&client_plug_mutex);
229*7c478bd9Sstevel@tonic-gate if (result != SASL_OK)
230*7c478bd9Sstevel@tonic-gate return result;
231*7c478bd9Sstevel@tonic-gate
232*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
233*7c478bd9Sstevel@tonic-gate
234*7c478bd9Sstevel@tonic-gate result = entry_point(cmechlist->utils, SASL_CLIENT_PLUG_VERSION, &version,
235*7c478bd9Sstevel@tonic-gate &pluglist, &plugcount);
236*7c478bd9Sstevel@tonic-gate
237*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
238*7c478bd9Sstevel@tonic-gate sun_reg = _is_sun_reg(pluglist);
239*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
240*7c478bd9Sstevel@tonic-gate if (result != SASL_OK)
241*7c478bd9Sstevel@tonic-gate {
242*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
243*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_plug_mutex);
244*7c478bd9Sstevel@tonic-gate __sasl_log(gctx, gctx->client_global_callbacks.callbacks, SASL_LOG_WARN,
245*7c478bd9Sstevel@tonic-gate "entry_point failed in sasl_client_add_plugin for %s",
246*7c478bd9Sstevel@tonic-gate plugname);
247*7c478bd9Sstevel@tonic-gate #else
248*7c478bd9Sstevel@tonic-gate _sasl_log(NULL, SASL_LOG_WARN,
249*7c478bd9Sstevel@tonic-gate "entry_point failed in sasl_client_add_plugin for %s",
250*7c478bd9Sstevel@tonic-gate plugname);
251*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
252*7c478bd9Sstevel@tonic-gate return result;
253*7c478bd9Sstevel@tonic-gate }
254*7c478bd9Sstevel@tonic-gate
255*7c478bd9Sstevel@tonic-gate if (version != SASL_CLIENT_PLUG_VERSION)
256*7c478bd9Sstevel@tonic-gate {
257*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
258*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_plug_mutex);
259*7c478bd9Sstevel@tonic-gate __sasl_log(gctx, gctx->client_global_callbacks.callbacks, SASL_LOG_WARN,
260*7c478bd9Sstevel@tonic-gate "version conflict in sasl_client_add_plugin for %s", plugname);
261*7c478bd9Sstevel@tonic-gate #else
262*7c478bd9Sstevel@tonic-gate _sasl_log(NULL, SASL_LOG_WARN,
263*7c478bd9Sstevel@tonic-gate "version conflict in sasl_client_add_plugin for %s", plugname);
264*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
265*7c478bd9Sstevel@tonic-gate return SASL_BADVERS;
266*7c478bd9Sstevel@tonic-gate }
267*7c478bd9Sstevel@tonic-gate
268*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
269*7c478bd9Sstevel@tonic-gate /* Check plugins to make sure mech_name is non-NULL */
270*7c478bd9Sstevel@tonic-gate for (lupe=0;lupe < plugcount ;lupe++) {
271*7c478bd9Sstevel@tonic-gate if (pluglist[lupe].mech_name == NULL)
272*7c478bd9Sstevel@tonic-gate break;
273*7c478bd9Sstevel@tonic-gate }
274*7c478bd9Sstevel@tonic-gate if (lupe < plugcount) {
275*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_plug_mutex);
276*7c478bd9Sstevel@tonic-gate __sasl_log(gctx, gctx->client_global_callbacks.callbacks,
277*7c478bd9Sstevel@tonic-gate SASL_LOG_ERR, "invalid client plugin %s", plugname);
278*7c478bd9Sstevel@tonic-gate return SASL_BADPROT;
279*7c478bd9Sstevel@tonic-gate }
280*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
281*7c478bd9Sstevel@tonic-gate
282*7c478bd9Sstevel@tonic-gate for (lupe=0;lupe< plugcount ;lupe++)
283*7c478bd9Sstevel@tonic-gate {
284*7c478bd9Sstevel@tonic-gate mech = sasl_ALLOC(sizeof(cmechanism_t));
285*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
286*7c478bd9Sstevel@tonic-gate if (! mech) {
287*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_plug_mutex);
288*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
289*7c478bd9Sstevel@tonic-gate }
290*7c478bd9Sstevel@tonic-gate mech->glob_context = pluglist->glob_context;
291*7c478bd9Sstevel@tonic-gate #else
292*7c478bd9Sstevel@tonic-gate if (! mech) return SASL_NOMEM;
293*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
294*7c478bd9Sstevel@tonic-gate
295*7c478bd9Sstevel@tonic-gate mech->plug=pluglist++;
296*7c478bd9Sstevel@tonic-gate if(_sasl_strdup(plugname, &mech->plugname, NULL) != SASL_OK) {
297*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
298*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_plug_mutex);
299*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
300*7c478bd9Sstevel@tonic-gate sasl_FREE(mech);
301*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
302*7c478bd9Sstevel@tonic-gate }
303*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
304*7c478bd9Sstevel@tonic-gate mech->sun_reg = sun_reg;
305*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
306*7c478bd9Sstevel@tonic-gate mech->version = version;
307*7c478bd9Sstevel@tonic-gate mech->next = cmechlist->mech_list;
308*7c478bd9Sstevel@tonic-gate cmechlist->mech_list = mech;
309*7c478bd9Sstevel@tonic-gate cmechlist->mech_length++;
310*7c478bd9Sstevel@tonic-gate }
311*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
312*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_plug_mutex);
313*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
314*7c478bd9Sstevel@tonic-gate
315*7c478bd9Sstevel@tonic-gate return SASL_OK;
316*7c478bd9Sstevel@tonic-gate }
317*7c478bd9Sstevel@tonic-gate
318*7c478bd9Sstevel@tonic-gate static int
319*7c478bd9Sstevel@tonic-gate client_idle(sasl_conn_t *conn)
320*7c478bd9Sstevel@tonic-gate {
321*7c478bd9Sstevel@tonic-gate cmechanism_t *m;
322*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
323*7c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = conn == NULL ? _sasl_gbl_ctx() : conn->gctx;
324*7c478bd9Sstevel@tonic-gate cmech_list_t *cmechlist = gctx->cmechlist;
325*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
326*7c478bd9Sstevel@tonic-gate
327*7c478bd9Sstevel@tonic-gate if (! cmechlist)
328*7c478bd9Sstevel@tonic-gate return 0;
329*7c478bd9Sstevel@tonic-gate
330*7c478bd9Sstevel@tonic-gate for (m = cmechlist->mech_list;
331*7c478bd9Sstevel@tonic-gate m;
332*7c478bd9Sstevel@tonic-gate m = m->next)
333*7c478bd9Sstevel@tonic-gate if (m->plug->idle
334*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
335*7c478bd9Sstevel@tonic-gate && m->plug->idle(m->glob_context,
336*7c478bd9Sstevel@tonic-gate #else
337*7c478bd9Sstevel@tonic-gate && m->plug->idle(m->plug->glob_context,
338*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
339*7c478bd9Sstevel@tonic-gate conn,
340*7c478bd9Sstevel@tonic-gate conn ? ((sasl_client_conn_t *)conn)->cparams : NULL))
341*7c478bd9Sstevel@tonic-gate return 1;
342*7c478bd9Sstevel@tonic-gate return 0;
343*7c478bd9Sstevel@tonic-gate }
344*7c478bd9Sstevel@tonic-gate
345*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
346*7c478bd9Sstevel@tonic-gate static int _load_client_plugins(_sasl_global_context_t *gctx)
347*7c478bd9Sstevel@tonic-gate {
348*7c478bd9Sstevel@tonic-gate int ret;
349*7c478bd9Sstevel@tonic-gate const add_plugin_list_t _ep_list[] = {
350*7c478bd9Sstevel@tonic-gate { "sasl_client_plug_init", (add_plugin_t *)_sasl_client_add_plugin },
351*7c478bd9Sstevel@tonic-gate { "sasl_canonuser_init", (add_plugin_t *)_sasl_canonuser_add_plugin },
352*7c478bd9Sstevel@tonic-gate { NULL, NULL }
353*7c478bd9Sstevel@tonic-gate };
354*7c478bd9Sstevel@tonic-gate const sasl_callback_t *callbacks = gctx->client_global_callbacks.callbacks;
355*7c478bd9Sstevel@tonic-gate
356*7c478bd9Sstevel@tonic-gate ret = _sasl_load_plugins(gctx, 0, _ep_list,
357*7c478bd9Sstevel@tonic-gate _sasl_find_getpath_callback(callbacks),
358*7c478bd9Sstevel@tonic-gate _sasl_find_verifyfile_callback(callbacks));
359*7c478bd9Sstevel@tonic-gate return (ret);
360*7c478bd9Sstevel@tonic-gate }
361*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
362*7c478bd9Sstevel@tonic-gate
363*7c478bd9Sstevel@tonic-gate /* initialize the SASL client drivers
364*7c478bd9Sstevel@tonic-gate * callbacks -- base callbacks for all client connections
365*7c478bd9Sstevel@tonic-gate * returns:
366*7c478bd9Sstevel@tonic-gate * SASL_OK -- Success
367*7c478bd9Sstevel@tonic-gate * SASL_NOMEM -- Not enough memory
368*7c478bd9Sstevel@tonic-gate * SASL_BADVERS -- Mechanism version mismatch
369*7c478bd9Sstevel@tonic-gate * SASL_BADPARAM -- error in config file
370*7c478bd9Sstevel@tonic-gate * SASL_NOMECH -- No mechanisms available
371*7c478bd9Sstevel@tonic-gate * ...
372*7c478bd9Sstevel@tonic-gate */
373*7c478bd9Sstevel@tonic-gate
374*7c478bd9Sstevel@tonic-gate int sasl_client_init(const sasl_callback_t *callbacks)
375*7c478bd9Sstevel@tonic-gate {
376*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
377*7c478bd9Sstevel@tonic-gate return _sasl_client_init(NULL, callbacks);
378*7c478bd9Sstevel@tonic-gate }
379*7c478bd9Sstevel@tonic-gate
380*7c478bd9Sstevel@tonic-gate int _sasl_client_init(void *ctx,
381*7c478bd9Sstevel@tonic-gate const sasl_callback_t *callbacks)
382*7c478bd9Sstevel@tonic-gate {
383*7c478bd9Sstevel@tonic-gate int ret;
384*7c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx;
385*7c478bd9Sstevel@tonic-gate
386*7c478bd9Sstevel@tonic-gate if (gctx == NULL)
387*7c478bd9Sstevel@tonic-gate gctx = _sasl_gbl_ctx();
388*7c478bd9Sstevel@tonic-gate
389*7c478bd9Sstevel@tonic-gate ret = LOCK_MUTEX(&init_client_mutex);
390*7c478bd9Sstevel@tonic-gate if (ret < 0) {
391*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
392*7c478bd9Sstevel@tonic-gate }
393*7c478bd9Sstevel@tonic-gate ret = LOCK_MUTEX(&client_active_mutex);
394*7c478bd9Sstevel@tonic-gate if (ret < 0) {
395*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_client_mutex);
396*7c478bd9Sstevel@tonic-gate return (SASL_FAIL);
397*7c478bd9Sstevel@tonic-gate }
398*7c478bd9Sstevel@tonic-gate if(gctx->sasl_client_active) {
399*7c478bd9Sstevel@tonic-gate /* We're already active, just increase our refcount */
400*7c478bd9Sstevel@tonic-gate /* xxx do something with the callback structure? */
401*7c478bd9Sstevel@tonic-gate gctx->sasl_client_active++;
402*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_active_mutex);
403*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_client_mutex);
404*7c478bd9Sstevel@tonic-gate return SASL_OK;
405*7c478bd9Sstevel@tonic-gate }
406*7c478bd9Sstevel@tonic-gate
407*7c478bd9Sstevel@tonic-gate gctx->client_global_callbacks.callbacks = callbacks;
408*7c478bd9Sstevel@tonic-gate gctx->client_global_callbacks.appname = NULL;
409*7c478bd9Sstevel@tonic-gate
410*7c478bd9Sstevel@tonic-gate gctx->cmechlist=sasl_ALLOC(sizeof(cmech_list_t));
411*7c478bd9Sstevel@tonic-gate if (gctx->cmechlist==NULL) {
412*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_client_mutex);
413*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_active_mutex);
414*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
415*7c478bd9Sstevel@tonic-gate }
416*7c478bd9Sstevel@tonic-gate
417*7c478bd9Sstevel@tonic-gate gctx->sasl_client_active = 1;
418*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&client_active_mutex);
419*7c478bd9Sstevel@tonic-gate
420*7c478bd9Sstevel@tonic-gate /* load plugins */
421*7c478bd9Sstevel@tonic-gate ret=init_mechlist(gctx);
422*7c478bd9Sstevel@tonic-gate
423*7c478bd9Sstevel@tonic-gate if (ret!=SASL_OK) {
424*7c478bd9Sstevel@tonic-gate client_done(gctx);
425*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_client_mutex);
426*7c478bd9Sstevel@tonic-gate return ret;
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate _sasl_client_add_plugin(gctx, "EXTERNAL", &external_client_plug_init);
429*7c478bd9Sstevel@tonic-gate
430*7c478bd9Sstevel@tonic-gate ret = _sasl_common_init(gctx, &gctx->client_global_callbacks, 0);
431*7c478bd9Sstevel@tonic-gate #else
432*7c478bd9Sstevel@tonic-gate int sasl_client_init(const sasl_callback_t *callbacks)
433*7c478bd9Sstevel@tonic-gate {
434*7c478bd9Sstevel@tonic-gate int ret;
435*7c478bd9Sstevel@tonic-gate const add_plugin_list_t ep_list[] = {
436*7c478bd9Sstevel@tonic-gate { "sasl_client_plug_init", (add_plugin_t *)sasl_client_add_plugin },
437*7c478bd9Sstevel@tonic-gate { "sasl_canonuser_init", (add_plugin_t *)sasl_canonuser_add_plugin },
438*7c478bd9Sstevel@tonic-gate { NULL, NULL }
439*7c478bd9Sstevel@tonic-gate };
440*7c478bd9Sstevel@tonic-gate
441*7c478bd9Sstevel@tonic-gate if(_sasl_client_active) {
442*7c478bd9Sstevel@tonic-gate /* We're already active, just increase our refcount */
443*7c478bd9Sstevel@tonic-gate /* xxx do something with the callback structure? */
444*7c478bd9Sstevel@tonic-gate _sasl_client_active++;
445*7c478bd9Sstevel@tonic-gate return SASL_OK;
446*7c478bd9Sstevel@tonic-gate }
447*7c478bd9Sstevel@tonic-gate
448*7c478bd9Sstevel@tonic-gate global_callbacks.callbacks = callbacks;
449*7c478bd9Sstevel@tonic-gate global_callbacks.appname = NULL;
450*7c478bd9Sstevel@tonic-gate
451*7c478bd9Sstevel@tonic-gate cmechlist=sasl_ALLOC(sizeof(cmech_list_t));
452*7c478bd9Sstevel@tonic-gate if (cmechlist==NULL) return SASL_NOMEM;
453*7c478bd9Sstevel@tonic-gate
454*7c478bd9Sstevel@tonic-gate /* We need to call client_done if we fail now */
455*7c478bd9Sstevel@tonic-gate _sasl_client_active = 1;
456*7c478bd9Sstevel@tonic-gate
457*7c478bd9Sstevel@tonic-gate /* load plugins */
458*7c478bd9Sstevel@tonic-gate ret=init_mechlist();
459*7c478bd9Sstevel@tonic-gate if (ret!=SASL_OK) {
460*7c478bd9Sstevel@tonic-gate client_done();
461*7c478bd9Sstevel@tonic-gate return ret;
462*7c478bd9Sstevel@tonic-gate }
463*7c478bd9Sstevel@tonic-gate
464*7c478bd9Sstevel@tonic-gate sasl_client_add_plugin("EXTERNAL", &external_client_plug_init);
465*7c478bd9Sstevel@tonic-gate
466*7c478bd9Sstevel@tonic-gate ret = _sasl_common_init(&global_callbacks);
467*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
468*7c478bd9Sstevel@tonic-gate
469*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK)
470*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
471*7c478bd9Sstevel@tonic-gate ret = _load_client_plugins(gctx);
472*7c478bd9Sstevel@tonic-gate #else
473*7c478bd9Sstevel@tonic-gate ret = _sasl_load_plugins(ep_list,
474*7c478bd9Sstevel@tonic-gate _sasl_find_getpath_callback(callbacks),
475*7c478bd9Sstevel@tonic-gate _sasl_find_verifyfile_callback(callbacks));
476*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
477*7c478bd9Sstevel@tonic-gate
478*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
479*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK)
480*7c478bd9Sstevel@tonic-gate /* If sasl_client_init returns error, sasl_done() need not be called */
481*7c478bd9Sstevel@tonic-gate ret = _sasl_build_mechlist(gctx);
482*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK) {
483*7c478bd9Sstevel@tonic-gate gctx->sasl_client_cleanup_hook = &client_done;
484*7c478bd9Sstevel@tonic-gate gctx->sasl_client_idle_hook = &client_idle;
485*7c478bd9Sstevel@tonic-gate } else {
486*7c478bd9Sstevel@tonic-gate client_done(gctx);
487*7c478bd9Sstevel@tonic-gate }
488*7c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_client_mutex);
489*7c478bd9Sstevel@tonic-gate #else
490*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK) {
491*7c478bd9Sstevel@tonic-gate _sasl_client_cleanup_hook = &client_done;
492*7c478bd9Sstevel@tonic-gate _sasl_client_idle_hook = &client_idle;
493*7c478bd9Sstevel@tonic-gate
494*7c478bd9Sstevel@tonic-gate ret = _sasl_build_mechlist();
495*7c478bd9Sstevel@tonic-gate } else {
496*7c478bd9Sstevel@tonic-gate client_done();
497*7c478bd9Sstevel@tonic-gate }
498*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
499*7c478bd9Sstevel@tonic-gate
500*7c478bd9Sstevel@tonic-gate return ret;
501*7c478bd9Sstevel@tonic-gate }
502*7c478bd9Sstevel@tonic-gate
503*7c478bd9Sstevel@tonic-gate static void client_dispose(sasl_conn_t *pconn)
504*7c478bd9Sstevel@tonic-gate {
505*7c478bd9Sstevel@tonic-gate sasl_client_conn_t *c_conn=(sasl_client_conn_t *) pconn;
506*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
507*7c478bd9Sstevel@tonic-gate sasl_free_t *free_func = c_conn->cparams->utils->free;
508*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
509*7c478bd9Sstevel@tonic-gate
510*7c478bd9Sstevel@tonic-gate if (c_conn->mech && c_conn->mech->plug->mech_dispose) {
511*7c478bd9Sstevel@tonic-gate c_conn->mech->plug->mech_dispose(pconn->context,
512*7c478bd9Sstevel@tonic-gate c_conn->cparams->utils);
513*7c478bd9Sstevel@tonic-gate }
514*7c478bd9Sstevel@tonic-gate
515*7c478bd9Sstevel@tonic-gate pconn->context = NULL;
516*7c478bd9Sstevel@tonic-gate
517*7c478bd9Sstevel@tonic-gate if (c_conn->clientFQDN)
518*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
519*7c478bd9Sstevel@tonic-gate free_func(c_conn->clientFQDN);
520*7c478bd9Sstevel@tonic-gate #else
521*7c478bd9Sstevel@tonic-gate sasl_FREE(c_conn->clientFQDN);
522*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
523*7c478bd9Sstevel@tonic-gate
524*7c478bd9Sstevel@tonic-gate if (c_conn->cparams) {
525*7c478bd9Sstevel@tonic-gate _sasl_free_utils(&(c_conn->cparams->utils));
526*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
527*7c478bd9Sstevel@tonic-gate free_func(c_conn->cparams);
528*7c478bd9Sstevel@tonic-gate #else
529*7c478bd9Sstevel@tonic-gate sasl_FREE(c_conn->cparams);
530*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
531*7c478bd9Sstevel@tonic-gate }
532*7c478bd9Sstevel@tonic-gate
533*7c478bd9Sstevel@tonic-gate _sasl_conn_dispose(pconn);
534*7c478bd9Sstevel@tonic-gate }
535*7c478bd9Sstevel@tonic-gate
536*7c478bd9Sstevel@tonic-gate /* initialize a client exchange based on the specified mechanism
537*7c478bd9Sstevel@tonic-gate * service -- registered name of the service using SASL (e.g. "imap")
538*7c478bd9Sstevel@tonic-gate * serverFQDN -- the fully qualified domain name of the server
539*7c478bd9Sstevel@tonic-gate * iplocalport -- client IPv4/IPv6 domain literal string with port
540*7c478bd9Sstevel@tonic-gate * (if NULL, then mechanisms requiring IPaddr are disabled)
541*7c478bd9Sstevel@tonic-gate * ipremoteport -- server IPv4/IPv6 domain literal string with port
542*7c478bd9Sstevel@tonic-gate * (if NULL, then mechanisms requiring IPaddr are disabled)
543*7c478bd9Sstevel@tonic-gate * prompt_supp -- list of client interactions supported
544*7c478bd9Sstevel@tonic-gate * may also include sasl_getopt_t context & call
545*7c478bd9Sstevel@tonic-gate * NULL prompt_supp = user/pass via SASL_INTERACT only
546*7c478bd9Sstevel@tonic-gate * NULL proc = interaction supported via SASL_INTERACT
547*7c478bd9Sstevel@tonic-gate * secflags -- security flags (see above)
548*7c478bd9Sstevel@tonic-gate * in/out:
549*7c478bd9Sstevel@tonic-gate * pconn -- connection negotiation structure
550*7c478bd9Sstevel@tonic-gate * pointer to NULL => allocate new
551*7c478bd9Sstevel@tonic-gate * non-NULL => recycle storage and go for next available mech
552*7c478bd9Sstevel@tonic-gate *
553*7c478bd9Sstevel@tonic-gate * Returns:
554*7c478bd9Sstevel@tonic-gate * SASL_OK -- success
555*7c478bd9Sstevel@tonic-gate * SASL_NOMECH -- no mechanism meets requested properties
556*7c478bd9Sstevel@tonic-gate * SASL_NOMEM -- not enough memory
557*7c478bd9Sstevel@tonic-gate */
558*7c478bd9Sstevel@tonic-gate int sasl_client_new(const char *service,
559*7c478bd9Sstevel@tonic-gate const char *serverFQDN,
560*7c478bd9Sstevel@tonic-gate const char *iplocalport,
561*7c478bd9Sstevel@tonic-gate const char *ipremoteport,
562*7c478bd9Sstevel@tonic-gate const sasl_callback_t *prompt_supp,
563*7c478bd9Sstevel@tonic-gate unsigned flags,
564*7c478bd9Sstevel@tonic-gate sasl_conn_t **pconn)
565*7c478bd9Sstevel@tonic-gate {
566*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
567*7c478bd9Sstevel@tonic-gate return _sasl_client_new(NULL, service, serverFQDN, iplocalport,
568*7c478bd9Sstevel@tonic-gate ipremoteport, prompt_supp, flags, pconn);
569*7c478bd9Sstevel@tonic-gate }
570*7c478bd9Sstevel@tonic-gate int _sasl_client_new(void *ctx,
571*7c478bd9Sstevel@tonic-gate const char *service,
572*7c478bd9Sstevel@tonic-gate const char *serverFQDN,
573*7c478bd9Sstevel@tonic-gate const char *iplocalport,
574*7c478bd9Sstevel@tonic-gate const char *ipremoteport,
575*7c478bd9Sstevel@tonic-gate const sasl_callback_t *prompt_supp,
576*7c478bd9Sstevel@tonic-gate unsigned flags,
577*7c478bd9Sstevel@tonic-gate sasl_conn_t **pconn)
578*7c478bd9Sstevel@tonic-gate {
579*7c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx;
580*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
581*7c478bd9Sstevel@tonic-gate int result;
582*7c478bd9Sstevel@tonic-gate char name[MAXHOSTNAMELEN];
583*7c478bd9Sstevel@tonic-gate sasl_client_conn_t *conn;
584*7c478bd9Sstevel@tonic-gate sasl_utils_t *utils;
585*7c478bd9Sstevel@tonic-gate
586*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
587*7c478bd9Sstevel@tonic-gate if (gctx == NULL)
588*7c478bd9Sstevel@tonic-gate gctx = _sasl_gbl_ctx();
589*7c478bd9Sstevel@tonic-gate
590*7c478bd9Sstevel@tonic-gate if(gctx->sasl_client_active==0) return SASL_NOTINIT;
591*7c478bd9Sstevel@tonic-gate #else
592*7c478bd9Sstevel@tonic-gate if(_sasl_client_active==0) return SASL_NOTINIT;
593*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
594*7c478bd9Sstevel@tonic-gate
595*7c478bd9Sstevel@tonic-gate /* Remember, iplocalport and ipremoteport can be NULL and be valid! */
596*7c478bd9Sstevel@tonic-gate if (!pconn || !service || !serverFQDN)
597*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM;
598*7c478bd9Sstevel@tonic-gate
599*7c478bd9Sstevel@tonic-gate *pconn=sasl_ALLOC(sizeof(sasl_client_conn_t));
600*7c478bd9Sstevel@tonic-gate if (*pconn==NULL) {
601*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
602*7c478bd9Sstevel@tonic-gate __sasl_log(gctx, gctx->client_global_callbacks.callbacks, SASL_LOG_ERR,
603*7c478bd9Sstevel@tonic-gate "Out of memory allocating connection context");
604*7c478bd9Sstevel@tonic-gate #else
605*7c478bd9Sstevel@tonic-gate _sasl_log(NULL, SASL_LOG_ERR,
606*7c478bd9Sstevel@tonic-gate "Out of memory allocating connection context");
607*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
608*7c478bd9Sstevel@tonic-gate return SASL_NOMEM;
609*7c478bd9Sstevel@tonic-gate }
610*7c478bd9Sstevel@tonic-gate memset(*pconn, 0, sizeof(sasl_client_conn_t));
611*7c478bd9Sstevel@tonic-gate
612*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
613*7c478bd9Sstevel@tonic-gate (*pconn)->gctx = gctx;
614*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
615*7c478bd9Sstevel@tonic-gate
616*7c478bd9Sstevel@tonic-gate (*pconn)->destroy_conn = &client_dispose;
617*7c478bd9Sstevel@tonic-gate
618*7c478bd9Sstevel@tonic-gate conn = (sasl_client_conn_t *)*pconn;
619*7c478bd9Sstevel@tonic-gate
620*7c478bd9Sstevel@tonic-gate conn->mech = NULL;
621*7c478bd9Sstevel@tonic-gate
622*7c478bd9Sstevel@tonic-gate conn->cparams=sasl_ALLOC(sizeof(sasl_client_params_t));
623*7c478bd9Sstevel@tonic-gate if (conn->cparams==NULL)
624*7c478bd9Sstevel@tonic-gate MEMERROR(*pconn);
625*7c478bd9Sstevel@tonic-gate memset(conn->cparams,0,sizeof(sasl_client_params_t));
626*7c478bd9Sstevel@tonic-gate
627*7c478bd9Sstevel@tonic-gate result = _sasl_conn_init(*pconn, service, flags, SASL_CONN_CLIENT,
628*7c478bd9Sstevel@tonic-gate &client_idle, serverFQDN,
629*7c478bd9Sstevel@tonic-gate iplocalport, ipremoteport,
630*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
631*7c478bd9Sstevel@tonic-gate prompt_supp, &gctx->client_global_callbacks);
632*7c478bd9Sstevel@tonic-gate #else
633*7c478bd9Sstevel@tonic-gate prompt_supp, &global_callbacks);
634*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
635*7c478bd9Sstevel@tonic-gate
636*7c478bd9Sstevel@tonic-gate if (result != SASL_OK) RETURN(*pconn, result);
637*7c478bd9Sstevel@tonic-gate
638*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
639*7c478bd9Sstevel@tonic-gate utils=_sasl_alloc_utils(gctx, *pconn, &gctx->client_global_callbacks);
640*7c478bd9Sstevel@tonic-gate #else
641*7c478bd9Sstevel@tonic-gate utils=_sasl_alloc_utils(*pconn, &global_callbacks);
642*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
643*7c478bd9Sstevel@tonic-gate if (utils==NULL)
644*7c478bd9Sstevel@tonic-gate MEMERROR(*pconn);
645*7c478bd9Sstevel@tonic-gate
646*7c478bd9Sstevel@tonic-gate utils->conn= *pconn;
647*7c478bd9Sstevel@tonic-gate
648*7c478bd9Sstevel@tonic-gate /* Setup the non-lazy parts of cparams, the rest is done in
649*7c478bd9Sstevel@tonic-gate * sasl_client_start */
650*7c478bd9Sstevel@tonic-gate conn->cparams->utils = utils;
651*7c478bd9Sstevel@tonic-gate conn->cparams->canon_user = &_sasl_canon_user;
652*7c478bd9Sstevel@tonic-gate conn->cparams->flags = flags;
653*7c478bd9Sstevel@tonic-gate conn->cparams->prompt_supp = (*pconn)->callbacks;
654*7c478bd9Sstevel@tonic-gate
655*7c478bd9Sstevel@tonic-gate /* get the clientFQDN (serverFQDN was set in _sasl_conn_init) */
656*7c478bd9Sstevel@tonic-gate memset(name, 0, sizeof(name));
657*7c478bd9Sstevel@tonic-gate gethostname(name, MAXHOSTNAMELEN);
658*7c478bd9Sstevel@tonic-gate
659*7c478bd9Sstevel@tonic-gate result = _sasl_strdup(name, &conn->clientFQDN, NULL);
660*7c478bd9Sstevel@tonic-gate
661*7c478bd9Sstevel@tonic-gate if(result == SASL_OK) return SASL_OK;
662*7c478bd9Sstevel@tonic-gate
663*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
664*7c478bd9Sstevel@tonic-gate conn->cparams->iplocalport = (*pconn)->iplocalport;
665*7c478bd9Sstevel@tonic-gate conn->cparams->iploclen = strlen((*pconn)->iplocalport);
666*7c478bd9Sstevel@tonic-gate conn->cparams->ipremoteport = (*pconn)->ipremoteport;
667*7c478bd9Sstevel@tonic-gate conn->cparams->ipremlen = strlen((*pconn)->ipremoteport);
668*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
669*7c478bd9Sstevel@tonic-gate
670*7c478bd9Sstevel@tonic-gate /* result isn't SASL_OK */
671*7c478bd9Sstevel@tonic-gate _sasl_conn_dispose(*pconn);
672*7c478bd9Sstevel@tonic-gate sasl_FREE(*pconn);
673*7c478bd9Sstevel@tonic-gate *pconn = NULL;
674*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
675*7c478bd9Sstevel@tonic-gate __sasl_log(gctx, gctx->client_global_callbacks.callbacks, SASL_LOG_ERR,
676*7c478bd9Sstevel@tonic-gate "Out of memory in sasl_client_new");
677*7c478bd9Sstevel@tonic-gate #else
678*7c478bd9Sstevel@tonic-gate _sasl_log(NULL, SASL_LOG_ERR, "Out of memory in sasl_client_new");
679*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
680*7c478bd9Sstevel@tonic-gate return result;
681*7c478bd9Sstevel@tonic-gate }
682*7c478bd9Sstevel@tonic-gate
683*7c478bd9Sstevel@tonic-gate static int have_prompts(sasl_conn_t *conn,
684*7c478bd9Sstevel@tonic-gate const sasl_client_plug_t *mech)
685*7c478bd9Sstevel@tonic-gate {
686*7c478bd9Sstevel@tonic-gate static const unsigned long default_prompts[] = {
687*7c478bd9Sstevel@tonic-gate SASL_CB_AUTHNAME,
688*7c478bd9Sstevel@tonic-gate SASL_CB_PASS,
689*7c478bd9Sstevel@tonic-gate SASL_CB_LIST_END
690*7c478bd9Sstevel@tonic-gate };
691*7c478bd9Sstevel@tonic-gate
692*7c478bd9Sstevel@tonic-gate const unsigned long *prompt;
693*7c478bd9Sstevel@tonic-gate int (*pproc)();
694*7c478bd9Sstevel@tonic-gate void *pcontext;
695*7c478bd9Sstevel@tonic-gate int result;
696*7c478bd9Sstevel@tonic-gate
697*7c478bd9Sstevel@tonic-gate for (prompt = (mech->required_prompts
698*7c478bd9Sstevel@tonic-gate ? mech->required_prompts :
699*7c478bd9Sstevel@tonic-gate default_prompts);
700*7c478bd9Sstevel@tonic-gate *prompt != SASL_CB_LIST_END;
701*7c478bd9Sstevel@tonic-gate prompt++) {
702*7c478bd9Sstevel@tonic-gate result = _sasl_getcallback(conn, *prompt, &pproc, &pcontext);
703*7c478bd9Sstevel@tonic-gate if (result != SASL_OK && result != SASL_INTERACT)
704*7c478bd9Sstevel@tonic-gate return 0; /* we don't have this required prompt */
705*7c478bd9Sstevel@tonic-gate }
706*7c478bd9Sstevel@tonic-gate
707*7c478bd9Sstevel@tonic-gate return 1; /* we have all the prompts */
708*7c478bd9Sstevel@tonic-gate }
709*7c478bd9Sstevel@tonic-gate
710*7c478bd9Sstevel@tonic-gate /* select a mechanism for a connection
711*7c478bd9Sstevel@tonic-gate * mechlist -- mechanisms server has available (punctuation ignored)
712*7c478bd9Sstevel@tonic-gate * secret -- optional secret from previous session
713*7c478bd9Sstevel@tonic-gate * output:
714*7c478bd9Sstevel@tonic-gate * prompt_need -- on SASL_INTERACT, list of prompts needed to continue
715*7c478bd9Sstevel@tonic-gate * clientout -- the initial client response to send to the server
716*7c478bd9Sstevel@tonic-gate * mech -- set to mechanism name
717*7c478bd9Sstevel@tonic-gate *
718*7c478bd9Sstevel@tonic-gate * Returns:
719*7c478bd9Sstevel@tonic-gate * SASL_OK -- success
720*7c478bd9Sstevel@tonic-gate * SASL_NOMEM -- not enough memory
721*7c478bd9Sstevel@tonic-gate * SASL_NOMECH -- no mechanism meets requested properties
722*7c478bd9Sstevel@tonic-gate * SASL_INTERACT -- user interaction needed to fill in prompt_need list
723*7c478bd9Sstevel@tonic-gate */
724*7c478bd9Sstevel@tonic-gate
725*7c478bd9Sstevel@tonic-gate /* xxx confirm this with rfc 2222
726*7c478bd9Sstevel@tonic-gate * SASL mechanism allowable characters are "AZaz-_"
727*7c478bd9Sstevel@tonic-gate * seperators can be any other characters and of any length
728*7c478bd9Sstevel@tonic-gate * even variable lengths between
729*7c478bd9Sstevel@tonic-gate *
730*7c478bd9Sstevel@tonic-gate * Apps should be encouraged to simply use space or comma space
731*7c478bd9Sstevel@tonic-gate * though
732*7c478bd9Sstevel@tonic-gate */
733*7c478bd9Sstevel@tonic-gate int sasl_client_start(sasl_conn_t *conn,
734*7c478bd9Sstevel@tonic-gate const char *mechlist,
735*7c478bd9Sstevel@tonic-gate sasl_interact_t **prompt_need,
736*7c478bd9Sstevel@tonic-gate const char **clientout,
737*7c478bd9Sstevel@tonic-gate unsigned *clientoutlen,
738*7c478bd9Sstevel@tonic-gate const char **mech)
739*7c478bd9Sstevel@tonic-gate {
740*7c478bd9Sstevel@tonic-gate sasl_client_conn_t *c_conn= (sasl_client_conn_t *) conn;
741*7c478bd9Sstevel@tonic-gate char name[SASL_MECHNAMEMAX + 1];
742*7c478bd9Sstevel@tonic-gate cmechanism_t *m=NULL,*bestm=NULL;
743*7c478bd9Sstevel@tonic-gate size_t pos=0,place;
744*7c478bd9Sstevel@tonic-gate size_t list_len;
745*7c478bd9Sstevel@tonic-gate sasl_ssf_t bestssf = 0, minssf = 0;
746*7c478bd9Sstevel@tonic-gate int result;
747*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
748*7c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = (conn == NULL) ?
749*7c478bd9Sstevel@tonic-gate _sasl_gbl_ctx() : conn->gctx;
750*7c478bd9Sstevel@tonic-gate cmech_list_t *cmechlist;
751*7c478bd9Sstevel@tonic-gate
752*7c478bd9Sstevel@tonic-gate if(gctx->sasl_client_active==0) return SASL_NOTINIT;
753*7c478bd9Sstevel@tonic-gate cmechlist = gctx->cmechlist;
754*7c478bd9Sstevel@tonic-gate #else
755*7c478bd9Sstevel@tonic-gate if(_sasl_client_active==0) return SASL_NOTINIT;
756*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
757*7c478bd9Sstevel@tonic-gate
758*7c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM;
759*7c478bd9Sstevel@tonic-gate
760*7c478bd9Sstevel@tonic-gate /* verify parameters */
761*7c478bd9Sstevel@tonic-gate if (mechlist == NULL)
762*7c478bd9Sstevel@tonic-gate PARAMERROR(conn);
763*7c478bd9Sstevel@tonic-gate
764*7c478bd9Sstevel@tonic-gate /* if prompt_need != NULL we've already been here
765*7c478bd9Sstevel@tonic-gate and just need to do the continue step again */
766*7c478bd9Sstevel@tonic-gate
767*7c478bd9Sstevel@tonic-gate /* do a step */
768*7c478bd9Sstevel@tonic-gate /* FIXME: Hopefully they only give us our own prompt_need back */
769*7c478bd9Sstevel@tonic-gate if (prompt_need && *prompt_need != NULL) {
770*7c478bd9Sstevel@tonic-gate goto dostep;
771*7c478bd9Sstevel@tonic-gate }
772*7c478bd9Sstevel@tonic-gate
773*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
774*7c478bd9Sstevel@tonic-gate if (c_conn->mech != NULL) {
775*7c478bd9Sstevel@tonic-gate if (c_conn->mech->plug->mech_dispose != NULL) {
776*7c478bd9Sstevel@tonic-gate c_conn->mech->plug->mech_dispose(conn->context,
777*7c478bd9Sstevel@tonic-gate c_conn->cparams->utils);
778*7c478bd9Sstevel@tonic-gate c_conn->mech = NULL;
779*7c478bd9Sstevel@tonic-gate }
780*7c478bd9Sstevel@tonic-gate }
781*7c478bd9Sstevel@tonic-gate memset(&conn->oparams, 0, sizeof(sasl_out_params_t));
782*7c478bd9Sstevel@tonic-gate
783*7c478bd9Sstevel@tonic-gate (void) _load_client_plugins(gctx);
784*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
785*7c478bd9Sstevel@tonic-gate
786*7c478bd9Sstevel@tonic-gate if(conn->props.min_ssf < conn->external.ssf) {
787*7c478bd9Sstevel@tonic-gate minssf = 0;
788*7c478bd9Sstevel@tonic-gate } else {
789*7c478bd9Sstevel@tonic-gate minssf = conn->props.min_ssf - conn->external.ssf;
790*7c478bd9Sstevel@tonic-gate }
791*7c478bd9Sstevel@tonic-gate
792*7c478bd9Sstevel@tonic-gate /* parse mechlist */
793*7c478bd9Sstevel@tonic-gate list_len = strlen(mechlist);
794*7c478bd9Sstevel@tonic-gate
795*7c478bd9Sstevel@tonic-gate while (pos<list_len)
796*7c478bd9Sstevel@tonic-gate {
797*7c478bd9Sstevel@tonic-gate place=0;
798*7c478bd9Sstevel@tonic-gate while ((pos<list_len) && (isalnum((unsigned char)mechlist[pos])
799*7c478bd9Sstevel@tonic-gate || mechlist[pos] == '_'
800*7c478bd9Sstevel@tonic-gate || mechlist[pos] == '-')) {
801*7c478bd9Sstevel@tonic-gate name[place]=mechlist[pos];
802*7c478bd9Sstevel@tonic-gate pos++;
803*7c478bd9Sstevel@tonic-gate place++;
804*7c478bd9Sstevel@tonic-gate if (SASL_MECHNAMEMAX < place) {
805*7c478bd9Sstevel@tonic-gate place--;
806*7c478bd9Sstevel@tonic-gate while(pos<list_len && (isalnum((unsigned char)mechlist[pos])
807*7c478bd9Sstevel@tonic-gate || mechlist[pos] == '_'
808*7c478bd9Sstevel@tonic-gate || mechlist[pos] == '-'))
809*7c478bd9Sstevel@tonic-gate pos++;
810*7c478bd9Sstevel@tonic-gate }
811*7c478bd9Sstevel@tonic-gate }
812*7c478bd9Sstevel@tonic-gate pos++;
813*7c478bd9Sstevel@tonic-gate name[place]=0;
814*7c478bd9Sstevel@tonic-gate
815*7c478bd9Sstevel@tonic-gate if (! place) continue;
816*7c478bd9Sstevel@tonic-gate
817*7c478bd9Sstevel@tonic-gate /* foreach in server list */
818*7c478bd9Sstevel@tonic-gate for (m = cmechlist->mech_list; m != NULL; m = m->next) {
819*7c478bd9Sstevel@tonic-gate int myflags;
820*7c478bd9Sstevel@tonic-gate
821*7c478bd9Sstevel@tonic-gate /* Is this the mechanism the server is suggesting? */
822*7c478bd9Sstevel@tonic-gate if (strcasecmp(m->plug->mech_name, name))
823*7c478bd9Sstevel@tonic-gate continue; /* no */
824*7c478bd9Sstevel@tonic-gate
825*7c478bd9Sstevel@tonic-gate /* Do we have the prompts for it? */
826*7c478bd9Sstevel@tonic-gate if (!have_prompts(conn, m->plug))
827*7c478bd9Sstevel@tonic-gate break;
828*7c478bd9Sstevel@tonic-gate
829*7c478bd9Sstevel@tonic-gate /* Is it strong enough? */
830*7c478bd9Sstevel@tonic-gate if (minssf > m->plug->max_ssf)
831*7c478bd9Sstevel@tonic-gate break;
832*7c478bd9Sstevel@tonic-gate
833*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
834*7c478bd9Sstevel@tonic-gate /* If not SUN supplied mech, it has no strength */
835*7c478bd9Sstevel@tonic-gate if (minssf > 0 && !m->sun_reg)
836*7c478bd9Sstevel@tonic-gate break;
837*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
838*7c478bd9Sstevel@tonic-gate
839*7c478bd9Sstevel@tonic-gate /* Does it meet our security properties? */
840*7c478bd9Sstevel@tonic-gate myflags = conn->props.security_flags;
841*7c478bd9Sstevel@tonic-gate
842*7c478bd9Sstevel@tonic-gate /* if there's an external layer this is no longer plaintext */
843*7c478bd9Sstevel@tonic-gate if ((conn->props.min_ssf <= conn->external.ssf) &&
844*7c478bd9Sstevel@tonic-gate (conn->external.ssf > 1)) {
845*7c478bd9Sstevel@tonic-gate myflags &= ~SASL_SEC_NOPLAINTEXT;
846*7c478bd9Sstevel@tonic-gate }
847*7c478bd9Sstevel@tonic-gate
848*7c478bd9Sstevel@tonic-gate if (((myflags ^ m->plug->security_flags) & myflags) != 0) {
849*7c478bd9Sstevel@tonic-gate break;
850*7c478bd9Sstevel@tonic-gate }
851*7c478bd9Sstevel@tonic-gate
852*7c478bd9Sstevel@tonic-gate /* Can we meet it's features? */
853*7c478bd9Sstevel@tonic-gate if ((m->plug->features & SASL_FEAT_NEEDSERVERFQDN)
854*7c478bd9Sstevel@tonic-gate && !conn->serverFQDN) {
855*7c478bd9Sstevel@tonic-gate break;
856*7c478bd9Sstevel@tonic-gate }
857*7c478bd9Sstevel@tonic-gate
858*7c478bd9Sstevel@tonic-gate /* Can it meet our features? */
859*7c478bd9Sstevel@tonic-gate if ((conn->flags & SASL_NEED_PROXY) &&
860*7c478bd9Sstevel@tonic-gate !(m->plug->features & SASL_FEAT_ALLOWS_PROXY)) {
861*7c478bd9Sstevel@tonic-gate break;
862*7c478bd9Sstevel@tonic-gate }
863*7c478bd9Sstevel@tonic-gate
864*7c478bd9Sstevel@tonic-gate #ifdef PREFER_MECH
865*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
866*7c478bd9Sstevel@tonic-gate if (strcasecmp(m->plug->mech_name, PREFER_MECH) &&
867*7c478bd9Sstevel@tonic-gate bestm && (m->sun_reg && m->plug->max_ssf <= bestssf) ||
868*7c478bd9Sstevel@tonic-gate (m->plug->max_ssf == 0)) {
869*7c478bd9Sstevel@tonic-gate #else
870*7c478bd9Sstevel@tonic-gate if (strcasecmp(m->plug->mech_name, PREFER_MECH) &&
871*7c478bd9Sstevel@tonic-gate bestm && m->plug->max_ssf <= bestssf) {
872*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
873*7c478bd9Sstevel@tonic-gate
874*7c478bd9Sstevel@tonic-gate /* this mechanism isn't our favorite, and it's no better
875*7c478bd9Sstevel@tonic-gate than what we already have! */
876*7c478bd9Sstevel@tonic-gate break;
877*7c478bd9Sstevel@tonic-gate }
878*7c478bd9Sstevel@tonic-gate #else
879*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
880*7c478bd9Sstevel@tonic-gate if (bestm && m->sun_reg && m->plug->max_ssf <= bestssf) {
881*7c478bd9Sstevel@tonic-gate #else
882*7c478bd9Sstevel@tonic-gate
883*7c478bd9Sstevel@tonic-gate if (bestm && m->plug->max_ssf <= bestssf) {
884*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
885*7c478bd9Sstevel@tonic-gate
886*7c478bd9Sstevel@tonic-gate /* this mechanism is no better than what we already have! */
887*7c478bd9Sstevel@tonic-gate break;
888*7c478bd9Sstevel@tonic-gate }
889*7c478bd9Sstevel@tonic-gate #endif
890*7c478bd9Sstevel@tonic-gate
891*7c478bd9Sstevel@tonic-gate /* compare security flags, only take new mechanism if it has
892*7c478bd9Sstevel@tonic-gate * all the security flags of the previous one.
893*7c478bd9Sstevel@tonic-gate *
894*7c478bd9Sstevel@tonic-gate * From the mechanisms we ship with, this yields the order:
895*7c478bd9Sstevel@tonic-gate *
896*7c478bd9Sstevel@tonic-gate * SRP
897*7c478bd9Sstevel@tonic-gate * GSSAPI + KERBEROS_V4
898*7c478bd9Sstevel@tonic-gate * DIGEST + OTP
899*7c478bd9Sstevel@tonic-gate * CRAM + EXTERNAL
900*7c478bd9Sstevel@tonic-gate * PLAIN + LOGIN + ANONYMOUS
901*7c478bd9Sstevel@tonic-gate *
902*7c478bd9Sstevel@tonic-gate * This might be improved on by comparing the numeric value of
903*7c478bd9Sstevel@tonic-gate * the bitwise-or'd security flags, which splits DIGEST/OTP,
904*7c478bd9Sstevel@tonic-gate * CRAM/EXTERNAL, and PLAIN/LOGIN from ANONYMOUS, but then we
905*7c478bd9Sstevel@tonic-gate * are depending on the numeric values of the flags (which may
906*7c478bd9Sstevel@tonic-gate * change, and their ordering could be considered dumb luck.
907*7c478bd9Sstevel@tonic-gate */
908*7c478bd9Sstevel@tonic-gate
909*7c478bd9Sstevel@tonic-gate if (bestm &&
910*7c478bd9Sstevel@tonic-gate ((m->plug->security_flags ^ bestm->plug->security_flags) &
911*7c478bd9Sstevel@tonic-gate bestm->plug->security_flags)) {
912*7c478bd9Sstevel@tonic-gate break;
913*7c478bd9Sstevel@tonic-gate }
914*7c478bd9Sstevel@tonic-gate
915*7c478bd9Sstevel@tonic-gate if (mech) {
916*7c478bd9Sstevel@tonic-gate *mech = m->plug->mech_name;
917*7c478bd9Sstevel@tonic-gate }
918*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
919*7c478bd9Sstevel@tonic-gate bestssf = m->sun_reg ? m->plug->max_ssf : 0;
920*7c478bd9Sstevel@tonic-gate #else
921*7c478bd9Sstevel@tonic-gate bestssf = m->plug->max_ssf;
922*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
923*7c478bd9Sstevel@tonic-gate bestm = m;
924*7c478bd9Sstevel@tonic-gate break;
925*7c478bd9Sstevel@tonic-gate }
926*7c478bd9Sstevel@tonic-gate }
927*7c478bd9Sstevel@tonic-gate
928*7c478bd9Sstevel@tonic-gate if (bestm == NULL) {
929*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
930*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, gettext("No worthy mechs found"));
931*7c478bd9Sstevel@tonic-gate #else
932*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "No worthy mechs found");
933*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
934*7c478bd9Sstevel@tonic-gate result = SASL_NOMECH;
935*7c478bd9Sstevel@tonic-gate goto done;
936*7c478bd9Sstevel@tonic-gate }
937*7c478bd9Sstevel@tonic-gate
938*7c478bd9Sstevel@tonic-gate /* make (the rest of) cparams */
939*7c478bd9Sstevel@tonic-gate c_conn->cparams->service = conn->service;
940*7c478bd9Sstevel@tonic-gate c_conn->cparams->servicelen = strlen(conn->service);
941*7c478bd9Sstevel@tonic-gate
942*7c478bd9Sstevel@tonic-gate c_conn->cparams->serverFQDN = conn->serverFQDN;
943*7c478bd9Sstevel@tonic-gate c_conn->cparams->slen = strlen(conn->serverFQDN);
944*7c478bd9Sstevel@tonic-gate
945*7c478bd9Sstevel@tonic-gate c_conn->cparams->clientFQDN = c_conn->clientFQDN;
946*7c478bd9Sstevel@tonic-gate c_conn->cparams->clen = strlen(c_conn->clientFQDN);
947*7c478bd9Sstevel@tonic-gate
948*7c478bd9Sstevel@tonic-gate c_conn->cparams->external_ssf = conn->external.ssf;
949*7c478bd9Sstevel@tonic-gate c_conn->cparams->props = conn->props;
950*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
951*7c478bd9Sstevel@tonic-gate if (!bestm->sun_reg) {
952*7c478bd9Sstevel@tonic-gate c_conn->cparams->props.min_ssf = 0;
953*7c478bd9Sstevel@tonic-gate c_conn->cparams->props.max_ssf = 0;
954*7c478bd9Sstevel@tonic-gate }
955*7c478bd9Sstevel@tonic-gate c_conn->base.sun_reg = bestm->sun_reg;
956*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
957*7c478bd9Sstevel@tonic-gate c_conn->mech = bestm;
958*7c478bd9Sstevel@tonic-gate
959*7c478bd9Sstevel@tonic-gate /* init that plugin */
960*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
961*7c478bd9Sstevel@tonic-gate result = c_conn->mech->plug->mech_new(c_conn->mech->glob_context,
962*7c478bd9Sstevel@tonic-gate #else
963*7c478bd9Sstevel@tonic-gate result = c_conn->mech->plug->mech_new(c_conn->mech->plug->glob_context,
964*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
965*7c478bd9Sstevel@tonic-gate c_conn->cparams,
966*7c478bd9Sstevel@tonic-gate &(conn->context));
967*7c478bd9Sstevel@tonic-gate if(result != SASL_OK) goto done;
968*7c478bd9Sstevel@tonic-gate
969*7c478bd9Sstevel@tonic-gate /* do a step -- but only if we can do a client-send-first */
970*7c478bd9Sstevel@tonic-gate dostep:
971*7c478bd9Sstevel@tonic-gate if(clientout) {
972*7c478bd9Sstevel@tonic-gate if(c_conn->mech->plug->features & SASL_FEAT_SERVER_FIRST) {
973*7c478bd9Sstevel@tonic-gate *clientout = NULL;
974*7c478bd9Sstevel@tonic-gate *clientoutlen = 0;
975*7c478bd9Sstevel@tonic-gate result = SASL_CONTINUE;
976*7c478bd9Sstevel@tonic-gate } else {
977*7c478bd9Sstevel@tonic-gate result = sasl_client_step(conn, NULL, 0, prompt_need,
978*7c478bd9Sstevel@tonic-gate clientout, clientoutlen);
979*7c478bd9Sstevel@tonic-gate }
980*7c478bd9Sstevel@tonic-gate }
981*7c478bd9Sstevel@tonic-gate else
982*7c478bd9Sstevel@tonic-gate result = SASL_CONTINUE;
983*7c478bd9Sstevel@tonic-gate
984*7c478bd9Sstevel@tonic-gate done:
985*7c478bd9Sstevel@tonic-gate RETURN(conn, result);
986*7c478bd9Sstevel@tonic-gate }
987*7c478bd9Sstevel@tonic-gate
988*7c478bd9Sstevel@tonic-gate /* do a single authentication step.
989*7c478bd9Sstevel@tonic-gate * serverin -- the server message received by the client, MUST have a NUL
990*7c478bd9Sstevel@tonic-gate * sentinel, not counted by serverinlen
991*7c478bd9Sstevel@tonic-gate * output:
992*7c478bd9Sstevel@tonic-gate * prompt_need -- on SASL_INTERACT, list of prompts needed to continue
993*7c478bd9Sstevel@tonic-gate * clientout -- the client response to send to the server
994*7c478bd9Sstevel@tonic-gate *
995*7c478bd9Sstevel@tonic-gate * returns:
996*7c478bd9Sstevel@tonic-gate * SASL_OK -- success
997*7c478bd9Sstevel@tonic-gate * SASL_INTERACT -- user interaction needed to fill in prompt_need list
998*7c478bd9Sstevel@tonic-gate * SASL_BADPROT -- server protocol incorrect/cancelled
999*7c478bd9Sstevel@tonic-gate * SASL_BADSERV -- server failed mutual auth
1000*7c478bd9Sstevel@tonic-gate */
1001*7c478bd9Sstevel@tonic-gate
1002*7c478bd9Sstevel@tonic-gate int sasl_client_step(sasl_conn_t *conn,
1003*7c478bd9Sstevel@tonic-gate const char *serverin,
1004*7c478bd9Sstevel@tonic-gate unsigned serverinlen,
1005*7c478bd9Sstevel@tonic-gate sasl_interact_t **prompt_need,
1006*7c478bd9Sstevel@tonic-gate const char **clientout,
1007*7c478bd9Sstevel@tonic-gate unsigned *clientoutlen)
1008*7c478bd9Sstevel@tonic-gate {
1009*7c478bd9Sstevel@tonic-gate sasl_client_conn_t *c_conn= (sasl_client_conn_t *) conn;
1010*7c478bd9Sstevel@tonic-gate int result;
1011*7c478bd9Sstevel@tonic-gate
1012*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1013*7c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = (conn == NULL) ?
1014*7c478bd9Sstevel@tonic-gate _sasl_gbl_ctx() : conn->gctx;
1015*7c478bd9Sstevel@tonic-gate
1016*7c478bd9Sstevel@tonic-gate if(gctx->sasl_client_active==0) return SASL_NOTINIT;
1017*7c478bd9Sstevel@tonic-gate #else
1018*7c478bd9Sstevel@tonic-gate if(_sasl_client_active==0) return SASL_NOTINIT;
1019*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1020*7c478bd9Sstevel@tonic-gate if(!conn) return SASL_BADPARAM;
1021*7c478bd9Sstevel@tonic-gate
1022*7c478bd9Sstevel@tonic-gate /* check parameters */
1023*7c478bd9Sstevel@tonic-gate if ((serverin==NULL) && (serverinlen>0))
1024*7c478bd9Sstevel@tonic-gate PARAMERROR(conn);
1025*7c478bd9Sstevel@tonic-gate
1026*7c478bd9Sstevel@tonic-gate /* Don't do another step if the plugin told us that we're done */
1027*7c478bd9Sstevel@tonic-gate if (conn->oparams.doneflag) {
1028*7c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, "attempting client step after doneflag");
1029*7c478bd9Sstevel@tonic-gate return SASL_FAIL;
1030*7c478bd9Sstevel@tonic-gate }
1031*7c478bd9Sstevel@tonic-gate
1032*7c478bd9Sstevel@tonic-gate if(clientout) *clientout = NULL;
1033*7c478bd9Sstevel@tonic-gate if(clientoutlen) *clientoutlen = 0;
1034*7c478bd9Sstevel@tonic-gate
1035*7c478bd9Sstevel@tonic-gate /* do a step */
1036*7c478bd9Sstevel@tonic-gate result = c_conn->mech->plug->mech_step(conn->context,
1037*7c478bd9Sstevel@tonic-gate c_conn->cparams,
1038*7c478bd9Sstevel@tonic-gate serverin,
1039*7c478bd9Sstevel@tonic-gate serverinlen,
1040*7c478bd9Sstevel@tonic-gate prompt_need,
1041*7c478bd9Sstevel@tonic-gate clientout, clientoutlen,
1042*7c478bd9Sstevel@tonic-gate &conn->oparams);
1043*7c478bd9Sstevel@tonic-gate
1044*7c478bd9Sstevel@tonic-gate if (result == SASL_OK) {
1045*7c478bd9Sstevel@tonic-gate /* So we're done on this end, but if both
1046*7c478bd9Sstevel@tonic-gate * 1. the mech does server-send-last
1047*7c478bd9Sstevel@tonic-gate * 2. the protocol does not
1048*7c478bd9Sstevel@tonic-gate * we need to return no data */
1049*7c478bd9Sstevel@tonic-gate if(!*clientout && !(conn->flags & SASL_SUCCESS_DATA)) {
1050*7c478bd9Sstevel@tonic-gate *clientout = "";
1051*7c478bd9Sstevel@tonic-gate *clientoutlen = 0;
1052*7c478bd9Sstevel@tonic-gate }
1053*7c478bd9Sstevel@tonic-gate
1054*7c478bd9Sstevel@tonic-gate if(!conn->oparams.maxoutbuf) {
1055*7c478bd9Sstevel@tonic-gate conn->oparams.maxoutbuf = conn->props.maxbufsize;
1056*7c478bd9Sstevel@tonic-gate }
1057*7c478bd9Sstevel@tonic-gate
1058*7c478bd9Sstevel@tonic-gate if(conn->oparams.user == NULL || conn->oparams.authid == NULL) {
1059*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1060*7c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR,
1061*7c478bd9Sstevel@tonic-gate "mech did not call canon_user for both authzid and authid");
1062*7c478bd9Sstevel@tonic-gate #else
1063*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0,
1064*7c478bd9Sstevel@tonic-gate "mech did not call canon_user for both authzid and authid");
1065*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1066*7c478bd9Sstevel@tonic-gate result = SASL_BADPROT;
1067*7c478bd9Sstevel@tonic-gate }
1068*7c478bd9Sstevel@tonic-gate }
1069*7c478bd9Sstevel@tonic-gate
1070*7c478bd9Sstevel@tonic-gate RETURN(conn,result);
1071*7c478bd9Sstevel@tonic-gate }
1072*7c478bd9Sstevel@tonic-gate
1073*7c478bd9Sstevel@tonic-gate /* returns the length of all the mechanisms
1074*7c478bd9Sstevel@tonic-gate * added up
1075*7c478bd9Sstevel@tonic-gate */
1076*7c478bd9Sstevel@tonic-gate
1077*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1078*7c478bd9Sstevel@tonic-gate static unsigned mech_names_len(_sasl_global_context_t *gctx)
1079*7c478bd9Sstevel@tonic-gate {
1080*7c478bd9Sstevel@tonic-gate cmech_list_t *cmechlist = gctx->cmechlist;
1081*7c478bd9Sstevel@tonic-gate #else
1082*7c478bd9Sstevel@tonic-gate static unsigned mech_names_len()
1083*7c478bd9Sstevel@tonic-gate {
1084*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1085*7c478bd9Sstevel@tonic-gate cmechanism_t *listptr;
1086*7c478bd9Sstevel@tonic-gate unsigned result = 0;
1087*7c478bd9Sstevel@tonic-gate
1088*7c478bd9Sstevel@tonic-gate for (listptr = cmechlist->mech_list;
1089*7c478bd9Sstevel@tonic-gate listptr;
1090*7c478bd9Sstevel@tonic-gate listptr = listptr->next)
1091*7c478bd9Sstevel@tonic-gate result += strlen(listptr->plug->mech_name);
1092*7c478bd9Sstevel@tonic-gate
1093*7c478bd9Sstevel@tonic-gate return result;
1094*7c478bd9Sstevel@tonic-gate }
1095*7c478bd9Sstevel@tonic-gate
1096*7c478bd9Sstevel@tonic-gate
1097*7c478bd9Sstevel@tonic-gate int _sasl_client_listmech(sasl_conn_t *conn,
1098*7c478bd9Sstevel@tonic-gate const char *prefix,
1099*7c478bd9Sstevel@tonic-gate const char *sep,
1100*7c478bd9Sstevel@tonic-gate const char *suffix,
1101*7c478bd9Sstevel@tonic-gate const char **result,
1102*7c478bd9Sstevel@tonic-gate unsigned *plen,
1103*7c478bd9Sstevel@tonic-gate int *pcount)
1104*7c478bd9Sstevel@tonic-gate {
1105*7c478bd9Sstevel@tonic-gate cmechanism_t *m=NULL;
1106*7c478bd9Sstevel@tonic-gate sasl_ssf_t minssf = 0;
1107*7c478bd9Sstevel@tonic-gate int ret;
1108*7c478bd9Sstevel@tonic-gate unsigned int resultlen;
1109*7c478bd9Sstevel@tonic-gate int flag;
1110*7c478bd9Sstevel@tonic-gate const char *mysep;
1111*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1112*7c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = conn == NULL ? _sasl_gbl_ctx() : conn->gctx;
1113*7c478bd9Sstevel@tonic-gate cmech_list_t *cmechlist;
1114*7c478bd9Sstevel@tonic-gate
1115*7c478bd9Sstevel@tonic-gate if(gctx->sasl_client_active==0) return SASL_NOTINIT;
1116*7c478bd9Sstevel@tonic-gate cmechlist = gctx->cmechlist;
1117*7c478bd9Sstevel@tonic-gate #else
1118*7c478bd9Sstevel@tonic-gate if(_sasl_client_active == 0) return SASL_NOTINIT;
1119*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1120*7c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM;
1121*7c478bd9Sstevel@tonic-gate if(conn->type != SASL_CONN_CLIENT) PARAMERROR(conn);
1122*7c478bd9Sstevel@tonic-gate
1123*7c478bd9Sstevel@tonic-gate if (! result)
1124*7c478bd9Sstevel@tonic-gate PARAMERROR(conn);
1125*7c478bd9Sstevel@tonic-gate
1126*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1127*7c478bd9Sstevel@tonic-gate (void) _load_client_plugins(gctx);
1128*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1129*7c478bd9Sstevel@tonic-gate
1130*7c478bd9Sstevel@tonic-gate if (plen != NULL)
1131*7c478bd9Sstevel@tonic-gate *plen = 0;
1132*7c478bd9Sstevel@tonic-gate if (pcount != NULL)
1133*7c478bd9Sstevel@tonic-gate *pcount = 0;
1134*7c478bd9Sstevel@tonic-gate
1135*7c478bd9Sstevel@tonic-gate if (sep) {
1136*7c478bd9Sstevel@tonic-gate mysep = sep;
1137*7c478bd9Sstevel@tonic-gate } else {
1138*7c478bd9Sstevel@tonic-gate mysep = " ";
1139*7c478bd9Sstevel@tonic-gate }
1140*7c478bd9Sstevel@tonic-gate
1141*7c478bd9Sstevel@tonic-gate if(conn->props.min_ssf < conn->external.ssf) {
1142*7c478bd9Sstevel@tonic-gate minssf = 0;
1143*7c478bd9Sstevel@tonic-gate } else {
1144*7c478bd9Sstevel@tonic-gate minssf = conn->props.min_ssf - conn->external.ssf;
1145*7c478bd9Sstevel@tonic-gate }
1146*7c478bd9Sstevel@tonic-gate
1147*7c478bd9Sstevel@tonic-gate if (! cmechlist || cmechlist->mech_length <= 0)
1148*7c478bd9Sstevel@tonic-gate INTERROR(conn, SASL_NOMECH);
1149*7c478bd9Sstevel@tonic-gate
1150*7c478bd9Sstevel@tonic-gate resultlen = (prefix ? strlen(prefix) : 0)
1151*7c478bd9Sstevel@tonic-gate + (strlen(mysep) * (cmechlist->mech_length - 1))
1152*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1153*7c478bd9Sstevel@tonic-gate + mech_names_len(gctx)
1154*7c478bd9Sstevel@tonic-gate #else
1155*7c478bd9Sstevel@tonic-gate + mech_names_len()
1156*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1157*7c478bd9Sstevel@tonic-gate + (suffix ? strlen(suffix) : 0)
1158*7c478bd9Sstevel@tonic-gate + 1;
1159*7c478bd9Sstevel@tonic-gate ret = _buf_alloc(&conn->mechlist_buf,
1160*7c478bd9Sstevel@tonic-gate &conn->mechlist_buf_len, resultlen);
1161*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) MEMERROR(conn);
1162*7c478bd9Sstevel@tonic-gate
1163*7c478bd9Sstevel@tonic-gate if (prefix)
1164*7c478bd9Sstevel@tonic-gate strcpy (conn->mechlist_buf,prefix);
1165*7c478bd9Sstevel@tonic-gate else
1166*7c478bd9Sstevel@tonic-gate *(conn->mechlist_buf) = '\0';
1167*7c478bd9Sstevel@tonic-gate
1168*7c478bd9Sstevel@tonic-gate flag = 0;
1169*7c478bd9Sstevel@tonic-gate for (m = cmechlist->mech_list; m != NULL; m = m->next) {
1170*7c478bd9Sstevel@tonic-gate /* do we have the prompts for it? */
1171*7c478bd9Sstevel@tonic-gate if (!have_prompts(conn, m->plug))
1172*7c478bd9Sstevel@tonic-gate continue;
1173*7c478bd9Sstevel@tonic-gate
1174*7c478bd9Sstevel@tonic-gate /* is it strong enough? */
1175*7c478bd9Sstevel@tonic-gate if (minssf > m->plug->max_ssf)
1176*7c478bd9Sstevel@tonic-gate continue;
1177*7c478bd9Sstevel@tonic-gate
1178*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1179*7c478bd9Sstevel@tonic-gate /* If not SUN supplied mech, it has no strength */
1180*7c478bd9Sstevel@tonic-gate if (minssf > 0 && !m->sun_reg)
1181*7c478bd9Sstevel@tonic-gate continue;
1182*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1183*7c478bd9Sstevel@tonic-gate
1184*7c478bd9Sstevel@tonic-gate /* does it meet our security properties? */
1185*7c478bd9Sstevel@tonic-gate if (((conn->props.security_flags ^ m->plug->security_flags)
1186*7c478bd9Sstevel@tonic-gate & conn->props.security_flags) != 0) {
1187*7c478bd9Sstevel@tonic-gate continue;
1188*7c478bd9Sstevel@tonic-gate }
1189*7c478bd9Sstevel@tonic-gate
1190*7c478bd9Sstevel@tonic-gate /* Can we meet it's features? */
1191*7c478bd9Sstevel@tonic-gate if ((m->plug->features & SASL_FEAT_NEEDSERVERFQDN)
1192*7c478bd9Sstevel@tonic-gate && !conn->serverFQDN) {
1193*7c478bd9Sstevel@tonic-gate continue;
1194*7c478bd9Sstevel@tonic-gate }
1195*7c478bd9Sstevel@tonic-gate
1196*7c478bd9Sstevel@tonic-gate /* Can it meet our features? */
1197*7c478bd9Sstevel@tonic-gate if ((conn->flags & SASL_NEED_PROXY) &&
1198*7c478bd9Sstevel@tonic-gate !(m->plug->features & SASL_FEAT_ALLOWS_PROXY)) {
1199*7c478bd9Sstevel@tonic-gate break;
1200*7c478bd9Sstevel@tonic-gate }
1201*7c478bd9Sstevel@tonic-gate
1202*7c478bd9Sstevel@tonic-gate /* Okay, we like it, add it to the list! */
1203*7c478bd9Sstevel@tonic-gate
1204*7c478bd9Sstevel@tonic-gate if (pcount != NULL)
1205*7c478bd9Sstevel@tonic-gate (*pcount)++;
1206*7c478bd9Sstevel@tonic-gate
1207*7c478bd9Sstevel@tonic-gate /* print seperator */
1208*7c478bd9Sstevel@tonic-gate if (flag) {
1209*7c478bd9Sstevel@tonic-gate strcat(conn->mechlist_buf, mysep);
1210*7c478bd9Sstevel@tonic-gate } else {
1211*7c478bd9Sstevel@tonic-gate flag = 1;
1212*7c478bd9Sstevel@tonic-gate }
1213*7c478bd9Sstevel@tonic-gate
1214*7c478bd9Sstevel@tonic-gate /* now print the mechanism name */
1215*7c478bd9Sstevel@tonic-gate strcat(conn->mechlist_buf, m->plug->mech_name);
1216*7c478bd9Sstevel@tonic-gate }
1217*7c478bd9Sstevel@tonic-gate
1218*7c478bd9Sstevel@tonic-gate if (suffix)
1219*7c478bd9Sstevel@tonic-gate strcat(conn->mechlist_buf,suffix);
1220*7c478bd9Sstevel@tonic-gate
1221*7c478bd9Sstevel@tonic-gate if (plen!=NULL)
1222*7c478bd9Sstevel@tonic-gate *plen=strlen(conn->mechlist_buf);
1223*7c478bd9Sstevel@tonic-gate
1224*7c478bd9Sstevel@tonic-gate *result = conn->mechlist_buf;
1225*7c478bd9Sstevel@tonic-gate
1226*7c478bd9Sstevel@tonic-gate return SASL_OK;
1227*7c478bd9Sstevel@tonic-gate }
1228*7c478bd9Sstevel@tonic-gate
1229*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1230*7c478bd9Sstevel@tonic-gate sasl_string_list_t *_sasl_client_mechs(_sasl_global_context_t *gctx)
1231*7c478bd9Sstevel@tonic-gate {
1232*7c478bd9Sstevel@tonic-gate cmech_list_t *cmechlist = gctx->cmechlist;
1233*7c478bd9Sstevel@tonic-gate #else
1234*7c478bd9Sstevel@tonic-gate sasl_string_list_t *_sasl_client_mechs(void)
1235*7c478bd9Sstevel@tonic-gate {
1236*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1237*7c478bd9Sstevel@tonic-gate cmechanism_t *listptr;
1238*7c478bd9Sstevel@tonic-gate sasl_string_list_t *retval = NULL, *next=NULL;
1239*7c478bd9Sstevel@tonic-gate
1240*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1241*7c478bd9Sstevel@tonic-gate if(!gctx->sasl_client_active) return NULL;
1242*7c478bd9Sstevel@tonic-gate #else
1243*7c478bd9Sstevel@tonic-gate if(!_sasl_client_active) return NULL;
1244*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1245*7c478bd9Sstevel@tonic-gate
1246*7c478bd9Sstevel@tonic-gate /* make list */
1247*7c478bd9Sstevel@tonic-gate for (listptr = cmechlist->mech_list; listptr; listptr = listptr->next) {
1248*7c478bd9Sstevel@tonic-gate next = sasl_ALLOC(sizeof(sasl_string_list_t));
1249*7c478bd9Sstevel@tonic-gate
1250*7c478bd9Sstevel@tonic-gate if(!next && !retval) return NULL;
1251*7c478bd9Sstevel@tonic-gate else if(!next) {
1252*7c478bd9Sstevel@tonic-gate next = retval->next;
1253*7c478bd9Sstevel@tonic-gate do {
1254*7c478bd9Sstevel@tonic-gate sasl_FREE(retval);
1255*7c478bd9Sstevel@tonic-gate retval = next;
1256*7c478bd9Sstevel@tonic-gate next = retval->next;
1257*7c478bd9Sstevel@tonic-gate } while(next);
1258*7c478bd9Sstevel@tonic-gate return NULL;
1259*7c478bd9Sstevel@tonic-gate }
1260*7c478bd9Sstevel@tonic-gate
1261*7c478bd9Sstevel@tonic-gate next->d = listptr->plug->mech_name;
1262*7c478bd9Sstevel@tonic-gate
1263*7c478bd9Sstevel@tonic-gate if(!retval) {
1264*7c478bd9Sstevel@tonic-gate next->next = NULL;
1265*7c478bd9Sstevel@tonic-gate retval = next;
1266*7c478bd9Sstevel@tonic-gate } else {
1267*7c478bd9Sstevel@tonic-gate next->next = retval;
1268*7c478bd9Sstevel@tonic-gate retval = next;
1269*7c478bd9Sstevel@tonic-gate }
1270*7c478bd9Sstevel@tonic-gate }
1271*7c478bd9Sstevel@tonic-gate
1272*7c478bd9Sstevel@tonic-gate return retval;
1273*7c478bd9Sstevel@tonic-gate }
1274