xref: /illumos-gate/usr/src/lib/libsasl/lib/server.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
6*7c478bd9Sstevel@tonic-gate 
7*7c478bd9Sstevel@tonic-gate /* SASL server API implementation
8*7c478bd9Sstevel@tonic-gate  * Rob Siemborski
9*7c478bd9Sstevel@tonic-gate  * Tim Martin
10*7c478bd9Sstevel@tonic-gate  * $Id: server.c,v 1.123 2003/04/16 19:36:01 rjs3 Exp $
11*7c478bd9Sstevel@tonic-gate  */
12*7c478bd9Sstevel@tonic-gate /*
13*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
14*7c478bd9Sstevel@tonic-gate  *
15*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
16*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
17*7c478bd9Sstevel@tonic-gate  * are met:
18*7c478bd9Sstevel@tonic-gate  *
19*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
20*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
21*7c478bd9Sstevel@tonic-gate  *
22*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
23*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
24*7c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
25*7c478bd9Sstevel@tonic-gate  *    distribution.
26*7c478bd9Sstevel@tonic-gate  *
27*7c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
28*7c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
29*7c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
30*7c478bd9Sstevel@tonic-gate  *    details, please contact
31*7c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
32*7c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
33*7c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
34*7c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
35*7c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
36*7c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
37*7c478bd9Sstevel@tonic-gate  *
38*7c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
39*7c478bd9Sstevel@tonic-gate  *    acknowledgment:
40*7c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
41*7c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
42*7c478bd9Sstevel@tonic-gate  *
43*7c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
44*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
45*7c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
46*7c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
47*7c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
48*7c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
49*7c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
50*7c478bd9Sstevel@tonic-gate  */
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate /* local functions/structs don't start with sasl
53*7c478bd9Sstevel@tonic-gate  */
54*7c478bd9Sstevel@tonic-gate #include <config.h>
55*7c478bd9Sstevel@tonic-gate #include <errno.h>
56*7c478bd9Sstevel@tonic-gate #include <stdio.h>
57*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
58*7c478bd9Sstevel@tonic-gate #include <limits.h>
59*7c478bd9Sstevel@tonic-gate #ifndef macintosh
60*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
62*7c478bd9Sstevel@tonic-gate #endif
63*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
64*7c478bd9Sstevel@tonic-gate #include <string.h>
65*7c478bd9Sstevel@tonic-gate #include <ctype.h>
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate #include "sasl.h"
68*7c478bd9Sstevel@tonic-gate #include "saslint.h"
69*7c478bd9Sstevel@tonic-gate #include "saslplug.h"
70*7c478bd9Sstevel@tonic-gate #include "saslutil.h"
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
73*7c478bd9Sstevel@tonic-gate #ifdef sun
74*7c478bd9Sstevel@tonic-gate /* gotta define gethostname ourselves on suns */
75*7c478bd9Sstevel@tonic-gate extern int gethostname(char *, int);
76*7c478bd9Sstevel@tonic-gate #endif
77*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate #define DEFAULT_CHECKPASS_MECH "auxprop"
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /* Contains functions:
82*7c478bd9Sstevel@tonic-gate  *
83*7c478bd9Sstevel@tonic-gate  * sasl_server_init
84*7c478bd9Sstevel@tonic-gate  * sasl_server_new
85*7c478bd9Sstevel@tonic-gate  * sasl_listmech
86*7c478bd9Sstevel@tonic-gate  * sasl_server_start
87*7c478bd9Sstevel@tonic-gate  * sasl_server_step
88*7c478bd9Sstevel@tonic-gate  * sasl_checkpass
89*7c478bd9Sstevel@tonic-gate  * sasl_checkapop
90*7c478bd9Sstevel@tonic-gate  * sasl_user_exists
91*7c478bd9Sstevel@tonic-gate  * sasl_setpass
92*7c478bd9Sstevel@tonic-gate  */
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
95*7c478bd9Sstevel@tonic-gate int _is_sasl_server_active(_sasl_global_context_t *gctx)
96*7c478bd9Sstevel@tonic-gate {
97*7c478bd9Sstevel@tonic-gate     return gctx->sasl_server_active;
98*7c478bd9Sstevel@tonic-gate }
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(init_server_mutex);
101*7c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(server_active_mutex);
102*7c478bd9Sstevel@tonic-gate /*
103*7c478bd9Sstevel@tonic-gate  * server_plug_mutex ensures only one server plugin is init'ed at a time
104*7c478bd9Sstevel@tonic-gate  * If a plugin is loaded more than once, the glob_context may be overwritten
105*7c478bd9Sstevel@tonic-gate  * which may lead to a memory leak. We keep glob_context with each mech
106*7c478bd9Sstevel@tonic-gate  * to avoid this problem.
107*7c478bd9Sstevel@tonic-gate  */
108*7c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(server_plug_mutex);
109*7c478bd9Sstevel@tonic-gate #else
110*7c478bd9Sstevel@tonic-gate /* if we've initialized the server sucessfully */
111*7c478bd9Sstevel@tonic-gate static int _sasl_server_active = 0;
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate /* For access by other modules */
114*7c478bd9Sstevel@tonic-gate int _is_sasl_server_active(void) { return _sasl_server_active; }
115*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate static int _sasl_checkpass(sasl_conn_t *conn,
118*7c478bd9Sstevel@tonic-gate 			   const char *user, unsigned userlen,
119*7c478bd9Sstevel@tonic-gate 			   const char *pass, unsigned passlen);
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
122*7c478bd9Sstevel@tonic-gate static mech_list_t *mechlist = NULL; /* global var which holds the list */
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate static sasl_global_callbacks_t global_callbacks;
125*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate /* set the password for a user
128*7c478bd9Sstevel@tonic-gate  *  conn        -- SASL connection
129*7c478bd9Sstevel@tonic-gate  *  user        -- user name
130*7c478bd9Sstevel@tonic-gate  *  pass        -- plaintext password, may be NULL to remove user
131*7c478bd9Sstevel@tonic-gate  *  passlen     -- length of password, 0 = strlen(pass)
132*7c478bd9Sstevel@tonic-gate  *  oldpass     -- NULL will sometimes work
133*7c478bd9Sstevel@tonic-gate  *  oldpasslen  -- length of password, 0 = strlen(oldpass)
134*7c478bd9Sstevel@tonic-gate  *  flags       -- see flags below
135*7c478bd9Sstevel@tonic-gate  *
136*7c478bd9Sstevel@tonic-gate  * returns:
137*7c478bd9Sstevel@tonic-gate  *  SASL_NOCHANGE  -- proper entry already exists
138*7c478bd9Sstevel@tonic-gate  *  SASL_NOMECH    -- no authdb supports password setting as configured
139*7c478bd9Sstevel@tonic-gate  *  SASL_NOVERIFY  -- user exists, but no settable password present
140*7c478bd9Sstevel@tonic-gate  *  SASL_DISABLED  -- account disabled
141*7c478bd9Sstevel@tonic-gate  *  SASL_PWLOCK    -- password locked
142*7c478bd9Sstevel@tonic-gate  *  SASL_WEAKPASS  -- password too weak for security policy
143*7c478bd9Sstevel@tonic-gate  *  SASL_NOUSERPASS -- user-supplied passwords not permitted
144*7c478bd9Sstevel@tonic-gate  *  SASL_FAIL      -- OS error
145*7c478bd9Sstevel@tonic-gate  *  SASL_BADPARAM  -- password too long
146*7c478bd9Sstevel@tonic-gate  *  SASL_OK        -- successful
147*7c478bd9Sstevel@tonic-gate  */
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate int sasl_setpass(sasl_conn_t *conn,
150*7c478bd9Sstevel@tonic-gate 		 const char *user,
151*7c478bd9Sstevel@tonic-gate 		 const char *pass, unsigned passlen,
152*7c478bd9Sstevel@tonic-gate 		 const char *oldpass,
153*7c478bd9Sstevel@tonic-gate 		 unsigned oldpasslen,
154*7c478bd9Sstevel@tonic-gate 		 unsigned flags)
155*7c478bd9Sstevel@tonic-gate {
156*7c478bd9Sstevel@tonic-gate     int result=SASL_OK, tmpresult;
157*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;
158*7c478bd9Sstevel@tonic-gate     sasl_server_userdb_setpass_t *setpass_cb = NULL;
159*7c478bd9Sstevel@tonic-gate     void *context = NULL;
160*7c478bd9Sstevel@tonic-gate     mechanism_t *m;
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
163*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx =
164*7c478bd9Sstevel@tonic-gate 		 (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
165*7c478bd9Sstevel@tonic-gate     mech_list_t *mechlist = gctx == NULL ? NULL : gctx->mechlist;
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate     if (!gctx->sasl_server_active || !mechlist) return SASL_NOTINIT;
168*7c478bd9Sstevel@tonic-gate #else
169*7c478bd9Sstevel@tonic-gate     if (!_sasl_server_active || !mechlist) return SASL_NOTINIT;
170*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate     /* check params */
173*7c478bd9Sstevel@tonic-gate     if (!conn) return SASL_BADPARAM;
174*7c478bd9Sstevel@tonic-gate     if (conn->type != SASL_CONN_SERVER) PARAMERROR(conn);
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate     if ((!(flags & SASL_SET_DISABLE) && passlen == 0)
177*7c478bd9Sstevel@tonic-gate         || ((flags & SASL_SET_CREATE) && (flags & SASL_SET_DISABLE)))
178*7c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate     /* call userdb callback function */
181*7c478bd9Sstevel@tonic-gate     result = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_SETPASS,
182*7c478bd9Sstevel@tonic-gate 			       &setpass_cb, &context);
183*7c478bd9Sstevel@tonic-gate     if(result == SASL_OK && setpass_cb) {
184*7c478bd9Sstevel@tonic-gate 	tmpresult = setpass_cb(conn, context, user, pass, passlen,
185*7c478bd9Sstevel@tonic-gate 			    s_conn->sparams->propctx, flags);
186*7c478bd9Sstevel@tonic-gate 	if(tmpresult != SASL_OK) {
187*7c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_ERR,
188*7c478bd9Sstevel@tonic-gate 		      "setpass callback failed for %s: %z",
189*7c478bd9Sstevel@tonic-gate 		      user, tmpresult);
190*7c478bd9Sstevel@tonic-gate 	} else {
191*7c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_NOTE,
192*7c478bd9Sstevel@tonic-gate 		      "setpass callback succeeded for %s", user);
193*7c478bd9Sstevel@tonic-gate 	}
194*7c478bd9Sstevel@tonic-gate     } else {
195*7c478bd9Sstevel@tonic-gate 	result = SASL_OK;
196*7c478bd9Sstevel@tonic-gate     }
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate     /* now we let the mechanisms set their secrets */
199*7c478bd9Sstevel@tonic-gate     for (m = mechlist->mech_list; m; m = m->next) {
200*7c478bd9Sstevel@tonic-gate 	if (!m->plug->setpass) {
201*7c478bd9Sstevel@tonic-gate 	    /* can't set pass for this mech */
202*7c478bd9Sstevel@tonic-gate 	    continue;
203*7c478bd9Sstevel@tonic-gate 	}
204*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
205*7c478bd9Sstevel@tonic-gate 	tmpresult = m->plug->setpass(m->glob_context,
206*7c478bd9Sstevel@tonic-gate #else
207*7c478bd9Sstevel@tonic-gate 	tmpresult = m->plug->setpass(m->plug->glob_context,
208*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
209*7c478bd9Sstevel@tonic-gate 				     ((sasl_server_conn_t *)conn)->sparams,
210*7c478bd9Sstevel@tonic-gate 				     user,
211*7c478bd9Sstevel@tonic-gate 				     pass,
212*7c478bd9Sstevel@tonic-gate 				     passlen,
213*7c478bd9Sstevel@tonic-gate 				     oldpass, oldpasslen,
214*7c478bd9Sstevel@tonic-gate 				     flags);
215*7c478bd9Sstevel@tonic-gate 	if (tmpresult == SASL_OK) {
216*7c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_NOTE,
217*7c478bd9Sstevel@tonic-gate 		      "%s: set secret for %s", m->plug->mech_name, user);
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	    m->condition = SASL_OK; /* if we previously thought the
220*7c478bd9Sstevel@tonic-gate 				       mechanism didn't have any user secrets
221*7c478bd9Sstevel@tonic-gate 				       we now think it does */
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	} else if (tmpresult == SASL_NOCHANGE) {
224*7c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_NOTE,
225*7c478bd9Sstevel@tonic-gate 		      "%s: secret not changed for %s", m->plug->mech_name, user);
226*7c478bd9Sstevel@tonic-gate 	} else {
227*7c478bd9Sstevel@tonic-gate 	    result = tmpresult;
228*7c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_ERR,
229*7c478bd9Sstevel@tonic-gate 		      "%s: failed to set secret for %s: %z (%m)",
230*7c478bd9Sstevel@tonic-gate 		      m->plug->mech_name, user, tmpresult,
231*7c478bd9Sstevel@tonic-gate #ifndef WIN32
232*7c478bd9Sstevel@tonic-gate 		      errno
233*7c478bd9Sstevel@tonic-gate #else
234*7c478bd9Sstevel@tonic-gate 		      GetLastError()
235*7c478bd9Sstevel@tonic-gate #endif
236*7c478bd9Sstevel@tonic-gate 		      );
237*7c478bd9Sstevel@tonic-gate 	}
238*7c478bd9Sstevel@tonic-gate     }
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate     RETURN(conn, result);
241*7c478bd9Sstevel@tonic-gate }
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
244*7c478bd9Sstevel@tonic-gate static void
245*7c478bd9Sstevel@tonic-gate server_dispose_mech_contexts(sasl_conn_t *pconn)
246*7c478bd9Sstevel@tonic-gate {
247*7c478bd9Sstevel@tonic-gate   sasl_server_conn_t *s_conn=  (sasl_server_conn_t *) pconn;
248*7c478bd9Sstevel@tonic-gate   context_list_t *cur, *cur_next;
249*7c478bd9Sstevel@tonic-gate   _sasl_global_context_t *gctx = pconn->gctx;
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate   for(cur = s_conn->mech_contexts; cur; cur=cur_next) {
252*7c478bd9Sstevel@tonic-gate       cur_next = cur->next;
253*7c478bd9Sstevel@tonic-gate       if(cur->context)
254*7c478bd9Sstevel@tonic-gate 	  cur->mech->plug->mech_dispose(cur->context, s_conn->sparams->utils);
255*7c478bd9Sstevel@tonic-gate       sasl_FREE(cur);
256*7c478bd9Sstevel@tonic-gate   }
257*7c478bd9Sstevel@tonic-gate   s_conn->mech_contexts = NULL;
258*7c478bd9Sstevel@tonic-gate }
259*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate /* local mechanism which disposes of server */
262*7c478bd9Sstevel@tonic-gate static void server_dispose(sasl_conn_t *pconn)
263*7c478bd9Sstevel@tonic-gate {
264*7c478bd9Sstevel@tonic-gate   sasl_server_conn_t *s_conn=  (sasl_server_conn_t *) pconn;
265*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
266*7c478bd9Sstevel@tonic-gate   _sasl_global_context_t *gctx = pconn->gctx;
267*7c478bd9Sstevel@tonic-gate #else
268*7c478bd9Sstevel@tonic-gate   context_list_t *cur, *cur_next;
269*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate   if (s_conn->mech
272*7c478bd9Sstevel@tonic-gate       && s_conn->mech->plug->mech_dispose) {
273*7c478bd9Sstevel@tonic-gate     s_conn->mech->plug->mech_dispose(pconn->context,
274*7c478bd9Sstevel@tonic-gate 				     s_conn->sparams->utils);
275*7c478bd9Sstevel@tonic-gate   }
276*7c478bd9Sstevel@tonic-gate   pconn->context = NULL;
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
279*7c478bd9Sstevel@tonic-gate   server_dispose_mech_contexts(pconn);
280*7c478bd9Sstevel@tonic-gate #else
281*7c478bd9Sstevel@tonic-gate   for(cur = s_conn->mech_contexts; cur; cur=cur_next) {
282*7c478bd9Sstevel@tonic-gate       cur_next = cur->next;
283*7c478bd9Sstevel@tonic-gate       if(cur->context)
284*7c478bd9Sstevel@tonic-gate 	  cur->mech->plug->mech_dispose(cur->context, s_conn->sparams->utils);
285*7c478bd9Sstevel@tonic-gate       sasl_FREE(cur);
286*7c478bd9Sstevel@tonic-gate   }
287*7c478bd9Sstevel@tonic-gate   s_conn->mech_contexts = NULL;
288*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate   _sasl_free_utils(&s_conn->sparams->utils);
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate   if (s_conn->sparams->propctx)
293*7c478bd9Sstevel@tonic-gate       prop_dispose(&s_conn->sparams->propctx);
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate   if (s_conn->user_realm)
296*7c478bd9Sstevel@tonic-gate       sasl_FREE(s_conn->user_realm);
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate   if (s_conn->sparams)
299*7c478bd9Sstevel@tonic-gate       sasl_FREE(s_conn->sparams);
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate   _sasl_conn_dispose(pconn);
302*7c478bd9Sstevel@tonic-gate }
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
305*7c478bd9Sstevel@tonic-gate static int init_mechlist(_sasl_global_context_t *gctx)
306*7c478bd9Sstevel@tonic-gate {
307*7c478bd9Sstevel@tonic-gate     mech_list_t *mechlist = gctx->mechlist;
308*7c478bd9Sstevel@tonic-gate #else
309*7c478bd9Sstevel@tonic-gate static int init_mechlist(void)
310*7c478bd9Sstevel@tonic-gate {
311*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
312*7c478bd9Sstevel@tonic-gate     sasl_utils_t *newutils = NULL;
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate     mechlist->mutex = sasl_MUTEX_ALLOC();
315*7c478bd9Sstevel@tonic-gate     if(!mechlist->mutex) return SASL_FAIL;
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate     /* set util functions - need to do rest */
318*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
319*7c478bd9Sstevel@tonic-gate     newutils = _sasl_alloc_utils(gctx, NULL, &gctx->server_global_callbacks);
320*7c478bd9Sstevel@tonic-gate #else
321*7c478bd9Sstevel@tonic-gate     newutils = _sasl_alloc_utils(NULL, &global_callbacks);
322*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
323*7c478bd9Sstevel@tonic-gate     if (newutils == NULL)
324*7c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate     newutils->checkpass = &_sasl_checkpass;
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate     mechlist->utils = newutils;
329*7c478bd9Sstevel@tonic-gate     mechlist->mech_list=NULL;
330*7c478bd9Sstevel@tonic-gate     mechlist->mech_length=0;
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate     return SASL_OK;
333*7c478bd9Sstevel@tonic-gate }
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
336*7c478bd9Sstevel@tonic-gate static int load_mech(_sasl_global_context_t *gctx, const char *mechname)
337*7c478bd9Sstevel@tonic-gate {
338*7c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
339*7c478bd9Sstevel@tonic-gate     void *context;
340*7c478bd9Sstevel@tonic-gate     const char *mlist = NULL;
341*7c478bd9Sstevel@tonic-gate     const char *cp;
342*7c478bd9Sstevel@tonic-gate     size_t len;
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate     /* No sasl_conn_t was given to getcallback, so we provide the
345*7c478bd9Sstevel@tonic-gate      * global callbacks structure */
346*7c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(NULL, SASL_CB_GETOPT, &getopt, &context) == SASL_OK)
347*7c478bd9Sstevel@tonic-gate 	(void)getopt(&gctx->server_global_callbacks, NULL,
348*7c478bd9Sstevel@tonic-gate 		"server_load_mech_list", &mlist, NULL);
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate     if (mlist == NULL)
351*7c478bd9Sstevel@tonic-gate 	return (1);
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate     len = strlen(mechname);
354*7c478bd9Sstevel@tonic-gate     while (*mlist && isspace((int) *mlist)) mlist++;
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate     while (*mlist) {
357*7c478bd9Sstevel@tonic-gate 	for (cp = mlist; *cp && !isspace((int) *cp); cp++);
358*7c478bd9Sstevel@tonic-gate 	if (((size_t) (cp - mlist) == len) &&
359*7c478bd9Sstevel@tonic-gate 		!strncasecmp(mlist, mechname, len))
360*7c478bd9Sstevel@tonic-gate 	    break;
361*7c478bd9Sstevel@tonic-gate 	mlist = cp;
362*7c478bd9Sstevel@tonic-gate 	while (*mlist && isspace((int) *mlist)) mlist++;
363*7c478bd9Sstevel@tonic-gate     }
364*7c478bd9Sstevel@tonic-gate     return (*mlist != '\0');
365*7c478bd9Sstevel@tonic-gate }
366*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate /*
369*7c478bd9Sstevel@tonic-gate  * parameters:
370*7c478bd9Sstevel@tonic-gate  *  p - entry point
371*7c478bd9Sstevel@tonic-gate  */
372*7c478bd9Sstevel@tonic-gate int sasl_server_add_plugin(const char *plugname,
373*7c478bd9Sstevel@tonic-gate 			   sasl_server_plug_init_t *p)
374*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
375*7c478bd9Sstevel@tonic-gate {
376*7c478bd9Sstevel@tonic-gate     return (_sasl_server_add_plugin(_sasl_gbl_ctx(), plugname, p));
377*7c478bd9Sstevel@tonic-gate }
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate int _sasl_server_add_plugin(void *ctx,
380*7c478bd9Sstevel@tonic-gate 			    const char *plugname,
381*7c478bd9Sstevel@tonic-gate 			    sasl_server_plug_init_t *p)
382*7c478bd9Sstevel@tonic-gate {
383*7c478bd9Sstevel@tonic-gate     int nplug = 0;
384*7c478bd9Sstevel@tonic-gate     int i;
385*7c478bd9Sstevel@tonic-gate     mechanism_t *m;
386*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx;
387*7c478bd9Sstevel@tonic-gate     mech_list_t *mechlist = gctx->mechlist;
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE START */
390*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE START */
391*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
392*7c478bd9Sstevel@tonic-gate     int sun_reg;
393*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
394*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE END */
395*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE END */
396*7c478bd9Sstevel@tonic-gate #else
397*7c478bd9Sstevel@tonic-gate {
398*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
399*7c478bd9Sstevel@tonic-gate     int plugcount;
400*7c478bd9Sstevel@tonic-gate     sasl_server_plug_t *pluglist;
401*7c478bd9Sstevel@tonic-gate     mechanism_t *mech;
402*7c478bd9Sstevel@tonic-gate     sasl_server_plug_init_t *entry_point;
403*7c478bd9Sstevel@tonic-gate     int result;
404*7c478bd9Sstevel@tonic-gate     int version;
405*7c478bd9Sstevel@tonic-gate     int lupe;
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate     if(!plugname || !p) return SASL_BADPARAM;
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
410*7c478bd9Sstevel@tonic-gate     if (mechlist == NULL) return SASL_BADPARAM;
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate     /* Check to see if this plugin has already been registered */
413*7c478bd9Sstevel@tonic-gate     m = mechlist->mech_list;
414*7c478bd9Sstevel@tonic-gate     for (i = 0; i < mechlist->mech_length; i++) {
415*7c478bd9Sstevel@tonic-gate 	if (strcmp(plugname, m->plugname) == 0)
416*7c478bd9Sstevel@tonic-gate 		return SASL_OK;
417*7c478bd9Sstevel@tonic-gate 	m = m->next;
418*7c478bd9Sstevel@tonic-gate     }
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate     result = LOCK_MUTEX(&server_plug_mutex);
421*7c478bd9Sstevel@tonic-gate     if (result != SASL_OK)
422*7c478bd9Sstevel@tonic-gate 	return result;
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
425*7c478bd9Sstevel@tonic-gate     entry_point = (sasl_server_plug_init_t *)p;
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate     /* call into the shared library asking for information about it */
428*7c478bd9Sstevel@tonic-gate     /* version is filled in with the version of the plugin */
429*7c478bd9Sstevel@tonic-gate     result = entry_point(mechlist->utils, SASL_SERVER_PLUG_VERSION, &version,
430*7c478bd9Sstevel@tonic-gate 			 &pluglist, &plugcount);
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE START */
433*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE START */
434*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
435*7c478bd9Sstevel@tonic-gate     sun_reg = _is_sun_reg(pluglist);
436*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
437*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE END */
438*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE END */
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
441*7c478bd9Sstevel@tonic-gate     if (result != SASL_OK) {
442*7c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_plug_mutex);
443*7c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks,
444*7c478bd9Sstevel@tonic-gate 		   SASL_LOG_DEBUG,
445*7c478bd9Sstevel@tonic-gate 		   "server add_plugin entry_point error %z", result);
446*7c478bd9Sstevel@tonic-gate #else
447*7c478bd9Sstevel@tonic-gate     if ((result != SASL_OK) && (result != SASL_NOUSER)) {
448*7c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_DEBUG,
449*7c478bd9Sstevel@tonic-gate 		  "server add_plugin entry_point error %z\n", result);
450*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
451*7c478bd9Sstevel@tonic-gate 	return result;
452*7c478bd9Sstevel@tonic-gate     }
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate     /* Make sure plugin is using the same SASL version as us */
455*7c478bd9Sstevel@tonic-gate     if (version != SASL_SERVER_PLUG_VERSION)
456*7c478bd9Sstevel@tonic-gate     {
457*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
458*7c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_plug_mutex);
459*7c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks,
460*7c478bd9Sstevel@tonic-gate 		   SASL_LOG_ERR, "version mismatch on plugin");
461*7c478bd9Sstevel@tonic-gate #else
462*7c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR,
463*7c478bd9Sstevel@tonic-gate 		  "version mismatch on plugin");
464*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
465*7c478bd9Sstevel@tonic-gate 	return SASL_BADVERS;
466*7c478bd9Sstevel@tonic-gate     }
467*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
468*7c478bd9Sstevel@tonic-gate     /* Check plugins to make sure mech_name is non-NULL */
469*7c478bd9Sstevel@tonic-gate     for (lupe=0;lupe < plugcount ;lupe++) {
470*7c478bd9Sstevel@tonic-gate 	if (pluglist[lupe].mech_name == NULL)
471*7c478bd9Sstevel@tonic-gate 	     break;
472*7c478bd9Sstevel@tonic-gate     }
473*7c478bd9Sstevel@tonic-gate     if (lupe < plugcount) {
474*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
475*7c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_plug_mutex);
476*7c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks,
477*7c478bd9Sstevel@tonic-gate 		   SASL_LOG_ERR, "invalid server plugin %s", plugname);
478*7c478bd9Sstevel@tonic-gate #else
479*7c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR, "invalid server plugin %s", plugname);
480*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
481*7c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
482*7c478bd9Sstevel@tonic-gate     }
483*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate     for (lupe=0;lupe < plugcount ;lupe++)
486*7c478bd9Sstevel@tonic-gate     {
487*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
488*7c478bd9Sstevel@tonic-gate 	if (!load_mech(gctx, pluglist->mech_name)) {
489*7c478bd9Sstevel@tonic-gate 	     pluglist++;
490*7c478bd9Sstevel@tonic-gate 	     continue;
491*7c478bd9Sstevel@tonic-gate 	}
492*7c478bd9Sstevel@tonic-gate 	nplug++;
493*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
494*7c478bd9Sstevel@tonic-gate 	mech = sasl_ALLOC(sizeof(mechanism_t));
495*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
496*7c478bd9Sstevel@tonic-gate 	if (! mech) {
497*7c478bd9Sstevel@tonic-gate 	    UNLOCK_MUTEX(&server_plug_mutex);
498*7c478bd9Sstevel@tonic-gate 	    return SASL_NOMEM;
499*7c478bd9Sstevel@tonic-gate 	}
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 	mech->glob_context = pluglist->glob_context;
502*7c478bd9Sstevel@tonic-gate #else
503*7c478bd9Sstevel@tonic-gate 	if (! mech) return SASL_NOMEM;
504*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 	mech->plug=pluglist++;
507*7c478bd9Sstevel@tonic-gate 	if(_sasl_strdup(plugname, &mech->plugname, NULL) != SASL_OK) {
508*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
509*7c478bd9Sstevel@tonic-gate 	    UNLOCK_MUTEX(&server_plug_mutex);
510*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
511*7c478bd9Sstevel@tonic-gate 	    sasl_FREE(mech);
512*7c478bd9Sstevel@tonic-gate 	    return SASL_NOMEM;
513*7c478bd9Sstevel@tonic-gate 	}
514*7c478bd9Sstevel@tonic-gate 	mech->version = version;
515*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
516*7c478bd9Sstevel@tonic-gate 	/* EXPORT DELETE START */
517*7c478bd9Sstevel@tonic-gate 	/* CRYPT DELETE START */
518*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
519*7c478bd9Sstevel@tonic-gate 	mech->sun_reg = sun_reg;
520*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
521*7c478bd9Sstevel@tonic-gate 	/* CRYPT DELETE END */
522*7c478bd9Sstevel@tonic-gate 	/* EXPORT DELETE END */
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 	/* whether this mech actually has any users in it's db */
525*7c478bd9Sstevel@tonic-gate 	mech->condition = SASL_OK;
526*7c478bd9Sstevel@tonic-gate #else
527*7c478bd9Sstevel@tonic-gate 	/* whether this mech actually has any users in it's db */
528*7c478bd9Sstevel@tonic-gate 	mech->condition = result; /* SASL_OK or SASL_NOUSER */
529*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	mech->next = mechlist->mech_list;
532*7c478bd9Sstevel@tonic-gate 	mechlist->mech_list = mech;
533*7c478bd9Sstevel@tonic-gate 	mechlist->mech_length++;
534*7c478bd9Sstevel@tonic-gate     }
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
537*7c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&server_plug_mutex);
538*7c478bd9Sstevel@tonic-gate     return (nplug == 0) ? SASL_NOMECH : SASL_OK;
539*7c478bd9Sstevel@tonic-gate #else
540*7c478bd9Sstevel@tonic-gate     return SASL_OK;
541*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
542*7c478bd9Sstevel@tonic-gate }
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
545*7c478bd9Sstevel@tonic-gate static int server_done(_sasl_global_context_t *gctx) {
546*7c478bd9Sstevel@tonic-gate   mech_list_t *mechlist = gctx->mechlist;
547*7c478bd9Sstevel@tonic-gate   _sasl_path_info_t *path_info, *p;
548*7c478bd9Sstevel@tonic-gate #else
549*7c478bd9Sstevel@tonic-gate static int server_done(void) {
550*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
551*7c478bd9Sstevel@tonic-gate   mechanism_t *m;
552*7c478bd9Sstevel@tonic-gate   mechanism_t *prevm;
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
555*7c478bd9Sstevel@tonic-gate   if(!gctx->sasl_server_active)
556*7c478bd9Sstevel@tonic-gate       return SASL_NOTINIT;
557*7c478bd9Sstevel@tonic-gate 
558*7c478bd9Sstevel@tonic-gate   if (LOCK_MUTEX(&server_active_mutex) < 0) {
559*7c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
560*7c478bd9Sstevel@tonic-gate   }
561*7c478bd9Sstevel@tonic-gate   gctx->sasl_server_active--;
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate   if(gctx->sasl_server_active) {
564*7c478bd9Sstevel@tonic-gate       /* Don't de-init yet! Our refcount is nonzero. */
565*7c478bd9Sstevel@tonic-gate       UNLOCK_MUTEX(&server_active_mutex);
566*7c478bd9Sstevel@tonic-gate       return SASL_CONTINUE;
567*7c478bd9Sstevel@tonic-gate   }
568*7c478bd9Sstevel@tonic-gate #else
569*7c478bd9Sstevel@tonic-gate   if(!_sasl_server_active)
570*7c478bd9Sstevel@tonic-gate       return SASL_NOTINIT;
571*7c478bd9Sstevel@tonic-gate   else
572*7c478bd9Sstevel@tonic-gate       _sasl_server_active--;
573*7c478bd9Sstevel@tonic-gate 
574*7c478bd9Sstevel@tonic-gate   if(_sasl_server_active) {
575*7c478bd9Sstevel@tonic-gate       /* Don't de-init yet! Our refcount is nonzero. */
576*7c478bd9Sstevel@tonic-gate       return SASL_CONTINUE;
577*7c478bd9Sstevel@tonic-gate   }
578*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate   if (mechlist != NULL)
581*7c478bd9Sstevel@tonic-gate   {
582*7c478bd9Sstevel@tonic-gate       m=mechlist->mech_list; /* m point to beginning of the list */
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate       while (m!=NULL)
585*7c478bd9Sstevel@tonic-gate       {
586*7c478bd9Sstevel@tonic-gate 	  prevm=m;
587*7c478bd9Sstevel@tonic-gate 	  m=m->next;
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 	  if (prevm->plug->mech_free) {
590*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
591*7c478bd9Sstevel@tonic-gate 	      prevm->plug->mech_free(prevm->glob_context,
592*7c478bd9Sstevel@tonic-gate #else
593*7c478bd9Sstevel@tonic-gate 	      prevm->plug->mech_free(prevm->plug->glob_context,
594*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
595*7c478bd9Sstevel@tonic-gate 				     mechlist->utils);
596*7c478bd9Sstevel@tonic-gate 	  }
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 	  sasl_FREE(prevm->plugname);
599*7c478bd9Sstevel@tonic-gate 	  sasl_FREE(prevm);
600*7c478bd9Sstevel@tonic-gate       }
601*7c478bd9Sstevel@tonic-gate       _sasl_free_utils(&mechlist->utils);
602*7c478bd9Sstevel@tonic-gate       sasl_MUTEX_FREE(mechlist->mutex);
603*7c478bd9Sstevel@tonic-gate       sasl_FREE(mechlist);
604*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
605*7c478bd9Sstevel@tonic-gate       gctx->mechlist = NULL;
606*7c478bd9Sstevel@tonic-gate #else
607*7c478bd9Sstevel@tonic-gate       mechlist = NULL;
608*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
609*7c478bd9Sstevel@tonic-gate   }
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate   /* Free the auxprop plugins */
612*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
613*7c478bd9Sstevel@tonic-gate   _sasl_auxprop_free(gctx);
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate   gctx->server_global_callbacks.callbacks = NULL;
616*7c478bd9Sstevel@tonic-gate   gctx->server_global_callbacks.appname = NULL;
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate   p = gctx->splug_path_info;
619*7c478bd9Sstevel@tonic-gate   while((path_info = p) != NULL) {
620*7c478bd9Sstevel@tonic-gate     sasl_FREE(path_info->path);
621*7c478bd9Sstevel@tonic-gate     p = path_info->next;
622*7c478bd9Sstevel@tonic-gate     sasl_FREE(path_info);
623*7c478bd9Sstevel@tonic-gate   }
624*7c478bd9Sstevel@tonic-gate   gctx->splug_path_info = NULL;
625*7c478bd9Sstevel@tonic-gate   UNLOCK_MUTEX(&server_active_mutex);
626*7c478bd9Sstevel@tonic-gate #else
627*7c478bd9Sstevel@tonic-gate   _sasl_auxprop_free();
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate   global_callbacks.callbacks = NULL;
630*7c478bd9Sstevel@tonic-gate   global_callbacks.appname = NULL;
631*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate   return SASL_OK;
634*7c478bd9Sstevel@tonic-gate }
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate static int server_idle(sasl_conn_t *conn)
637*7c478bd9Sstevel@tonic-gate {
638*7c478bd9Sstevel@tonic-gate     mechanism_t *m;
639*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
640*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx;
641*7c478bd9Sstevel@tonic-gate     mech_list_t *mechlist;
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate     if (conn == NULL)
644*7c478bd9Sstevel@tonic-gate         gctx = _sasl_gbl_ctx();
645*7c478bd9Sstevel@tonic-gate     else
646*7c478bd9Sstevel@tonic-gate         gctx = conn->gctx;
647*7c478bd9Sstevel@tonic-gate   mechlist = gctx->mechlist;
648*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
649*7c478bd9Sstevel@tonic-gate     if (! mechlist)
650*7c478bd9Sstevel@tonic-gate 	return 0;
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate     for (m = mechlist->mech_list;
653*7c478bd9Sstevel@tonic-gate 	 m!=NULL;
654*7c478bd9Sstevel@tonic-gate 	 m = m->next)
655*7c478bd9Sstevel@tonic-gate 	if (m->plug->idle
656*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
657*7c478bd9Sstevel@tonic-gate 	    &&  m->plug->idle(m->glob_context,
658*7c478bd9Sstevel@tonic-gate #else
659*7c478bd9Sstevel@tonic-gate 	    &&  m->plug->idle(m->plug->glob_context,
660*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
661*7c478bd9Sstevel@tonic-gate 			      conn,
662*7c478bd9Sstevel@tonic-gate 			      conn ? ((sasl_server_conn_t *)conn)->sparams : NULL))
663*7c478bd9Sstevel@tonic-gate 	    return 1;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate     return 0;
666*7c478bd9Sstevel@tonic-gate }
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
669*7c478bd9Sstevel@tonic-gate static int load_config(_sasl_global_context_t *gctx,
670*7c478bd9Sstevel@tonic-gate 		       const sasl_callback_t *verifyfile_cb)
671*7c478bd9Sstevel@tonic-gate {
672*7c478bd9Sstevel@tonic-gate   int result;
673*7c478bd9Sstevel@tonic-gate   const char *conf_to_config = NULL;
674*7c478bd9Sstevel@tonic-gate   const char *conf_file = NULL;
675*7c478bd9Sstevel@tonic-gate   int conf_len;
676*7c478bd9Sstevel@tonic-gate   sasl_global_callbacks_t global_callbacks = gctx->server_global_callbacks;
677*7c478bd9Sstevel@tonic-gate   char *alloc_file_name=NULL;
678*7c478bd9Sstevel@tonic-gate   int len;
679*7c478bd9Sstevel@tonic-gate   const sasl_callback_t *getconf_cb=NULL;
680*7c478bd9Sstevel@tonic-gate   struct stat buf;
681*7c478bd9Sstevel@tonic-gate   int full_file = 0;
682*7c478bd9Sstevel@tonic-gate   int file_exists = 0;
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate   /* get the path to the plugins; for now the config file will reside there */
685*7c478bd9Sstevel@tonic-gate   getconf_cb = _sasl_find_getconf_callback(global_callbacks.callbacks);
686*7c478bd9Sstevel@tonic-gate   if (getconf_cb==NULL) return SASL_BADPARAM;
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate   result = ((sasl_getpath_t *)(getconf_cb->proc))(getconf_cb->context,
689*7c478bd9Sstevel@tonic-gate 						  &conf_to_config);
690*7c478bd9Sstevel@tonic-gate   if (result!=SASL_OK) goto done;
691*7c478bd9Sstevel@tonic-gate   if (conf_to_config == NULL) conf_to_config = "";
692*7c478bd9Sstevel@tonic-gate   else {
693*7c478bd9Sstevel@tonic-gate 	if (stat(conf_to_config, &buf))
694*7c478bd9Sstevel@tonic-gate 		goto process_file;
695*7c478bd9Sstevel@tonic-gate 	full_file = !S_ISDIR(buf.st_mode);
696*7c478bd9Sstevel@tonic-gate   }
697*7c478bd9Sstevel@tonic-gate 
698*7c478bd9Sstevel@tonic-gate   if (!full_file) {
699*7c478bd9Sstevel@tonic-gate     conf_len = strlen(conf_to_config);
700*7c478bd9Sstevel@tonic-gate     len = strlen(conf_to_config)+2+ strlen(global_callbacks.appname)+5+1;
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate     if (len > PATH_MAX ) {
703*7c478bd9Sstevel@tonic-gate       result = SASL_FAIL;
704*7c478bd9Sstevel@tonic-gate       goto done;
705*7c478bd9Sstevel@tonic-gate     }
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate     /* construct the filename for the config file */
708*7c478bd9Sstevel@tonic-gate     alloc_file_name = sasl_ALLOC(len);
709*7c478bd9Sstevel@tonic-gate     if (! alloc_file_name) {
710*7c478bd9Sstevel@tonic-gate         result = SASL_NOMEM;
711*7c478bd9Sstevel@tonic-gate         goto done;
712*7c478bd9Sstevel@tonic-gate     }
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate     snprintf(alloc_file_name, len, "%.*s/%s.conf", conf_len, conf_to_config,
715*7c478bd9Sstevel@tonic-gate 	   global_callbacks.appname);
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate   }
718*7c478bd9Sstevel@tonic-gate   conf_file = full_file ? conf_to_config : alloc_file_name;
719*7c478bd9Sstevel@tonic-gate 
720*7c478bd9Sstevel@tonic-gate   if (full_file || stat(conf_file, &buf) == 0)
721*7c478bd9Sstevel@tonic-gate 	file_exists = S_ISREG(buf.st_mode);
722*7c478bd9Sstevel@tonic-gate 
723*7c478bd9Sstevel@tonic-gate process_file:
724*7c478bd9Sstevel@tonic-gate   /* Check to see if anything has changed */
725*7c478bd9Sstevel@tonic-gate   if (file_exists && gctx->config_path != NULL &&
726*7c478bd9Sstevel@tonic-gate 	strcmp(conf_file, gctx->config_path) == 0 &&
727*7c478bd9Sstevel@tonic-gate 	gctx->config_last_read == buf.st_mtime) {
728*7c478bd9Sstevel@tonic-gate     /* File has not changed */
729*7c478bd9Sstevel@tonic-gate     goto done;
730*7c478bd9Sstevel@tonic-gate   } else if (gctx->config_path == NULL) {
731*7c478bd9Sstevel@tonic-gate     /* No new file, nothing has changed  */
732*7c478bd9Sstevel@tonic-gate     if (!file_exists)
733*7c478bd9Sstevel@tonic-gate 	goto done;
734*7c478bd9Sstevel@tonic-gate   } else {
735*7c478bd9Sstevel@tonic-gate     sasl_config_free(gctx);
736*7c478bd9Sstevel@tonic-gate     if (!file_exists) {
737*7c478bd9Sstevel@tonic-gate 	gctx->config_path = NULL;
738*7c478bd9Sstevel@tonic-gate 	goto done;
739*7c478bd9Sstevel@tonic-gate     }
740*7c478bd9Sstevel@tonic-gate   }
741*7c478bd9Sstevel@tonic-gate   gctx->config_last_read = buf.st_mtime;
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate   /* Ask the application if it's safe to use this file */
744*7c478bd9Sstevel@tonic-gate   result = ((sasl_verifyfile_t *)(verifyfile_cb->proc))(verifyfile_cb->context,
745*7c478bd9Sstevel@tonic-gate 		conf_file, SASL_VRFY_CONF);
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate   /* returns continue if this file is to be skipped */
748*7c478bd9Sstevel@tonic-gate 
749*7c478bd9Sstevel@tonic-gate   /* returns SASL_CONTINUE if doesn't exist
750*7c478bd9Sstevel@tonic-gate    * if doesn't exist we can continue using default behavior
751*7c478bd9Sstevel@tonic-gate    */
752*7c478bd9Sstevel@tonic-gate   if (result==SASL_OK)
753*7c478bd9Sstevel@tonic-gate     result=sasl_config_init(gctx, conf_file);
754*7c478bd9Sstevel@tonic-gate 
755*7c478bd9Sstevel@tonic-gate  done:
756*7c478bd9Sstevel@tonic-gate   if (alloc_file_name) sasl_FREE(alloc_file_name);
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate   return result;
759*7c478bd9Sstevel@tonic-gate }
760*7c478bd9Sstevel@tonic-gate #else
761*7c478bd9Sstevel@tonic-gate static int load_config(const sasl_callback_t *verifyfile_cb)
762*7c478bd9Sstevel@tonic-gate {
763*7c478bd9Sstevel@tonic-gate   int result;
764*7c478bd9Sstevel@tonic-gate   const char *path_to_config=NULL;
765*7c478bd9Sstevel@tonic-gate   const char *c;
766*7c478bd9Sstevel@tonic-gate   unsigned path_len;
767*7c478bd9Sstevel@tonic-gate 
768*7c478bd9Sstevel@tonic-gate   char *config_filename=NULL;
769*7c478bd9Sstevel@tonic-gate   int len;
770*7c478bd9Sstevel@tonic-gate   const sasl_callback_t *getpath_cb=NULL;
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate   /* get the path to the plugins; for now the config file will reside there */
773*7c478bd9Sstevel@tonic-gate   getpath_cb=_sasl_find_getpath_callback( global_callbacks.callbacks );
774*7c478bd9Sstevel@tonic-gate   if (getpath_cb==NULL) return SASL_BADPARAM;
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate   /* getpath_cb->proc MUST be a sasl_getpath_t; if only c had a type
777*7c478bd9Sstevel@tonic-gate      system */
778*7c478bd9Sstevel@tonic-gate   result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context,
779*7c478bd9Sstevel@tonic-gate 						  &path_to_config);
780*7c478bd9Sstevel@tonic-gate   if (result!=SASL_OK) goto done;
781*7c478bd9Sstevel@tonic-gate   if (path_to_config == NULL) path_to_config = "";
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate   c = strchr(path_to_config, PATHS_DELIMITER);
784*7c478bd9Sstevel@tonic-gate 
785*7c478bd9Sstevel@tonic-gate   /* length = length of path + '/' + length of appname + ".conf" + 1
786*7c478bd9Sstevel@tonic-gate      for '\0' */
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate   if(c != NULL)
789*7c478bd9Sstevel@tonic-gate     path_len = c - path_to_config;
790*7c478bd9Sstevel@tonic-gate   else
791*7c478bd9Sstevel@tonic-gate     path_len = strlen(path_to_config);
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate   len = path_len + 2 + strlen(global_callbacks.appname) + 5 + 1;
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate   if (len > PATH_MAX ) {
796*7c478bd9Sstevel@tonic-gate       result = SASL_FAIL;
797*7c478bd9Sstevel@tonic-gate       goto done;
798*7c478bd9Sstevel@tonic-gate   }
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate   /* construct the filename for the config file */
801*7c478bd9Sstevel@tonic-gate   config_filename = sasl_ALLOC(len);
802*7c478bd9Sstevel@tonic-gate   if (! config_filename) {
803*7c478bd9Sstevel@tonic-gate       result = SASL_NOMEM;
804*7c478bd9Sstevel@tonic-gate       goto done;
805*7c478bd9Sstevel@tonic-gate   }
806*7c478bd9Sstevel@tonic-gate 
807*7c478bd9Sstevel@tonic-gate   snprintf(config_filename, len, "%.*s/%s.conf", path_len, path_to_config,
808*7c478bd9Sstevel@tonic-gate 	   global_callbacks.appname);
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate   /* Ask the application if it's safe to use this file */
811*7c478bd9Sstevel@tonic-gate   result = ((sasl_verifyfile_t *)(verifyfile_cb->proc))(verifyfile_cb->context,
812*7c478bd9Sstevel@tonic-gate 					config_filename, SASL_VRFY_CONF);
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate   /* returns continue if this file is to be skipped */
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate   /* returns SASL_CONTINUE if doesn't exist
817*7c478bd9Sstevel@tonic-gate    * if doesn't exist we can continue using default behavior
818*7c478bd9Sstevel@tonic-gate    */
819*7c478bd9Sstevel@tonic-gate   if (result==SASL_OK)
820*7c478bd9Sstevel@tonic-gate     result=sasl_config_init(config_filename);
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate  done:
823*7c478bd9Sstevel@tonic-gate   if (config_filename) sasl_FREE(config_filename);
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate   return result;
826*7c478bd9Sstevel@tonic-gate }
827*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
828*7c478bd9Sstevel@tonic-gate 
829*7c478bd9Sstevel@tonic-gate /*
830*7c478bd9Sstevel@tonic-gate  * Verify that all the callbacks are valid
831*7c478bd9Sstevel@tonic-gate  */
832*7c478bd9Sstevel@tonic-gate static int verify_server_callbacks(const sasl_callback_t *callbacks)
833*7c478bd9Sstevel@tonic-gate {
834*7c478bd9Sstevel@tonic-gate     if (callbacks == NULL) return SASL_OK;
835*7c478bd9Sstevel@tonic-gate 
836*7c478bd9Sstevel@tonic-gate     while (callbacks->id != SASL_CB_LIST_END) {
837*7c478bd9Sstevel@tonic-gate 	if (callbacks->proc==NULL) return SASL_FAIL;
838*7c478bd9Sstevel@tonic-gate 
839*7c478bd9Sstevel@tonic-gate 	callbacks++;
840*7c478bd9Sstevel@tonic-gate     }
841*7c478bd9Sstevel@tonic-gate 
842*7c478bd9Sstevel@tonic-gate     return SASL_OK;
843*7c478bd9Sstevel@tonic-gate }
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
846*7c478bd9Sstevel@tonic-gate static char *grab_field(char *line, char **eofield)
847*7c478bd9Sstevel@tonic-gate {
848*7c478bd9Sstevel@tonic-gate     int d = 0;
849*7c478bd9Sstevel@tonic-gate     char *field;
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate     while (isspace((int) *line)) line++;
852*7c478bd9Sstevel@tonic-gate 
853*7c478bd9Sstevel@tonic-gate     /* find end of field */
854*7c478bd9Sstevel@tonic-gate     while (line[d] && !isspace(((int) line[d]))) d++;
855*7c478bd9Sstevel@tonic-gate     field = sasl_ALLOC(d + 1);
856*7c478bd9Sstevel@tonic-gate     if (!field) { return NULL; }
857*7c478bd9Sstevel@tonic-gate     memcpy(field, line, d);
858*7c478bd9Sstevel@tonic-gate     field[d] = '\0';
859*7c478bd9Sstevel@tonic-gate     *eofield = line + d;
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate     return field;
862*7c478bd9Sstevel@tonic-gate }
863*7c478bd9Sstevel@tonic-gate 
864*7c478bd9Sstevel@tonic-gate struct secflag_map_s {
865*7c478bd9Sstevel@tonic-gate     char *name;
866*7c478bd9Sstevel@tonic-gate     int value;
867*7c478bd9Sstevel@tonic-gate };
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate struct secflag_map_s secflag_map[] = {
870*7c478bd9Sstevel@tonic-gate     { "noplaintext", SASL_SEC_NOPLAINTEXT },
871*7c478bd9Sstevel@tonic-gate     { "noactive", SASL_SEC_NOACTIVE },
872*7c478bd9Sstevel@tonic-gate     { "nodictionary", SASL_SEC_NODICTIONARY },
873*7c478bd9Sstevel@tonic-gate     { "forward_secrecy", SASL_SEC_FORWARD_SECRECY },
874*7c478bd9Sstevel@tonic-gate     { "noanonymous", SASL_SEC_NOANONYMOUS },
875*7c478bd9Sstevel@tonic-gate     { "pass_credentials", SASL_SEC_PASS_CREDENTIALS },
876*7c478bd9Sstevel@tonic-gate     { "mutual_auth", SASL_SEC_MUTUAL_AUTH },
877*7c478bd9Sstevel@tonic-gate     { NULL, 0x0 }
878*7c478bd9Sstevel@tonic-gate };
879*7c478bd9Sstevel@tonic-gate 
880*7c478bd9Sstevel@tonic-gate static int parse_mechlist_file(const char *mechlistfile)
881*7c478bd9Sstevel@tonic-gate {
882*7c478bd9Sstevel@tonic-gate     FILE *f;
883*7c478bd9Sstevel@tonic-gate     char buf[1024];
884*7c478bd9Sstevel@tonic-gate     char *t, *ptr;
885*7c478bd9Sstevel@tonic-gate     int r = 0;
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate     f = fopen(mechlistfile, "r");
888*7c478bd9Sstevel@tonic-gate     if (!f) return SASL_FAIL;
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate     r = SASL_OK;
891*7c478bd9Sstevel@tonic-gate     while (fgets(buf, sizeof(buf), f) != NULL) {
892*7c478bd9Sstevel@tonic-gate 	mechanism_t *n = sasl_ALLOC(sizeof(mechanism_t));
893*7c478bd9Sstevel@tonic-gate 	sasl_server_plug_t *nplug;
894*7c478bd9Sstevel@tonic-gate 
895*7c478bd9Sstevel@tonic-gate 	if (n == NULL) { r = SASL_NOMEM; break; }
896*7c478bd9Sstevel@tonic-gate 	n->version = SASL_SERVER_PLUG_VERSION;
897*7c478bd9Sstevel@tonic-gate 	n->condition = SASL_CONTINUE;
898*7c478bd9Sstevel@tonic-gate 	nplug = sasl_ALLOC(sizeof(sasl_server_plug_t));
899*7c478bd9Sstevel@tonic-gate 	if (nplug == NULL) { r = SASL_NOMEM; break; }
900*7c478bd9Sstevel@tonic-gate 	memset(nplug, 0, sizeof(sasl_server_plug_t));
901*7c478bd9Sstevel@tonic-gate 
902*7c478bd9Sstevel@tonic-gate 	/* each line is:
903*7c478bd9Sstevel@tonic-gate 	   plugin-file WS mech_name WS max_ssf *(WS security_flag) RET
904*7c478bd9Sstevel@tonic-gate 	*/
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate 	/* grab file */
907*7c478bd9Sstevel@tonic-gate 	n->f = grab_field(buf, &ptr);
908*7c478bd9Sstevel@tonic-gate 
909*7c478bd9Sstevel@tonic-gate 	/* grab mech_name */
910*7c478bd9Sstevel@tonic-gate 	nplug->mech_name = grab_field(ptr, &ptr);
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate 	/* grab max_ssf */
913*7c478bd9Sstevel@tonic-gate 	nplug->max_ssf = strtol(ptr, &ptr, 10);
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 	/* grab security flags */
916*7c478bd9Sstevel@tonic-gate 	while (*ptr != '\n') {
917*7c478bd9Sstevel@tonic-gate 	    struct secflag_map_s *map;
918*7c478bd9Sstevel@tonic-gate 
919*7c478bd9Sstevel@tonic-gate 	    /* read security flag */
920*7c478bd9Sstevel@tonic-gate 	    t = grab_field(ptr, &ptr);
921*7c478bd9Sstevel@tonic-gate 	    map = secflag_map;
922*7c478bd9Sstevel@tonic-gate 	    while (map->name) {
923*7c478bd9Sstevel@tonic-gate 		if (!strcasecmp(t, map->name)) {
924*7c478bd9Sstevel@tonic-gate 		    nplug->security_flags |= map->value;
925*7c478bd9Sstevel@tonic-gate 		    break;
926*7c478bd9Sstevel@tonic-gate 		}
927*7c478bd9Sstevel@tonic-gate 		map++;
928*7c478bd9Sstevel@tonic-gate 	    }
929*7c478bd9Sstevel@tonic-gate 	    if (!map->name) {
930*7c478bd9Sstevel@tonic-gate 		_sasl_log(NULL, SASL_LOG_ERR,
931*7c478bd9Sstevel@tonic-gate 			  "%s: couldn't identify flag '%s'",
932*7c478bd9Sstevel@tonic-gate 			  nplug->mech_name, t);
933*7c478bd9Sstevel@tonic-gate 	    }
934*7c478bd9Sstevel@tonic-gate 	    free(t);
935*7c478bd9Sstevel@tonic-gate 	}
936*7c478bd9Sstevel@tonic-gate 
937*7c478bd9Sstevel@tonic-gate 	/* insert mechanism into mechlist */
938*7c478bd9Sstevel@tonic-gate 	n->plug = nplug;
939*7c478bd9Sstevel@tonic-gate 	n->next = mechlist->mech_list;
940*7c478bd9Sstevel@tonic-gate 	mechlist->mech_list = n;
941*7c478bd9Sstevel@tonic-gate 	mechlist->mech_length++;
942*7c478bd9Sstevel@tonic-gate     }
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate     fclose(f);
945*7c478bd9Sstevel@tonic-gate     return r;
946*7c478bd9Sstevel@tonic-gate }
947*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
948*7c478bd9Sstevel@tonic-gate 
949*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
950*7c478bd9Sstevel@tonic-gate static int _load_server_plugins(_sasl_global_context_t *gctx)
951*7c478bd9Sstevel@tonic-gate {
952*7c478bd9Sstevel@tonic-gate     int ret;
953*7c478bd9Sstevel@tonic-gate     const add_plugin_list_t _ep_list[] = {
954*7c478bd9Sstevel@tonic-gate 	{ "sasl_server_plug_init", (add_plugin_t *)_sasl_server_add_plugin },
955*7c478bd9Sstevel@tonic-gate 	{ "sasl_auxprop_plug_init", (add_plugin_t *)_sasl_auxprop_add_plugin },
956*7c478bd9Sstevel@tonic-gate 	{ "sasl_canonuser_init", (add_plugin_t *)_sasl_canonuser_add_plugin },
957*7c478bd9Sstevel@tonic-gate 	{ NULL, NULL }
958*7c478bd9Sstevel@tonic-gate     };
959*7c478bd9Sstevel@tonic-gate     const sasl_callback_t *callbacks = gctx->server_global_callbacks.callbacks;
960*7c478bd9Sstevel@tonic-gate 
961*7c478bd9Sstevel@tonic-gate     ret = _sasl_load_plugins(gctx, 1, _ep_list,
962*7c478bd9Sstevel@tonic-gate 			     _sasl_find_getpath_callback(callbacks),
963*7c478bd9Sstevel@tonic-gate 			     _sasl_find_verifyfile_callback(callbacks));
964*7c478bd9Sstevel@tonic-gate     return (ret);
965*7c478bd9Sstevel@tonic-gate }
966*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate /* initialize server drivers, done once per process
969*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
970*7c478bd9Sstevel@tonic-gate  *  callbacks      -- callbacks for all server connections
971*7c478bd9Sstevel@tonic-gate  *  appname        -- name of calling application (for config)
972*7c478bd9Sstevel@tonic-gate #else
973*7c478bd9Sstevel@tonic-gate  *  callbacks      -- callbacks for all server connections; must include
974*7c478bd9Sstevel@tonic-gate  *                    getopt callback
975*7c478bd9Sstevel@tonic-gate  *  appname        -- name of calling application (for lower level logging)
976*7c478bd9Sstevel@tonic-gate  * results:
977*7c478bd9Sstevel@tonic-gate  *  state          -- server state
978*7c478bd9Sstevel@tonic-gate #endif
979*7c478bd9Sstevel@tonic-gate  * returns:
980*7c478bd9Sstevel@tonic-gate  *  SASL_OK        -- success
981*7c478bd9Sstevel@tonic-gate  *  SASL_BADPARAM  -- error in config file
982*7c478bd9Sstevel@tonic-gate  *  SASL_NOMEM     -- memory failure
983*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
984*7c478bd9Sstevel@tonic-gate  *  SASL_BADVERS   -- Mechanism version mismatch
985*7c478bd9Sstevel@tonic-gate #endif
986*7c478bd9Sstevel@tonic-gate  */
987*7c478bd9Sstevel@tonic-gate 
988*7c478bd9Sstevel@tonic-gate int sasl_server_init(const sasl_callback_t *callbacks,
989*7c478bd9Sstevel@tonic-gate 		     const char *appname)
990*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
991*7c478bd9Sstevel@tonic-gate {
992*7c478bd9Sstevel@tonic-gate 	return _sasl_server_init(NULL, callbacks, appname);
993*7c478bd9Sstevel@tonic-gate }
994*7c478bd9Sstevel@tonic-gate 
995*7c478bd9Sstevel@tonic-gate int _sasl_server_init(void *ctx, const sasl_callback_t *callbacks,
996*7c478bd9Sstevel@tonic-gate 		     const char *appname)
997*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
998*7c478bd9Sstevel@tonic-gate {
999*7c478bd9Sstevel@tonic-gate     int ret;
1000*7c478bd9Sstevel@tonic-gate     const sasl_callback_t *vf;
1001*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1002*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx;
1003*7c478bd9Sstevel@tonic-gate #else
1004*7c478bd9Sstevel@tonic-gate     const char *pluginfile = NULL;
1005*7c478bd9Sstevel@tonic-gate #ifdef PIC
1006*7c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
1007*7c478bd9Sstevel@tonic-gate     void *context;
1008*7c478bd9Sstevel@tonic-gate #endif
1009*7c478bd9Sstevel@tonic-gate 
1010*7c478bd9Sstevel@tonic-gate     const add_plugin_list_t ep_list[] = {
1011*7c478bd9Sstevel@tonic-gate 	{ "sasl_server_plug_init", (add_plugin_t *)sasl_server_add_plugin },
1012*7c478bd9Sstevel@tonic-gate 	{ "sasl_auxprop_plug_init", (add_plugin_t *)sasl_auxprop_add_plugin },
1013*7c478bd9Sstevel@tonic-gate 	{ "sasl_canonuser_init", (add_plugin_t *)sasl_canonuser_add_plugin },
1014*7c478bd9Sstevel@tonic-gate 	{ NULL, NULL }
1015*7c478bd9Sstevel@tonic-gate     };
1016*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1017*7c478bd9Sstevel@tonic-gate 
1018*7c478bd9Sstevel@tonic-gate     /* we require the appname to be non-null and short enough to be a path */
1019*7c478bd9Sstevel@tonic-gate     if (!appname || strlen(appname) >= PATH_MAX)
1020*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
1021*7c478bd9Sstevel@tonic-gate 
1022*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1023*7c478bd9Sstevel@tonic-gate     /* Process only one _sasl_server_init() at a time */
1024*7c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&init_server_mutex) < 0)
1025*7c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
1026*7c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&server_active_mutex) < 0)
1027*7c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate     if (gctx->sasl_server_active) {
1030*7c478bd9Sstevel@tonic-gate 	/* We're already active, just increase our refcount */
1031*7c478bd9Sstevel@tonic-gate 	/* xxx do something with the callback structure? */
1032*7c478bd9Sstevel@tonic-gate 	gctx->sasl_server_active++;
1033*7c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_active_mutex);
1034*7c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
1035*7c478bd9Sstevel@tonic-gate 	return SASL_OK;
1036*7c478bd9Sstevel@tonic-gate     }
1037*7c478bd9Sstevel@tonic-gate 
1038*7c478bd9Sstevel@tonic-gate     ret = _sasl_common_init(gctx, &gctx->server_global_callbacks, 1);
1039*7c478bd9Sstevel@tonic-gate     if (ret != SASL_OK) {
1040*7c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_active_mutex);
1041*7c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
1042*7c478bd9Sstevel@tonic-gate 	return ret;
1043*7c478bd9Sstevel@tonic-gate     }
1044*7c478bd9Sstevel@tonic-gate #else
1045*7c478bd9Sstevel@tonic-gate     if (_sasl_server_active) {
1046*7c478bd9Sstevel@tonic-gate 	/* We're already active, just increase our refcount */
1047*7c478bd9Sstevel@tonic-gate 	/* xxx do something with the callback structure? */
1048*7c478bd9Sstevel@tonic-gate 	_sasl_server_active++;
1049*7c478bd9Sstevel@tonic-gate 	return SASL_OK;
1050*7c478bd9Sstevel@tonic-gate     }
1051*7c478bd9Sstevel@tonic-gate 
1052*7c478bd9Sstevel@tonic-gate     ret = _sasl_common_init(&global_callbacks);
1053*7c478bd9Sstevel@tonic-gate     if (ret != SASL_OK)
1054*7c478bd9Sstevel@tonic-gate 	return ret;
1055*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate     /* verify that the callbacks look ok */
1058*7c478bd9Sstevel@tonic-gate     ret = verify_server_callbacks(callbacks);
1059*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1060*7c478bd9Sstevel@tonic-gate     if (ret != SASL_OK) {
1061*7c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_active_mutex);
1062*7c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
1063*7c478bd9Sstevel@tonic-gate 	return ret;
1064*7c478bd9Sstevel@tonic-gate     }
1065*7c478bd9Sstevel@tonic-gate 
1066*7c478bd9Sstevel@tonic-gate     gctx->server_global_callbacks.callbacks = callbacks;
1067*7c478bd9Sstevel@tonic-gate     gctx->server_global_callbacks.appname = appname;
1068*7c478bd9Sstevel@tonic-gate 
1069*7c478bd9Sstevel@tonic-gate     /* If we fail now, we have to call server_done */
1070*7c478bd9Sstevel@tonic-gate     gctx->sasl_server_active = 1;
1071*7c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&server_active_mutex);
1072*7c478bd9Sstevel@tonic-gate 
1073*7c478bd9Sstevel@tonic-gate     /* allocate mechlist and set it to empty */
1074*7c478bd9Sstevel@tonic-gate     gctx->mechlist = sasl_ALLOC(sizeof(mech_list_t));
1075*7c478bd9Sstevel@tonic-gate     if (gctx->mechlist == NULL) {
1076*7c478bd9Sstevel@tonic-gate 	server_done(gctx);
1077*7c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
1078*7c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
1079*7c478bd9Sstevel@tonic-gate     }
1080*7c478bd9Sstevel@tonic-gate 
1081*7c478bd9Sstevel@tonic-gate     ret = init_mechlist(gctx);
1082*7c478bd9Sstevel@tonic-gate 
1083*7c478bd9Sstevel@tonic-gate     if (ret != SASL_OK) {
1084*7c478bd9Sstevel@tonic-gate 	server_done(gctx);
1085*7c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
1086*7c478bd9Sstevel@tonic-gate 	return ret;
1087*7c478bd9Sstevel@tonic-gate     }
1088*7c478bd9Sstevel@tonic-gate #else
1089*7c478bd9Sstevel@tonic-gate     if (ret != SASL_OK)
1090*7c478bd9Sstevel@tonic-gate 	return ret;
1091*7c478bd9Sstevel@tonic-gate 
1092*7c478bd9Sstevel@tonic-gate     global_callbacks.callbacks = callbacks;
1093*7c478bd9Sstevel@tonic-gate     global_callbacks.appname = appname;
1094*7c478bd9Sstevel@tonic-gate 
1095*7c478bd9Sstevel@tonic-gate     /* If we fail now, we have to call server_done */
1096*7c478bd9Sstevel@tonic-gate     _sasl_server_active = 1;
1097*7c478bd9Sstevel@tonic-gate 
1098*7c478bd9Sstevel@tonic-gate     /* allocate mechlist and set it to empty */
1099*7c478bd9Sstevel@tonic-gate     mechlist = sasl_ALLOC(sizeof(mech_list_t));
1100*7c478bd9Sstevel@tonic-gate     if (mechlist == NULL) {
1101*7c478bd9Sstevel@tonic-gate 	server_done();
1102*7c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
1103*7c478bd9Sstevel@tonic-gate     }
1104*7c478bd9Sstevel@tonic-gate 
1105*7c478bd9Sstevel@tonic-gate     ret = init_mechlist();
1106*7c478bd9Sstevel@tonic-gate     if (ret != SASL_OK) {
1107*7c478bd9Sstevel@tonic-gate 	server_done();
1108*7c478bd9Sstevel@tonic-gate 	return ret;
1109*7c478bd9Sstevel@tonic-gate     }
1110*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1111*7c478bd9Sstevel@tonic-gate 
1112*7c478bd9Sstevel@tonic-gate     vf = _sasl_find_verifyfile_callback(callbacks);
1113*7c478bd9Sstevel@tonic-gate 
1114*7c478bd9Sstevel@tonic-gate     /* load config file if applicable */
1115*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1116*7c478bd9Sstevel@tonic-gate     ret = load_config(gctx, vf);
1117*7c478bd9Sstevel@tonic-gate     if ((ret != SASL_OK) && (ret != SASL_CONTINUE)) {
1118*7c478bd9Sstevel@tonic-gate 	server_done(gctx);
1119*7c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
1120*7c478bd9Sstevel@tonic-gate #else
1121*7c478bd9Sstevel@tonic-gate     ret = load_config(vf);
1122*7c478bd9Sstevel@tonic-gate     if ((ret != SASL_OK) && (ret != SASL_CONTINUE)) {
1123*7c478bd9Sstevel@tonic-gate 	server_done();
1124*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1125*7c478bd9Sstevel@tonic-gate 	return ret;
1126*7c478bd9Sstevel@tonic-gate     }
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate     /* load internal plugins */
1129*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1130*7c478bd9Sstevel@tonic-gate     _sasl_server_add_plugin(gctx, "EXTERNAL", &external_server_plug_init);
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate /* NOTE: plugin_list option not supported in SUN SDK */
1133*7c478bd9Sstevel@tonic-gate     {
1134*7c478bd9Sstevel@tonic-gate #else
1135*7c478bd9Sstevel@tonic-gate     sasl_server_add_plugin("EXTERNAL", &external_server_plug_init);
1136*7c478bd9Sstevel@tonic-gate 
1137*7c478bd9Sstevel@tonic-gate #ifdef PIC
1138*7c478bd9Sstevel@tonic-gate     /* delayed loading of plugins? (DSO only, as it doesn't
1139*7c478bd9Sstevel@tonic-gate      * make much [any] sense to delay in the static library case) */
1140*7c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(NULL, SASL_CB_GETOPT, &getopt, &context)
1141*7c478bd9Sstevel@tonic-gate 	   == SASL_OK) {
1142*7c478bd9Sstevel@tonic-gate 	/* No sasl_conn_t was given to getcallback, so we provide the
1143*7c478bd9Sstevel@tonic-gate 	 * global callbacks structure */
1144*7c478bd9Sstevel@tonic-gate 	ret = getopt(&global_callbacks, NULL, "plugin_list", &pluginfile, NULL);
1145*7c478bd9Sstevel@tonic-gate     }
1146*7c478bd9Sstevel@tonic-gate #endif
1147*7c478bd9Sstevel@tonic-gate 
1148*7c478bd9Sstevel@tonic-gate     if (pluginfile != NULL) {
1149*7c478bd9Sstevel@tonic-gate 	/* this file should contain a list of plugins available.
1150*7c478bd9Sstevel@tonic-gate 	   we'll load on demand. */
1151*7c478bd9Sstevel@tonic-gate 
1152*7c478bd9Sstevel@tonic-gate 	/* Ask the application if it's safe to use this file */
1153*7c478bd9Sstevel@tonic-gate 	ret = ((sasl_verifyfile_t *)(vf->proc))(vf->context,
1154*7c478bd9Sstevel@tonic-gate 						pluginfile,
1155*7c478bd9Sstevel@tonic-gate 						SASL_VRFY_CONF);
1156*7c478bd9Sstevel@tonic-gate 	if (ret != SASL_OK) {
1157*7c478bd9Sstevel@tonic-gate 	    _sasl_log(NULL, SASL_LOG_ERR,
1158*7c478bd9Sstevel@tonic-gate 		      "unable to load plugin list %s: %z", pluginfile, ret);
1159*7c478bd9Sstevel@tonic-gate 	}
1160*7c478bd9Sstevel@tonic-gate 
1161*7c478bd9Sstevel@tonic-gate 	if (ret == SASL_OK) {
1162*7c478bd9Sstevel@tonic-gate 	    ret = parse_mechlist_file(pluginfile);
1163*7c478bd9Sstevel@tonic-gate 	}
1164*7c478bd9Sstevel@tonic-gate     } else {
1165*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1166*7c478bd9Sstevel@tonic-gate 	/* load all plugins now */
1167*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1168*7c478bd9Sstevel@tonic-gate 	ret = _load_server_plugins(gctx);
1169*7c478bd9Sstevel@tonic-gate #else
1170*7c478bd9Sstevel@tonic-gate 	ret = _sasl_load_plugins(ep_list,
1171*7c478bd9Sstevel@tonic-gate 				 _sasl_find_getpath_callback(callbacks),
1172*7c478bd9Sstevel@tonic-gate 				 _sasl_find_verifyfile_callback(callbacks));
1173*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1174*7c478bd9Sstevel@tonic-gate     }
1175*7c478bd9Sstevel@tonic-gate 
1176*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1177*7c478bd9Sstevel@tonic-gate     if (ret == SASL_OK)
1178*7c478bd9Sstevel@tonic-gate 	ret = _sasl_build_mechlist(gctx);
1179*7c478bd9Sstevel@tonic-gate     if (ret == SASL_OK) {
1180*7c478bd9Sstevel@tonic-gate 	gctx->sasl_server_cleanup_hook = &server_done;
1181*7c478bd9Sstevel@tonic-gate 	gctx->sasl_server_idle_hook = &server_idle;
1182*7c478bd9Sstevel@tonic-gate     } else {
1183*7c478bd9Sstevel@tonic-gate 	server_done(gctx);
1184*7c478bd9Sstevel@tonic-gate     }
1185*7c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&init_server_mutex);
1186*7c478bd9Sstevel@tonic-gate #else
1187*7c478bd9Sstevel@tonic-gate     if (ret == SASL_OK) {
1188*7c478bd9Sstevel@tonic-gate 	_sasl_server_cleanup_hook = &server_done;
1189*7c478bd9Sstevel@tonic-gate 	_sasl_server_idle_hook = &server_idle;
1190*7c478bd9Sstevel@tonic-gate 
1191*7c478bd9Sstevel@tonic-gate 	ret = _sasl_build_mechlist();
1192*7c478bd9Sstevel@tonic-gate     } else {
1193*7c478bd9Sstevel@tonic-gate 	server_done();
1194*7c478bd9Sstevel@tonic-gate     }
1195*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1196*7c478bd9Sstevel@tonic-gate 
1197*7c478bd9Sstevel@tonic-gate     return ret;
1198*7c478bd9Sstevel@tonic-gate }
1199*7c478bd9Sstevel@tonic-gate 
1200*7c478bd9Sstevel@tonic-gate /*
1201*7c478bd9Sstevel@tonic-gate  * Once we have the users plaintext password we
1202*7c478bd9Sstevel@tonic-gate  * may want to transition them. That is put entries
1203*7c478bd9Sstevel@tonic-gate  * for them in the passwd database for other
1204*7c478bd9Sstevel@tonic-gate  * stronger mechanism
1205*7c478bd9Sstevel@tonic-gate  *
1206*7c478bd9Sstevel@tonic-gate  * for example PLAIN -> CRAM-MD5
1207*7c478bd9Sstevel@tonic-gate  */
1208*7c478bd9Sstevel@tonic-gate static int
1209*7c478bd9Sstevel@tonic-gate _sasl_transition(sasl_conn_t * conn,
1210*7c478bd9Sstevel@tonic-gate 		 const char * pass,
1211*7c478bd9Sstevel@tonic-gate 		 unsigned passlen)
1212*7c478bd9Sstevel@tonic-gate {
1213*7c478bd9Sstevel@tonic-gate     const char *dotrans = "n";
1214*7c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
1215*7c478bd9Sstevel@tonic-gate     int result = SASL_OK;
1216*7c478bd9Sstevel@tonic-gate     void *context;
1217*7c478bd9Sstevel@tonic-gate 
1218*7c478bd9Sstevel@tonic-gate     if (! conn)
1219*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
1220*7c478bd9Sstevel@tonic-gate 
1221*7c478bd9Sstevel@tonic-gate     if (! conn->oparams.authid)
1222*7c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
1223*7c478bd9Sstevel@tonic-gate 
1224*7c478bd9Sstevel@tonic-gate     /* check if this is enabled: default to false */
1225*7c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK)
1226*7c478bd9Sstevel@tonic-gate     {
1227*7c478bd9Sstevel@tonic-gate 	getopt(context, NULL, "auto_transition", &dotrans, NULL);
1228*7c478bd9Sstevel@tonic-gate 	if (dotrans == NULL) dotrans = "n";
1229*7c478bd9Sstevel@tonic-gate     }
1230*7c478bd9Sstevel@tonic-gate 
1231*7c478bd9Sstevel@tonic-gate     if (*dotrans == '1' || *dotrans == 'y' ||
1232*7c478bd9Sstevel@tonic-gate 	(*dotrans == 'o' && dotrans[1] == 'n') || *dotrans == 't') {
1233*7c478bd9Sstevel@tonic-gate 	/* ok, it's on! */
1234*7c478bd9Sstevel@tonic-gate 	result = sasl_setpass(conn,
1235*7c478bd9Sstevel@tonic-gate 			      conn->oparams.authid,
1236*7c478bd9Sstevel@tonic-gate 			      pass,
1237*7c478bd9Sstevel@tonic-gate 			      passlen,
1238*7c478bd9Sstevel@tonic-gate 			      NULL, 0, 0);
1239*7c478bd9Sstevel@tonic-gate     }
1240*7c478bd9Sstevel@tonic-gate 
1241*7c478bd9Sstevel@tonic-gate     RETURN(conn,result);
1242*7c478bd9Sstevel@tonic-gate }
1243*7c478bd9Sstevel@tonic-gate 
1244*7c478bd9Sstevel@tonic-gate 
1245*7c478bd9Sstevel@tonic-gate /* create context for a single SASL connection
1246*7c478bd9Sstevel@tonic-gate  *  service        -- registered name of the service using SASL (e.g. "imap")
1247*7c478bd9Sstevel@tonic-gate  *  serverFQDN     -- Fully qualified domain name of server.  NULL means use
1248*7c478bd9Sstevel@tonic-gate  *                    gethostname() or equivalent.
1249*7c478bd9Sstevel@tonic-gate  *                    Useful for multi-homed servers.
1250*7c478bd9Sstevel@tonic-gate  *  user_realm     -- permits multiple user realms on server, NULL = default
1251*7c478bd9Sstevel@tonic-gate  *  iplocalport    -- server IPv4/IPv6 domain literal string with port
1252*7c478bd9Sstevel@tonic-gate  *                    (if NULL, then mechanisms requiring IPaddr are disabled)
1253*7c478bd9Sstevel@tonic-gate  *  ipremoteport   -- client IPv4/IPv6 domain literal string with port
1254*7c478bd9Sstevel@tonic-gate  *                    (if NULL, then mechanisms requiring IPaddr are disabled)
1255*7c478bd9Sstevel@tonic-gate  *  callbacks      -- callbacks (e.g., authorization, lang, new getopt context)
1256*7c478bd9Sstevel@tonic-gate  *  flags          -- usage flags (see above)
1257*7c478bd9Sstevel@tonic-gate  * returns:
1258*7c478bd9Sstevel@tonic-gate  *  pconn          -- new connection context
1259*7c478bd9Sstevel@tonic-gate  *
1260*7c478bd9Sstevel@tonic-gate  * returns:
1261*7c478bd9Sstevel@tonic-gate  *  SASL_OK        -- success
1262*7c478bd9Sstevel@tonic-gate  *  SASL_NOMEM     -- not enough memory
1263*7c478bd9Sstevel@tonic-gate  */
1264*7c478bd9Sstevel@tonic-gate 
1265*7c478bd9Sstevel@tonic-gate int sasl_server_new(const char *service,
1266*7c478bd9Sstevel@tonic-gate 		    const char *serverFQDN,
1267*7c478bd9Sstevel@tonic-gate 		    const char *user_realm,
1268*7c478bd9Sstevel@tonic-gate 		    const char *iplocalport,
1269*7c478bd9Sstevel@tonic-gate 		    const char *ipremoteport,
1270*7c478bd9Sstevel@tonic-gate 		    const sasl_callback_t *callbacks,
1271*7c478bd9Sstevel@tonic-gate 		    unsigned flags,
1272*7c478bd9Sstevel@tonic-gate 		    sasl_conn_t **pconn)
1273*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1274*7c478bd9Sstevel@tonic-gate {
1275*7c478bd9Sstevel@tonic-gate     return _sasl_server_new(NULL, service, serverFQDN, user_realm, iplocalport,
1276*7c478bd9Sstevel@tonic-gate 			   ipremoteport, callbacks, flags, pconn);
1277*7c478bd9Sstevel@tonic-gate }
1278*7c478bd9Sstevel@tonic-gate 
1279*7c478bd9Sstevel@tonic-gate int _sasl_server_new(void *ctx,
1280*7c478bd9Sstevel@tonic-gate 		    const char *service,
1281*7c478bd9Sstevel@tonic-gate 		    const char *serverFQDN,
1282*7c478bd9Sstevel@tonic-gate 		    const char *user_realm,
1283*7c478bd9Sstevel@tonic-gate 		    const char *iplocalport,
1284*7c478bd9Sstevel@tonic-gate 		    const char *ipremoteport,
1285*7c478bd9Sstevel@tonic-gate 		    const sasl_callback_t *callbacks,
1286*7c478bd9Sstevel@tonic-gate 		    unsigned flags,
1287*7c478bd9Sstevel@tonic-gate 		    sasl_conn_t **pconn)
1288*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1289*7c478bd9Sstevel@tonic-gate {
1290*7c478bd9Sstevel@tonic-gate   int result;
1291*7c478bd9Sstevel@tonic-gate   sasl_server_conn_t *serverconn;
1292*7c478bd9Sstevel@tonic-gate   sasl_utils_t *utils;
1293*7c478bd9Sstevel@tonic-gate   sasl_getopt_t *getopt;
1294*7c478bd9Sstevel@tonic-gate   void *context;
1295*7c478bd9Sstevel@tonic-gate   const char *log_level;
1296*7c478bd9Sstevel@tonic-gate 
1297*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1298*7c478bd9Sstevel@tonic-gate   _sasl_global_context_t *gctx = (ctx == NULL) ? _sasl_gbl_ctx() : ctx;
1299*7c478bd9Sstevel@tonic-gate 
1300*7c478bd9Sstevel@tonic-gate   if (gctx->sasl_server_active==0) return SASL_NOTINIT;
1301*7c478bd9Sstevel@tonic-gate #else
1302*7c478bd9Sstevel@tonic-gate   if (_sasl_server_active==0) return SASL_NOTINIT;
1303*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1304*7c478bd9Sstevel@tonic-gate   if (! pconn) return SASL_FAIL;
1305*7c478bd9Sstevel@tonic-gate   if (! service) return SASL_FAIL;
1306*7c478bd9Sstevel@tonic-gate 
1307*7c478bd9Sstevel@tonic-gate   *pconn=sasl_ALLOC(sizeof(sasl_server_conn_t));
1308*7c478bd9Sstevel@tonic-gate   if (*pconn==NULL) return SASL_NOMEM;
1309*7c478bd9Sstevel@tonic-gate 
1310*7c478bd9Sstevel@tonic-gate   memset(*pconn, 0, sizeof(sasl_server_conn_t));
1311*7c478bd9Sstevel@tonic-gate 
1312*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1313*7c478bd9Sstevel@tonic-gate   (*pconn)->gctx = gctx;
1314*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1315*7c478bd9Sstevel@tonic-gate 
1316*7c478bd9Sstevel@tonic-gate   serverconn = (sasl_server_conn_t *)*pconn;
1317*7c478bd9Sstevel@tonic-gate 
1318*7c478bd9Sstevel@tonic-gate   /* make sparams */
1319*7c478bd9Sstevel@tonic-gate   serverconn->sparams=sasl_ALLOC(sizeof(sasl_server_params_t));
1320*7c478bd9Sstevel@tonic-gate   if (serverconn->sparams==NULL)
1321*7c478bd9Sstevel@tonic-gate       MEMERROR(*pconn);
1322*7c478bd9Sstevel@tonic-gate 
1323*7c478bd9Sstevel@tonic-gate   memset(serverconn->sparams, 0, sizeof(sasl_server_params_t));
1324*7c478bd9Sstevel@tonic-gate 
1325*7c478bd9Sstevel@tonic-gate   (*pconn)->destroy_conn = &server_dispose;
1326*7c478bd9Sstevel@tonic-gate   result = _sasl_conn_init(*pconn, service, flags, SASL_CONN_SERVER,
1327*7c478bd9Sstevel@tonic-gate 			   &server_idle, serverFQDN,
1328*7c478bd9Sstevel@tonic-gate 			   iplocalport, ipremoteport,
1329*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1330*7c478bd9Sstevel@tonic-gate 			   callbacks, &gctx->server_global_callbacks);
1331*7c478bd9Sstevel@tonic-gate #else
1332*7c478bd9Sstevel@tonic-gate 			   callbacks, &global_callbacks);
1333*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1334*7c478bd9Sstevel@tonic-gate   if (result != SASL_OK)
1335*7c478bd9Sstevel@tonic-gate       goto done_error;
1336*7c478bd9Sstevel@tonic-gate 
1337*7c478bd9Sstevel@tonic-gate 
1338*7c478bd9Sstevel@tonic-gate   /* set util functions - need to do rest */
1339*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1340*7c478bd9Sstevel@tonic-gate   utils=_sasl_alloc_utils(gctx, *pconn, &gctx->server_global_callbacks);
1341*7c478bd9Sstevel@tonic-gate #else
1342*7c478bd9Sstevel@tonic-gate   utils=_sasl_alloc_utils(*pconn, &global_callbacks);
1343*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1344*7c478bd9Sstevel@tonic-gate   if (!utils) {
1345*7c478bd9Sstevel@tonic-gate       result = SASL_NOMEM;
1346*7c478bd9Sstevel@tonic-gate       goto done_error;
1347*7c478bd9Sstevel@tonic-gate   }
1348*7c478bd9Sstevel@tonic-gate 
1349*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1350*7c478bd9Sstevel@tonic-gate   utils->checkpass = &_sasl_checkpass;
1351*7c478bd9Sstevel@tonic-gate #else /* _SUN_SDK_ */
1352*7c478bd9Sstevel@tonic-gate   utils->checkpass = &sasl_checkpass;
1353*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1354*7c478bd9Sstevel@tonic-gate 
1355*7c478bd9Sstevel@tonic-gate   /* Setup the propctx -> We'll assume the default size */
1356*7c478bd9Sstevel@tonic-gate   serverconn->sparams->propctx=prop_new(0);
1357*7c478bd9Sstevel@tonic-gate   if(!serverconn->sparams->propctx) {
1358*7c478bd9Sstevel@tonic-gate       result = SASL_NOMEM;
1359*7c478bd9Sstevel@tonic-gate       goto done_error;
1360*7c478bd9Sstevel@tonic-gate   }
1361*7c478bd9Sstevel@tonic-gate 
1362*7c478bd9Sstevel@tonic-gate   serverconn->sparams->service = (*pconn)->service;
1363*7c478bd9Sstevel@tonic-gate   serverconn->sparams->servicelen = strlen((*pconn)->service);
1364*7c478bd9Sstevel@tonic-gate 
1365*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1366*7c478bd9Sstevel@tonic-gate   serverconn->sparams->appname = gctx->server_global_callbacks.appname;
1367*7c478bd9Sstevel@tonic-gate   serverconn->sparams->applen = strlen(gctx->server_global_callbacks.appname);
1368*7c478bd9Sstevel@tonic-gate #else
1369*7c478bd9Sstevel@tonic-gate   serverconn->sparams->appname = global_callbacks.appname;
1370*7c478bd9Sstevel@tonic-gate   serverconn->sparams->applen = strlen(global_callbacks.appname);
1371*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1372*7c478bd9Sstevel@tonic-gate 
1373*7c478bd9Sstevel@tonic-gate   serverconn->sparams->serverFQDN = (*pconn)->serverFQDN;
1374*7c478bd9Sstevel@tonic-gate   serverconn->sparams->slen = strlen((*pconn)->serverFQDN);
1375*7c478bd9Sstevel@tonic-gate 
1376*7c478bd9Sstevel@tonic-gate   if (user_realm) {
1377*7c478bd9Sstevel@tonic-gate       result = _sasl_strdup(user_realm, &serverconn->user_realm, NULL);
1378*7c478bd9Sstevel@tonic-gate       serverconn->sparams->urlen = strlen(user_realm);
1379*7c478bd9Sstevel@tonic-gate       serverconn->sparams->user_realm = serverconn->user_realm;
1380*7c478bd9Sstevel@tonic-gate   } else {
1381*7c478bd9Sstevel@tonic-gate       serverconn->user_realm = NULL;
1382*7c478bd9Sstevel@tonic-gate       /* the sparams is already zeroed */
1383*7c478bd9Sstevel@tonic-gate   }
1384*7c478bd9Sstevel@tonic-gate 
1385*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1386*7c478bd9Sstevel@tonic-gate   serverconn->sparams->iplocalport = (*pconn)->iplocalport;
1387*7c478bd9Sstevel@tonic-gate   serverconn->sparams->iploclen = strlen((*pconn)->iplocalport);
1388*7c478bd9Sstevel@tonic-gate   serverconn->sparams->ipremoteport = (*pconn)->ipremoteport;
1389*7c478bd9Sstevel@tonic-gate   serverconn->sparams->ipremlen = strlen((*pconn)->ipremoteport);
1390*7c478bd9Sstevel@tonic-gate 
1391*7c478bd9Sstevel@tonic-gate   serverconn->sparams->callbacks = callbacks;
1392*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1393*7c478bd9Sstevel@tonic-gate 
1394*7c478bd9Sstevel@tonic-gate   log_level = NULL;
1395*7c478bd9Sstevel@tonic-gate   if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) {
1396*7c478bd9Sstevel@tonic-gate     getopt(context, NULL, "log_level", &log_level, NULL);
1397*7c478bd9Sstevel@tonic-gate   }
1398*7c478bd9Sstevel@tonic-gate   serverconn->sparams->log_level = log_level ? atoi(log_level) : SASL_LOG_ERR;
1399*7c478bd9Sstevel@tonic-gate 
1400*7c478bd9Sstevel@tonic-gate   serverconn->sparams->utils = utils;
1401*7c478bd9Sstevel@tonic-gate   serverconn->sparams->transition = &_sasl_transition;
1402*7c478bd9Sstevel@tonic-gate   serverconn->sparams->canon_user = &_sasl_canon_user;
1403*7c478bd9Sstevel@tonic-gate   serverconn->sparams->props = serverconn->base.props;
1404*7c478bd9Sstevel@tonic-gate   serverconn->sparams->flags = flags;
1405*7c478bd9Sstevel@tonic-gate 
1406*7c478bd9Sstevel@tonic-gate   if(result == SASL_OK) return SASL_OK;
1407*7c478bd9Sstevel@tonic-gate 
1408*7c478bd9Sstevel@tonic-gate  done_error:
1409*7c478bd9Sstevel@tonic-gate   _sasl_conn_dispose(*pconn);
1410*7c478bd9Sstevel@tonic-gate   sasl_FREE(*pconn);
1411*7c478bd9Sstevel@tonic-gate   *pconn = NULL;
1412*7c478bd9Sstevel@tonic-gate   return result;
1413*7c478bd9Sstevel@tonic-gate }
1414*7c478bd9Sstevel@tonic-gate 
1415*7c478bd9Sstevel@tonic-gate /*
1416*7c478bd9Sstevel@tonic-gate  * The rule is:
1417*7c478bd9Sstevel@tonic-gate  * IF mech strength + external strength < min ssf THEN FAIL
1418*7c478bd9Sstevel@tonic-gate  * We also have to look at the security properties and make sure
1419*7c478bd9Sstevel@tonic-gate  * that this mechanism has everything we want
1420*7c478bd9Sstevel@tonic-gate  */
1421*7c478bd9Sstevel@tonic-gate static int mech_permitted(sasl_conn_t *conn,
1422*7c478bd9Sstevel@tonic-gate 			  mechanism_t *mech)
1423*7c478bd9Sstevel@tonic-gate {
1424*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *s_conn = (sasl_server_conn_t *)conn;
1425*7c478bd9Sstevel@tonic-gate     const sasl_server_plug_t *plug;
1426*7c478bd9Sstevel@tonic-gate     int myflags;
1427*7c478bd9Sstevel@tonic-gate     context_list_t *cur;
1428*7c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
1429*7c478bd9Sstevel@tonic-gate     void *context;
1430*7c478bd9Sstevel@tonic-gate     sasl_ssf_t minssf = 0;
1431*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1432*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx;
1433*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1434*7c478bd9Sstevel@tonic-gate 
1435*7c478bd9Sstevel@tonic-gate     if(!conn) return 0;
1436*7c478bd9Sstevel@tonic-gate 
1437*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1438*7c478bd9Sstevel@tonic-gate     gctx = conn->gctx;
1439*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1440*7c478bd9Sstevel@tonic-gate 
1441*7c478bd9Sstevel@tonic-gate     if(! mech || ! mech->plug) {
1442*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1443*7c478bd9Sstevel@tonic-gate 	if(conn) _sasl_log(conn, SASL_LOG_WARN, "Parameter error");
1444*7c478bd9Sstevel@tonic-gate #else
1445*7c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
1446*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1447*7c478bd9Sstevel@tonic-gate 	return 0;
1448*7c478bd9Sstevel@tonic-gate     }
1449*7c478bd9Sstevel@tonic-gate 
1450*7c478bd9Sstevel@tonic-gate     plug = mech->plug;
1451*7c478bd9Sstevel@tonic-gate 
1452*7c478bd9Sstevel@tonic-gate     /* get the list of allowed mechanisms (default = all) */
1453*7c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
1454*7c478bd9Sstevel@tonic-gate             == SASL_OK) {
1455*7c478bd9Sstevel@tonic-gate 	const char *mlist = NULL;
1456*7c478bd9Sstevel@tonic-gate 
1457*7c478bd9Sstevel@tonic-gate 	getopt(context, NULL, "mech_list", &mlist, NULL);
1458*7c478bd9Sstevel@tonic-gate 
1459*7c478bd9Sstevel@tonic-gate 	/* if we have a list, check the plugin against it */
1460*7c478bd9Sstevel@tonic-gate 	if (mlist) {
1461*7c478bd9Sstevel@tonic-gate 	    const char *cp;
1462*7c478bd9Sstevel@tonic-gate 
1463*7c478bd9Sstevel@tonic-gate 	    while (*mlist) {
1464*7c478bd9Sstevel@tonic-gate 		for (cp = mlist; *cp && !isspace((int) *cp); cp++);
1465*7c478bd9Sstevel@tonic-gate 		if (((size_t) (cp - mlist) == strlen(plug->mech_name)) &&
1466*7c478bd9Sstevel@tonic-gate 		    !strncasecmp(mlist, plug->mech_name,
1467*7c478bd9Sstevel@tonic-gate 				 strlen(plug->mech_name))) {
1468*7c478bd9Sstevel@tonic-gate 		    break;
1469*7c478bd9Sstevel@tonic-gate 		}
1470*7c478bd9Sstevel@tonic-gate 		mlist = cp;
1471*7c478bd9Sstevel@tonic-gate 		while (*mlist && isspace((int) *mlist)) mlist++;
1472*7c478bd9Sstevel@tonic-gate 	    }
1473*7c478bd9Sstevel@tonic-gate 
1474*7c478bd9Sstevel@tonic-gate 	    if (!*mlist) return 0;  /* reached EOS -> not in our list */
1475*7c478bd9Sstevel@tonic-gate 	}
1476*7c478bd9Sstevel@tonic-gate     }
1477*7c478bd9Sstevel@tonic-gate 
1478*7c478bd9Sstevel@tonic-gate     /* setup parameters for the call to mech_avail */
1479*7c478bd9Sstevel@tonic-gate     s_conn->sparams->serverFQDN=conn->serverFQDN;
1480*7c478bd9Sstevel@tonic-gate     s_conn->sparams->service=conn->service;
1481*7c478bd9Sstevel@tonic-gate     s_conn->sparams->user_realm=s_conn->user_realm;
1482*7c478bd9Sstevel@tonic-gate     s_conn->sparams->props=conn->props;
1483*7c478bd9Sstevel@tonic-gate     s_conn->sparams->external_ssf=conn->external.ssf;
1484*7c478bd9Sstevel@tonic-gate 
1485*7c478bd9Sstevel@tonic-gate     /* Check if we have banished this one already */
1486*7c478bd9Sstevel@tonic-gate     for(cur = s_conn->mech_contexts; cur; cur=cur->next) {
1487*7c478bd9Sstevel@tonic-gate 	if(cur->mech == mech) {
1488*7c478bd9Sstevel@tonic-gate 	    /* If it's not mech_avail'd, then stop now */
1489*7c478bd9Sstevel@tonic-gate 	    if(!cur->context) return 0;
1490*7c478bd9Sstevel@tonic-gate 	    break;
1491*7c478bd9Sstevel@tonic-gate 	}
1492*7c478bd9Sstevel@tonic-gate     }
1493*7c478bd9Sstevel@tonic-gate 
1494*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE START */
1495*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE START */
1496*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1497*7c478bd9Sstevel@tonic-gate     if (!mech->sun_reg) {
1498*7c478bd9Sstevel@tonic-gate 	s_conn->sparams->props.min_ssf = 0;
1499*7c478bd9Sstevel@tonic-gate 	s_conn->sparams->props.max_ssf = 0;
1500*7c478bd9Sstevel@tonic-gate     }
1501*7c478bd9Sstevel@tonic-gate     s_conn->base.sun_reg = mech->sun_reg;
1502*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1503*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE END */
1504*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE END */
1505*7c478bd9Sstevel@tonic-gate     if (conn->props.min_ssf < conn->external.ssf) {
1506*7c478bd9Sstevel@tonic-gate 	minssf = 0;
1507*7c478bd9Sstevel@tonic-gate     } else {
1508*7c478bd9Sstevel@tonic-gate 	minssf = conn->props.min_ssf - conn->external.ssf;
1509*7c478bd9Sstevel@tonic-gate     }
1510*7c478bd9Sstevel@tonic-gate 
1511*7c478bd9Sstevel@tonic-gate     /* Generic mechanism */
1512*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE START */
1513*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE START */
1514*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1515*7c478bd9Sstevel@tonic-gate     /* If not SUN supplied mech, it has no strength */
1516*7c478bd9Sstevel@tonic-gate     if (plug->max_ssf < minssf || (minssf > 0 && !mech->sun_reg)) {
1517*7c478bd9Sstevel@tonic-gate #else
1518*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE END */
1519*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE END */
1520*7c478bd9Sstevel@tonic-gate     if (plug->max_ssf < minssf) {
1521*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE START */
1522*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE START */
1523*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1524*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE END */
1525*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE END */
1526*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1527*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, SASL_NOLOG,
1528*7c478bd9Sstevel@tonic-gate 		      gettext("mech %s is too weak"), plug->mech_name);
1529*7c478bd9Sstevel@tonic-gate #else
1530*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, SASL_NOLOG,
1531*7c478bd9Sstevel@tonic-gate 		      "mech %s is too weak", plug->mech_name);
1532*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1533*7c478bd9Sstevel@tonic-gate 	return 0; /* too weak */
1534*7c478bd9Sstevel@tonic-gate     }
1535*7c478bd9Sstevel@tonic-gate 
1536*7c478bd9Sstevel@tonic-gate     context = NULL;
1537*7c478bd9Sstevel@tonic-gate     if(plug->mech_avail
1538*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1539*7c478bd9Sstevel@tonic-gate        && plug->mech_avail(mech->glob_context,
1540*7c478bd9Sstevel@tonic-gate #else
1541*7c478bd9Sstevel@tonic-gate        && plug->mech_avail(plug->glob_context,
1542*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1543*7c478bd9Sstevel@tonic-gate 			   s_conn->sparams, (void **)&context) != SASL_OK ) {
1544*7c478bd9Sstevel@tonic-gate 	/* Mark this mech as no good for this connection */
1545*7c478bd9Sstevel@tonic-gate 	cur = sasl_ALLOC(sizeof(context_list_t));
1546*7c478bd9Sstevel@tonic-gate 	if(!cur) {
1547*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1548*7c478bd9Sstevel@tonic-gate 	    if(conn) _sasl_log(conn, SASL_LOG_WARN, "Out of Memory");
1549*7c478bd9Sstevel@tonic-gate #else
1550*7c478bd9Sstevel@tonic-gate 	    MEMERROR(conn);
1551*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1552*7c478bd9Sstevel@tonic-gate 	    return 0;
1553*7c478bd9Sstevel@tonic-gate 	}
1554*7c478bd9Sstevel@tonic-gate 	cur->context = NULL;
1555*7c478bd9Sstevel@tonic-gate 	cur->mech = mech;
1556*7c478bd9Sstevel@tonic-gate 	cur->next = s_conn->mech_contexts;
1557*7c478bd9Sstevel@tonic-gate 	s_conn->mech_contexts = cur;
1558*7c478bd9Sstevel@tonic-gate 
1559*7c478bd9Sstevel@tonic-gate 	/* Error should be set by mech_avail call */
1560*7c478bd9Sstevel@tonic-gate 	return 0;
1561*7c478bd9Sstevel@tonic-gate     } else if(context) {
1562*7c478bd9Sstevel@tonic-gate 	/* Save this context */
1563*7c478bd9Sstevel@tonic-gate 	cur = sasl_ALLOC(sizeof(context_list_t));
1564*7c478bd9Sstevel@tonic-gate 	if(!cur) {
1565*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1566*7c478bd9Sstevel@tonic-gate 	    if(conn) _sasl_log(conn, SASL_LOG_WARN, "Out of Memory");
1567*7c478bd9Sstevel@tonic-gate #else
1568*7c478bd9Sstevel@tonic-gate 	    MEMERROR(conn);
1569*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1570*7c478bd9Sstevel@tonic-gate 	    return 0;
1571*7c478bd9Sstevel@tonic-gate 	}
1572*7c478bd9Sstevel@tonic-gate 	cur->context = context;
1573*7c478bd9Sstevel@tonic-gate 	cur->mech = mech;
1574*7c478bd9Sstevel@tonic-gate 	cur->next = s_conn->mech_contexts;
1575*7c478bd9Sstevel@tonic-gate 	s_conn->mech_contexts = cur;
1576*7c478bd9Sstevel@tonic-gate     }
1577*7c478bd9Sstevel@tonic-gate 
1578*7c478bd9Sstevel@tonic-gate     /* Generic mechanism */
1579*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE START */
1580*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE START */
1581*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1582*7c478bd9Sstevel@tonic-gate     /* If not SUN supplied mech, it has no strength */
1583*7c478bd9Sstevel@tonic-gate     if (plug->max_ssf < minssf || (minssf > 0 && !mech->sun_reg)) {
1584*7c478bd9Sstevel@tonic-gate #else
1585*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE END */
1586*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE END */
1587*7c478bd9Sstevel@tonic-gate     if (plug->max_ssf < minssf) {
1588*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE START */
1589*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE START */
1590*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1591*7c478bd9Sstevel@tonic-gate     /* CRYPT DELETE END */
1592*7c478bd9Sstevel@tonic-gate     /* EXPORT DELETE END */
1593*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1594*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, SASL_NOLOG, gettext("too weak"));
1595*7c478bd9Sstevel@tonic-gate #else
1596*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, SASL_NOLOG, "too weak");
1597*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1598*7c478bd9Sstevel@tonic-gate 	return 0; /* too weak */
1599*7c478bd9Sstevel@tonic-gate     }
1600*7c478bd9Sstevel@tonic-gate 
1601*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1602*7c478bd9Sstevel@tonic-gate     /* if there are no users in the secrets database we can't use this
1603*7c478bd9Sstevel@tonic-gate        mechanism */
1604*7c478bd9Sstevel@tonic-gate     if (mech->condition == SASL_NOUSER) {
1605*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, "no users in secrets db");
1606*7c478bd9Sstevel@tonic-gate 	return 0;
1607*7c478bd9Sstevel@tonic-gate     }
1608*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1609*7c478bd9Sstevel@tonic-gate 
1610*7c478bd9Sstevel@tonic-gate     /* Can it meet our features? */
1611*7c478bd9Sstevel@tonic-gate     if ((conn->flags & SASL_NEED_PROXY) &&
1612*7c478bd9Sstevel@tonic-gate 	!(plug->features & SASL_FEAT_ALLOWS_PROXY)) {
1613*7c478bd9Sstevel@tonic-gate 	return 0;
1614*7c478bd9Sstevel@tonic-gate     }
1615*7c478bd9Sstevel@tonic-gate 
1616*7c478bd9Sstevel@tonic-gate     /* security properties---if there are any flags that differ and are
1617*7c478bd9Sstevel@tonic-gate        in what the connection are requesting, then fail */
1618*7c478bd9Sstevel@tonic-gate 
1619*7c478bd9Sstevel@tonic-gate     /* special case plaintext */
1620*7c478bd9Sstevel@tonic-gate     myflags = conn->props.security_flags;
1621*7c478bd9Sstevel@tonic-gate 
1622*7c478bd9Sstevel@tonic-gate     /* if there's an external layer this is no longer plaintext */
1623*7c478bd9Sstevel@tonic-gate     if ((conn->props.min_ssf <= conn->external.ssf) &&
1624*7c478bd9Sstevel@tonic-gate 	(conn->external.ssf > 1)) {
1625*7c478bd9Sstevel@tonic-gate 	myflags &= ~SASL_SEC_NOPLAINTEXT;
1626*7c478bd9Sstevel@tonic-gate     }
1627*7c478bd9Sstevel@tonic-gate 
1628*7c478bd9Sstevel@tonic-gate     /* do we want to special case SASL_SEC_PASS_CREDENTIALS? nah.. */
1629*7c478bd9Sstevel@tonic-gate     if (((myflags ^ plug->security_flags) & myflags) != 0) {
1630*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1631*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, SASL_NOLOG,
1632*7c478bd9Sstevel@tonic-gate 		      gettext("security flags do not match required"));
1633*7c478bd9Sstevel@tonic-gate #else
1634*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, SASL_NOLOG,
1635*7c478bd9Sstevel@tonic-gate 		      "security flags do not match required");
1636*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1637*7c478bd9Sstevel@tonic-gate 	return 0;
1638*7c478bd9Sstevel@tonic-gate     }
1639*7c478bd9Sstevel@tonic-gate 
1640*7c478bd9Sstevel@tonic-gate     /* Check Features */
1641*7c478bd9Sstevel@tonic-gate     if(plug->features & SASL_FEAT_GETSECRET) {
1642*7c478bd9Sstevel@tonic-gate 	/* We no longer support sasl_server_{get,put}secret */
1643*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1644*7c478bd9Sstevel@tonic-gate 	_sasl_log(conn, SASL_LOG_ERR,
1645*7c478bd9Sstevel@tonic-gate 		  "mech %s requires unprovided secret facility",
1646*7c478bd9Sstevel@tonic-gate 		  plug->mech_name);
1647*7c478bd9Sstevel@tonic-gate #else
1648*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0,
1649*7c478bd9Sstevel@tonic-gate 		      "mech %s requires unprovided secret facility",
1650*7c478bd9Sstevel@tonic-gate 		      plug->mech_name);
1651*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1652*7c478bd9Sstevel@tonic-gate 	return 0;
1653*7c478bd9Sstevel@tonic-gate     }
1654*7c478bd9Sstevel@tonic-gate 
1655*7c478bd9Sstevel@tonic-gate     return 1;
1656*7c478bd9Sstevel@tonic-gate }
1657*7c478bd9Sstevel@tonic-gate 
1658*7c478bd9Sstevel@tonic-gate /*
1659*7c478bd9Sstevel@tonic-gate  * make the authorization
1660*7c478bd9Sstevel@tonic-gate  *
1661*7c478bd9Sstevel@tonic-gate  */
1662*7c478bd9Sstevel@tonic-gate 
1663*7c478bd9Sstevel@tonic-gate static int do_authorization(sasl_server_conn_t *s_conn)
1664*7c478bd9Sstevel@tonic-gate {
1665*7c478bd9Sstevel@tonic-gate     int ret;
1666*7c478bd9Sstevel@tonic-gate     sasl_authorize_t *authproc;
1667*7c478bd9Sstevel@tonic-gate     void *auth_context;
1668*7c478bd9Sstevel@tonic-gate 
1669*7c478bd9Sstevel@tonic-gate     /* now let's see if authname is allowed to proxy for username! */
1670*7c478bd9Sstevel@tonic-gate 
1671*7c478bd9Sstevel@tonic-gate     /* check the proxy callback */
1672*7c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(&s_conn->base, SASL_CB_PROXY_POLICY,
1673*7c478bd9Sstevel@tonic-gate 			  &authproc, &auth_context) != SASL_OK) {
1674*7c478bd9Sstevel@tonic-gate 	INTERROR(&s_conn->base, SASL_NOAUTHZ);
1675*7c478bd9Sstevel@tonic-gate     }
1676*7c478bd9Sstevel@tonic-gate 
1677*7c478bd9Sstevel@tonic-gate     ret = authproc(&(s_conn->base), auth_context,
1678*7c478bd9Sstevel@tonic-gate 		   s_conn->base.oparams.user, s_conn->base.oparams.ulen,
1679*7c478bd9Sstevel@tonic-gate 		   s_conn->base.oparams.authid, s_conn->base.oparams.alen,
1680*7c478bd9Sstevel@tonic-gate 		   s_conn->user_realm,
1681*7c478bd9Sstevel@tonic-gate 		   (s_conn->user_realm ? strlen(s_conn->user_realm) : 0),
1682*7c478bd9Sstevel@tonic-gate 		   s_conn->sparams->propctx);
1683*7c478bd9Sstevel@tonic-gate 
1684*7c478bd9Sstevel@tonic-gate     RETURN(&s_conn->base, ret);
1685*7c478bd9Sstevel@tonic-gate }
1686*7c478bd9Sstevel@tonic-gate 
1687*7c478bd9Sstevel@tonic-gate 
1688*7c478bd9Sstevel@tonic-gate /* start a mechanism exchange within a connection context
1689*7c478bd9Sstevel@tonic-gate  *  mech           -- the mechanism name client requested
1690*7c478bd9Sstevel@tonic-gate  *  clientin       -- client initial response (NUL terminated), NULL if empty
1691*7c478bd9Sstevel@tonic-gate  *  clientinlen    -- length of initial response
1692*7c478bd9Sstevel@tonic-gate  *  serverout      -- initial server challenge, NULL if done
1693*7c478bd9Sstevel@tonic-gate  *                    (library handles freeing this string)
1694*7c478bd9Sstevel@tonic-gate  *  serveroutlen   -- length of initial server challenge
1695*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1696*7c478bd9Sstevel@tonic-gate  * conn            -- the sasl connection
1697*7c478bd9Sstevel@tonic-gate #else
1698*7c478bd9Sstevel@tonic-gate  * output:
1699*7c478bd9Sstevel@tonic-gate  *  pconn          -- the connection negotiation state on success
1700*7c478bd9Sstevel@tonic-gate #endif
1701*7c478bd9Sstevel@tonic-gate  *
1702*7c478bd9Sstevel@tonic-gate  * Same returns as sasl_server_step() or
1703*7c478bd9Sstevel@tonic-gate  * SASL_NOMECH if mechanism not available.
1704*7c478bd9Sstevel@tonic-gate  */
1705*7c478bd9Sstevel@tonic-gate int sasl_server_start(sasl_conn_t *conn,
1706*7c478bd9Sstevel@tonic-gate 		      const char *mech,
1707*7c478bd9Sstevel@tonic-gate 		      const char *clientin,
1708*7c478bd9Sstevel@tonic-gate 		      unsigned clientinlen,
1709*7c478bd9Sstevel@tonic-gate 		      const char **serverout,
1710*7c478bd9Sstevel@tonic-gate 		      unsigned *serveroutlen)
1711*7c478bd9Sstevel@tonic-gate {
1712*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *s_conn=(sasl_server_conn_t *) conn;
1713*7c478bd9Sstevel@tonic-gate     int result;
1714*7c478bd9Sstevel@tonic-gate     context_list_t *cur, **prev;
1715*7c478bd9Sstevel@tonic-gate     mechanism_t *m;
1716*7c478bd9Sstevel@tonic-gate 
1717*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1718*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx =
1719*7c478bd9Sstevel@tonic-gate 		 (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
1720*7c478bd9Sstevel@tonic-gate     mech_list_t *mechlist;
1721*7c478bd9Sstevel@tonic-gate 
1722*7c478bd9Sstevel@tonic-gate     if (gctx->sasl_server_active==0) return SASL_NOTINIT;
1723*7c478bd9Sstevel@tonic-gate     if (! conn)
1724*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
1725*7c478bd9Sstevel@tonic-gate 
1726*7c478bd9Sstevel@tonic-gate     (void)_load_server_plugins(gctx);
1727*7c478bd9Sstevel@tonic-gate     mechlist = gctx->mechlist;
1728*7c478bd9Sstevel@tonic-gate     m=mechlist->mech_list;
1729*7c478bd9Sstevel@tonic-gate     result = load_config(gctx, _sasl_find_verifyfile_callback(
1730*7c478bd9Sstevel@tonic-gate 	gctx->server_global_callbacks.callbacks));
1731*7c478bd9Sstevel@tonic-gate     if (result != SASL_OK)
1732*7c478bd9Sstevel@tonic-gate 	return (result);
1733*7c478bd9Sstevel@tonic-gate #else
1734*7c478bd9Sstevel@tonic-gate     if (_sasl_server_active==0) return SASL_NOTINIT;
1735*7c478bd9Sstevel@tonic-gate 
1736*7c478bd9Sstevel@tonic-gate     /* make sure mech is valid mechanism
1737*7c478bd9Sstevel@tonic-gate        if not return appropriate error */
1738*7c478bd9Sstevel@tonic-gate     m=mechlist->mech_list;
1739*7c478bd9Sstevel@tonic-gate 
1740*7c478bd9Sstevel@tonic-gate     /* check parameters */
1741*7c478bd9Sstevel@tonic-gate     if(!conn) return SASL_BADPARAM;
1742*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1743*7c478bd9Sstevel@tonic-gate 
1744*7c478bd9Sstevel@tonic-gate     if (!mech || ((clientin==NULL) && (clientinlen>0)))
1745*7c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
1746*7c478bd9Sstevel@tonic-gate 
1747*7c478bd9Sstevel@tonic-gate     if(serverout) *serverout = NULL;
1748*7c478bd9Sstevel@tonic-gate     if(serveroutlen) *serveroutlen = 0;
1749*7c478bd9Sstevel@tonic-gate 
1750*7c478bd9Sstevel@tonic-gate     while (m!=NULL)
1751*7c478bd9Sstevel@tonic-gate     {
1752*7c478bd9Sstevel@tonic-gate 	if ( strcasecmp(mech,m->plug->mech_name)==0)
1753*7c478bd9Sstevel@tonic-gate 	{
1754*7c478bd9Sstevel@tonic-gate 	    break;
1755*7c478bd9Sstevel@tonic-gate 	}
1756*7c478bd9Sstevel@tonic-gate 	m=m->next;
1757*7c478bd9Sstevel@tonic-gate     }
1758*7c478bd9Sstevel@tonic-gate 
1759*7c478bd9Sstevel@tonic-gate     if (m==NULL) {
1760*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1761*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, gettext("Couldn't find mech %s"), mech);
1762*7c478bd9Sstevel@tonic-gate #else
1763*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, "Couldn't find mech %s", mech);
1764*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
1765*7c478bd9Sstevel@tonic-gate 	result = SASL_NOMECH;
1766*7c478bd9Sstevel@tonic-gate 	goto done;
1767*7c478bd9Sstevel@tonic-gate     }
1768*7c478bd9Sstevel@tonic-gate 
1769*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1770*7c478bd9Sstevel@tonic-gate     server_dispose_mech_contexts(conn);
1771*7c478bd9Sstevel@tonic-gate #endif /*_SUN_SDK_ */
1772*7c478bd9Sstevel@tonic-gate 
1773*7c478bd9Sstevel@tonic-gate     /* Make sure that we're willing to use this mech */
1774*7c478bd9Sstevel@tonic-gate     if (! mech_permitted(conn, m)) {
1775*7c478bd9Sstevel@tonic-gate 	result = SASL_NOMECH;
1776*7c478bd9Sstevel@tonic-gate 	goto done;
1777*7c478bd9Sstevel@tonic-gate     }
1778*7c478bd9Sstevel@tonic-gate 
1779*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1780*7c478bd9Sstevel@tonic-gate     if(conn->context) {
1781*7c478bd9Sstevel@tonic-gate 	s_conn->mech->plug->mech_dispose(conn->context, s_conn->sparams->utils);
1782*7c478bd9Sstevel@tonic-gate 	conn->context = NULL;
1783*7c478bd9Sstevel@tonic-gate     }
1784*7c478bd9Sstevel@tonic-gate     memset(&conn->oparams, 0, sizeof(sasl_out_params_t));
1785*7c478bd9Sstevel@tonic-gate #else
1786*7c478bd9Sstevel@tonic-gate     if (m->condition == SASL_CONTINUE) {
1787*7c478bd9Sstevel@tonic-gate 	sasl_server_plug_init_t *entry_point;
1788*7c478bd9Sstevel@tonic-gate 	void *library = NULL;
1789*7c478bd9Sstevel@tonic-gate 	sasl_server_plug_t *pluglist;
1790*7c478bd9Sstevel@tonic-gate 	int version, plugcount;
1791*7c478bd9Sstevel@tonic-gate 	int l = 0;
1792*7c478bd9Sstevel@tonic-gate 
1793*7c478bd9Sstevel@tonic-gate 	/* need to load this plugin */
1794*7c478bd9Sstevel@tonic-gate 	result = _sasl_get_plugin(m->f,
1795*7c478bd9Sstevel@tonic-gate 		    _sasl_find_verifyfile_callback(global_callbacks.callbacks),
1796*7c478bd9Sstevel@tonic-gate 				  &library);
1797*7c478bd9Sstevel@tonic-gate 
1798*7c478bd9Sstevel@tonic-gate 	if (result == SASL_OK) {
1799*7c478bd9Sstevel@tonic-gate 	    result = _sasl_locate_entry(library, "sasl_server_plug_init",
1800*7c478bd9Sstevel@tonic-gate 					(void **)&entry_point);
1801*7c478bd9Sstevel@tonic-gate 	}
1802*7c478bd9Sstevel@tonic-gate 
1803*7c478bd9Sstevel@tonic-gate 	if (result == SASL_OK) {
1804*7c478bd9Sstevel@tonic-gate 	    result = entry_point(mechlist->utils, SASL_SERVER_PLUG_VERSION,
1805*7c478bd9Sstevel@tonic-gate 				 &version, &pluglist, &plugcount);
1806*7c478bd9Sstevel@tonic-gate 	}
1807*7c478bd9Sstevel@tonic-gate 
1808*7c478bd9Sstevel@tonic-gate 	if (result == SASL_OK) {
1809*7c478bd9Sstevel@tonic-gate 	    /* find the correct mechanism in this plugin */
1810*7c478bd9Sstevel@tonic-gate 	    for (l = 0; l < plugcount; l++) {
1811*7c478bd9Sstevel@tonic-gate 		if (!strcasecmp(pluglist[l].mech_name,
1812*7c478bd9Sstevel@tonic-gate 				m->plug->mech_name)) break;
1813*7c478bd9Sstevel@tonic-gate 	    }
1814*7c478bd9Sstevel@tonic-gate 	    if (l == plugcount) {
1815*7c478bd9Sstevel@tonic-gate 		result = SASL_NOMECH;
1816*7c478bd9Sstevel@tonic-gate 	    }
1817*7c478bd9Sstevel@tonic-gate 	}
1818*7c478bd9Sstevel@tonic-gate 	if (result == SASL_OK) {
1819*7c478bd9Sstevel@tonic-gate 	    /* check that the parameters are the same */
1820*7c478bd9Sstevel@tonic-gate 	    if ((pluglist[l].max_ssf != m->plug->max_ssf) ||
1821*7c478bd9Sstevel@tonic-gate 		(pluglist[l].security_flags != m->plug->security_flags)) {
1822*7c478bd9Sstevel@tonic-gate 		_sasl_log(conn, SASL_LOG_ERR,
1823*7c478bd9Sstevel@tonic-gate 			  "%s: security parameters don't match mechlist file",
1824*7c478bd9Sstevel@tonic-gate 			  pluglist[l].mech_name);
1825*7c478bd9Sstevel@tonic-gate 		result = SASL_NOMECH;
1826*7c478bd9Sstevel@tonic-gate 	    }
1827*7c478bd9Sstevel@tonic-gate 	}
1828*7c478bd9Sstevel@tonic-gate 	if (result == SASL_OK) {
1829*7c478bd9Sstevel@tonic-gate 	    /* copy mechlist over */
1830*7c478bd9Sstevel@tonic-gate 	    sasl_FREE((sasl_server_plug_t *) m->plug);
1831*7c478bd9Sstevel@tonic-gate 	    m->plug = &pluglist[l];
1832*7c478bd9Sstevel@tonic-gate 	    m->condition = SASL_OK;
1833*7c478bd9Sstevel@tonic-gate 	}
1834*7c478bd9Sstevel@tonic-gate 
1835*7c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) {
1836*7c478bd9Sstevel@tonic-gate 	    /* The library will eventually be freed, don't sweat it */
1837*7c478bd9Sstevel@tonic-gate 	    RETURN(conn, result);
1838*7c478bd9Sstevel@tonic-gate 	}
1839*7c478bd9Sstevel@tonic-gate     }
1840*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1841*7c478bd9Sstevel@tonic-gate 
1842*7c478bd9Sstevel@tonic-gate     /* We used to setup sparams HERE, but now it's done
1843*7c478bd9Sstevel@tonic-gate        inside of mech_permitted (which is called above) */
1844*7c478bd9Sstevel@tonic-gate     prev = &s_conn->mech_contexts;
1845*7c478bd9Sstevel@tonic-gate     for(cur = *prev; cur; prev=&cur->next,cur=cur->next) {
1846*7c478bd9Sstevel@tonic-gate 	if(cur->mech == m) {
1847*7c478bd9Sstevel@tonic-gate 	    if(!cur->context) {
1848*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1849*7c478bd9Sstevel@tonic-gate 		_sasl_log(conn, SASL_LOG_ERR,
1850*7c478bd9Sstevel@tonic-gate 			  "Got past mech_permitted with a disallowed mech!");
1851*7c478bd9Sstevel@tonic-gate #else
1852*7c478bd9Sstevel@tonic-gate 		sasl_seterror(conn, 0,
1853*7c478bd9Sstevel@tonic-gate 			      "Got past mech_permitted with a disallowed mech!");
1854*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1855*7c478bd9Sstevel@tonic-gate 		return SASL_NOMECH;
1856*7c478bd9Sstevel@tonic-gate 	    }
1857*7c478bd9Sstevel@tonic-gate 	    /* If we find it, we need to pull cur out of the
1858*7c478bd9Sstevel@tonic-gate 	       list so it won't be freed later! */
1859*7c478bd9Sstevel@tonic-gate 	    (*prev)->next = cur->next;
1860*7c478bd9Sstevel@tonic-gate 	    conn->context = cur->context;
1861*7c478bd9Sstevel@tonic-gate 	    sasl_FREE(cur);
1862*7c478bd9Sstevel@tonic-gate 	}
1863*7c478bd9Sstevel@tonic-gate     }
1864*7c478bd9Sstevel@tonic-gate 
1865*7c478bd9Sstevel@tonic-gate     s_conn->mech = m;
1866*7c478bd9Sstevel@tonic-gate 
1867*7c478bd9Sstevel@tonic-gate     if(!conn->context) {
1868*7c478bd9Sstevel@tonic-gate 	/* Note that we don't hand over a new challenge */
1869*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1870*7c478bd9Sstevel@tonic-gate 	result = s_conn->mech->plug->mech_new(s_conn->mech->glob_context,
1871*7c478bd9Sstevel@tonic-gate #else
1872*7c478bd9Sstevel@tonic-gate 	result = s_conn->mech->plug->mech_new(s_conn->mech->plug->glob_context,
1873*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1874*7c478bd9Sstevel@tonic-gate 					      s_conn->sparams,
1875*7c478bd9Sstevel@tonic-gate 					      NULL,
1876*7c478bd9Sstevel@tonic-gate 					      0,
1877*7c478bd9Sstevel@tonic-gate 					      &(conn->context));
1878*7c478bd9Sstevel@tonic-gate     } else {
1879*7c478bd9Sstevel@tonic-gate 	/* the work was already done by mech_avail! */
1880*7c478bd9Sstevel@tonic-gate 	result = SASL_OK;
1881*7c478bd9Sstevel@tonic-gate     }
1882*7c478bd9Sstevel@tonic-gate 
1883*7c478bd9Sstevel@tonic-gate     if (result == SASL_OK) {
1884*7c478bd9Sstevel@tonic-gate          if(clientin) {
1885*7c478bd9Sstevel@tonic-gate             if(s_conn->mech->plug->features & SASL_FEAT_SERVER_FIRST) {
1886*7c478bd9Sstevel@tonic-gate                 /* Remote sent first, but mechanism does not support it.
1887*7c478bd9Sstevel@tonic-gate                  * RFC 2222 says we fail at this point. */
1888*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1889*7c478bd9Sstevel@tonic-gate 		_sasl_log(conn, SASL_LOG_ERR,
1890*7c478bd9Sstevel@tonic-gate                           "Remote sent first but mech does not allow it.");
1891*7c478bd9Sstevel@tonic-gate #else
1892*7c478bd9Sstevel@tonic-gate                 sasl_seterror(conn, 0,
1893*7c478bd9Sstevel@tonic-gate                               "Remote sent first but mech does not allow it.");
1894*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1895*7c478bd9Sstevel@tonic-gate                 result = SASL_BADPROT;
1896*7c478bd9Sstevel@tonic-gate             } else {
1897*7c478bd9Sstevel@tonic-gate                 /* Mech wants client-first, so let them have it */
1898*7c478bd9Sstevel@tonic-gate                 result = sasl_server_step(conn,
1899*7c478bd9Sstevel@tonic-gate                                           clientin, clientinlen,
1900*7c478bd9Sstevel@tonic-gate                                           serverout, serveroutlen);
1901*7c478bd9Sstevel@tonic-gate             }
1902*7c478bd9Sstevel@tonic-gate         } else {
1903*7c478bd9Sstevel@tonic-gate             if(s_conn->mech->plug->features & SASL_FEAT_WANT_CLIENT_FIRST) {
1904*7c478bd9Sstevel@tonic-gate                 /* Mech wants client first anyway, so we should do that */
1905*7c478bd9Sstevel@tonic-gate                 *serverout = "";
1906*7c478bd9Sstevel@tonic-gate                 *serveroutlen = 0;
1907*7c478bd9Sstevel@tonic-gate                 result = SASL_CONTINUE;
1908*7c478bd9Sstevel@tonic-gate             } else {
1909*7c478bd9Sstevel@tonic-gate                 /* Mech wants server-first, so let them have it */
1910*7c478bd9Sstevel@tonic-gate                 result = sasl_server_step(conn,
1911*7c478bd9Sstevel@tonic-gate                                           clientin, clientinlen,
1912*7c478bd9Sstevel@tonic-gate                                           serverout, serveroutlen);
1913*7c478bd9Sstevel@tonic-gate             }
1914*7c478bd9Sstevel@tonic-gate 	}
1915*7c478bd9Sstevel@tonic-gate     }
1916*7c478bd9Sstevel@tonic-gate 
1917*7c478bd9Sstevel@tonic-gate  done:
1918*7c478bd9Sstevel@tonic-gate     if(   result != SASL_OK
1919*7c478bd9Sstevel@tonic-gate        && result != SASL_CONTINUE
1920*7c478bd9Sstevel@tonic-gate        && result != SASL_INTERACT) {
1921*7c478bd9Sstevel@tonic-gate 	if(conn->context) {
1922*7c478bd9Sstevel@tonic-gate 	    s_conn->mech->plug->mech_dispose(conn->context,
1923*7c478bd9Sstevel@tonic-gate 					     s_conn->sparams->utils);
1924*7c478bd9Sstevel@tonic-gate 	    conn->context = NULL;
1925*7c478bd9Sstevel@tonic-gate 	}
1926*7c478bd9Sstevel@tonic-gate     }
1927*7c478bd9Sstevel@tonic-gate 
1928*7c478bd9Sstevel@tonic-gate     RETURN(conn,result);
1929*7c478bd9Sstevel@tonic-gate }
1930*7c478bd9Sstevel@tonic-gate 
1931*7c478bd9Sstevel@tonic-gate 
1932*7c478bd9Sstevel@tonic-gate /* perform one step of the SASL exchange
1933*7c478bd9Sstevel@tonic-gate  *  inputlen & input -- client data
1934*7c478bd9Sstevel@tonic-gate  *                      NULL on first step if no optional client step
1935*7c478bd9Sstevel@tonic-gate  *  outputlen & output -- set to the server data to transmit
1936*7c478bd9Sstevel@tonic-gate  *                        to the client in the next step
1937*7c478bd9Sstevel@tonic-gate  *                        (library handles freeing this)
1938*7c478bd9Sstevel@tonic-gate  *
1939*7c478bd9Sstevel@tonic-gate  * returns:
1940*7c478bd9Sstevel@tonic-gate  *  SASL_OK        -- exchange is complete.
1941*7c478bd9Sstevel@tonic-gate  *  SASL_CONTINUE  -- indicates another step is necessary.
1942*7c478bd9Sstevel@tonic-gate  *  SASL_TRANS     -- entry for user exists, but not for mechanism
1943*7c478bd9Sstevel@tonic-gate  *                    and transition is possible
1944*7c478bd9Sstevel@tonic-gate  *  SASL_BADPARAM  -- service name needed
1945*7c478bd9Sstevel@tonic-gate  *  SASL_BADPROT   -- invalid input from client
1946*7c478bd9Sstevel@tonic-gate  *  ...
1947*7c478bd9Sstevel@tonic-gate  */
1948*7c478bd9Sstevel@tonic-gate 
1949*7c478bd9Sstevel@tonic-gate int sasl_server_step(sasl_conn_t *conn,
1950*7c478bd9Sstevel@tonic-gate 		     const char *clientin,
1951*7c478bd9Sstevel@tonic-gate 		     unsigned clientinlen,
1952*7c478bd9Sstevel@tonic-gate 		     const char **serverout,
1953*7c478bd9Sstevel@tonic-gate 		     unsigned *serveroutlen)
1954*7c478bd9Sstevel@tonic-gate {
1955*7c478bd9Sstevel@tonic-gate     int ret;
1956*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;  /* cast */
1957*7c478bd9Sstevel@tonic-gate 
1958*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1959*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx =
1960*7c478bd9Sstevel@tonic-gate 		 (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
1961*7c478bd9Sstevel@tonic-gate 
1962*7c478bd9Sstevel@tonic-gate     /* check parameters */
1963*7c478bd9Sstevel@tonic-gate     if (gctx->sasl_server_active==0) return SASL_NOTINIT;
1964*7c478bd9Sstevel@tonic-gate #else
1965*7c478bd9Sstevel@tonic-gate     /* check parameters */
1966*7c478bd9Sstevel@tonic-gate     if (_sasl_server_active==0) return SASL_NOTINIT;
1967*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1968*7c478bd9Sstevel@tonic-gate     if (!conn) return SASL_BADPARAM;
1969*7c478bd9Sstevel@tonic-gate     if ((clientin==NULL) && (clientinlen>0))
1970*7c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
1971*7c478bd9Sstevel@tonic-gate 
1972*7c478bd9Sstevel@tonic-gate     /* If we've already done the last send, return! */
1973*7c478bd9Sstevel@tonic-gate     if(s_conn->sent_last == 1) {
1974*7c478bd9Sstevel@tonic-gate 	return SASL_OK;
1975*7c478bd9Sstevel@tonic-gate     }
1976*7c478bd9Sstevel@tonic-gate 
1977*7c478bd9Sstevel@tonic-gate     /* Don't do another step if the plugin told us that we're done */
1978*7c478bd9Sstevel@tonic-gate     if (conn->oparams.doneflag) {
1979*7c478bd9Sstevel@tonic-gate 	_sasl_log(conn, SASL_LOG_ERR, "attempting server step after doneflag");
1980*7c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
1981*7c478bd9Sstevel@tonic-gate     }
1982*7c478bd9Sstevel@tonic-gate 
1983*7c478bd9Sstevel@tonic-gate     if(serverout) *serverout = NULL;
1984*7c478bd9Sstevel@tonic-gate     if(serveroutlen) *serveroutlen = 0;
1985*7c478bd9Sstevel@tonic-gate 
1986*7c478bd9Sstevel@tonic-gate     ret = s_conn->mech->plug->mech_step(conn->context,
1987*7c478bd9Sstevel@tonic-gate 					s_conn->sparams,
1988*7c478bd9Sstevel@tonic-gate 					clientin,
1989*7c478bd9Sstevel@tonic-gate 					clientinlen,
1990*7c478bd9Sstevel@tonic-gate 					serverout,
1991*7c478bd9Sstevel@tonic-gate 					serveroutlen,
1992*7c478bd9Sstevel@tonic-gate 					&conn->oparams);
1993*7c478bd9Sstevel@tonic-gate 
1994*7c478bd9Sstevel@tonic-gate     if (ret == SASL_OK) {
1995*7c478bd9Sstevel@tonic-gate 	ret = do_authorization(s_conn);
1996*7c478bd9Sstevel@tonic-gate     }
1997*7c478bd9Sstevel@tonic-gate 
1998*7c478bd9Sstevel@tonic-gate     if (ret == SASL_OK) {
1999*7c478bd9Sstevel@tonic-gate 	/* if we're done, we need to watch out for the following:
2000*7c478bd9Sstevel@tonic-gate 	 * 1. the mech does server-send-last
2001*7c478bd9Sstevel@tonic-gate 	 * 2. the protocol does not
2002*7c478bd9Sstevel@tonic-gate 	 *
2003*7c478bd9Sstevel@tonic-gate 	 * in this case, return SASL_CONTINUE and remember we are done.
2004*7c478bd9Sstevel@tonic-gate 	 */
2005*7c478bd9Sstevel@tonic-gate 	if(*serverout && !(conn->flags & SASL_SUCCESS_DATA)) {
2006*7c478bd9Sstevel@tonic-gate 	    s_conn->sent_last = 1;
2007*7c478bd9Sstevel@tonic-gate 	    ret = SASL_CONTINUE;
2008*7c478bd9Sstevel@tonic-gate 	}
2009*7c478bd9Sstevel@tonic-gate 	if(!conn->oparams.maxoutbuf) {
2010*7c478bd9Sstevel@tonic-gate 	    conn->oparams.maxoutbuf = conn->props.maxbufsize;
2011*7c478bd9Sstevel@tonic-gate 	}
2012*7c478bd9Sstevel@tonic-gate 
2013*7c478bd9Sstevel@tonic-gate 	if(conn->oparams.user == NULL || conn->oparams.authid == NULL) {
2014*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2015*7c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_ERR,
2016*7c478bd9Sstevel@tonic-gate 		      "mech did not call canon_user for both authzid "
2017*7c478bd9Sstevel@tonic-gate 		      "and authid");
2018*7c478bd9Sstevel@tonic-gate #else
2019*7c478bd9Sstevel@tonic-gate 	    sasl_seterror(conn, 0,
2020*7c478bd9Sstevel@tonic-gate 			  "mech did not call canon_user for both authzid " \
2021*7c478bd9Sstevel@tonic-gate 			  "and authid");
2022*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2023*7c478bd9Sstevel@tonic-gate 	    ret = SASL_BADPROT;
2024*7c478bd9Sstevel@tonic-gate 	}
2025*7c478bd9Sstevel@tonic-gate     }
2026*7c478bd9Sstevel@tonic-gate 
2027*7c478bd9Sstevel@tonic-gate     if(   ret != SASL_OK
2028*7c478bd9Sstevel@tonic-gate        && ret != SASL_CONTINUE
2029*7c478bd9Sstevel@tonic-gate        && ret != SASL_INTERACT) {
2030*7c478bd9Sstevel@tonic-gate 	if(conn->context) {
2031*7c478bd9Sstevel@tonic-gate 	    s_conn->mech->plug->mech_dispose(conn->context,
2032*7c478bd9Sstevel@tonic-gate 					     s_conn->sparams->utils);
2033*7c478bd9Sstevel@tonic-gate 	    conn->context = NULL;
2034*7c478bd9Sstevel@tonic-gate 	}
2035*7c478bd9Sstevel@tonic-gate     }
2036*7c478bd9Sstevel@tonic-gate 
2037*7c478bd9Sstevel@tonic-gate     RETURN(conn, ret);
2038*7c478bd9Sstevel@tonic-gate }
2039*7c478bd9Sstevel@tonic-gate 
2040*7c478bd9Sstevel@tonic-gate /* returns the length of all the mechanisms
2041*7c478bd9Sstevel@tonic-gate  * added up
2042*7c478bd9Sstevel@tonic-gate  */
2043*7c478bd9Sstevel@tonic-gate 
2044*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2045*7c478bd9Sstevel@tonic-gate static unsigned mech_names_len(_sasl_global_context_t *gctx)
2046*7c478bd9Sstevel@tonic-gate {
2047*7c478bd9Sstevel@tonic-gate   mech_list_t *mechlist = gctx->mechlist;
2048*7c478bd9Sstevel@tonic-gate #else
2049*7c478bd9Sstevel@tonic-gate static unsigned mech_names_len()
2050*7c478bd9Sstevel@tonic-gate {
2051*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2052*7c478bd9Sstevel@tonic-gate   mechanism_t *listptr;
2053*7c478bd9Sstevel@tonic-gate   unsigned result = 0;
2054*7c478bd9Sstevel@tonic-gate 
2055*7c478bd9Sstevel@tonic-gate   for (listptr = mechlist->mech_list;
2056*7c478bd9Sstevel@tonic-gate        listptr;
2057*7c478bd9Sstevel@tonic-gate        listptr = listptr->next)
2058*7c478bd9Sstevel@tonic-gate     result += strlen(listptr->plug->mech_name);
2059*7c478bd9Sstevel@tonic-gate 
2060*7c478bd9Sstevel@tonic-gate   return result;
2061*7c478bd9Sstevel@tonic-gate }
2062*7c478bd9Sstevel@tonic-gate 
2063*7c478bd9Sstevel@tonic-gate /* This returns a list of mechanisms in a NUL-terminated string
2064*7c478bd9Sstevel@tonic-gate  *
2065*7c478bd9Sstevel@tonic-gate  * The default behavior is to seperate with spaces if sep==NULL
2066*7c478bd9Sstevel@tonic-gate  */
2067*7c478bd9Sstevel@tonic-gate int _sasl_server_listmech(sasl_conn_t *conn,
2068*7c478bd9Sstevel@tonic-gate 			  const char *user __attribute__((unused)),
2069*7c478bd9Sstevel@tonic-gate 			  const char *prefix,
2070*7c478bd9Sstevel@tonic-gate 			  const char *sep,
2071*7c478bd9Sstevel@tonic-gate 			  const char *suffix,
2072*7c478bd9Sstevel@tonic-gate 			  const char **result,
2073*7c478bd9Sstevel@tonic-gate 			  unsigned *plen,
2074*7c478bd9Sstevel@tonic-gate 			  int *pcount)
2075*7c478bd9Sstevel@tonic-gate {
2076*7c478bd9Sstevel@tonic-gate   int lup;
2077*7c478bd9Sstevel@tonic-gate   mechanism_t *listptr;
2078*7c478bd9Sstevel@tonic-gate   int ret;
2079*7c478bd9Sstevel@tonic-gate   int resultlen;
2080*7c478bd9Sstevel@tonic-gate   int flag;
2081*7c478bd9Sstevel@tonic-gate   const char *mysep;
2082*7c478bd9Sstevel@tonic-gate 
2083*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2084*7c478bd9Sstevel@tonic-gate   _sasl_global_context_t *gctx;
2085*7c478bd9Sstevel@tonic-gate    mech_list_t *mechlist;
2086*7c478bd9Sstevel@tonic-gate 
2087*7c478bd9Sstevel@tonic-gate   if (!conn) return SASL_BADPARAM;
2088*7c478bd9Sstevel@tonic-gate    /* if there hasn't been a sasl_sever_init() fail */
2089*7c478bd9Sstevel@tonic-gate   gctx = conn->gctx;
2090*7c478bd9Sstevel@tonic-gate   if (gctx->sasl_server_active==0) return SASL_NOTINIT;
2091*7c478bd9Sstevel@tonic-gate 
2092*7c478bd9Sstevel@tonic-gate   (void)_load_server_plugins(gctx);
2093*7c478bd9Sstevel@tonic-gate   mechlist = gctx->mechlist;
2094*7c478bd9Sstevel@tonic-gate #else
2095*7c478bd9Sstevel@tonic-gate   /* if there hasn't been a sasl_sever_init() fail */
2096*7c478bd9Sstevel@tonic-gate   if (_sasl_server_active==0) return SASL_NOTINIT;
2097*7c478bd9Sstevel@tonic-gate   if (!conn) return SASL_BADPARAM;
2098*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2099*7c478bd9Sstevel@tonic-gate   if (conn->type != SASL_CONN_SERVER) PARAMERROR(conn);
2100*7c478bd9Sstevel@tonic-gate 
2101*7c478bd9Sstevel@tonic-gate   if (! result)
2102*7c478bd9Sstevel@tonic-gate       PARAMERROR(conn);
2103*7c478bd9Sstevel@tonic-gate 
2104*7c478bd9Sstevel@tonic-gate   if (plen != NULL)
2105*7c478bd9Sstevel@tonic-gate       *plen = 0;
2106*7c478bd9Sstevel@tonic-gate   if (pcount != NULL)
2107*7c478bd9Sstevel@tonic-gate       *pcount = 0;
2108*7c478bd9Sstevel@tonic-gate 
2109*7c478bd9Sstevel@tonic-gate   if (sep) {
2110*7c478bd9Sstevel@tonic-gate       mysep = sep;
2111*7c478bd9Sstevel@tonic-gate   } else {
2112*7c478bd9Sstevel@tonic-gate       mysep = " ";
2113*7c478bd9Sstevel@tonic-gate   }
2114*7c478bd9Sstevel@tonic-gate 
2115*7c478bd9Sstevel@tonic-gate   if (! mechlist || mechlist->mech_length <= 0)
2116*7c478bd9Sstevel@tonic-gate       INTERROR(conn, SASL_NOMECH);
2117*7c478bd9Sstevel@tonic-gate 
2118*7c478bd9Sstevel@tonic-gate   resultlen = (prefix ? strlen(prefix) : 0)
2119*7c478bd9Sstevel@tonic-gate             + (strlen(mysep) * (mechlist->mech_length - 1))
2120*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2121*7c478bd9Sstevel@tonic-gate 	    + mech_names_len(gctx)
2122*7c478bd9Sstevel@tonic-gate #else
2123*7c478bd9Sstevel@tonic-gate 	    + mech_names_len()
2124*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2125*7c478bd9Sstevel@tonic-gate             + (suffix ? strlen(suffix) : 0)
2126*7c478bd9Sstevel@tonic-gate 	    + 1;
2127*7c478bd9Sstevel@tonic-gate   ret = _buf_alloc(&conn->mechlist_buf,
2128*7c478bd9Sstevel@tonic-gate 		   &conn->mechlist_buf_len, resultlen);
2129*7c478bd9Sstevel@tonic-gate   if(ret != SASL_OK) MEMERROR(conn);
2130*7c478bd9Sstevel@tonic-gate 
2131*7c478bd9Sstevel@tonic-gate   if (prefix)
2132*7c478bd9Sstevel@tonic-gate     strcpy (conn->mechlist_buf,prefix);
2133*7c478bd9Sstevel@tonic-gate   else
2134*7c478bd9Sstevel@tonic-gate     *(conn->mechlist_buf) = '\0';
2135*7c478bd9Sstevel@tonic-gate 
2136*7c478bd9Sstevel@tonic-gate   listptr = mechlist->mech_list;
2137*7c478bd9Sstevel@tonic-gate 
2138*7c478bd9Sstevel@tonic-gate   flag = 0;
2139*7c478bd9Sstevel@tonic-gate   /* make list */
2140*7c478bd9Sstevel@tonic-gate   for (lup = 0; lup < mechlist->mech_length; lup++) {
2141*7c478bd9Sstevel@tonic-gate       /* currently, we don't use the "user" parameter for anything */
2142*7c478bd9Sstevel@tonic-gate       if (mech_permitted(conn, listptr)) {
2143*7c478bd9Sstevel@tonic-gate 	  if (pcount != NULL)
2144*7c478bd9Sstevel@tonic-gate 	      (*pcount)++;
2145*7c478bd9Sstevel@tonic-gate 
2146*7c478bd9Sstevel@tonic-gate 	  /* print seperator */
2147*7c478bd9Sstevel@tonic-gate 	  if (flag) {
2148*7c478bd9Sstevel@tonic-gate 	      strcat(conn->mechlist_buf, mysep);
2149*7c478bd9Sstevel@tonic-gate 	  } else {
2150*7c478bd9Sstevel@tonic-gate 	      flag = 1;
2151*7c478bd9Sstevel@tonic-gate 	  }
2152*7c478bd9Sstevel@tonic-gate 
2153*7c478bd9Sstevel@tonic-gate 	  /* now print the mechanism name */
2154*7c478bd9Sstevel@tonic-gate 	  strcat(conn->mechlist_buf, listptr->plug->mech_name);
2155*7c478bd9Sstevel@tonic-gate       }
2156*7c478bd9Sstevel@tonic-gate 
2157*7c478bd9Sstevel@tonic-gate       listptr = listptr->next;
2158*7c478bd9Sstevel@tonic-gate   }
2159*7c478bd9Sstevel@tonic-gate 
2160*7c478bd9Sstevel@tonic-gate   if (suffix)
2161*7c478bd9Sstevel@tonic-gate       strcat(conn->mechlist_buf,suffix);
2162*7c478bd9Sstevel@tonic-gate 
2163*7c478bd9Sstevel@tonic-gate   if (plen!=NULL)
2164*7c478bd9Sstevel@tonic-gate       *plen=strlen(conn->mechlist_buf);
2165*7c478bd9Sstevel@tonic-gate 
2166*7c478bd9Sstevel@tonic-gate   *result = conn->mechlist_buf;
2167*7c478bd9Sstevel@tonic-gate 
2168*7c478bd9Sstevel@tonic-gate   return SASL_OK;
2169*7c478bd9Sstevel@tonic-gate }
2170*7c478bd9Sstevel@tonic-gate 
2171*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2172*7c478bd9Sstevel@tonic-gate sasl_string_list_t *_sasl_server_mechs(_sasl_global_context_t *gctx)
2173*7c478bd9Sstevel@tonic-gate #else
2174*7c478bd9Sstevel@tonic-gate sasl_string_list_t *_sasl_server_mechs(void)
2175*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2176*7c478bd9Sstevel@tonic-gate {
2177*7c478bd9Sstevel@tonic-gate   mechanism_t *listptr;
2178*7c478bd9Sstevel@tonic-gate   sasl_string_list_t *retval = NULL, *next=NULL;
2179*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2180*7c478bd9Sstevel@tonic-gate   mech_list_t *mechlist = gctx->mechlist;
2181*7c478bd9Sstevel@tonic-gate 
2182*7c478bd9Sstevel@tonic-gate   if(!gctx->sasl_server_active) return NULL;
2183*7c478bd9Sstevel@tonic-gate #else
2184*7c478bd9Sstevel@tonic-gate   if(!_sasl_server_active) return NULL;
2185*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2186*7c478bd9Sstevel@tonic-gate 
2187*7c478bd9Sstevel@tonic-gate   /* make list */
2188*7c478bd9Sstevel@tonic-gate   for (listptr = mechlist->mech_list; listptr; listptr = listptr->next) {
2189*7c478bd9Sstevel@tonic-gate       next = sasl_ALLOC(sizeof(sasl_string_list_t));
2190*7c478bd9Sstevel@tonic-gate 
2191*7c478bd9Sstevel@tonic-gate       if(!next && !retval) return NULL;
2192*7c478bd9Sstevel@tonic-gate       else if(!next) {
2193*7c478bd9Sstevel@tonic-gate 	  next = retval->next;
2194*7c478bd9Sstevel@tonic-gate 	  do {
2195*7c478bd9Sstevel@tonic-gate 	      sasl_FREE(retval);
2196*7c478bd9Sstevel@tonic-gate 	      retval = next;
2197*7c478bd9Sstevel@tonic-gate 	      next = retval->next;
2198*7c478bd9Sstevel@tonic-gate 	  } while(next);
2199*7c478bd9Sstevel@tonic-gate 	  return NULL;
2200*7c478bd9Sstevel@tonic-gate       }
2201*7c478bd9Sstevel@tonic-gate 
2202*7c478bd9Sstevel@tonic-gate       next->d = listptr->plug->mech_name;
2203*7c478bd9Sstevel@tonic-gate 
2204*7c478bd9Sstevel@tonic-gate       if(!retval) {
2205*7c478bd9Sstevel@tonic-gate 	  next->next = NULL;
2206*7c478bd9Sstevel@tonic-gate 	  retval = next;
2207*7c478bd9Sstevel@tonic-gate       } else {
2208*7c478bd9Sstevel@tonic-gate 	  next->next = retval;
2209*7c478bd9Sstevel@tonic-gate 	  retval = next;
2210*7c478bd9Sstevel@tonic-gate       }
2211*7c478bd9Sstevel@tonic-gate   }
2212*7c478bd9Sstevel@tonic-gate 
2213*7c478bd9Sstevel@tonic-gate   return retval;
2214*7c478bd9Sstevel@tonic-gate }
2215*7c478bd9Sstevel@tonic-gate 
2216*7c478bd9Sstevel@tonic-gate #define EOSTR(s,n) (((s)[n] == '\0') || ((s)[n] == ' ') || ((s)[n] == '\t'))
2217*7c478bd9Sstevel@tonic-gate static int is_mech(const char *t, const char *m)
2218*7c478bd9Sstevel@tonic-gate {
2219*7c478bd9Sstevel@tonic-gate     int sl = strlen(m);
2220*7c478bd9Sstevel@tonic-gate     return ((!strncasecmp(m, t, sl)) && EOSTR(t, sl));
2221*7c478bd9Sstevel@tonic-gate }
2222*7c478bd9Sstevel@tonic-gate 
2223*7c478bd9Sstevel@tonic-gate /* returns OK if it's valid */
2224*7c478bd9Sstevel@tonic-gate static int _sasl_checkpass(sasl_conn_t *conn,
2225*7c478bd9Sstevel@tonic-gate 			   const char *user,
2226*7c478bd9Sstevel@tonic-gate 			   unsigned userlen __attribute__((unused)),
2227*7c478bd9Sstevel@tonic-gate 			   const char *pass,
2228*7c478bd9Sstevel@tonic-gate 			   unsigned passlen __attribute__((unused)))
2229*7c478bd9Sstevel@tonic-gate {
2230*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;
2231*7c478bd9Sstevel@tonic-gate     int result;
2232*7c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
2233*7c478bd9Sstevel@tonic-gate     sasl_server_userdb_checkpass_t *checkpass_cb;
2234*7c478bd9Sstevel@tonic-gate     void *context;
2235*7c478bd9Sstevel@tonic-gate     const char *mlist = NULL, *mech = NULL;
2236*7c478bd9Sstevel@tonic-gate     struct sasl_verify_password_s *v;
2237*7c478bd9Sstevel@tonic-gate     const char *service = conn->service;
2238*7c478bd9Sstevel@tonic-gate 
2239*7c478bd9Sstevel@tonic-gate     /* call userdb callback function, if available */
2240*7c478bd9Sstevel@tonic-gate     result = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_CHECKPASS,
2241*7c478bd9Sstevel@tonic-gate 			       &checkpass_cb, &context);
2242*7c478bd9Sstevel@tonic-gate     if(result == SASL_OK && checkpass_cb) {
2243*7c478bd9Sstevel@tonic-gate 	result = checkpass_cb(conn, context, user, pass, strlen(pass),
2244*7c478bd9Sstevel@tonic-gate 			      s_conn->sparams->propctx);
2245*7c478bd9Sstevel@tonic-gate 	if(result == SASL_OK)
2246*7c478bd9Sstevel@tonic-gate 	    return SASL_OK;
2247*7c478bd9Sstevel@tonic-gate     }
2248*7c478bd9Sstevel@tonic-gate 
2249*7c478bd9Sstevel@tonic-gate     /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */
2250*7c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
2251*7c478bd9Sstevel@tonic-gate             == SASL_OK) {
2252*7c478bd9Sstevel@tonic-gate         getopt(context, NULL, "pwcheck_method", &mlist, NULL);
2253*7c478bd9Sstevel@tonic-gate     }
2254*7c478bd9Sstevel@tonic-gate 
2255*7c478bd9Sstevel@tonic-gate     if(!mlist) mlist = DEFAULT_CHECKPASS_MECH;
2256*7c478bd9Sstevel@tonic-gate 
2257*7c478bd9Sstevel@tonic-gate     result = SASL_NOMECH;
2258*7c478bd9Sstevel@tonic-gate 
2259*7c478bd9Sstevel@tonic-gate     mech = mlist;
2260*7c478bd9Sstevel@tonic-gate     while (*mech && result != SASL_OK) {
2261*7c478bd9Sstevel@tonic-gate 	for (v = _sasl_verify_password; v->name; v++) {
2262*7c478bd9Sstevel@tonic-gate 	    if(is_mech(mech, v->name)) {
2263*7c478bd9Sstevel@tonic-gate 		result = v->verify(conn, user, pass, service,
2264*7c478bd9Sstevel@tonic-gate 				   s_conn->user_realm);
2265*7c478bd9Sstevel@tonic-gate 		break;
2266*7c478bd9Sstevel@tonic-gate 	    }
2267*7c478bd9Sstevel@tonic-gate 	}
2268*7c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) {
2269*7c478bd9Sstevel@tonic-gate 	    /* skip to next mech in list */
2270*7c478bd9Sstevel@tonic-gate 	    while (*mech && !isspace((int) *mech)) mech++;
2271*7c478bd9Sstevel@tonic-gate 	    while (*mech && isspace((int) *mech)) mech++;
2272*7c478bd9Sstevel@tonic-gate 	}
2273*7c478bd9Sstevel@tonic-gate     }
2274*7c478bd9Sstevel@tonic-gate 
2275*7c478bd9Sstevel@tonic-gate     if (result == SASL_NOMECH) {
2276*7c478bd9Sstevel@tonic-gate 	/* no mechanism available ?!? */
2277*7c478bd9Sstevel@tonic-gate 	_sasl_log(conn, SASL_LOG_ERR, "unknown password verifier %s", mech);
2278*7c478bd9Sstevel@tonic-gate     }
2279*7c478bd9Sstevel@tonic-gate 
2280*7c478bd9Sstevel@tonic-gate     if (result != SASL_OK)
2281*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
2282*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, SASL_NOLOG, gettext("checkpass failed"));
2283*7c478bd9Sstevel@tonic-gate #else
2284*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, SASL_NOLOG, "checkpass failed");
2285*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
2286*7c478bd9Sstevel@tonic-gate 
2287*7c478bd9Sstevel@tonic-gate     RETURN(conn, result);
2288*7c478bd9Sstevel@tonic-gate }
2289*7c478bd9Sstevel@tonic-gate 
2290*7c478bd9Sstevel@tonic-gate /* check if a plaintext password is valid
2291*7c478bd9Sstevel@tonic-gate  *   if user is NULL, check if plaintext passwords are enabled
2292*7c478bd9Sstevel@tonic-gate  * inputs:
2293*7c478bd9Sstevel@tonic-gate  *  user          -- user to query in current user_domain
2294*7c478bd9Sstevel@tonic-gate  *  userlen       -- length of username, 0 = strlen(user)
2295*7c478bd9Sstevel@tonic-gate  *  pass          -- plaintext password to check
2296*7c478bd9Sstevel@tonic-gate  *  passlen       -- length of password, 0 = strlen(pass)
2297*7c478bd9Sstevel@tonic-gate  * returns
2298*7c478bd9Sstevel@tonic-gate  *  SASL_OK       -- success
2299*7c478bd9Sstevel@tonic-gate  *  SASL_NOMECH   -- mechanism not supported
2300*7c478bd9Sstevel@tonic-gate  *  SASL_NOVERIFY -- user found, but no verifier
2301*7c478bd9Sstevel@tonic-gate  *  SASL_NOUSER   -- user not found
2302*7c478bd9Sstevel@tonic-gate  */
2303*7c478bd9Sstevel@tonic-gate int sasl_checkpass(sasl_conn_t *conn,
2304*7c478bd9Sstevel@tonic-gate 		   const char *user,
2305*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2306*7c478bd9Sstevel@tonic-gate 		   unsigned userlen,
2307*7c478bd9Sstevel@tonic-gate #else /* _SUN_SDK_ */
2308*7c478bd9Sstevel@tonic-gate 		   unsigned userlen __attribute__((unused)),
2309*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2310*7c478bd9Sstevel@tonic-gate 		   const char *pass,
2311*7c478bd9Sstevel@tonic-gate 		   unsigned passlen)
2312*7c478bd9Sstevel@tonic-gate {
2313*7c478bd9Sstevel@tonic-gate     int result;
2314*7c478bd9Sstevel@tonic-gate 
2315*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2316*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx =
2317*7c478bd9Sstevel@tonic-gate 		 (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
2318*7c478bd9Sstevel@tonic-gate 
2319*7c478bd9Sstevel@tonic-gate     if (gctx->sasl_server_active==0) return SASL_NOTINIT;
2320*7c478bd9Sstevel@tonic-gate 
2321*7c478bd9Sstevel@tonic-gate     /* A NULL user means the caller is checking if plaintext authentication
2322*7c478bd9Sstevel@tonic-gate      * is enabled.  But if no connection context is supplied, we have no
2323*7c478bd9Sstevel@tonic-gate      * appropriate policy to check against.  So for consistant global
2324*7c478bd9Sstevel@tonic-gate      * behavior we always say plaintext is enabled in this case.
2325*7c478bd9Sstevel@tonic-gate      */
2326*7c478bd9Sstevel@tonic-gate     if (!user && !conn) return SASL_OK;
2327*7c478bd9Sstevel@tonic-gate 
2328*7c478bd9Sstevel@tonic-gate     if (!conn) return SASL_BADPARAM;
2329*7c478bd9Sstevel@tonic-gate 
2330*7c478bd9Sstevel@tonic-gate     /* Check connection security policy to see if plaintext password
2331*7c478bd9Sstevel@tonic-gate      * authentication is permitted.
2332*7c478bd9Sstevel@tonic-gate      *
2333*7c478bd9Sstevel@tonic-gate      * XXX TODO FIXME:
2334*7c478bd9Sstevel@tonic-gate      * This should call mech_permitted with the PLAIN mechanism,
2335*7c478bd9Sstevel@tonic-gate      * since all plaintext mechanisms should fall under the same
2336*7c478bd9Sstevel@tonic-gate      * security policy guidelines.  But to keep code changes and
2337*7c478bd9Sstevel@tonic-gate      * risk to a minimum at this juncture, we do the minimal
2338*7c478bd9Sstevel@tonic-gate      * security strength and plaintext policy checks which are
2339*7c478bd9Sstevel@tonic-gate      * most likely to be deployed and useful in the field.
2340*7c478bd9Sstevel@tonic-gate      */
2341*7c478bd9Sstevel@tonic-gate     if (conn->props.min_ssf > conn->external.ssf)
2342*7c478bd9Sstevel@tonic-gate       RETURN(conn, SASL_TOOWEAK);
2343*7c478bd9Sstevel@tonic-gate     if ((conn->props.security_flags & SASL_SEC_NOPLAINTEXT) != 0
2344*7c478bd9Sstevel@tonic-gate       && conn->external.ssf == 0)
2345*7c478bd9Sstevel@tonic-gate       RETURN(conn, SASL_ENCRYPT);
2346*7c478bd9Sstevel@tonic-gate 
2347*7c478bd9Sstevel@tonic-gate     if (!user)
2348*7c478bd9Sstevel@tonic-gate       return SASL_OK;
2349*7c478bd9Sstevel@tonic-gate #else
2350*7c478bd9Sstevel@tonic-gate     if (_sasl_server_active==0) return SASL_NOTINIT;
2351*7c478bd9Sstevel@tonic-gate 
2352*7c478bd9Sstevel@tonic-gate     /* check if it's just a query if we are enabled */
2353*7c478bd9Sstevel@tonic-gate     if (!user)
2354*7c478bd9Sstevel@tonic-gate 	return SASL_OK;
2355*7c478bd9Sstevel@tonic-gate 
2356*7c478bd9Sstevel@tonic-gate     if (!conn) return SASL_BADPARAM;
2357*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2358*7c478bd9Sstevel@tonic-gate 
2359*7c478bd9Sstevel@tonic-gate     /* check params */
2360*7c478bd9Sstevel@tonic-gate     if (pass == NULL)
2361*7c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
2362*7c478bd9Sstevel@tonic-gate 
2363*7c478bd9Sstevel@tonic-gate     /* canonicalize the username */
2364*7c478bd9Sstevel@tonic-gate     result = _sasl_canon_user(conn, user, 0,
2365*7c478bd9Sstevel@tonic-gate 			      SASL_CU_AUTHID | SASL_CU_AUTHZID,
2366*7c478bd9Sstevel@tonic-gate 			      &(conn->oparams));
2367*7c478bd9Sstevel@tonic-gate     if(result != SASL_OK) RETURN(conn, result);
2368*7c478bd9Sstevel@tonic-gate     user = conn->oparams.user;
2369*7c478bd9Sstevel@tonic-gate 
2370*7c478bd9Sstevel@tonic-gate     /* Check the password */
2371*7c478bd9Sstevel@tonic-gate     result = _sasl_checkpass(conn, user, strlen(user), pass, strlen(pass));
2372*7c478bd9Sstevel@tonic-gate 
2373*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2374*7c478bd9Sstevel@tonic-gate     if (result == SASL_OK) {
2375*7c478bd9Sstevel@tonic-gate       result = do_authorization((sasl_server_conn_t *) conn);
2376*7c478bd9Sstevel@tonic-gate     }
2377*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2378*7c478bd9Sstevel@tonic-gate 
2379*7c478bd9Sstevel@tonic-gate     if (result == SASL_OK)
2380*7c478bd9Sstevel@tonic-gate 	result = _sasl_transition(conn, pass, passlen);
2381*7c478bd9Sstevel@tonic-gate 
2382*7c478bd9Sstevel@tonic-gate     RETURN(conn,result);
2383*7c478bd9Sstevel@tonic-gate }
2384*7c478bd9Sstevel@tonic-gate 
2385*7c478bd9Sstevel@tonic-gate /* check if a user exists on server
2386*7c478bd9Sstevel@tonic-gate  *  conn          -- connection context (may be NULL, used to hold last error)
2387*7c478bd9Sstevel@tonic-gate  *  service       -- registered name of the service using SASL (e.g. "imap")
2388*7c478bd9Sstevel@tonic-gate  *  user_realm    -- permits multiple user realms on server, NULL = default
2389*7c478bd9Sstevel@tonic-gate  *  user          -- NUL terminated user name
2390*7c478bd9Sstevel@tonic-gate  *
2391*7c478bd9Sstevel@tonic-gate  * returns:
2392*7c478bd9Sstevel@tonic-gate  *  SASL_OK       -- success
2393*7c478bd9Sstevel@tonic-gate  *  SASL_DISABLED -- account disabled [FIXME: currently not detected]
2394*7c478bd9Sstevel@tonic-gate  *  SASL_NOUSER   -- user not found
2395*7c478bd9Sstevel@tonic-gate  *  SASL_NOVERIFY -- user found, but no usable mechanism [FIXME: not supported]
2396*7c478bd9Sstevel@tonic-gate  *  SASL_NOMECH   -- no mechanisms enabled
2397*7c478bd9Sstevel@tonic-gate  */
2398*7c478bd9Sstevel@tonic-gate int sasl_user_exists(sasl_conn_t *conn,
2399*7c478bd9Sstevel@tonic-gate 		     const char *service,
2400*7c478bd9Sstevel@tonic-gate 		     const char *user_realm,
2401*7c478bd9Sstevel@tonic-gate 		     const char *user)
2402*7c478bd9Sstevel@tonic-gate {
2403*7c478bd9Sstevel@tonic-gate     int result=SASL_NOMECH;
2404*7c478bd9Sstevel@tonic-gate     const char *mlist = NULL, *mech = NULL;
2405*7c478bd9Sstevel@tonic-gate     void *context;
2406*7c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
2407*7c478bd9Sstevel@tonic-gate     struct sasl_verify_password_s *v;
2408*7c478bd9Sstevel@tonic-gate 
2409*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2410*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx =
2411*7c478bd9Sstevel@tonic-gate 		 (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
2412*7c478bd9Sstevel@tonic-gate 
2413*7c478bd9Sstevel@tonic-gate     /* check params */
2414*7c478bd9Sstevel@tonic-gate     if (gctx->sasl_server_active==0) return SASL_NOTINIT;
2415*7c478bd9Sstevel@tonic-gate #else
2416*7c478bd9Sstevel@tonic-gate     /* check params */
2417*7c478bd9Sstevel@tonic-gate     if (_sasl_server_active==0) return SASL_NOTINIT;
2418*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2419*7c478bd9Sstevel@tonic-gate     if (!conn) return SASL_BADPARAM;
2420*7c478bd9Sstevel@tonic-gate     if (!user || conn->type != SASL_CONN_SERVER)
2421*7c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
2422*7c478bd9Sstevel@tonic-gate 
2423*7c478bd9Sstevel@tonic-gate     if(!service) service = conn->service;
2424*7c478bd9Sstevel@tonic-gate 
2425*7c478bd9Sstevel@tonic-gate     /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */
2426*7c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
2427*7c478bd9Sstevel@tonic-gate             == SASL_OK) {
2428*7c478bd9Sstevel@tonic-gate         getopt(context, NULL, "pwcheck_method", &mlist, NULL);
2429*7c478bd9Sstevel@tonic-gate     }
2430*7c478bd9Sstevel@tonic-gate 
2431*7c478bd9Sstevel@tonic-gate     if(!mlist) mlist = DEFAULT_CHECKPASS_MECH;
2432*7c478bd9Sstevel@tonic-gate 
2433*7c478bd9Sstevel@tonic-gate     result = SASL_NOMECH;
2434*7c478bd9Sstevel@tonic-gate 
2435*7c478bd9Sstevel@tonic-gate     mech = mlist;
2436*7c478bd9Sstevel@tonic-gate     while (*mech && result != SASL_OK) {
2437*7c478bd9Sstevel@tonic-gate 	for (v = _sasl_verify_password; v->name; v++) {
2438*7c478bd9Sstevel@tonic-gate 	    if(is_mech(mech, v->name)) {
2439*7c478bd9Sstevel@tonic-gate 		result = v->verify(conn, user, NULL, service, user_realm);
2440*7c478bd9Sstevel@tonic-gate 		break;
2441*7c478bd9Sstevel@tonic-gate 	    }
2442*7c478bd9Sstevel@tonic-gate 	}
2443*7c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) {
2444*7c478bd9Sstevel@tonic-gate 	    /* skip to next mech in list */
2445*7c478bd9Sstevel@tonic-gate 	    while (*mech && !isspace((int) *mech)) mech++;
2446*7c478bd9Sstevel@tonic-gate 	    while (*mech && isspace((int) *mech)) mech++;
2447*7c478bd9Sstevel@tonic-gate 	}
2448*7c478bd9Sstevel@tonic-gate     }
2449*7c478bd9Sstevel@tonic-gate 
2450*7c478bd9Sstevel@tonic-gate     /* Screen out the SASL_BADPARAM response
2451*7c478bd9Sstevel@tonic-gate      * we'll get from not giving a password */
2452*7c478bd9Sstevel@tonic-gate     if(result == SASL_BADPARAM) {
2453*7c478bd9Sstevel@tonic-gate 	result = SASL_OK;
2454*7c478bd9Sstevel@tonic-gate     }
2455*7c478bd9Sstevel@tonic-gate 
2456*7c478bd9Sstevel@tonic-gate     if (result == SASL_NOMECH) {
2457*7c478bd9Sstevel@tonic-gate 	/* no mechanism available ?!? */
2458*7c478bd9Sstevel@tonic-gate 	_sasl_log(conn, SASL_LOG_ERR, "no plaintext password verifier?");
2459*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
2460*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, SASL_NOLOG, "no plaintext password verifier?");
2461*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
2462*7c478bd9Sstevel@tonic-gate     }
2463*7c478bd9Sstevel@tonic-gate 
2464*7c478bd9Sstevel@tonic-gate     RETURN(conn, result);
2465*7c478bd9Sstevel@tonic-gate }
2466*7c478bd9Sstevel@tonic-gate 
2467*7c478bd9Sstevel@tonic-gate /* check if an apop exchange is valid
2468*7c478bd9Sstevel@tonic-gate  *  (note this is an optional part of the SASL API)
2469*7c478bd9Sstevel@tonic-gate  *  if challenge is NULL, just check if APOP is enabled
2470*7c478bd9Sstevel@tonic-gate  * inputs:
2471*7c478bd9Sstevel@tonic-gate  *  challenge     -- challenge which was sent to client
2472*7c478bd9Sstevel@tonic-gate  *  challen       -- length of challenge, 0 = strlen(challenge)
2473*7c478bd9Sstevel@tonic-gate  *  response      -- client response, "<user> <digest>" (RFC 1939)
2474*7c478bd9Sstevel@tonic-gate  *  resplen       -- length of response, 0 = strlen(response)
2475*7c478bd9Sstevel@tonic-gate  * returns
2476*7c478bd9Sstevel@tonic-gate  *  SASL_OK       -- success
2477*7c478bd9Sstevel@tonic-gate  *  SASL_BADAUTH  -- authentication failed
2478*7c478bd9Sstevel@tonic-gate  *  SASL_BADPARAM -- missing challenge
2479*7c478bd9Sstevel@tonic-gate  *  SASL_BADPROT  -- protocol error (e.g., response in wrong format)
2480*7c478bd9Sstevel@tonic-gate  *  SASL_NOVERIFY -- user found, but no verifier
2481*7c478bd9Sstevel@tonic-gate  *  SASL_NOMECH   -- mechanism not supported
2482*7c478bd9Sstevel@tonic-gate  *  SASL_NOUSER   -- user not found
2483*7c478bd9Sstevel@tonic-gate  */
2484*7c478bd9Sstevel@tonic-gate int sasl_checkapop(sasl_conn_t *conn,
2485*7c478bd9Sstevel@tonic-gate #ifdef DO_SASL_CHECKAPOP
2486*7c478bd9Sstevel@tonic-gate  		   const char *challenge,
2487*7c478bd9Sstevel@tonic-gate  		   unsigned challen __attribute__((unused)),
2488*7c478bd9Sstevel@tonic-gate  		   const char *response,
2489*7c478bd9Sstevel@tonic-gate  		   unsigned resplen __attribute__((unused)))
2490*7c478bd9Sstevel@tonic-gate #else
2491*7c478bd9Sstevel@tonic-gate  		   const char *challenge __attribute__((unused)),
2492*7c478bd9Sstevel@tonic-gate  		   unsigned challen __attribute__((unused)),
2493*7c478bd9Sstevel@tonic-gate  		   const char *response __attribute__((unused)),
2494*7c478bd9Sstevel@tonic-gate  		   unsigned resplen __attribute__((unused)))
2495*7c478bd9Sstevel@tonic-gate #endif
2496*7c478bd9Sstevel@tonic-gate {
2497*7c478bd9Sstevel@tonic-gate #ifdef DO_SASL_CHECKAPOP
2498*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;
2499*7c478bd9Sstevel@tonic-gate     char *user, *user_end;
2500*7c478bd9Sstevel@tonic-gate     const char *password_request[] = { SASL_AUX_PASSWORD, NULL };
2501*7c478bd9Sstevel@tonic-gate     size_t user_len;
2502*7c478bd9Sstevel@tonic-gate     int result;
2503*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2504*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx =
2505*7c478bd9Sstevel@tonic-gate 		 (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
2506*7c478bd9Sstevel@tonic-gate 
2507*7c478bd9Sstevel@tonic-gate     if (gctx->sasl_server_active==0)
2508*7c478bd9Sstevel@tonic-gate         return SASL_NOTINIT;
2509*7c478bd9Sstevel@tonic-gate #else
2510*7c478bd9Sstevel@tonic-gate     if (_sasl_server_active==0)
2511*7c478bd9Sstevel@tonic-gate 	return SASL_NOTINIT;
2512*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2513*7c478bd9Sstevel@tonic-gate 
2514*7c478bd9Sstevel@tonic-gate     /* check if it's just a query if we are enabled */
2515*7c478bd9Sstevel@tonic-gate     if(!challenge)
2516*7c478bd9Sstevel@tonic-gate 	return SASL_OK;
2517*7c478bd9Sstevel@tonic-gate 
2518*7c478bd9Sstevel@tonic-gate     /* check params */
2519*7c478bd9Sstevel@tonic-gate     if (!conn) return SASL_BADPARAM;
2520*7c478bd9Sstevel@tonic-gate     if (!response)
2521*7c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
2522*7c478bd9Sstevel@tonic-gate 
2523*7c478bd9Sstevel@tonic-gate     /* Parse out username and digest.
2524*7c478bd9Sstevel@tonic-gate      *
2525*7c478bd9Sstevel@tonic-gate      * Per RFC 1939, response must be "<user> <digest>", where
2526*7c478bd9Sstevel@tonic-gate      * <digest> is a 16-octet value which is sent in hexadecimal
2527*7c478bd9Sstevel@tonic-gate      * format, using lower-case ASCII characters.
2528*7c478bd9Sstevel@tonic-gate      */
2529*7c478bd9Sstevel@tonic-gate     user_end = strrchr(response, ' ');
2530*7c478bd9Sstevel@tonic-gate     if (!user_end || strspn(user_end + 1, "0123456789abcdef") != 32)
2531*7c478bd9Sstevel@tonic-gate     {
2532*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
2533*7c478bd9Sstevel@tonic-gate         sasl_seterror(conn, 0, gettext("Bad Digest"));
2534*7c478bd9Sstevel@tonic-gate #else
2535*7c478bd9Sstevel@tonic-gate         sasl_seterror(conn, 0, "Bad Digest");
2536*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
2537*7c478bd9Sstevel@tonic-gate         RETURN(conn,SASL_BADPROT);
2538*7c478bd9Sstevel@tonic-gate     }
2539*7c478bd9Sstevel@tonic-gate 
2540*7c478bd9Sstevel@tonic-gate     user_len = (size_t)(user_end - response);
2541*7c478bd9Sstevel@tonic-gate     user = sasl_ALLOC(user_len + 1);
2542*7c478bd9Sstevel@tonic-gate     memcpy(user, response, user_len);
2543*7c478bd9Sstevel@tonic-gate     user[user_len] = '\0';
2544*7c478bd9Sstevel@tonic-gate 
2545*7c478bd9Sstevel@tonic-gate     result = prop_request(s_conn->sparams->propctx, password_request);
2546*7c478bd9Sstevel@tonic-gate     if(result != SASL_OK)
2547*7c478bd9Sstevel@tonic-gate     {
2548*7c478bd9Sstevel@tonic-gate         sasl_FREE(user);
2549*7c478bd9Sstevel@tonic-gate         RETURN(conn, result);
2550*7c478bd9Sstevel@tonic-gate     }
2551*7c478bd9Sstevel@tonic-gate 
2552*7c478bd9Sstevel@tonic-gate     /* Cannonify it */
2553*7c478bd9Sstevel@tonic-gate     result = _sasl_canon_user(conn, user, user_len,
2554*7c478bd9Sstevel@tonic-gate 	                      SASL_CU_AUTHID | SASL_CU_AUTHZID,
2555*7c478bd9Sstevel@tonic-gate 	                      &(conn->oparams));
2556*7c478bd9Sstevel@tonic-gate     sasl_FREE(user);
2557*7c478bd9Sstevel@tonic-gate 
2558*7c478bd9Sstevel@tonic-gate     if(result != SASL_OK) RETURN(conn, result);
2559*7c478bd9Sstevel@tonic-gate 
2560*7c478bd9Sstevel@tonic-gate     /* Do APOP verification */
2561*7c478bd9Sstevel@tonic-gate     result = _sasl_auxprop_verify_apop(conn, conn->oparams.authid,
2562*7c478bd9Sstevel@tonic-gate 	challenge, user_end + 1, s_conn->user_realm);
2563*7c478bd9Sstevel@tonic-gate 
2564*7c478bd9Sstevel@tonic-gate     /* If verification failed, we don't want to encourage getprop to work */
2565*7c478bd9Sstevel@tonic-gate     if(result != SASL_OK) {
2566*7c478bd9Sstevel@tonic-gate 	conn->oparams.user = NULL;
2567*7c478bd9Sstevel@tonic-gate 	conn->oparams.authid = NULL;
2568*7c478bd9Sstevel@tonic-gate     }
2569*7c478bd9Sstevel@tonic-gate 
2570*7c478bd9Sstevel@tonic-gate     RETURN(conn, result);
2571*7c478bd9Sstevel@tonic-gate #else /* sasl_checkapop was disabled at compile time */
2572*7c478bd9Sstevel@tonic-gate     sasl_seterror(conn, SASL_NOLOG,
2573*7c478bd9Sstevel@tonic-gate 	"sasl_checkapop called, but was disabled at compile time");
2574*7c478bd9Sstevel@tonic-gate     RETURN(conn, SASL_NOMECH);
2575*7c478bd9Sstevel@tonic-gate #endif /* DO_SASL_CHECKAPOP */
2576*7c478bd9Sstevel@tonic-gate }
2577*7c478bd9Sstevel@tonic-gate 
2578