xref: /illumos-gate/usr/src/lib/libsasl/lib/server.c (revision 694c35fa)
17c478bd9Sstevel@tonic-gate /*
2*004388ebScasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /* SASL server API implementation
77c478bd9Sstevel@tonic-gate  * Rob Siemborski
87c478bd9Sstevel@tonic-gate  * Tim Martin
97c478bd9Sstevel@tonic-gate  * $Id: server.c,v 1.123 2003/04/16 19:36:01 rjs3 Exp $
107c478bd9Sstevel@tonic-gate  */
117c478bd9Sstevel@tonic-gate /*
127c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
157c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
167c478bd9Sstevel@tonic-gate  * are met:
177c478bd9Sstevel@tonic-gate  *
187c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
197c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
227c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
237c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
247c478bd9Sstevel@tonic-gate  *    distribution.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
277c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
287c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
297c478bd9Sstevel@tonic-gate  *    details, please contact
307c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
317c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
327c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
337c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
347c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
357c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
387c478bd9Sstevel@tonic-gate  *    acknowledgment:
397c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
407c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
437c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
447c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
457c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
467c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
477c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
487c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /* local functions/structs don't start with sasl
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate #include <config.h>
547c478bd9Sstevel@tonic-gate #include <errno.h>
557c478bd9Sstevel@tonic-gate #include <stdio.h>
567c478bd9Sstevel@tonic-gate #include <stdlib.h>
577c478bd9Sstevel@tonic-gate #include <limits.h>
587c478bd9Sstevel@tonic-gate #ifndef macintosh
597c478bd9Sstevel@tonic-gate #include <sys/types.h>
607c478bd9Sstevel@tonic-gate #include <sys/stat.h>
617c478bd9Sstevel@tonic-gate #endif
627c478bd9Sstevel@tonic-gate #include <fcntl.h>
637c478bd9Sstevel@tonic-gate #include <string.h>
647c478bd9Sstevel@tonic-gate #include <ctype.h>
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #include "sasl.h"
677c478bd9Sstevel@tonic-gate #include "saslint.h"
687c478bd9Sstevel@tonic-gate #include "saslplug.h"
697c478bd9Sstevel@tonic-gate #include "saslutil.h"
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
727c478bd9Sstevel@tonic-gate #ifdef sun
737c478bd9Sstevel@tonic-gate /* gotta define gethostname ourselves on suns */
747c478bd9Sstevel@tonic-gate extern int gethostname(char *, int);
757c478bd9Sstevel@tonic-gate #endif
767c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #define DEFAULT_CHECKPASS_MECH "auxprop"
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /* Contains functions:
817c478bd9Sstevel@tonic-gate  *
827c478bd9Sstevel@tonic-gate  * sasl_server_init
837c478bd9Sstevel@tonic-gate  * sasl_server_new
847c478bd9Sstevel@tonic-gate  * sasl_listmech
857c478bd9Sstevel@tonic-gate  * sasl_server_start
867c478bd9Sstevel@tonic-gate  * sasl_server_step
877c478bd9Sstevel@tonic-gate  * sasl_checkpass
887c478bd9Sstevel@tonic-gate  * sasl_checkapop
897c478bd9Sstevel@tonic-gate  * sasl_user_exists
907c478bd9Sstevel@tonic-gate  * sasl_setpass
917c478bd9Sstevel@tonic-gate  */
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
_is_sasl_server_active(_sasl_global_context_t * gctx)947c478bd9Sstevel@tonic-gate int _is_sasl_server_active(_sasl_global_context_t *gctx)
957c478bd9Sstevel@tonic-gate {
967c478bd9Sstevel@tonic-gate     return gctx->sasl_server_active;
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(init_server_mutex);
1007c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(server_active_mutex);
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate  * server_plug_mutex ensures only one server plugin is init'ed at a time
1037c478bd9Sstevel@tonic-gate  * If a plugin is loaded more than once, the glob_context may be overwritten
1047c478bd9Sstevel@tonic-gate  * which may lead to a memory leak. We keep glob_context with each mech
1057c478bd9Sstevel@tonic-gate  * to avoid this problem.
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(server_plug_mutex);
1087c478bd9Sstevel@tonic-gate #else
1097c478bd9Sstevel@tonic-gate /* if we've initialized the server sucessfully */
1107c478bd9Sstevel@tonic-gate static int _sasl_server_active = 0;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /* For access by other modules */
_is_sasl_server_active(void)1137c478bd9Sstevel@tonic-gate int _is_sasl_server_active(void) { return _sasl_server_active; }
1147c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate static int _sasl_checkpass(sasl_conn_t *conn,
1177c478bd9Sstevel@tonic-gate 			   const char *user, unsigned userlen,
1187c478bd9Sstevel@tonic-gate 			   const char *pass, unsigned passlen);
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1217c478bd9Sstevel@tonic-gate static mech_list_t *mechlist = NULL; /* global var which holds the list */
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate static sasl_global_callbacks_t global_callbacks;
1247c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate /* set the password for a user
1277c478bd9Sstevel@tonic-gate  *  conn        -- SASL connection
1287c478bd9Sstevel@tonic-gate  *  user        -- user name
1297c478bd9Sstevel@tonic-gate  *  pass        -- plaintext password, may be NULL to remove user
1307c478bd9Sstevel@tonic-gate  *  passlen     -- length of password, 0 = strlen(pass)
1317c478bd9Sstevel@tonic-gate  *  oldpass     -- NULL will sometimes work
1327c478bd9Sstevel@tonic-gate  *  oldpasslen  -- length of password, 0 = strlen(oldpass)
1337c478bd9Sstevel@tonic-gate  *  flags       -- see flags below
1347c478bd9Sstevel@tonic-gate  *
1357c478bd9Sstevel@tonic-gate  * returns:
1367c478bd9Sstevel@tonic-gate  *  SASL_NOCHANGE  -- proper entry already exists
1377c478bd9Sstevel@tonic-gate  *  SASL_NOMECH    -- no authdb supports password setting as configured
1387c478bd9Sstevel@tonic-gate  *  SASL_NOVERIFY  -- user exists, but no settable password present
1397c478bd9Sstevel@tonic-gate  *  SASL_DISABLED  -- account disabled
1407c478bd9Sstevel@tonic-gate  *  SASL_PWLOCK    -- password locked
1417c478bd9Sstevel@tonic-gate  *  SASL_WEAKPASS  -- password too weak for security policy
1427c478bd9Sstevel@tonic-gate  *  SASL_NOUSERPASS -- user-supplied passwords not permitted
1437c478bd9Sstevel@tonic-gate  *  SASL_FAIL      -- OS error
1447c478bd9Sstevel@tonic-gate  *  SASL_BADPARAM  -- password too long
1457c478bd9Sstevel@tonic-gate  *  SASL_OK        -- successful
1467c478bd9Sstevel@tonic-gate  */
1477c478bd9Sstevel@tonic-gate 
sasl_setpass(sasl_conn_t * conn,const char * user,const char * pass,unsigned passlen,const char * oldpass,unsigned oldpasslen,unsigned flags)1487c478bd9Sstevel@tonic-gate int sasl_setpass(sasl_conn_t *conn,
1497c478bd9Sstevel@tonic-gate 		 const char *user,
1507c478bd9Sstevel@tonic-gate 		 const char *pass, unsigned passlen,
1517c478bd9Sstevel@tonic-gate 		 const char *oldpass,
1527c478bd9Sstevel@tonic-gate 		 unsigned oldpasslen,
1537c478bd9Sstevel@tonic-gate 		 unsigned flags)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate     int result=SASL_OK, tmpresult;
1567c478bd9Sstevel@tonic-gate     sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;
1577c478bd9Sstevel@tonic-gate     sasl_server_userdb_setpass_t *setpass_cb = NULL;
1587c478bd9Sstevel@tonic-gate     void *context = NULL;
1597c478bd9Sstevel@tonic-gate     mechanism_t *m;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1627c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx =
1637c478bd9Sstevel@tonic-gate 		 (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
1647c478bd9Sstevel@tonic-gate     mech_list_t *mechlist = gctx == NULL ? NULL : gctx->mechlist;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate     if (!gctx->sasl_server_active || !mechlist) return SASL_NOTINIT;
1677c478bd9Sstevel@tonic-gate #else
1687c478bd9Sstevel@tonic-gate     if (!_sasl_server_active || !mechlist) return SASL_NOTINIT;
1697c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate     /* check params */
1727c478bd9Sstevel@tonic-gate     if (!conn) return SASL_BADPARAM;
1737c478bd9Sstevel@tonic-gate     if (conn->type != SASL_CONN_SERVER) PARAMERROR(conn);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate     if ((!(flags & SASL_SET_DISABLE) && passlen == 0)
1767c478bd9Sstevel@tonic-gate         || ((flags & SASL_SET_CREATE) && (flags & SASL_SET_DISABLE)))
1777c478bd9Sstevel@tonic-gate 	PARAMERROR(conn);
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate     /* call userdb callback function */
1807c478bd9Sstevel@tonic-gate     result = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_SETPASS,
1817c478bd9Sstevel@tonic-gate 			       &setpass_cb, &context);
1827c478bd9Sstevel@tonic-gate     if(result == SASL_OK && setpass_cb) {
1837c478bd9Sstevel@tonic-gate 	tmpresult = setpass_cb(conn, context, user, pass, passlen,
1847c478bd9Sstevel@tonic-gate 			    s_conn->sparams->propctx, flags);
1857c478bd9Sstevel@tonic-gate 	if(tmpresult != SASL_OK) {
1867c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_ERR,
1877c478bd9Sstevel@tonic-gate 		      "setpass callback failed for %s: %z",
1887c478bd9Sstevel@tonic-gate 		      user, tmpresult);
1897c478bd9Sstevel@tonic-gate 	} else {
1907c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_NOTE,
1917c478bd9Sstevel@tonic-gate 		      "setpass callback succeeded for %s", user);
1927c478bd9Sstevel@tonic-gate 	}
1937c478bd9Sstevel@tonic-gate     } else {
1947c478bd9Sstevel@tonic-gate 	result = SASL_OK;
1957c478bd9Sstevel@tonic-gate     }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate     /* now we let the mechanisms set their secrets */
1987c478bd9Sstevel@tonic-gate     for (m = mechlist->mech_list; m; m = m->next) {
1997c478bd9Sstevel@tonic-gate 	if (!m->plug->setpass) {
2007c478bd9Sstevel@tonic-gate 	    /* can't set pass for this mech */
2017c478bd9Sstevel@tonic-gate 	    continue;
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2047c478bd9Sstevel@tonic-gate 	tmpresult = m->plug->setpass(m->glob_context,
2057c478bd9Sstevel@tonic-gate #else
2067c478bd9Sstevel@tonic-gate 	tmpresult = m->plug->setpass(m->plug->glob_context,
2077c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2087c478bd9Sstevel@tonic-gate 				     ((sasl_server_conn_t *)conn)->sparams,
2097c478bd9Sstevel@tonic-gate 				     user,
2107c478bd9Sstevel@tonic-gate 				     pass,
2117c478bd9Sstevel@tonic-gate 				     passlen,
2127c478bd9Sstevel@tonic-gate 				     oldpass, oldpasslen,
2137c478bd9Sstevel@tonic-gate 				     flags);
2147c478bd9Sstevel@tonic-gate 	if (tmpresult == SASL_OK) {
2157c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_NOTE,
2167c478bd9Sstevel@tonic-gate 		      "%s: set secret for %s", m->plug->mech_name, user);
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	    m->condition = SASL_OK; /* if we previously thought the
2197c478bd9Sstevel@tonic-gate 				       mechanism didn't have any user secrets
2207c478bd9Sstevel@tonic-gate 				       we now think it does */
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	} else if (tmpresult == SASL_NOCHANGE) {
2237c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_NOTE,
2247c478bd9Sstevel@tonic-gate 		      "%s: secret not changed for %s", m->plug->mech_name, user);
2257c478bd9Sstevel@tonic-gate 	} else {
2267c478bd9Sstevel@tonic-gate 	    result = tmpresult;
2277c478bd9Sstevel@tonic-gate 	    _sasl_log(conn, SASL_LOG_ERR,
2287c478bd9Sstevel@tonic-gate 		      "%s: failed to set secret for %s: %z (%m)",
2297c478bd9Sstevel@tonic-gate 		      m->plug->mech_name, user, tmpresult,
2307c478bd9Sstevel@tonic-gate #ifndef WIN32
2317c478bd9Sstevel@tonic-gate 		      errno
2327c478bd9Sstevel@tonic-gate #else
2337c478bd9Sstevel@tonic-gate 		      GetLastError()
2347c478bd9Sstevel@tonic-gate #endif
2357c478bd9Sstevel@tonic-gate 		      );
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate     }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate     RETURN(conn, result);
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2437c478bd9Sstevel@tonic-gate static void
server_dispose_mech_contexts(sasl_conn_t * pconn)2447c478bd9Sstevel@tonic-gate server_dispose_mech_contexts(sasl_conn_t *pconn)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate   sasl_server_conn_t *s_conn=  (sasl_server_conn_t *) pconn;
2477c478bd9Sstevel@tonic-gate   context_list_t *cur, *cur_next;
2487c478bd9Sstevel@tonic-gate   _sasl_global_context_t *gctx = pconn->gctx;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate   for(cur = s_conn->mech_contexts; cur; cur=cur_next) {
2517c478bd9Sstevel@tonic-gate       cur_next = cur->next;
2527c478bd9Sstevel@tonic-gate       if(cur->context)
2537c478bd9Sstevel@tonic-gate 	  cur->mech->plug->mech_dispose(cur->context, s_conn->sparams->utils);
2547c478bd9Sstevel@tonic-gate       sasl_FREE(cur);
2557c478bd9Sstevel@tonic-gate   }
2567c478bd9Sstevel@tonic-gate   s_conn->mech_contexts = NULL;
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate /* local mechanism which disposes of server */
server_dispose(sasl_conn_t * pconn)2617c478bd9Sstevel@tonic-gate static void server_dispose(sasl_conn_t *pconn)
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate   sasl_server_conn_t *s_conn=  (sasl_server_conn_t *) pconn;
2647c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2657c478bd9Sstevel@tonic-gate   _sasl_global_context_t *gctx = pconn->gctx;
2667c478bd9Sstevel@tonic-gate #else
2677c478bd9Sstevel@tonic-gate   context_list_t *cur, *cur_next;
2687c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate   if (s_conn->mech
2717c478bd9Sstevel@tonic-gate       && s_conn->mech->plug->mech_dispose) {
2727c478bd9Sstevel@tonic-gate     s_conn->mech->plug->mech_dispose(pconn->context,
2737c478bd9Sstevel@tonic-gate 				     s_conn->sparams->utils);
2747c478bd9Sstevel@tonic-gate   }
2757c478bd9Sstevel@tonic-gate   pconn->context = NULL;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2787c478bd9Sstevel@tonic-gate   server_dispose_mech_contexts(pconn);
2797c478bd9Sstevel@tonic-gate #else
2807c478bd9Sstevel@tonic-gate   for(cur = s_conn->mech_contexts; cur; cur=cur_next) {
2817c478bd9Sstevel@tonic-gate       cur_next = cur->next;
2827c478bd9Sstevel@tonic-gate       if(cur->context)
2837c478bd9Sstevel@tonic-gate 	  cur->mech->plug->mech_dispose(cur->context, s_conn->sparams->utils);
2847c478bd9Sstevel@tonic-gate       sasl_FREE(cur);
2857c478bd9Sstevel@tonic-gate   }
2867c478bd9Sstevel@tonic-gate   s_conn->mech_contexts = NULL;
2877c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate   _sasl_free_utils(&s_conn->sparams->utils);
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate   if (s_conn->sparams->propctx)
2927c478bd9Sstevel@tonic-gate       prop_dispose(&s_conn->sparams->propctx);
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate   if (s_conn->user_realm)
2957c478bd9Sstevel@tonic-gate       sasl_FREE(s_conn->user_realm);
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate   if (s_conn->sparams)
2987c478bd9Sstevel@tonic-gate       sasl_FREE(s_conn->sparams);
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate   _sasl_conn_dispose(pconn);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
init_mechlist(_sasl_global_context_t * gctx)3047c478bd9Sstevel@tonic-gate static int init_mechlist(_sasl_global_context_t *gctx)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate     mech_list_t *mechlist = gctx->mechlist;
3077c478bd9Sstevel@tonic-gate #else
3087c478bd9Sstevel@tonic-gate static int init_mechlist(void)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
3117c478bd9Sstevel@tonic-gate     sasl_utils_t *newutils = NULL;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate     mechlist->mutex = sasl_MUTEX_ALLOC();
3147c478bd9Sstevel@tonic-gate     if(!mechlist->mutex) return SASL_FAIL;
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate     /* set util functions - need to do rest */
3177c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
3187c478bd9Sstevel@tonic-gate     newutils = _sasl_alloc_utils(gctx, NULL, &gctx->server_global_callbacks);
3197c478bd9Sstevel@tonic-gate #else
3207c478bd9Sstevel@tonic-gate     newutils = _sasl_alloc_utils(NULL, &global_callbacks);
3217c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
3227c478bd9Sstevel@tonic-gate     if (newutils == NULL)
3237c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate     newutils->checkpass = &_sasl_checkpass;
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate     mechlist->utils = newutils;
3287c478bd9Sstevel@tonic-gate     mechlist->mech_list=NULL;
3297c478bd9Sstevel@tonic-gate     mechlist->mech_length=0;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate     return SASL_OK;
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
3357c478bd9Sstevel@tonic-gate static int load_mech(_sasl_global_context_t *gctx, const char *mechname)
3367c478bd9Sstevel@tonic-gate {
3377c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
3387c478bd9Sstevel@tonic-gate     void *context;
3397c478bd9Sstevel@tonic-gate     const char *mlist = NULL;
3407c478bd9Sstevel@tonic-gate     const char *cp;
3417c478bd9Sstevel@tonic-gate     size_t len;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate     /* No sasl_conn_t was given to getcallback, so we provide the
3447c478bd9Sstevel@tonic-gate      * global callbacks structure */
3457c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(NULL, SASL_CB_GETOPT, &getopt, &context) == SASL_OK)
3467c478bd9Sstevel@tonic-gate 	(void)getopt(&gctx->server_global_callbacks, NULL,
3477c478bd9Sstevel@tonic-gate 		"server_load_mech_list", &mlist, NULL);
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate     if (mlist == NULL)
3507c478bd9Sstevel@tonic-gate 	return (1);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate     len = strlen(mechname);
3537c478bd9Sstevel@tonic-gate     while (*mlist && isspace((int) *mlist)) mlist++;
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate     while (*mlist) {
3567c478bd9Sstevel@tonic-gate 	for (cp = mlist; *cp && !isspace((int) *cp); cp++);
3577c478bd9Sstevel@tonic-gate 	if (((size_t) (cp - mlist) == len) &&
3587c478bd9Sstevel@tonic-gate 		!strncasecmp(mlist, mechname, len))
3597c478bd9Sstevel@tonic-gate 	    break;
3607c478bd9Sstevel@tonic-gate 	mlist = cp;
3617c478bd9Sstevel@tonic-gate 	while (*mlist && isspace((int) *mlist)) mlist++;
3627c478bd9Sstevel@tonic-gate     }
3637c478bd9Sstevel@tonic-gate     return (*mlist != '\0');
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /*
3687c478bd9Sstevel@tonic-gate  * parameters:
3697c478bd9Sstevel@tonic-gate  *  p - entry point
3707c478bd9Sstevel@tonic-gate  */
3717c478bd9Sstevel@tonic-gate int sasl_server_add_plugin(const char *plugname,
3727c478bd9Sstevel@tonic-gate 			   sasl_server_plug_init_t *p)
3737c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate     return (_sasl_server_add_plugin(_sasl_gbl_ctx(), plugname, p));
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate int _sasl_server_add_plugin(void *ctx,
3797c478bd9Sstevel@tonic-gate 			    const char *plugname,
3807c478bd9Sstevel@tonic-gate 			    sasl_server_plug_init_t *p)
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate     int nplug = 0;
3837c478bd9Sstevel@tonic-gate     int i;
3847c478bd9Sstevel@tonic-gate     mechanism_t *m;
3857c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx;
3867c478bd9Sstevel@tonic-gate     mech_list_t *mechlist = gctx->mechlist;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
3897c478bd9Sstevel@tonic-gate     int sun_reg;
3907c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
3917c478bd9Sstevel@tonic-gate #else
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
3947c478bd9Sstevel@tonic-gate     int plugcount;
3957c478bd9Sstevel@tonic-gate     sasl_server_plug_t *pluglist;
3967c478bd9Sstevel@tonic-gate     mechanism_t *mech;
3977c478bd9Sstevel@tonic-gate     sasl_server_plug_init_t *entry_point;
3987c478bd9Sstevel@tonic-gate     int result;
3997c478bd9Sstevel@tonic-gate     int version;
4007c478bd9Sstevel@tonic-gate     int lupe;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate     if(!plugname || !p) return SASL_BADPARAM;
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4057c478bd9Sstevel@tonic-gate     if (mechlist == NULL) return SASL_BADPARAM;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate     /* Check to see if this plugin has already been registered */
4087c478bd9Sstevel@tonic-gate     m = mechlist->mech_list;
4097c478bd9Sstevel@tonic-gate     for (i = 0; i < mechlist->mech_length; i++) {
4107c478bd9Sstevel@tonic-gate 	if (strcmp(plugname, m->plugname) == 0)
4117c478bd9Sstevel@tonic-gate 		return SASL_OK;
4127c478bd9Sstevel@tonic-gate 	m = m->next;
4137c478bd9Sstevel@tonic-gate     }
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate     result = LOCK_MUTEX(&server_plug_mutex);
4167c478bd9Sstevel@tonic-gate     if (result != SASL_OK)
4177c478bd9Sstevel@tonic-gate 	return result;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4207c478bd9Sstevel@tonic-gate     entry_point = (sasl_server_plug_init_t *)p;
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate     /* call into the shared library asking for information about it */
4237c478bd9Sstevel@tonic-gate     /* version is filled in with the version of the plugin */
4247c478bd9Sstevel@tonic-gate     result = entry_point(mechlist->utils, SASL_SERVER_PLUG_VERSION, &version,
4257c478bd9Sstevel@tonic-gate 			 &pluglist, &plugcount);
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
4287c478bd9Sstevel@tonic-gate     sun_reg = _is_sun_reg(pluglist);
4297c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4327c478bd9Sstevel@tonic-gate     if (result != SASL_OK) {
4337c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_plug_mutex);
4347c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks,
4357c478bd9Sstevel@tonic-gate 		   SASL_LOG_DEBUG,
4367c478bd9Sstevel@tonic-gate 		   "server add_plugin entry_point error %z", result);
4377c478bd9Sstevel@tonic-gate #else
4387c478bd9Sstevel@tonic-gate     if ((result != SASL_OK) && (result != SASL_NOUSER)) {
4397c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_DEBUG,
4407c478bd9Sstevel@tonic-gate 		  "server add_plugin entry_point error %z\n", result);
4417c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4427c478bd9Sstevel@tonic-gate 	return result;
4437c478bd9Sstevel@tonic-gate     }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate     /* Make sure plugin is using the same SASL version as us */
4467c478bd9Sstevel@tonic-gate     if (version != SASL_SERVER_PLUG_VERSION)
4477c478bd9Sstevel@tonic-gate     {
4487c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4497c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_plug_mutex);
4507c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks,
4517c478bd9Sstevel@tonic-gate 		   SASL_LOG_ERR, "version mismatch on plugin");
4527c478bd9Sstevel@tonic-gate #else
4537c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR,
4547c478bd9Sstevel@tonic-gate 		  "version mismatch on plugin");
4557c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4567c478bd9Sstevel@tonic-gate 	return SASL_BADVERS;
4577c478bd9Sstevel@tonic-gate     }
4587c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4597c478bd9Sstevel@tonic-gate     /* Check plugins to make sure mech_name is non-NULL */
4607c478bd9Sstevel@tonic-gate     for (lupe=0;lupe < plugcount ;lupe++) {
4617c478bd9Sstevel@tonic-gate 	if (pluglist[lupe].mech_name == NULL)
4627c478bd9Sstevel@tonic-gate 	     break;
4637c478bd9Sstevel@tonic-gate     }
4647c478bd9Sstevel@tonic-gate     if (lupe < plugcount) {
4657c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4667c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_plug_mutex);
4677c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks,
4687c478bd9Sstevel@tonic-gate 		   SASL_LOG_ERR, "invalid server plugin %s", plugname);
4697c478bd9Sstevel@tonic-gate #else
4707c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR, "invalid server plugin %s", plugname);
4717c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4727c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
4737c478bd9Sstevel@tonic-gate     }
4747c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate     for (lupe=0;lupe < plugcount ;lupe++)
4777c478bd9Sstevel@tonic-gate     {
4787c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4797c478bd9Sstevel@tonic-gate 	if (!load_mech(gctx, pluglist->mech_name)) {
4807c478bd9Sstevel@tonic-gate 	     pluglist++;
4817c478bd9Sstevel@tonic-gate 	     continue;
4827c478bd9Sstevel@tonic-gate 	}
4837c478bd9Sstevel@tonic-gate 	nplug++;
4847c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4857c478bd9Sstevel@tonic-gate 	mech = sasl_ALLOC(sizeof(mechanism_t));
4867c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4877c478bd9Sstevel@tonic-gate 	if (! mech) {
4887c478bd9Sstevel@tonic-gate 	    UNLOCK_MUTEX(&server_plug_mutex);
4897c478bd9Sstevel@tonic-gate 	    return SASL_NOMEM;
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	mech->glob_context = pluglist->glob_context;
4937c478bd9Sstevel@tonic-gate #else
4947c478bd9Sstevel@tonic-gate 	if (! mech) return SASL_NOMEM;
4957c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	mech->plug=pluglist++;
4987c478bd9Sstevel@tonic-gate 	if(_sasl_strdup(plugname, &mech->plugname, NULL) != SASL_OK) {
4997c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5007c478bd9Sstevel@tonic-gate 	    UNLOCK_MUTEX(&server_plug_mutex);
5017c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5027c478bd9Sstevel@tonic-gate 	    sasl_FREE(mech);
5037c478bd9Sstevel@tonic-gate 	    return SASL_NOMEM;
5047c478bd9Sstevel@tonic-gate 	}
5057c478bd9Sstevel@tonic-gate 	mech->version = version;
5067c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5077c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
5087c478bd9Sstevel@tonic-gate 	mech->sun_reg = sun_reg;
5097c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	/* whether this mech actually has any users in it's db */
5127c478bd9Sstevel@tonic-gate 	mech->condition = SASL_OK;
5137c478bd9Sstevel@tonic-gate #else
5147c478bd9Sstevel@tonic-gate 	/* whether this mech actually has any users in it's db */
5157c478bd9Sstevel@tonic-gate 	mech->condition = result; /* SASL_OK or SASL_NOUSER */
5167c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	mech->next = mechlist->mech_list;
5197c478bd9Sstevel@tonic-gate 	mechlist->mech_list = mech;
5207c478bd9Sstevel@tonic-gate 	mechlist->mech_length++;
5217c478bd9Sstevel@tonic-gate     }
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5247c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&server_plug_mutex);
5257c478bd9Sstevel@tonic-gate     return (nplug == 0) ? SASL_NOMECH : SASL_OK;
5267c478bd9Sstevel@tonic-gate #else
5277c478bd9Sstevel@tonic-gate     return SASL_OK;
5287c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5327c478bd9Sstevel@tonic-gate static int server_done(_sasl_global_context_t *gctx) {
5337c478bd9Sstevel@tonic-gate   mech_list_t *mechlist = gctx->mechlist;
5347c478bd9Sstevel@tonic-gate   _sasl_path_info_t *path_info, *p;
5357c478bd9Sstevel@tonic-gate #else
5367c478bd9Sstevel@tonic-gate static int server_done(void) {
5377c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5387c478bd9Sstevel@tonic-gate   mechanism_t *m;
5397c478bd9Sstevel@tonic-gate   mechanism_t *prevm;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5427c478bd9Sstevel@tonic-gate   if(!gctx->sasl_server_active)
5437c478bd9Sstevel@tonic-gate       return SASL_NOTINIT;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate   if (LOCK_MUTEX(&server_active_mutex) < 0) {
5467c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
5477c478bd9Sstevel@tonic-gate   }
5487c478bd9Sstevel@tonic-gate   gctx->sasl_server_active--;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate   if(gctx->sasl_server_active) {
5517c478bd9Sstevel@tonic-gate       /* Don't de-init yet! Our refcount is nonzero. */
5527c478bd9Sstevel@tonic-gate       UNLOCK_MUTEX(&server_active_mutex);
5537c478bd9Sstevel@tonic-gate       return SASL_CONTINUE;
5547c478bd9Sstevel@tonic-gate   }
5557c478bd9Sstevel@tonic-gate #else
5567c478bd9Sstevel@tonic-gate   if(!_sasl_server_active)
5577c478bd9Sstevel@tonic-gate       return SASL_NOTINIT;
5587c478bd9Sstevel@tonic-gate   else
5597c478bd9Sstevel@tonic-gate       _sasl_server_active--;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate   if(_sasl_server_active) {
5627c478bd9Sstevel@tonic-gate       /* Don't de-init yet! Our refcount is nonzero. */
5637c478bd9Sstevel@tonic-gate       return SASL_CONTINUE;
5647c478bd9Sstevel@tonic-gate   }
5657c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate   if (mechlist != NULL)
5687c478bd9Sstevel@tonic-gate   {
5697c478bd9Sstevel@tonic-gate       m=mechlist->mech_list; /* m point to beginning of the list */
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate       while (m!=NULL)
5727c478bd9Sstevel@tonic-gate       {
5737c478bd9Sstevel@tonic-gate 	  prevm=m;
5747c478bd9Sstevel@tonic-gate 	  m=m->next;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	  if (prevm->plug->mech_free) {
5777c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5787c478bd9Sstevel@tonic-gate 	      prevm->plug->mech_free(prevm->glob_context,
5797c478bd9Sstevel@tonic-gate #else
5807c478bd9Sstevel@tonic-gate 	      prevm->plug->mech_free(prevm->plug->glob_context,
5817c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5827c478bd9Sstevel@tonic-gate 				     mechlist->utils);
5837c478bd9Sstevel@tonic-gate 	  }
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	  sasl_FREE(prevm->plugname);
5867c478bd9Sstevel@tonic-gate 	  sasl_FREE(prevm);
5877c478bd9Sstevel@tonic-gate       }
5887c478bd9Sstevel@tonic-gate       _sasl_free_utils(&mechlist->utils);
5897c478bd9Sstevel@tonic-gate       sasl_MUTEX_FREE(mechlist->mutex);
5907c478bd9Sstevel@tonic-gate       sasl_FREE(mechlist);
5917c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5927c478bd9Sstevel@tonic-gate       gctx->mechlist = NULL;
5937c478bd9Sstevel@tonic-gate #else
5947c478bd9Sstevel@tonic-gate       mechlist = NULL;
5957c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5967c478bd9Sstevel@tonic-gate   }
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate   /* Free the auxprop plugins */
5997c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6007c478bd9Sstevel@tonic-gate   _sasl_auxprop_free(gctx);
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate   gctx->server_global_callbacks.callbacks = NULL;
6037c478bd9Sstevel@tonic-gate   gctx->server_global_callbacks.appname = NULL;
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate   p = gctx->splug_path_info;
6067c478bd9Sstevel@tonic-gate   while((path_info = p) != NULL) {
6077c478bd9Sstevel@tonic-gate     sasl_FREE(path_info->path);
6087c478bd9Sstevel@tonic-gate     p = path_info->next;
6097c478bd9Sstevel@tonic-gate     sasl_FREE(path_info);
6107c478bd9Sstevel@tonic-gate   }
6117c478bd9Sstevel@tonic-gate   gctx->splug_path_info = NULL;
6127c478bd9Sstevel@tonic-gate   UNLOCK_MUTEX(&server_active_mutex);
6137c478bd9Sstevel@tonic-gate #else
6147c478bd9Sstevel@tonic-gate   _sasl_auxprop_free();
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate   global_callbacks.callbacks = NULL;
6177c478bd9Sstevel@tonic-gate   global_callbacks.appname = NULL;
6187c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate   return SASL_OK;
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate static int server_idle(sasl_conn_t *conn)
6247c478bd9Sstevel@tonic-gate {
6257c478bd9Sstevel@tonic-gate     mechanism_t *m;
6267c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6277c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx;
6287c478bd9Sstevel@tonic-gate     mech_list_t *mechlist;
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate     if (conn == NULL)
6317c478bd9Sstevel@tonic-gate         gctx = _sasl_gbl_ctx();
6327c478bd9Sstevel@tonic-gate     else
6337c478bd9Sstevel@tonic-gate         gctx = conn->gctx;
6347c478bd9Sstevel@tonic-gate   mechlist = gctx->mechlist;
6357c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
6367c478bd9Sstevel@tonic-gate     if (! mechlist)
6377c478bd9Sstevel@tonic-gate 	return 0;
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate     for (m = mechlist->mech_list;
6407c478bd9Sstevel@tonic-gate 	 m!=NULL;
6417c478bd9Sstevel@tonic-gate 	 m = m->next)
6427c478bd9Sstevel@tonic-gate 	if (m->plug->idle
6437c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6447c478bd9Sstevel@tonic-gate 	    &&  m->plug->idle(m->glob_context,
6457c478bd9Sstevel@tonic-gate #else
6467c478bd9Sstevel@tonic-gate 	    &&  m->plug->idle(m->plug->glob_context,
6477c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
6487c478bd9Sstevel@tonic-gate 			      conn,
6497c478bd9Sstevel@tonic-gate 			      conn ? ((sasl_server_conn_t *)conn)->sparams : NULL))
6507c478bd9Sstevel@tonic-gate 	    return 1;
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate     return 0;
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6567c478bd9Sstevel@tonic-gate static int load_config(_sasl_global_context_t *gctx,
6577c478bd9Sstevel@tonic-gate 		       const sasl_callback_t *verifyfile_cb)
6587c478bd9Sstevel@tonic-gate {
6597c478bd9Sstevel@tonic-gate   int result;
6607c478bd9Sstevel@tonic-gate   const char *conf_to_config = NULL;
6617c478bd9Sstevel@tonic-gate   const char *conf_file = NULL;
6627c478bd9Sstevel@tonic-gate   int conf_len;
6637c478bd9Sstevel@tonic-gate   sasl_global_callbacks_t global_callbacks = gctx->server_global_callbacks;
6647c478bd9Sstevel@tonic-gate   char *alloc_file_name=NULL;
6657c478bd9Sstevel@tonic-gate   int len;
6667c478bd9Sstevel@tonic-gate   const sasl_callback_t *getconf_cb=NULL;
6677c478bd9Sstevel@tonic-gate   struct stat buf;
6687c478bd9Sstevel@tonic-gate   int full_file = 0;
6697c478bd9Sstevel@tonic-gate   int file_exists = 0;
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate   /* get the path to the plugins; for now the config file will reside there */
6727c478bd9Sstevel@tonic-gate   getconf_cb = _sasl_find_getconf_callback(global_callbacks.callbacks);
6737c478bd9Sstevel@tonic-gate   if (getconf_cb==NULL) return SASL_BADPARAM;
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate   result = ((sasl_getpath_t *)(getconf_cb->proc))(getconf_cb->context,
6767c478bd9Sstevel@tonic-gate 						  &conf_to_config);
6777c478bd9Sstevel@tonic-gate   if (result!=SASL_OK) goto done;
6787c478bd9Sstevel@tonic-gate   if (conf_to_config == NULL) conf_to_config = "";
6797c478bd9Sstevel@tonic-gate   else {
6807c478bd9Sstevel@tonic-gate 	if (stat(conf_to_config, &buf))
6817c478bd9Sstevel@tonic-gate 		goto process_file;
6827c478bd9Sstevel@tonic-gate 	full_file = !S_ISDIR(buf.st_mode);
6837c478bd9Sstevel@tonic-gate   }
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate   if (!full_file) {
6867c478bd9Sstevel@tonic-gate     conf_len = strlen(conf_to_config);
6877c478bd9Sstevel@tonic-gate     len = strlen(conf_to_config)+2+ strlen(global_callbacks.appname)+5+1;
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate     if (len > PATH_MAX ) {
6907c478bd9Sstevel@tonic-gate       result = SASL_FAIL;
6917c478bd9Sstevel@tonic-gate       goto done;
6927c478bd9Sstevel@tonic-gate     }
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate     /* construct the filename for the config file */
6957c478bd9Sstevel@tonic-gate     alloc_file_name = sasl_ALLOC(len);
6967c478bd9Sstevel@tonic-gate     if (! alloc_file_name) {
6977c478bd9Sstevel@tonic-gate         result = SASL_NOMEM;
6987c478bd9Sstevel@tonic-gate         goto done;
6997c478bd9Sstevel@tonic-gate     }
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate     snprintf(alloc_file_name, len, "%.*s/%s.conf", conf_len, conf_to_config,
7027c478bd9Sstevel@tonic-gate 	   global_callbacks.appname);
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate   }
7057c478bd9Sstevel@tonic-gate   conf_file = full_file ? conf_to_config : alloc_file_name;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate   if (full_file || stat(conf_file, &buf) == 0)
7087c478bd9Sstevel@tonic-gate 	file_exists = S_ISREG(buf.st_mode);
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate process_file:
7117c478bd9Sstevel@tonic-gate   /* Check to see if anything has changed */
7127c478bd9Sstevel@tonic-gate   if (file_exists && gctx->config_path != NULL &&
7137c478bd9Sstevel@tonic-gate 	strcmp(conf_file, gctx->config_path) == 0 &&
7147c478bd9Sstevel@tonic-gate 	gctx->config_last_read == buf.st_mtime) {
7157c478bd9Sstevel@tonic-gate     /* File has not changed */
7167c478bd9Sstevel@tonic-gate     goto done;
7177c478bd9Sstevel@tonic-gate   } else if (gctx->config_path == NULL) {
7187c478bd9Sstevel@tonic-gate     /* No new file, nothing has changed  */
7197c478bd9Sstevel@tonic-gate     if (!file_exists)
7207c478bd9Sstevel@tonic-gate 	goto done;
7217c478bd9Sstevel@tonic-gate   } else {
7227c478bd9Sstevel@tonic-gate     sasl_config_free(gctx);
7237c478bd9Sstevel@tonic-gate     if (!file_exists) {
7247c478bd9Sstevel@tonic-gate 	gctx->config_path = NULL;
7257c478bd9Sstevel@tonic-gate 	goto done;
7267c478bd9Sstevel@tonic-gate     }
7277c478bd9Sstevel@tonic-gate   }
7287c478bd9Sstevel@tonic-gate   gctx->config_last_read = buf.st_mtime;
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate   /* Ask the application if it's safe to use this file */
7317c478bd9Sstevel@tonic-gate   result = ((sasl_verifyfile_t *)(verifyfile_cb->proc))(verifyfile_cb->context,
7327c478bd9Sstevel@tonic-gate 		conf_file, SASL_VRFY_CONF);
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate   /* returns continue if this file is to be skipped */
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate   /* returns SASL_CONTINUE if doesn't exist
7377c478bd9Sstevel@tonic-gate    * if doesn't exist we can continue using default behavior
7387c478bd9Sstevel@tonic-gate    */
7397c478bd9Sstevel@tonic-gate   if (result==SASL_OK)
7407c478bd9Sstevel@tonic-gate     result=sasl_config_init(gctx, conf_file);
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate  done:
7437c478bd9Sstevel@tonic-gate   if (alloc_file_name) sasl_FREE(alloc_file_name);
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate   return result;
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate #else
7487c478bd9Sstevel@tonic-gate static int load_config(const sasl_callback_t *verifyfile_cb)
7497c478bd9Sstevel@tonic-gate {
7507c478bd9Sstevel@tonic-gate   int result;
7517c478bd9Sstevel@tonic-gate   const char *path_to_config=NULL;
7527c478bd9Sstevel@tonic-gate   const char *c;
7537c478bd9Sstevel@tonic-gate   unsigned path_len;
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate   char *config_filename=NULL;
7567c478bd9Sstevel@tonic-gate   int len;
7577c478bd9Sstevel@tonic-gate   const sasl_callback_t *getpath_cb=NULL;
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate   /* get the path to the plugins; for now the config file will reside there */
7607c478bd9Sstevel@tonic-gate   getpath_cb=_sasl_find_getpath_callback( global_callbacks.callbacks );
7617c478bd9Sstevel@tonic-gate   if (getpath_cb==NULL) return SASL_BADPARAM;
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate   /* getpath_cb->proc MUST be a sasl_getpath_t; if only c had a type
7647c478bd9Sstevel@tonic-gate      system */
7657c478bd9Sstevel@tonic-gate   result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context,
7667c478bd9Sstevel@tonic-gate 						  &path_to_config);
7677c478bd9Sstevel@tonic-gate   if (result!=SASL_OK) goto done;
7687c478bd9Sstevel@tonic-gate   if (path_to_config == NULL) path_to_config = "";
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate   c = strchr(path_to_config, PATHS_DELIMITER);
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate   /* length = length of path + '/' + length of appname + ".conf" + 1
7737c478bd9Sstevel@tonic-gate      for '\0' */
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate   if(c != NULL)
7767c478bd9Sstevel@tonic-gate     path_len = c - path_to_config;
7777c478bd9Sstevel@tonic-gate   else
7787c478bd9Sstevel@tonic-gate     path_len = strlen(path_to_config);
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate   len = path_len + 2 + strlen(global_callbacks.appname) + 5 + 1;
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate   if (len > PATH_MAX ) {
7837c478bd9Sstevel@tonic-gate       result = SASL_FAIL;
7847c478bd9Sstevel@tonic-gate       goto done;
7857c478bd9Sstevel@tonic-gate   }
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate   /* construct the filename for the config file */
7887c478bd9Sstevel@tonic-gate   config_filename = sasl_ALLOC(len);
7897c478bd9Sstevel@tonic-gate   if (! config_filename) {
7907c478bd9Sstevel@tonic-gate       result = SASL_NOMEM;
7917c478bd9Sstevel@tonic-gate       goto done;
7927c478bd9Sstevel@tonic-gate   }
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate   snprintf(config_filename, len, "%.*s/%s.conf", path_len, path_to_config,
7957c478bd9Sstevel@tonic-gate 	   global_callbacks.appname);
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate   /* Ask the application if it's safe to use this file */
7987c478bd9Sstevel@tonic-gate   result = ((sasl_verifyfile_t *)(verifyfile_cb->proc))(verifyfile_cb->context,
7997c478bd9Sstevel@tonic-gate 					config_filename, SASL_VRFY_CONF);
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate   /* returns continue if this file is to be skipped */
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate   /* returns SASL_CONTINUE if doesn't exist
8047c478bd9Sstevel@tonic-gate    * if doesn't exist we can continue using default behavior
8057c478bd9Sstevel@tonic-gate    */
8067c478bd9Sstevel@tonic-gate   if (result==SASL_OK)
8077c478bd9Sstevel@tonic-gate     result=sasl_config_init(config_filename);
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate  done:
8107c478bd9Sstevel@tonic-gate   if (config_filename) sasl_FREE(config_filename);
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate   return result;
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate /*
8177c478bd9Sstevel@tonic-gate  * Verify that all the callbacks are valid
8187c478bd9Sstevel@tonic-gate  */
8197c478bd9Sstevel@tonic-gate static int verify_server_callbacks(const sasl_callback_t *callbacks)
8207c478bd9Sstevel@tonic-gate {
8217c478bd9Sstevel@tonic-gate     if (callbacks == NULL) return SASL_OK;
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate     while (callbacks->id != SASL_CB_LIST_END) {
8247c478bd9Sstevel@tonic-gate 	if (callbacks->proc==NULL) return SASL_FAIL;
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 	callbacks++;
8277c478bd9Sstevel@tonic-gate     }
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate     return SASL_OK;
8307c478bd9Sstevel@tonic-gate }
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
8337c478bd9Sstevel@tonic-gate static char *grab_field(char *line, char **eofield)
8347c478bd9Sstevel@tonic-gate {
8357c478bd9Sstevel@tonic-gate     int d = 0;
8367c478bd9Sstevel@tonic-gate     char *field;
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate     while (isspace((int) *line)) line++;
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate     /* find end of field */
8417c478bd9Sstevel@tonic-gate     while (line[d] && !isspace(((int) line[d]))) d++;
8427c478bd9Sstevel@tonic-gate     field = sasl_ALLOC(d + 1);
8437c478bd9Sstevel@tonic-gate     if (!field) { return NULL; }
8447c478bd9Sstevel@tonic-gate     memcpy(field, line, d);
8457c478bd9Sstevel@tonic-gate     field[d] = '\0';
8467c478bd9Sstevel@tonic-gate     *eofield = line + d;
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate     return field;
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate struct secflag_map_s {
8527c478bd9Sstevel@tonic-gate     char *name;
8537c478bd9Sstevel@tonic-gate     int value;
8547c478bd9Sstevel@tonic-gate };
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate struct secflag_map_s secflag_map[] = {
8577c478bd9Sstevel@tonic-gate     { "noplaintext", SASL_SEC_NOPLAINTEXT },
8587c478bd9Sstevel@tonic-gate     { "noactive", SASL_SEC_NOACTIVE },
8597c478bd9Sstevel@tonic-gate     { "nodictionary", SASL_SEC_NODICTIONARY },
8607c478bd9Sstevel@tonic-gate     { "forward_secrecy", SASL_SEC_FORWARD_SECRECY },
8617c478bd9Sstevel@tonic-gate     { "noanonymous", SASL_SEC_NOANONYMOUS },
8627c478bd9Sstevel@tonic-gate     { "pass_credentials", SASL_SEC_PASS_CREDENTIALS },
8637c478bd9Sstevel@tonic-gate     { "mutual_auth", SASL_SEC_MUTUAL_AUTH },
8647c478bd9Sstevel@tonic-gate     { NULL, 0x0 }
8657c478bd9Sstevel@tonic-gate };
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate static int parse_mechlist_file(const char *mechlistfile)
8687c478bd9Sstevel@tonic-gate {
8697c478bd9Sstevel@tonic-gate     FILE *f;
8707c478bd9Sstevel@tonic-gate     char buf[1024];
8717c478bd9Sstevel@tonic-gate     char *t, *ptr;
8727c478bd9Sstevel@tonic-gate     int r = 0;
8737c478bd9Sstevel@tonic-gate 
874*004388ebScasper     f = fopen(mechlistfile, "rF");
8757c478bd9Sstevel@tonic-gate     if (!f) return SASL_FAIL;
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate     r = SASL_OK;
8787c478bd9Sstevel@tonic-gate     while (fgets(buf, sizeof(buf), f) != NULL) {
8797c478bd9Sstevel@tonic-gate 	mechanism_t *n = sasl_ALLOC(sizeof(mechanism_t));
8807c478bd9Sstevel@tonic-gate 	sasl_server_plug_t *nplug;
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 	if (n == NULL) { r = SASL_NOMEM; break; }
8837c478bd9Sstevel@tonic-gate 	n->version = SASL_SERVER_PLUG_VERSION;
8847c478bd9Sstevel@tonic-gate 	n->condition = SASL_CONTINUE;
8857c478bd9Sstevel@tonic-gate 	nplug = sasl_ALLOC(sizeof(sasl_server_plug_t));
8867c478bd9Sstevel@tonic-gate 	if (nplug == NULL) { r = SASL_NOMEM; break; }
8877c478bd9Sstevel@tonic-gate 	memset(nplug, 0, sizeof(sasl_server_plug_t));
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 	/* each line is:
8907c478bd9Sstevel@tonic-gate 	   plugin-file WS mech_name WS max_ssf *(WS security_flag) RET
8917c478bd9Sstevel@tonic-gate 	*/
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	/* grab file */
8947c478bd9Sstevel@tonic-gate 	n->f = grab_field(buf, &ptr);
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 	/* grab mech_name */
8977c478bd9Sstevel@tonic-gate 	nplug->mech_name = grab_field(ptr, &ptr);
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	/* grab max_ssf */
9007c478bd9Sstevel@tonic-gate 	nplug->max_ssf = strtol(ptr, &ptr, 10);
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	/* grab security flags */
9037c478bd9Sstevel@tonic-gate 	while (*ptr != '\n') {
9047c478bd9Sstevel@tonic-gate 	    struct secflag_map_s *map;
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 	    /* read security flag */
9077c478bd9Sstevel@tonic-gate 	    t = grab_field(ptr, &ptr);
9087c478bd9Sstevel@tonic-gate 	    map = secflag_map;
9097c478bd9Sstevel@tonic-gate 	    while (map->name) {
9107c478bd9Sstevel@tonic-gate 		if (!strcasecmp(t, map->name)) {
9117c478bd9Sstevel@tonic-gate 		    nplug->security_flags |= map->value;
9127c478bd9Sstevel@tonic-gate 		    break;
9137c478bd9Sstevel@tonic-gate 		}
9147c478bd9Sstevel@tonic-gate 		map++;
9157c478bd9Sstevel@tonic-gate 	    }
9167c478bd9Sstevel@tonic-gate 	    if (!map->name) {
9177c478bd9Sstevel@tonic-gate 		_sasl_log(NULL, SASL_LOG_ERR,
9187c478bd9Sstevel@tonic-gate 			  "%s: couldn't identify flag '%s'",
9197c478bd9Sstevel@tonic-gate 			  nplug->mech_name, t);
9207c478bd9Sstevel@tonic-gate 	    }
9217c478bd9Sstevel@tonic-gate 	    free(t);
9227c478bd9Sstevel@tonic-gate 	}
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 	/* insert mechanism into mechlist */
9257c478bd9Sstevel@tonic-gate 	n->plug = nplug;
9267c478bd9Sstevel@tonic-gate 	n->next = mechlist->mech_list;
9277c478bd9Sstevel@tonic-gate 	mechlist->mech_list = n;
9287c478bd9Sstevel@tonic-gate 	mechlist->mech_length++;
9297c478bd9Sstevel@tonic-gate     }
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate     fclose(f);
9327c478bd9Sstevel@tonic-gate     return r;
9337c478bd9Sstevel@tonic-gate }
9347c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
9377c478bd9Sstevel@tonic-gate static int _load_server_plugins(_sasl_global_context_t *gctx)
9387c478bd9Sstevel@tonic-gate {
9397c478bd9Sstevel@tonic-gate     int ret;
9407c478bd9Sstevel@tonic-gate     const add_plugin_list_t _ep_list[] = {
9417c478bd9Sstevel@tonic-gate 	{ "sasl_server_plug_init", (add_plugin_t *)_sasl_server_add_plugin },
9427c478bd9Sstevel@tonic-gate 	{ "sasl_auxprop_plug_init", (add_plugin_t *)_sasl_auxprop_add_plugin },
9437c478bd9Sstevel@tonic-gate 	{ "sasl_canonuser_init", (add_plugin_t *)_sasl_canonuser_add_plugin },
9447c478bd9Sstevel@tonic-gate 	{ NULL, NULL }
9457c478bd9Sstevel@tonic-gate     };
9467c478bd9Sstevel@tonic-gate     const sasl_callback_t *callbacks = gctx->server_global_callbacks.callbacks;
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate     ret = _sasl_load_plugins(gctx, 1, _ep_list,
9497c478bd9Sstevel@tonic-gate 			     _sasl_find_getpath_callback(callbacks),
9507c478bd9Sstevel@tonic-gate 			     _sasl_find_verifyfile_callback(callbacks));
9517c478bd9Sstevel@tonic-gate     return (ret);
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate /* initialize server drivers, done once per process
9567c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
9577c478bd9Sstevel@tonic-gate  *  callbacks      -- callbacks for all server connections
9587c478bd9Sstevel@tonic-gate  *  appname        -- name of calling application (for config)
9597c478bd9Sstevel@tonic-gate #else
9607c478bd9Sstevel@tonic-gate  *  callbacks      -- callbacks for all server connections; must include
9617c478bd9Sstevel@tonic-gate  *                    getopt callback
9627c478bd9Sstevel@tonic-gate  *  appname        -- name of calling application (for lower level logging)
9637c478bd9Sstevel@tonic-gate  * results:
9647c478bd9Sstevel@tonic-gate  *  state          -- server state
9657c478bd9Sstevel@tonic-gate #endif
9667c478bd9Sstevel@tonic-gate  * returns:
9677c478bd9Sstevel@tonic-gate  *  SASL_OK        -- success
9687c478bd9Sstevel@tonic-gate  *  SASL_BADPARAM  -- error in config file
9697c478bd9Sstevel@tonic-gate  *  SASL_NOMEM     -- memory failure
9707c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
9717c478bd9Sstevel@tonic-gate  *  SASL_BADVERS   -- Mechanism version mismatch
9727c478bd9Sstevel@tonic-gate #endif
9737c478bd9Sstevel@tonic-gate  */
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate int sasl_server_init(const sasl_callback_t *callbacks,
9767c478bd9Sstevel@tonic-gate 		     const char *appname)
9777c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
9787c478bd9Sstevel@tonic-gate {
9797c478bd9Sstevel@tonic-gate 	return _sasl_server_init(NULL, callbacks, appname);
9807c478bd9Sstevel@tonic-gate }
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate int _sasl_server_init(void *ctx, const sasl_callback_t *callbacks,
9837c478bd9Sstevel@tonic-gate 		     const char *appname)
9847c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
9857c478bd9Sstevel@tonic-gate {
9867c478bd9Sstevel@tonic-gate     int ret;
9877c478bd9Sstevel@tonic-gate     const sasl_callback_t *vf;
9887c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
9897c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx;
9907c478bd9Sstevel@tonic-gate #else
9917c478bd9Sstevel@tonic-gate     const char *pluginfile = NULL;
9927c478bd9Sstevel@tonic-gate #ifdef PIC
9937c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
9947c478bd9Sstevel@tonic-gate     void *context;
9957c478bd9Sstevel@tonic-gate #endif
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate     const add_plugin_list_t ep_list[] = {
9987c478bd9Sstevel@tonic-gate 	{ "sasl_server_plug_init", (add_plugin_t *)sasl_server_add_plugin },
9997c478bd9Sstevel@tonic-gate 	{ "sasl_auxprop_plug_init", (add_plugin_t *)sasl_auxprop_add_plugin },
10007c478bd9Sstevel@tonic-gate 	{ "sasl_canonuser_init", (add_plugin_t *)sasl_canonuser_add_plugin },
10017c478bd9Sstevel@tonic-gate 	{ NULL, NULL }
10027c478bd9Sstevel@tonic-gate     };
10037c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate     /* we require the appname to be non-null and short enough to be a path */
10067c478bd9Sstevel@tonic-gate     if (!appname || strlen(appname) >= PATH_MAX)
10077c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
10107c478bd9Sstevel@tonic-gate     /* Process only one _sasl_server_init() at a time */
10117c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&init_server_mutex) < 0)
10127c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
10137c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&server_active_mutex) < 0)
10147c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate     if (gctx->sasl_server_active) {
10177c478bd9Sstevel@tonic-gate 	/* We're already active, just increase our refcount */
10187c478bd9Sstevel@tonic-gate 	/* xxx do something with the callback structure? */
10197c478bd9Sstevel@tonic-gate 	gctx->sasl_server_active++;
10207c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_active_mutex);
10217c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
10227c478bd9Sstevel@tonic-gate 	return SASL_OK;
10237c478bd9Sstevel@tonic-gate     }
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate     ret = _sasl_common_init(gctx, &gctx->server_global_callbacks, 1);
10267c478bd9Sstevel@tonic-gate     if (ret != SASL_OK) {
10277c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_active_mutex);
10287c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
10297c478bd9Sstevel@tonic-gate 	return ret;
10307c478bd9Sstevel@tonic-gate     }
10317c478bd9Sstevel@tonic-gate #else
10327c478bd9Sstevel@tonic-gate     if (_sasl_server_active) {
10337c478bd9Sstevel@tonic-gate 	/* We're already active, just increase our refcount */
10347c478bd9Sstevel@tonic-gate 	/* xxx do something with the callback structure? */
10357c478bd9Sstevel@tonic-gate 	_sasl_server_active++;
10367c478bd9Sstevel@tonic-gate 	return SASL_OK;
10377c478bd9Sstevel@tonic-gate     }
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate     ret = _sasl_common_init(&global_callbacks);
10407c478bd9Sstevel@tonic-gate     if (ret != SASL_OK)
10417c478bd9Sstevel@tonic-gate 	return ret;
10427c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate     /* verify that the callbacks look ok */
10457c478bd9Sstevel@tonic-gate     ret = verify_server_callbacks(callbacks);
10467c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
10477c478bd9Sstevel@tonic-gate     if (ret != SASL_OK) {
10487c478bd9Sstevel@tonic-gate 	UNLOCK_MUTEX(&server_active_mutex);
10497c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
10507c478bd9Sstevel@tonic-gate 	return ret;
10517c478bd9Sstevel@tonic-gate     }
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate     gctx->server_global_callbacks.callbacks = callbacks;
10547c478bd9Sstevel@tonic-gate     gctx->server_global_callbacks.appname = appname;
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate     /* If we fail now, we have to call server_done */
10577c478bd9Sstevel@tonic-gate     gctx->sasl_server_active = 1;
10587c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&server_active_mutex);
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate     /* allocate mechlist and set it to empty */
10617c478bd9Sstevel@tonic-gate     gctx->mechlist = sasl_ALLOC(sizeof(mech_list_t));
10627c478bd9Sstevel@tonic-gate     if (gctx->mechlist == NULL) {
10637c478bd9Sstevel@tonic-gate 	server_done(gctx);
10647c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
10657c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
10667c478bd9Sstevel@tonic-gate     }
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate     ret = init_mechlist(gctx);
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate     if (ret != SASL_OK) {
10717c478bd9Sstevel@tonic-gate 	server_done(gctx);
10727c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
10737c478bd9Sstevel@tonic-gate 	return ret;
10747c478bd9Sstevel@tonic-gate     }
10757c478bd9Sstevel@tonic-gate #else
10767c478bd9Sstevel@tonic-gate     if (ret != SASL_OK)
10777c478bd9Sstevel@tonic-gate 	return ret;
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate     global_callbacks.callbacks = callbacks;
10807c478bd9Sstevel@tonic-gate     global_callbacks.appname = appname;
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate     /* If we fail now, we have to call server_done */
10837c478bd9Sstevel@tonic-gate     _sasl_server_active = 1;
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate     /* allocate mechlist and set it to empty */
10867c478bd9Sstevel@tonic-gate     mechlist = sasl_ALLOC(sizeof(mech_list_t));
10877c478bd9Sstevel@tonic-gate     if (mechlist == NULL) {
10887c478bd9Sstevel@tonic-gate 	server_done();
10897c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
10907c478bd9Sstevel@tonic-gate     }
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate     ret = init_mechlist();
10937c478bd9Sstevel@tonic-gate     if (ret != SASL_OK) {
10947c478bd9Sstevel@tonic-gate 	server_done();
10957c478bd9Sstevel@tonic-gate 	return ret;
10967c478bd9Sstevel@tonic-gate     }
10977c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate     vf = _sasl_find_verifyfile_callback(callbacks);
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate     /* load config file if applicable */
11027c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
11037c478bd9Sstevel@tonic-gate     ret = load_config(gctx, vf);
11047c478bd9Sstevel@tonic-gate     if ((ret != SASL_OK) && (ret != SASL_CONTINUE)) {
11057c478bd9Sstevel@tonic-gate 	server_done(gctx);
11067c478bd9Sstevel@tonic-gate   	UNLOCK_MUTEX(&init_server_mutex);
11077c478bd9Sstevel@tonic-gate #else
11087c478bd9Sstevel@tonic-gate     ret = load_config(vf);
11097c478bd9Sstevel@tonic-gate     if ((ret != SASL_OK) && (ret != SASL_CONTINUE)) {
11107c478bd9Sstevel@tonic-gate 	server_done();
11117c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
11127c478bd9Sstevel@tonic-gate 	return ret;
11137c478bd9Sstevel@tonic-gate     }
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate     /* load internal plugins */
11167c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
11177c478bd9Sstevel@tonic-gate     _sasl_server_add_plugin(gctx, "EXTERNAL", &external_server_plug_init);
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate /* NOTE: plugin_list option not supported in SUN SDK */
11207c478bd9Sstevel@tonic-gate     {
11217c478bd9Sstevel@tonic-gate #else
11227c478bd9Sstevel@tonic-gate     sasl_server_add_plugin("EXTERNAL", &external_server_plug_init);
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate #ifdef PIC
11257c478bd9Sstevel@tonic-gate     /* delayed loading of plugins? (DSO only, as it doesn't
11267c478bd9Sstevel@tonic-gate      * make much [any] sense to delay in the static library case) */
11277c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(NULL, SASL_CB_GETOPT, &getopt, &context)
11287c478bd9Sstevel@tonic-gate 	   == SASL_OK) {
11297c478bd9Sstevel@tonic-gate 	/* No sasl_conn_t was given to getcallback, so we provide the
11307c478bd9Sstevel@tonic-gate 	 * global callbacks structure */
11317c478bd9Sstevel@tonic-gate 	ret = getopt(&global_callbacks, NULL, "plugin_list", &pluginfile, NULL);
11327c478bd9Sstevel@tonic-gate     }
11337c478bd9Sstevel@tonic-gate #endif
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate     if (pluginfile != NULL) {
11367c478bd9Sstevel@tonic-gate 	/* this file should contain a list of plugins available.
11377c478bd9Sstevel@tonic-gate 	   we'll load on demand. */
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 	/* Ask the application if it's safe to use this file */
11407c478bd9Sstevel@tonic-gate 	ret = ((sasl_verifyfile_t *)(vf->proc))(vf->context,
11417c478bd9Sstevel@tonic-gate 						pluginfile,
11427c478bd9Sstevel@tonic-gate 						SASL_VRFY_CONF);
11437c478bd9Sstevel@tonic-gate 	if (ret != SASL_OK) {
11447c478bd9Sstevel@tonic-gate 	    _sasl_log(NULL, SASL_LOG_ERR,
11457c478bd9Sstevel@tonic-gate 		      "unable to load plugin list %s: %z", pluginfile, ret);
11467c478bd9Sstevel@tonic-gate 	}
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate 	if (ret == SASL_OK) {
11497c478bd9Sstevel@tonic-gate 	    ret = parse_mechlist_file(pluginfile);
11507c478bd9Sstevel@tonic-gate 	}
11517c478bd9Sstevel@tonic-gate     } else {
11527c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
11537c478bd9Sstevel@tonic-gate 	/* load all plugins now */
11547c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
11557c478bd9Sstevel@tonic-gate 	ret = _load_server_plugins(gctx);
11567c478bd9Sstevel@tonic-gate #else
11577c478bd9Sstevel@tonic-gate 	ret = _sasl_load_plugins(ep_list,
11587c478bd9Sstevel@tonic-gate 				 _sasl_find_getpath_callback(callbacks),
11597c478bd9Sstevel@tonic-gate 				 _sasl_find_verifyfile_callback(callbacks));
11607c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
11617c478bd9Sstevel@tonic-gate     }
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
11647c478bd9Sstevel@tonic-gate     if (ret == SASL_OK)
11657c478bd9Sstevel@tonic-gate 	ret = _sasl_build_mechlist(gctx);
11667c478bd9Sstevel@tonic-gate     if (ret == SASL_OK) {
11677c478bd9Sstevel@tonic-gate 	gctx->sasl_server_cleanup_hook = &server_done;
11687c478bd9Sstevel@tonic-gate 	gctx->sasl_server_idle_hook = &server_idle;
11697c478bd9Sstevel@tonic-gate     } else {
11707c478bd9Sstevel@tonic-gate 	server_done(gctx);
11717c478bd9Sstevel@tonic-gate     }
11727c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&init_server_mutex);
11737c478bd9Sstevel@tonic-gate #else
11747c478bd9Sstevel@tonic-gate     if (ret == SASL_OK) {
11757c478bd9Sstevel@tonic-gate 	_sasl_server_cleanup_hook = &server_done;
11767c478bd9Sstevel@tonic-gate 	_sasl_server_idle_hook = &server_idle;
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 	ret = _sasl_build_mechlist();
11797c478bd9Sstevel@tonic-gate     } else {
11807c478bd9Sstevel@tonic-gate 	server_done();
11817c478bd9Sstevel@tonic-gate     }
11827c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate     return ret;
11857c478bd9Sstevel@tonic-gate }
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate /*
11887c478bd9<