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 /*
11887c478bd9Sstevel@tonic-gate * Once we have the users plaintext password we
11897c478bd9Sstevel@tonic-gate * may want to transition them. That is put entries
11907c478bd9Sstevel@tonic-gate * for them in the passwd database for other
11917c478bd9Sstevel@tonic-gate * stronger mechanism
11927c478bd9Sstevel@tonic-gate *
11937c478bd9Sstevel@tonic-gate * for example PLAIN -> CRAM-MD5
11947c478bd9Sstevel@tonic-gate */
11957c478bd9Sstevel@tonic-gate static int
11967c478bd9Sstevel@tonic-gate _sasl_transition(sasl_conn_t * conn,
11977c478bd9Sstevel@tonic-gate const char * pass,
11987c478bd9Sstevel@tonic-gate unsigned passlen)
11997c478bd9Sstevel@tonic-gate {
12007c478bd9Sstevel@tonic-gate const char *dotrans = "n";
12017c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt;
12027c478bd9Sstevel@tonic-gate int result = SASL_OK;
12037c478bd9Sstevel@tonic-gate void *context;
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate if (! conn)
12067c478bd9Sstevel@tonic-gate return SASL_BADPARAM;
12077c478bd9Sstevel@tonic-gate
12087c478bd9Sstevel@tonic-gate if (! conn->oparams.authid)
12097c478bd9Sstevel@tonic-gate PARAMERROR(conn);
12107c478bd9Sstevel@tonic-gate
12117c478bd9Sstevel@tonic-gate /* check if this is enabled: default to false */
12127c478bd9Sstevel@tonic-gate if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK)
12137c478bd9Sstevel@tonic-gate {
12147c478bd9Sstevel@tonic-gate getopt(context, NULL, "auto_transition", &dotrans, NULL);
12157c478bd9Sstevel@tonic-gate if (dotrans == NULL) dotrans = "n";
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate
12187c478bd9Sstevel@tonic-gate if (*dotrans == '1' || *dotrans == 'y' ||
12197c478bd9Sstevel@tonic-gate (*dotrans == 'o' && dotrans[1] == 'n') || *dotrans == 't') {
12207c478bd9Sstevel@tonic-gate /* ok, it's on! */
12217c478bd9Sstevel@tonic-gate result = sasl_setpass(conn,
12227c478bd9Sstevel@tonic-gate conn->oparams.authid,
12237c478bd9Sstevel@tonic-gate pass,
12247c478bd9Sstevel@tonic-gate passlen,
12257c478bd9Sstevel@tonic-gate NULL, 0, 0);
12267c478bd9Sstevel@tonic-gate }
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate RETURN(conn,result);
12297c478bd9Sstevel@tonic-gate }
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gate /* create context for a single SASL connection
12337c478bd9Sstevel@tonic-gate * service -- registered name of the service using SASL (e.g. "imap")
12347c478bd9Sstevel@tonic-gate * serverFQDN -- Fully qualified domain name of server. NULL means use
12357c478bd9Sstevel@tonic-gate * gethostname() or equivalent.
12367c478bd9Sstevel@tonic-gate * Useful for multi-homed servers.
12377c478bd9Sstevel@tonic-gate * user_realm -- permits multiple user realms on server, NULL = default
12387c478bd9Sstevel@tonic-gate * iplocalport -- server IPv4/IPv6 domain literal string with port
12397c478bd9Sstevel@tonic-gate * (if NULL, then mechanisms requiring IPaddr are disabled)
12407c478bd9Sstevel@tonic-gate * ipremoteport -- client IPv4/IPv6 domain literal string with port
12417c478bd9Sstevel@tonic-gate * (if NULL, then mechanisms requiring IPaddr are disabled)
12427c478bd9Sstevel@tonic-gate * callbacks -- callbacks (e.g., authorization, lang, new getopt context)
12437c478bd9Sstevel@tonic-gate * flags -- usage flags (see above)
12447c478bd9Sstevel@tonic-gate * returns:
12457c478bd9Sstevel@tonic-gate * pconn -- new connection context
12467c478bd9Sstevel@tonic-gate *
12477c478bd9Sstevel@tonic-gate * returns:
12487c478bd9Sstevel@tonic-gate * SASL_OK -- success
12497c478bd9Sstevel@tonic-gate * SASL_NOMEM -- not enough memory
12507c478bd9Sstevel@tonic-gate */
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate int sasl_server_new(const char *service,
12537c478bd9Sstevel@tonic-gate const char *serverFQDN,
12547c478bd9Sstevel@tonic-gate const char *user_realm,
12557c478bd9Sstevel@tonic-gate const char *iplocalport,
12567c478bd9Sstevel@tonic-gate const char *ipremoteport,
12577c478bd9Sstevel@tonic-gate const sasl_callback_t *callbacks,
12587c478bd9Sstevel@tonic-gate unsigned flags,
12597c478bd9Sstevel@tonic-gate sasl_conn_t **pconn)
12607c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
12617c478bd9Sstevel@tonic-gate {
12627c478bd9Sstevel@tonic-gate return _sasl_server_new(NULL, service, serverFQDN, user_realm, iplocalport,
12637c478bd9Sstevel@tonic-gate ipremoteport, callbacks, flags, pconn);
12647c478bd9Sstevel@tonic-gate }
12657c478bd9Sstevel@tonic-gate
12667c478bd9Sstevel@tonic-gate int _sasl_server_new(void *ctx,
12677c478bd9Sstevel@tonic-gate const char *service,
12687c478bd9Sstevel@tonic-gate const char *serverFQDN,
12697c478bd9Sstevel@tonic-gate const char *user_realm,
12707c478bd9Sstevel@tonic-gate const char *iplocalport,
12717c478bd9Sstevel@tonic-gate const char *ipremoteport,
12727c478bd9Sstevel@tonic-gate const sasl_callback_t *callbacks,
12737c478bd9Sstevel@tonic-gate unsigned flags,
12747c478bd9Sstevel@tonic-gate sasl_conn_t **pconn)
12757c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
12767c478bd9Sstevel@tonic-gate {
12777c478bd9Sstevel@tonic-gate int result;
12787c478bd9Sstevel@tonic-gate sasl_server_conn_t *serverconn;
12797c478bd9Sstevel@tonic-gate sasl_utils_t *utils;
12807c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt;
12817c478bd9Sstevel@tonic-gate void *context;
12827c478bd9Sstevel@tonic-gate const char *log_level;
12837c478bd9Sstevel@tonic-gate
12847c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
12857c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = (ctx == NULL) ? _sasl_gbl_ctx() : ctx;
12867c478bd9Sstevel@tonic-gate
12877c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT;
12887c478bd9Sstevel@tonic-gate #else
12897c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT;
12907c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
12917c478bd9Sstevel@tonic-gate if (! pconn) return SASL_FAIL;
12927c478bd9Sstevel@tonic-gate if (! service) return SASL_FAIL;
12937c478bd9Sstevel@tonic-gate
12947c478bd9Sstevel@tonic-gate *pconn=sasl_ALLOC(sizeof(sasl_server_conn_t));
12957c478bd9Sstevel@tonic-gate if (*pconn==NULL) return SASL_NOMEM;
12967c478bd9Sstevel@tonic-gate
12977c478bd9Sstevel@tonic-gate memset(*pconn, 0, sizeof(sasl_server_conn_t));
12987c478bd9Sstevel@tonic-gate
12997c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
13007c478bd9Sstevel@tonic-gate (*pconn)->gctx = gctx;
13017c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
13027c478bd9Sstevel@tonic-gate
13037c478bd9Sstevel@tonic-gate serverconn = (sasl_server_conn_t *)*pconn;
13047c478bd9Sstevel@tonic-gate
13057c478bd9Sstevel@tonic-gate /* make sparams */
13067c478bd9Sstevel@tonic-gate serverconn->sparams=sasl_ALLOC(sizeof(sasl_server_params_t));
13077c478bd9Sstevel@tonic-gate if (serverconn->sparams==NULL)
13087c478bd9Sstevel@tonic-gate MEMERROR(*pconn);
13097c478bd9Sstevel@tonic-gate
13107c478bd9Sstevel@tonic-gate memset(serverconn->sparams, 0, sizeof(sasl_server_params_t));
13117c478bd9Sstevel@tonic-gate
13127c478bd9Sstevel@tonic-gate (*pconn)->destroy_conn = &server_dispose;
13137c478bd9Sstevel@tonic-gate result = _sasl_conn_init(*pconn, service, flags, SASL_CONN_SERVER,
13147c478bd9Sstevel@tonic-gate &server_idle, serverFQDN,
13157c478bd9Sstevel@tonic-gate iplocalport, ipremoteport,
13167c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
13177c478bd9Sstevel@tonic-gate callbacks, &gctx->server_global_callbacks);
13187c478bd9Sstevel@tonic-gate #else
13197c478bd9Sstevel@tonic-gate callbacks, &global_callbacks);
13207c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
13217c478bd9Sstevel@tonic-gate if (result != SASL_OK)
13227c478bd9Sstevel@tonic-gate goto done_error;
13237c478bd9Sstevel@tonic-gate
13247c478bd9Sstevel@tonic-gate
13257c478bd9Sstevel@tonic-gate /* set util functions - need to do rest */
13267c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
13277c478bd9Sstevel@tonic-gate utils=_sasl_alloc_utils(gctx, *pconn, &gctx->server_global_callbacks);
13287c478bd9Sstevel@tonic-gate #else
13297c478bd9Sstevel@tonic-gate utils=_sasl_alloc_utils(*pconn, &global_callbacks);
13307c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
13317c478bd9Sstevel@tonic-gate if (!utils) {
13327c478bd9Sstevel@tonic-gate result = SASL_NOMEM;
13337c478bd9Sstevel@tonic-gate goto done_error;
13347c478bd9Sstevel@tonic-gate }
13357c478bd9Sstevel@tonic-gate
13367c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
13377c478bd9Sstevel@tonic-gate utils->checkpass = &_sasl_checkpass;
13387c478bd9Sstevel@tonic-gate #else /* _SUN_SDK_ */
13397c478bd9Sstevel@tonic-gate utils->checkpass = &sasl_checkpass;
13407c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
13417c478bd9Sstevel@tonic-gate
13427c478bd9Sstevel@tonic-gate /* Setup the propctx -> We'll assume the default size */
13437c478bd9Sstevel@tonic-gate serverconn->sparams->propctx=prop_new(0);
13447c478bd9Sstevel@tonic-gate if(!serverconn->sparams->propctx) {
13457c478bd9Sstevel@tonic-gate result = SASL_NOMEM;
13467c478bd9Sstevel@tonic-gate goto done_error;
13477c478bd9Sstevel@tonic-gate }
13487c478bd9Sstevel@tonic-gate
13497c478bd9Sstevel@tonic-gate serverconn->sparams->service = (*pconn)->service;
13507c478bd9Sstevel@tonic-gate serverconn->sparams->servicelen = strlen((*pconn)->service);
13517c478bd9Sstevel@tonic-gate
13527c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
13537c478bd9Sstevel@tonic-gate serverconn->sparams->appname = gctx->server_global_callbacks.appname;
13547c478bd9Sstevel@tonic-gate serverconn->sparams->applen = strlen(gctx->server_global_callbacks.appname);
13557c478bd9Sstevel@tonic-gate #else
13567c478bd9Sstevel@tonic-gate serverconn->sparams->appname = global_callbacks.appname;
13577c478bd9Sstevel@tonic-gate serverconn->sparams->applen = strlen(global_callbacks.appname);
13587c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
13597c478bd9Sstevel@tonic-gate
13607c478bd9Sstevel@tonic-gate serverconn->sparams->serverFQDN = (*pconn)->serverFQDN;
13617c478bd9Sstevel@tonic-gate serverconn->sparams->slen = strlen((*pconn)->serverFQDN);
13627c478bd9Sstevel@tonic-gate
13637c478bd9Sstevel@tonic-gate if (user_realm) {
13647c478bd9Sstevel@tonic-gate result = _sasl_strdup(user_realm, &serverconn->user_realm, NULL);
13657c478bd9Sstevel@tonic-gate serverconn->sparams->urlen = strlen(user_realm);
13667c478bd9Sstevel@tonic-gate serverconn->sparams->user_realm = serverconn->user_realm;
13677c478bd9Sstevel@tonic-gate } else {
13687c478bd9Sstevel@tonic-gate serverconn->user_realm = NULL;
13697c478bd9Sstevel@tonic-gate /* the sparams is already zeroed */
13707c478bd9Sstevel@tonic-gate }
13717c478bd9Sstevel@tonic-gate
13727c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
13737c478bd9Sstevel@tonic-gate serverconn->sparams->iplocalport = (*pconn)->iplocalport;
13747c478bd9Sstevel@tonic-gate serverconn->sparams->iploclen = strlen((*pconn)->iplocalport);
13757c478bd9Sstevel@tonic-gate serverconn->sparams->ipremoteport = (*pconn)->ipremoteport;
13767c478bd9Sstevel@tonic-gate serverconn->sparams->ipremlen = strlen((*pconn)->ipremoteport);
13777c478bd9Sstevel@tonic-gate
13787c478bd9Sstevel@tonic-gate serverconn->sparams->callbacks = callbacks;
13797c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
13807c478bd9Sstevel@tonic-gate
13817c478bd9Sstevel@tonic-gate log_level = NULL;
13827c478bd9Sstevel@tonic-gate if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) {
13837c478bd9Sstevel@tonic-gate getopt(context, NULL, "log_level", &log_level, NULL);
13847c478bd9Sstevel@tonic-gate }
13857c478bd9Sstevel@tonic-gate serverconn->sparams->log_level = log_level ? atoi(log_level) : SASL_LOG_ERR;
13867c478bd9Sstevel@tonic-gate
13877c478bd9Sstevel@tonic-gate serverconn->sparams->utils = utils;
13887c478bd9Sstevel@tonic-gate serverconn->sparams->transition = &_sasl_transition;
13897c478bd9Sstevel@tonic-gate serverconn->sparams->canon_user = &_sasl_canon_user;
13907c478bd9Sstevel@tonic-gate serverconn->sparams->props = serverconn->base.props;
13917c478bd9Sstevel@tonic-gate serverconn->sparams->flags = flags;
13927c478bd9Sstevel@tonic-gate
13937c478bd9Sstevel@tonic-gate if(result == SASL_OK) return SASL_OK;
13947c478bd9Sstevel@tonic-gate
13957c478bd9Sstevel@tonic-gate done_error:
13967c478bd9Sstevel@tonic-gate _sasl_conn_dispose(*pconn);
13977c478bd9Sstevel@tonic-gate sasl_FREE(*pconn);
13987c478bd9Sstevel@tonic-gate *pconn = NULL;
13997c478bd9Sstevel@tonic-gate return result;
14007c478bd9Sstevel@tonic-gate }
14017c478bd9Sstevel@tonic-gate
14027c478bd9Sstevel@tonic-gate /*
14037c478bd9Sstevel@tonic-gate * The rule is:
14047c478bd9Sstevel@tonic-gate * IF mech strength + external strength < min ssf THEN FAIL
14057c478bd9Sstevel@tonic-gate * We also have to look at the security properties and make sure
14067c478bd9Sstevel@tonic-gate * that this mechanism has everything we want
14077c478bd9Sstevel@tonic-gate */
14087c478bd9Sstevel@tonic-gate static int mech_permitted(sasl_conn_t *conn,
14097c478bd9Sstevel@tonic-gate mechanism_t *mech)
14107c478bd9Sstevel@tonic-gate {
14117c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn = (sasl_server_conn_t *)conn;
14127c478bd9Sstevel@tonic-gate const sasl_server_plug_t *plug;
14137c478bd9Sstevel@tonic-gate int myflags;
14147c478bd9Sstevel@tonic-gate context_list_t *cur;
14157c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt;
14167c478bd9Sstevel@tonic-gate void *context;
14177c478bd9Sstevel@tonic-gate sasl_ssf_t minssf = 0;
14187c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
14197c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx;
14207c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
14217c478bd9Sstevel@tonic-gate
14227c478bd9Sstevel@tonic-gate if(!conn) return 0;
14237c478bd9Sstevel@tonic-gate
14247c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
14257c478bd9Sstevel@tonic-gate gctx = conn->gctx;
14267c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate if(! mech || ! mech->plug) {
14297c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
14307c478bd9Sstevel@tonic-gate if(conn) _sasl_log(conn, SASL_LOG_WARN, "Parameter error");
14317c478bd9Sstevel@tonic-gate #else
14327c478bd9Sstevel@tonic-gate PARAMERROR(conn);
14337c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
14347c478bd9Sstevel@tonic-gate return 0;
14357c478bd9Sstevel@tonic-gate }
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate plug = mech->plug;
14387c478bd9Sstevel@tonic-gate
14397c478bd9Sstevel@tonic-gate /* get the list of allowed mechanisms (default = all) */
14407c478bd9Sstevel@tonic-gate if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
14417c478bd9Sstevel@tonic-gate == SASL_OK) {
14427c478bd9Sstevel@tonic-gate const char *mlist = NULL;
14437c478bd9Sstevel@tonic-gate
14447c478bd9Sstevel@tonic-gate getopt(context, NULL, "mech_list", &mlist, NULL);
14457c478bd9Sstevel@tonic-gate
14467c478bd9Sstevel@tonic-gate /* if we have a list, check the plugin against it */
14477c478bd9Sstevel@tonic-gate if (mlist) {
14487c478bd9Sstevel@tonic-gate const char *cp;
14497c478bd9Sstevel@tonic-gate
14507c478bd9Sstevel@tonic-gate while (*mlist) {
14517c478bd9Sstevel@tonic-gate for (cp = mlist; *cp && !isspace((int) *cp); cp++);
14527c478bd9Sstevel@tonic-gate if (((size_t) (cp - mlist) == strlen(plug->mech_name)) &&
14537c478bd9Sstevel@tonic-gate !strncasecmp(mlist, plug->mech_name,
14547c478bd9Sstevel@tonic-gate strlen(plug->mech_name))) {
14557c478bd9Sstevel@tonic-gate break;
14567c478bd9Sstevel@tonic-gate }
14577c478bd9Sstevel@tonic-gate mlist = cp;
14587c478bd9Sstevel@tonic-gate while (*mlist && isspace((int) *mlist)) mlist++;
14597c478bd9Sstevel@tonic-gate }
14607c478bd9Sstevel@tonic-gate
14617c478bd9Sstevel@tonic-gate if (!*mlist) return 0; /* reached EOS -> not in our list */
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate }
14647c478bd9Sstevel@tonic-gate
14657c478bd9Sstevel@tonic-gate /* setup parameters for the call to mech_avail */
14667c478bd9Sstevel@tonic-gate s_conn->sparams->serverFQDN=conn->serverFQDN;
14677c478bd9Sstevel@tonic-gate s_conn->sparams->service=conn->service;
14687c478bd9Sstevel@tonic-gate s_conn->sparams->user_realm=s_conn->user_realm;
14697c478bd9Sstevel@tonic-gate s_conn->sparams->props=conn->props;
14707c478bd9Sstevel@tonic-gate s_conn->sparams->external_ssf=conn->external.ssf;
14717c478bd9Sstevel@tonic-gate
14727c478bd9Sstevel@tonic-gate /* Check if we have banished this one already */
14737c478bd9Sstevel@tonic-gate for(cur = s_conn->mech_contexts; cur; cur=cur->next) {
14747c478bd9Sstevel@tonic-gate if(cur->mech == mech) {
14757c478bd9Sstevel@tonic-gate /* If it's not mech_avail'd, then stop now */
14767c478bd9Sstevel@tonic-gate if(!cur->context) return 0;
14777c478bd9Sstevel@tonic-gate break;
14787c478bd9Sstevel@tonic-gate }
14797c478bd9Sstevel@tonic-gate }
14807c478bd9Sstevel@tonic-gate
14817c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
14827c478bd9Sstevel@tonic-gate if (!mech->sun_reg) {
14837c478bd9Sstevel@tonic-gate s_conn->sparams->props.min_ssf = 0;
14847c478bd9Sstevel@tonic-gate s_conn->sparams->props.max_ssf = 0;
14857c478bd9Sstevel@tonic-gate }
14867c478bd9Sstevel@tonic-gate s_conn->base.sun_reg = mech->sun_reg;
14877c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
14887c478bd9Sstevel@tonic-gate if (conn->props.min_ssf < conn->external.ssf) {
14897c478bd9Sstevel@tonic-gate minssf = 0;
14907c478bd9Sstevel@tonic-gate } else {
14917c478bd9Sstevel@tonic-gate minssf = conn->props.min_ssf - conn->external.ssf;
14927c478bd9Sstevel@tonic-gate }
14937c478bd9Sstevel@tonic-gate
14947c478bd9Sstevel@tonic-gate /* Generic mechanism */
14957c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
14967c478bd9Sstevel@tonic-gate /* If not SUN supplied mech, it has no strength */
14977c478bd9Sstevel@tonic-gate if (plug->max_ssf < minssf || (minssf > 0 && !mech->sun_reg)) {
14987c478bd9Sstevel@tonic-gate #else
14997c478bd9Sstevel@tonic-gate if (plug->max_ssf < minssf) {
15007c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
15017c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
15027c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG,
15037c478bd9Sstevel@tonic-gate gettext("mech %s is too weak"), plug->mech_name);
15047c478bd9Sstevel@tonic-gate #else
15057c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG,
15067c478bd9Sstevel@tonic-gate "mech %s is too weak", plug->mech_name);
15077c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
15087c478bd9Sstevel@tonic-gate return 0; /* too weak */
15097c478bd9Sstevel@tonic-gate }
15107c478bd9Sstevel@tonic-gate
15117c478bd9Sstevel@tonic-gate context = NULL;
15127c478bd9Sstevel@tonic-gate if(plug->mech_avail
15137c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
15147c478bd9Sstevel@tonic-gate && plug->mech_avail(mech->glob_context,
15157c478bd9Sstevel@tonic-gate #else
15167c478bd9Sstevel@tonic-gate && plug->mech_avail(plug->glob_context,
15177c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
15187c478bd9Sstevel@tonic-gate s_conn->sparams, (void **)&context) != SASL_OK ) {
15197c478bd9Sstevel@tonic-gate /* Mark this mech as no good for this connection */
15207c478bd9Sstevel@tonic-gate cur = sasl_ALLOC(sizeof(context_list_t));
15217c478bd9Sstevel@tonic-gate if(!cur) {
15227c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
15237c478bd9Sstevel@tonic-gate if(conn) _sasl_log(conn, SASL_LOG_WARN, "Out of Memory");
15247c478bd9Sstevel@tonic-gate #else
15257c478bd9Sstevel@tonic-gate MEMERROR(conn);
15267c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
15277c478bd9Sstevel@tonic-gate return 0;
15287c478bd9Sstevel@tonic-gate }
15297c478bd9Sstevel@tonic-gate cur->context = NULL;
15307c478bd9Sstevel@tonic-gate cur->mech = mech;
15317c478bd9Sstevel@tonic-gate cur->next = s_conn->mech_contexts;
15327c478bd9Sstevel@tonic-gate s_conn->mech_contexts = cur;
15337c478bd9Sstevel@tonic-gate
15347c478bd9Sstevel@tonic-gate /* Error should be set by mech_avail call */
15357c478bd9Sstevel@tonic-gate return 0;
15367c478bd9Sstevel@tonic-gate } else if(context) {
15377c478bd9Sstevel@tonic-gate /* Save this context */
15387c478bd9Sstevel@tonic-gate cur = sasl_ALLOC(sizeof(context_list_t));
15397c478bd9Sstevel@tonic-gate if(!cur) {
15407c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
15417c478bd9Sstevel@tonic-gate if(conn) _sasl_log(conn, SASL_LOG_WARN, "Out of Memory");
15427c478bd9Sstevel@tonic-gate #else
15437c478bd9Sstevel@tonic-gate MEMERROR(conn);
15447c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
15457c478bd9Sstevel@tonic-gate return 0;
15467c478bd9Sstevel@tonic-gate }
15477c478bd9Sstevel@tonic-gate cur->context = context;
15487c478bd9Sstevel@tonic-gate cur->mech = mech;
15497c478bd9Sstevel@tonic-gate cur->next = s_conn->mech_contexts;
15507c478bd9Sstevel@tonic-gate s_conn->mech_contexts = cur;
15517c478bd9Sstevel@tonic-gate }
15527c478bd9Sstevel@tonic-gate
15537c478bd9Sstevel@tonic-gate /* Generic mechanism */
15547c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
15557c478bd9Sstevel@tonic-gate /* If not SUN supplied mech, it has no strength */
15567c478bd9Sstevel@tonic-gate if (plug->max_ssf < minssf || (minssf > 0 && !mech->sun_reg)) {
15577c478bd9Sstevel@tonic-gate #else
15587c478bd9Sstevel@tonic-gate if (plug->max_ssf < minssf) {
15597c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
15607c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
15617c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, gettext("too weak"));
15627c478bd9Sstevel@tonic-gate #else
15637c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, "too weak");
15647c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
15657c478bd9Sstevel@tonic-gate return 0; /* too weak */
15667c478bd9Sstevel@tonic-gate }
15677c478bd9Sstevel@tonic-gate
15687c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
15697c478bd9Sstevel@tonic-gate /* if there are no users in the secrets database we can't use this
15707c478bd9Sstevel@tonic-gate mechanism */
15717c478bd9Sstevel@tonic-gate if (mech->condition == SASL_NOUSER) {
15727c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "no users in secrets db");
15737c478bd9Sstevel@tonic-gate return 0;
15747c478bd9Sstevel@tonic-gate }
15757c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
15767c478bd9Sstevel@tonic-gate
15777c478bd9Sstevel@tonic-gate /* Can it meet our features? */
15787c478bd9Sstevel@tonic-gate if ((conn->flags & SASL_NEED_PROXY) &&
15797c478bd9Sstevel@tonic-gate !(plug->features & SASL_FEAT_ALLOWS_PROXY)) {
15807c478bd9Sstevel@tonic-gate return 0;
15817c478bd9Sstevel@tonic-gate }
15827c478bd9Sstevel@tonic-gate
15837c478bd9Sstevel@tonic-gate /* security properties---if there are any flags that differ and are
15847c478bd9Sstevel@tonic-gate in what the connection are requesting, then fail */
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate /* special case plaintext */
15877c478bd9Sstevel@tonic-gate myflags = conn->props.security_flags;
15887c478bd9Sstevel@tonic-gate
15897c478bd9Sstevel@tonic-gate /* if there's an external layer this is no longer plaintext */
15907c478bd9Sstevel@tonic-gate if ((conn->props.min_ssf <= conn->external.ssf) &&
15917c478bd9Sstevel@tonic-gate (conn->external.ssf > 1)) {
15927c478bd9Sstevel@tonic-gate myflags &= ~SASL_SEC_NOPLAINTEXT;
15937c478bd9Sstevel@tonic-gate }
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate /* do we want to special case SASL_SEC_PASS_CREDENTIALS? nah.. */
15967c478bd9Sstevel@tonic-gate if (((myflags ^ plug->security_flags) & myflags) != 0) {
15977c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
15987c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG,
15997c478bd9Sstevel@tonic-gate gettext("security flags do not match required"));
16007c478bd9Sstevel@tonic-gate #else
16017c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG,
16027c478bd9Sstevel@tonic-gate "security flags do not match required");
16037c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
16047c478bd9Sstevel@tonic-gate return 0;
16057c478bd9Sstevel@tonic-gate }
16067c478bd9Sstevel@tonic-gate
16077c478bd9Sstevel@tonic-gate /* Check Features */
16087c478bd9Sstevel@tonic-gate if(plug->features & SASL_FEAT_GETSECRET) {
16097c478bd9Sstevel@tonic-gate /* We no longer support sasl_server_{get,put}secret */
16107c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
16117c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR,
16127c478bd9Sstevel@tonic-gate "mech %s requires unprovided secret facility",
16137c478bd9Sstevel@tonic-gate plug->mech_name);
16147c478bd9Sstevel@tonic-gate #else
16157c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0,
16167c478bd9Sstevel@tonic-gate "mech %s requires unprovided secret facility",
16177c478bd9Sstevel@tonic-gate plug->mech_name);
16187c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
16197c478bd9Sstevel@tonic-gate return 0;
16207c478bd9Sstevel@tonic-gate }
16217c478bd9Sstevel@tonic-gate
16227c478bd9Sstevel@tonic-gate return 1;
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate
16257c478bd9Sstevel@tonic-gate /*
16267c478bd9Sstevel@tonic-gate * make the authorization
16277c478bd9Sstevel@tonic-gate *
16287c478bd9Sstevel@tonic-gate */
16297c478bd9Sstevel@tonic-gate
16307c478bd9Sstevel@tonic-gate static int do_authorization(sasl_server_conn_t *s_conn)
16317c478bd9Sstevel@tonic-gate {
16327c478bd9Sstevel@tonic-gate int ret;
16337c478bd9Sstevel@tonic-gate sasl_authorize_t *authproc;
16347c478bd9Sstevel@tonic-gate void *auth_context;
16357c478bd9Sstevel@tonic-gate
16367c478bd9Sstevel@tonic-gate /* now let's see if authname is allowed to proxy for username! */
16377c478bd9Sstevel@tonic-gate
16387c478bd9Sstevel@tonic-gate /* check the proxy callback */
16397c478bd9Sstevel@tonic-gate if (_sasl_getcallback(&s_conn->base, SASL_CB_PROXY_POLICY,
16407c478bd9Sstevel@tonic-gate &authproc, &auth_context) != SASL_OK) {
16417c478bd9Sstevel@tonic-gate INTERROR(&s_conn->base, SASL_NOAUTHZ);
16427c478bd9Sstevel@tonic-gate }
16437c478bd9Sstevel@tonic-gate
16447c478bd9Sstevel@tonic-gate ret = authproc(&(s_conn->base), auth_context,
16457c478bd9Sstevel@tonic-gate s_conn->base.oparams.user, s_conn->base.oparams.ulen,
16467c478bd9Sstevel@tonic-gate s_conn->base.oparams.authid, s_conn->base.oparams.alen,
16477c478bd9Sstevel@tonic-gate s_conn->user_realm,
16487c478bd9Sstevel@tonic-gate (s_conn->user_realm ? strlen(s_conn->user_realm) : 0),
16497c478bd9Sstevel@tonic-gate s_conn->sparams->propctx);
16507c478bd9Sstevel@tonic-gate
16517c478bd9Sstevel@tonic-gate RETURN(&s_conn->base, ret);
16527c478bd9Sstevel@tonic-gate }
16537c478bd9Sstevel@tonic-gate
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate /* start a mechanism exchange within a connection context
16567c478bd9Sstevel@tonic-gate * mech -- the mechanism name client requested
16577c478bd9Sstevel@tonic-gate * clientin -- client initial response (NUL terminated), NULL if empty
16587c478bd9Sstevel@tonic-gate * clientinlen -- length of initial response
16597c478bd9Sstevel@tonic-gate * serverout -- initial server challenge, NULL if done
16607c478bd9Sstevel@tonic-gate * (library handles freeing this string)
16617c478bd9Sstevel@tonic-gate * serveroutlen -- length of initial server challenge
16627c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
16637c478bd9Sstevel@tonic-gate * conn -- the sasl connection
16647c478bd9Sstevel@tonic-gate #else
16657c478bd9Sstevel@tonic-gate * output:
16667c478bd9Sstevel@tonic-gate * pconn -- the connection negotiation state on success
16677c478bd9Sstevel@tonic-gate #endif
16687c478bd9Sstevel@tonic-gate *
16697c478bd9Sstevel@tonic-gate * Same returns as sasl_server_step() or
16707c478bd9Sstevel@tonic-gate * SASL_NOMECH if mechanism not available.
16717c478bd9Sstevel@tonic-gate */
16727c478bd9Sstevel@tonic-gate int sasl_server_start(sasl_conn_t *conn,
16737c478bd9Sstevel@tonic-gate const char *mech,
16747c478bd9Sstevel@tonic-gate const char *clientin,
16757c478bd9Sstevel@tonic-gate unsigned clientinlen,
16767c478bd9Sstevel@tonic-gate const char **serverout,
16777c478bd9Sstevel@tonic-gate unsigned *serveroutlen)
16787c478bd9Sstevel@tonic-gate {
16797c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn=(sasl_server_conn_t *) conn;
16807c478bd9Sstevel@tonic-gate int result;
16817c478bd9Sstevel@tonic-gate context_list_t *cur, **prev;
16827c478bd9Sstevel@tonic-gate mechanism_t *m;
16837c478bd9Sstevel@tonic-gate
16847c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
16857c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx =
16867c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
16877c478bd9Sstevel@tonic-gate mech_list_t *mechlist;
16887c478bd9Sstevel@tonic-gate
16897c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT;
16907c478bd9Sstevel@tonic-gate if (! conn)
16917c478bd9Sstevel@tonic-gate return SASL_BADPARAM;
16927c478bd9Sstevel@tonic-gate
16937c478bd9Sstevel@tonic-gate (void)_load_server_plugins(gctx);
16947c478bd9Sstevel@tonic-gate mechlist = gctx->mechlist;
16957c478bd9Sstevel@tonic-gate m=mechlist->mech_list;
16967c478bd9Sstevel@tonic-gate result = load_config(gctx, _sasl_find_verifyfile_callback(
16977c478bd9Sstevel@tonic-gate gctx->server_global_callbacks.callbacks));
16987c478bd9Sstevel@tonic-gate if (result != SASL_OK)
16997c478bd9Sstevel@tonic-gate return (result);
17007c478bd9Sstevel@tonic-gate #else
17017c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT;
17027c478bd9Sstevel@tonic-gate
17037c478bd9Sstevel@tonic-gate /* make sure mech is valid mechanism
17047c478bd9Sstevel@tonic-gate if not return appropriate error */
17057c478bd9Sstevel@tonic-gate m=mechlist->mech_list;
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate /* check parameters */
17087c478bd9Sstevel@tonic-gate if(!conn) return SASL_BADPARAM;
17097c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate if (!mech || ((clientin==NULL) && (clientinlen>0)))
17127c478bd9Sstevel@tonic-gate PARAMERROR(conn);
17137c478bd9Sstevel@tonic-gate
17147c478bd9Sstevel@tonic-gate if(serverout) *serverout = NULL;
17157c478bd9Sstevel@tonic-gate if(serveroutlen) *serveroutlen = 0;
17167c478bd9Sstevel@tonic-gate
17177c478bd9Sstevel@tonic-gate while (m!=NULL)
17187c478bd9Sstevel@tonic-gate {
17197c478bd9Sstevel@tonic-gate if ( strcasecmp(mech,m->plug->mech_name)==0)
17207c478bd9Sstevel@tonic-gate {
17217c478bd9Sstevel@tonic-gate break;
17227c478bd9Sstevel@tonic-gate }
17237c478bd9Sstevel@tonic-gate m=m->next;
17247c478bd9Sstevel@tonic-gate }
17257c478bd9Sstevel@tonic-gate
17267c478bd9Sstevel@tonic-gate if (m==NULL) {
17277c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
17287c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, gettext("Couldn't find mech %s"), mech);
17297c478bd9Sstevel@tonic-gate #else
17307c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "Couldn't find mech %s", mech);
17317c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
17327c478bd9Sstevel@tonic-gate result = SASL_NOMECH;
17337c478bd9Sstevel@tonic-gate goto done;
17347c478bd9Sstevel@tonic-gate }
17357c478bd9Sstevel@tonic-gate
17367c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
17377c478bd9Sstevel@tonic-gate server_dispose_mech_contexts(conn);
17387c478bd9Sstevel@tonic-gate #endif /*_SUN_SDK_ */
17397c478bd9Sstevel@tonic-gate
17407c478bd9Sstevel@tonic-gate /* Make sure that we're willing to use this mech */
17417c478bd9Sstevel@tonic-gate if (! mech_permitted(conn, m)) {
17427c478bd9Sstevel@tonic-gate result = SASL_NOMECH;
17437c478bd9Sstevel@tonic-gate goto done;
17447c478bd9Sstevel@tonic-gate }
17457c478bd9Sstevel@tonic-gate
17467c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
17477c478bd9Sstevel@tonic-gate if(conn->context) {
17487c478bd9Sstevel@tonic-gate s_conn->mech->plug->mech_dispose(conn->context, s_conn->sparams->utils);
17497c478bd9Sstevel@tonic-gate conn->context = NULL;
17507c478bd9Sstevel@tonic-gate }
17517c478bd9Sstevel@tonic-gate memset(&conn->oparams, 0, sizeof(sasl_out_params_t));
17527c478bd9Sstevel@tonic-gate #else
17537c478bd9Sstevel@tonic-gate if (m->condition == SASL_CONTINUE) {
17547c478bd9Sstevel@tonic-gate sasl_server_plug_init_t *entry_point;
17557c478bd9Sstevel@tonic-gate void *library = NULL;
17567c478bd9Sstevel@tonic-gate sasl_server_plug_t *pluglist;
17577c478bd9Sstevel@tonic-gate int version, plugcount;
17587c478bd9Sstevel@tonic-gate int l = 0;
17597c478bd9Sstevel@tonic-gate
17607c478bd9Sstevel@tonic-gate /* need to load this plugin */
17617c478bd9Sstevel@tonic-gate result = _sasl_get_plugin(m->f,
17627c478bd9Sstevel@tonic-gate _sasl_find_verifyfile_callback(global_callbacks.callbacks),
17637c478bd9Sstevel@tonic-gate &library);
17647c478bd9Sstevel@tonic-gate
17657c478bd9Sstevel@tonic-gate if (result == SASL_OK) {
17667c478bd9Sstevel@tonic-gate result = _sasl_locate_entry(library, "sasl_server_plug_init",
17677c478bd9Sstevel@tonic-gate (void **)&entry_point);
17687c478bd9Sstevel@tonic-gate }
17697c478bd9Sstevel@tonic-gate
17707c478bd9Sstevel@tonic-gate if (result == SASL_OK) {
17717c478bd9Sstevel@tonic-gate result = entry_point(mechlist->utils, SASL_SERVER_PLUG_VERSION,
17727c478bd9Sstevel@tonic-gate &version, &pluglist, &plugcount);
17737c478bd9Sstevel@tonic-gate }
17747c478bd9Sstevel@tonic-gate
17757c478bd9Sstevel@tonic-gate if (result == SASL_OK) {
17767c478bd9Sstevel@tonic-gate /* find the correct mechanism in this plugin */
17777c478bd9Sstevel@tonic-gate for (l = 0; l < plugcount; l++) {
17787c478bd9Sstevel@tonic-gate if (!strcasecmp(pluglist[l].mech_name,
17797c478bd9Sstevel@tonic-gate m->plug->mech_name)) break;
17807c478bd9Sstevel@tonic-gate }
17817c478bd9Sstevel@tonic-gate if (l == plugcount) {
17827c478bd9Sstevel@tonic-gate result = SASL_NOMECH;
17837c478bd9Sstevel@tonic-gate }
17847c478bd9Sstevel@tonic-gate }
17857c478bd9Sstevel@tonic-gate if (result == SASL_OK) {
17867c478bd9Sstevel@tonic-gate /* check that the parameters are the same */
17877c478bd9Sstevel@tonic-gate if ((pluglist[l].max_ssf != m->plug->max_ssf) ||
17887c478bd9Sstevel@tonic-gate (pluglist[l].security_flags != m->plug->security_flags)) {
17897c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR,
17907c478bd9Sstevel@tonic-gate "%s: security parameters don't match mechlist file",
17917c478bd9Sstevel@tonic-gate pluglist[l].mech_name);
17927c478bd9Sstevel@tonic-gate result = SASL_NOMECH;
17937c478bd9Sstevel@tonic-gate }
17947c478bd9Sstevel@tonic-gate }
17957c478bd9Sstevel@tonic-gate if (result == SASL_OK) {
17967c478bd9Sstevel@tonic-gate /* copy mechlist over */
17977c478bd9Sstevel@tonic-gate sasl_FREE((sasl_server_plug_t *) m->plug);
17987c478bd9Sstevel@tonic-gate m->plug = &pluglist[l];
17997c478bd9Sstevel@tonic-gate m->condition = SASL_OK;
18007c478bd9Sstevel@tonic-gate }
18017c478bd9Sstevel@tonic-gate
18027c478bd9Sstevel@tonic-gate if (result != SASL_OK) {
18037c478bd9Sstevel@tonic-gate /* The library will eventually be freed, don't sweat it */
18047c478bd9Sstevel@tonic-gate RETURN(conn, result);
18057c478bd9Sstevel@tonic-gate }
18067c478bd9Sstevel@tonic-gate }
18077c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
18087c478bd9Sstevel@tonic-gate
18097c478bd9Sstevel@tonic-gate /* We used to setup sparams HERE, but now it's done
18107c478bd9Sstevel@tonic-gate inside of mech_permitted (which is called above) */
18117c478bd9Sstevel@tonic-gate prev = &s_conn->mech_contexts;
18127c478bd9Sstevel@tonic-gate for(cur = *prev; cur; prev=&cur->next,cur=cur->next) {
18137c478bd9Sstevel@tonic-gate if(cur->mech == m) {
18147c478bd9Sstevel@tonic-gate if(!cur->context) {
18157c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
18167c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR,
18177c478bd9Sstevel@tonic-gate "Got past mech_permitted with a disallowed mech!");
18187c478bd9Sstevel@tonic-gate #else
18197c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0,
18207c478bd9Sstevel@tonic-gate "Got past mech_permitted with a disallowed mech!");
18217c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
18227c478bd9Sstevel@tonic-gate return SASL_NOMECH;
18237c478bd9Sstevel@tonic-gate }
18247c478bd9Sstevel@tonic-gate /* If we find it, we need to pull cur out of the
18257c478bd9Sstevel@tonic-gate list so it won't be freed later! */
18267c478bd9Sstevel@tonic-gate (*prev)->next = cur->next;
18277c478bd9Sstevel@tonic-gate conn->context = cur->context;
18287c478bd9Sstevel@tonic-gate sasl_FREE(cur);
18297c478bd9Sstevel@tonic-gate }
18307c478bd9Sstevel@tonic-gate }
18317c478bd9Sstevel@tonic-gate
18327c478bd9Sstevel@tonic-gate s_conn->mech = m;
18337c478bd9Sstevel@tonic-gate
18347c478bd9Sstevel@tonic-gate if(!conn->context) {
18357c478bd9Sstevel@tonic-gate /* Note that we don't hand over a new challenge */
18367c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
18377c478bd9Sstevel@tonic-gate result = s_conn->mech->plug->mech_new(s_conn->mech->glob_context,
18387c478bd9Sstevel@tonic-gate #else
18397c478bd9Sstevel@tonic-gate result = s_conn->mech->plug->mech_new(s_conn->mech->plug->glob_context,
18407c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
18417c478bd9Sstevel@tonic-gate s_conn->sparams,
18427c478bd9Sstevel@tonic-gate NULL,
18437c478bd9Sstevel@tonic-gate 0,
18447c478bd9Sstevel@tonic-gate &(conn->context));
18457c478bd9Sstevel@tonic-gate } else {
18467c478bd9Sstevel@tonic-gate /* the work was already done by mech_avail! */
18477c478bd9Sstevel@tonic-gate result = SASL_OK;
18487c478bd9Sstevel@tonic-gate }
18497c478bd9Sstevel@tonic-gate
18507c478bd9Sstevel@tonic-gate if (result == SASL_OK) {
18517c478bd9Sstevel@tonic-gate if(clientin) {
18527c478bd9Sstevel@tonic-gate if(s_conn->mech->plug->features & SASL_FEAT_SERVER_FIRST) {
18537c478bd9Sstevel@tonic-gate /* Remote sent first, but mechanism does not support it.
18547c478bd9Sstevel@tonic-gate * RFC 2222 says we fail at this point. */
18557c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
18567c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR,
18577c478bd9Sstevel@tonic-gate "Remote sent first but mech does not allow it.");
18587c478bd9Sstevel@tonic-gate #else
18597c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0,
18607c478bd9Sstevel@tonic-gate "Remote sent first but mech does not allow it.");
18617c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
18627c478bd9Sstevel@tonic-gate result = SASL_BADPROT;
18637c478bd9Sstevel@tonic-gate } else {
18647c478bd9Sstevel@tonic-gate /* Mech wants client-first, so let them have it */
18657c478bd9Sstevel@tonic-gate result = sasl_server_step(conn,
18667c478bd9Sstevel@tonic-gate clientin, clientinlen,
18677c478bd9Sstevel@tonic-gate serverout, serveroutlen);
18687c478bd9Sstevel@tonic-gate }
18697c478bd9Sstevel@tonic-gate } else {
18707c478bd9Sstevel@tonic-gate if(s_conn->mech->plug->features & SASL_FEAT_WANT_CLIENT_FIRST) {
18717c478bd9Sstevel@tonic-gate /* Mech wants client first anyway, so we should do that */
18727c478bd9Sstevel@tonic-gate *serverout = "";
18737c478bd9Sstevel@tonic-gate *serveroutlen = 0;
18747c478bd9Sstevel@tonic-gate result = SASL_CONTINUE;
18757c478bd9Sstevel@tonic-gate } else {
18767c478bd9Sstevel@tonic-gate /* Mech wants server-first, so let them have it */
18777c478bd9Sstevel@tonic-gate result = sasl_server_step(conn,
18787c478bd9Sstevel@tonic-gate clientin, clientinlen,
18797c478bd9Sstevel@tonic-gate serverout, serveroutlen);
18807c478bd9Sstevel@tonic-gate }
18817c478bd9Sstevel@tonic-gate }
18827c478bd9Sstevel@tonic-gate }
18837c478bd9Sstevel@tonic-gate
18847c478bd9Sstevel@tonic-gate done:
18857c478bd9Sstevel@tonic-gate if( result != SASL_OK
18867c478bd9Sstevel@tonic-gate && result != SASL_CONTINUE
18877c478bd9Sstevel@tonic-gate && result != SASL_INTERACT) {
18887c478bd9Sstevel@tonic-gate if(conn->context) {
18897c478bd9Sstevel@tonic-gate s_conn->mech->plug->mech_dispose(conn->context,
18907c478bd9Sstevel@tonic-gate s_conn->sparams->utils);
18917c478bd9Sstevel@tonic-gate conn->context = NULL;
18927c478bd9Sstevel@tonic-gate }
18937c478bd9Sstevel@tonic-gate }
18947c478bd9Sstevel@tonic-gate
18957c478bd9Sstevel@tonic-gate RETURN(conn,result);
18967c478bd9Sstevel@tonic-gate }
18977c478bd9Sstevel@tonic-gate
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate /* perform one step of the SASL exchange
19007c478bd9Sstevel@tonic-gate * inputlen & input -- client data
19017c478bd9Sstevel@tonic-gate * NULL on first step if no optional client step
19027c478bd9Sstevel@tonic-gate * outputlen & output -- set to the server data to transmit
19037c478bd9Sstevel@tonic-gate * to the client in the next step
19047c478bd9Sstevel@tonic-gate * (library handles freeing this)
19057c478bd9Sstevel@tonic-gate *
19067c478bd9Sstevel@tonic-gate * returns:
19077c478bd9Sstevel@tonic-gate * SASL_OK -- exchange is complete.
19087c478bd9Sstevel@tonic-gate * SASL_CONTINUE -- indicates another step is necessary.
19097c478bd9Sstevel@tonic-gate * SASL_TRANS -- entry for user exists, but not for mechanism
19107c478bd9Sstevel@tonic-gate * and transition is possible
19117c478bd9Sstevel@tonic-gate * SASL_BADPARAM -- service name needed
19127c478bd9Sstevel@tonic-gate * SASL_BADPROT -- invalid input from client
19137c478bd9Sstevel@tonic-gate * ...
19147c478bd9Sstevel@tonic-gate */
19157c478bd9Sstevel@tonic-gate
19167c478bd9Sstevel@tonic-gate int sasl_server_step(sasl_conn_t *conn,
19177c478bd9Sstevel@tonic-gate const char *clientin,
19187c478bd9Sstevel@tonic-gate unsigned clientinlen,
19197c478bd9Sstevel@tonic-gate const char **serverout,
19207c478bd9Sstevel@tonic-gate unsigned *serveroutlen)
19217c478bd9Sstevel@tonic-gate {
19227c478bd9Sstevel@tonic-gate int ret;
19237c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn; /* cast */
19247c478bd9Sstevel@tonic-gate
19257c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
19267c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx =
19277c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
19287c478bd9Sstevel@tonic-gate
19297c478bd9Sstevel@tonic-gate /* check parameters */
19307c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT;
19317c478bd9Sstevel@tonic-gate #else
19327c478bd9Sstevel@tonic-gate /* check parameters */
19337c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT;
19347c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
19357c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM;
19367c478bd9Sstevel@tonic-gate if ((clientin==NULL) && (clientinlen>0))
19377c478bd9Sstevel@tonic-gate PARAMERROR(conn);
19387c478bd9Sstevel@tonic-gate
19397c478bd9Sstevel@tonic-gate /* If we've already done the last send, return! */
19407c478bd9Sstevel@tonic-gate if(s_conn->sent_last == 1) {
19417c478bd9Sstevel@tonic-gate return SASL_OK;
19427c478bd9Sstevel@tonic-gate }
19437c478bd9Sstevel@tonic-gate
19447c478bd9Sstevel@tonic-gate /* Don't do another step if the plugin told us that we're done */
19457c478bd9Sstevel@tonic-gate if (conn->oparams.doneflag) {
19467c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, "attempting server step after doneflag");
19477c478bd9Sstevel@tonic-gate return SASL_FAIL;
19487c478bd9Sstevel@tonic-gate }
19497c478bd9Sstevel@tonic-gate
19507c478bd9Sstevel@tonic-gate if(serverout) *serverout = NULL;
19517c478bd9Sstevel@tonic-gate if(serveroutlen) *serveroutlen = 0;
19527c478bd9Sstevel@tonic-gate
19537c478bd9Sstevel@tonic-gate ret = s_conn->mech->plug->mech_step(conn->context,
19547c478bd9Sstevel@tonic-gate s_conn->sparams,
19557c478bd9Sstevel@tonic-gate clientin,
19567c478bd9Sstevel@tonic-gate clientinlen,
19577c478bd9Sstevel@tonic-gate serverout,
19587c478bd9Sstevel@tonic-gate serveroutlen,
19597c478bd9Sstevel@tonic-gate &conn->oparams);
19607c478bd9Sstevel@tonic-gate
19617c478bd9Sstevel@tonic-gate if (ret == SASL_OK) {
19627c478bd9Sstevel@tonic-gate ret = do_authorization(s_conn);
19637c478bd9Sstevel@tonic-gate }
19647c478bd9Sstevel@tonic-gate
19657c478bd9Sstevel@tonic-gate if (ret == SASL_OK) {
19667c478bd9Sstevel@tonic-gate /* if we're done, we need to watch out for the following:
19677c478bd9Sstevel@tonic-gate * 1. the mech does server-send-last
19687c478bd9Sstevel@tonic-gate * 2. the protocol does not
19697c478bd9Sstevel@tonic-gate *
19707c478bd9Sstevel@tonic-gate * in this case, return SASL_CONTINUE and remember we are done.
19717c478bd9Sstevel@tonic-gate */
19727c478bd9Sstevel@tonic-gate if(*serverout && !(conn->flags & SASL_SUCCESS_DATA)) {
19737c478bd9Sstevel@tonic-gate s_conn->sent_last = 1;
19747c478bd9Sstevel@tonic-gate ret = SASL_CONTINUE;
19757c478bd9Sstevel@tonic-gate }
19767c478bd9Sstevel@tonic-gate if(!conn->oparams.maxoutbuf) {
19777c478bd9Sstevel@tonic-gate conn->oparams.maxoutbuf = conn->props.maxbufsize;
19787c478bd9Sstevel@tonic-gate }
19797c478bd9Sstevel@tonic-gate
19807c478bd9Sstevel@tonic-gate if(conn->oparams.user == NULL || conn->oparams.authid == NULL) {
19817c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
19827c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR,
19837c478bd9Sstevel@tonic-gate "mech did not call canon_user for both authzid "
19847c478bd9Sstevel@tonic-gate "and authid");
19857c478bd9Sstevel@tonic-gate #else
19867c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0,
19877c478bd9Sstevel@tonic-gate "mech did not call canon_user for both authzid " \
19887c478bd9Sstevel@tonic-gate "and authid");
19897c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
19907c478bd9Sstevel@tonic-gate ret = SASL_BADPROT;
19917c478bd9Sstevel@tonic-gate }
19927c478bd9Sstevel@tonic-gate }
19937c478bd9Sstevel@tonic-gate
19947c478bd9Sstevel@tonic-gate if( ret != SASL_OK
19957c478bd9Sstevel@tonic-gate && ret != SASL_CONTINUE
19967c478bd9Sstevel@tonic-gate && ret != SASL_INTERACT) {
19977c478bd9Sstevel@tonic-gate if(conn->context) {
19987c478bd9Sstevel@tonic-gate s_conn->mech->plug->mech_dispose(conn->context,
19997c478bd9Sstevel@tonic-gate s_conn->sparams->utils);
20007c478bd9Sstevel@tonic-gate conn->context = NULL;
20017c478bd9Sstevel@tonic-gate }
20027c478bd9Sstevel@tonic-gate }
20037c478bd9Sstevel@tonic-gate
20047c478bd9Sstevel@tonic-gate RETURN(conn, ret);
20057c478bd9Sstevel@tonic-gate }
20067c478bd9Sstevel@tonic-gate
20077c478bd9Sstevel@tonic-gate /* returns the length of all the mechanisms
20087c478bd9Sstevel@tonic-gate * added up
20097c478bd9Sstevel@tonic-gate */
20107c478bd9Sstevel@tonic-gate
20117c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
20127c478bd9Sstevel@tonic-gate static unsigned mech_names_len(_sasl_global_context_t *gctx)
20137c478bd9Sstevel@tonic-gate {
20147c478bd9Sstevel@tonic-gate mech_list_t *mechlist = gctx->mechlist;
20157c478bd9Sstevel@tonic-gate #else
20167c478bd9Sstevel@tonic-gate static unsigned mech_names_len()
20177c478bd9Sstevel@tonic-gate {
20187c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
20197c478bd9Sstevel@tonic-gate mechanism_t *listptr;
20207c478bd9Sstevel@tonic-gate unsigned result = 0;
20217c478bd9Sstevel@tonic-gate
20227c478bd9Sstevel@tonic-gate for (listptr = mechlist->mech_list;
20237c478bd9Sstevel@tonic-gate listptr;
20247c478bd9Sstevel@tonic-gate listptr = listptr->next)
20257c478bd9Sstevel@tonic-gate result += strlen(listptr->plug->mech_name);
20267c478bd9Sstevel@tonic-gate
20277c478bd9Sstevel@tonic-gate return result;
20287c478bd9Sstevel@tonic-gate }
20297c478bd9Sstevel@tonic-gate
20307c478bd9Sstevel@tonic-gate /* This returns a list of mechanisms in a NUL-terminated string
20317c478bd9Sstevel@tonic-gate *
20327c478bd9Sstevel@tonic-gate * The default behavior is to seperate with spaces if sep==NULL
20337c478bd9Sstevel@tonic-gate */
20347c478bd9Sstevel@tonic-gate int _sasl_server_listmech(sasl_conn_t *conn,
20357c478bd9Sstevel@tonic-gate const char *user __attribute__((unused)),
20367c478bd9Sstevel@tonic-gate const char *prefix,
20377c478bd9Sstevel@tonic-gate const char *sep,
20387c478bd9Sstevel@tonic-gate const char *suffix,
20397c478bd9Sstevel@tonic-gate const char **result,
20407c478bd9Sstevel@tonic-gate unsigned *plen,
20417c478bd9Sstevel@tonic-gate int *pcount)
20427c478bd9Sstevel@tonic-gate {
20437c478bd9Sstevel@tonic-gate int lup;
20447c478bd9Sstevel@tonic-gate mechanism_t *listptr;
20457c478bd9Sstevel@tonic-gate int ret;
20467c478bd9Sstevel@tonic-gate int resultlen;
20477c478bd9Sstevel@tonic-gate int flag;
20487c478bd9Sstevel@tonic-gate const char *mysep;
20497c478bd9Sstevel@tonic-gate
20507c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
20517c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx;
20527c478bd9Sstevel@tonic-gate mech_list_t *mechlist;
20537c478bd9Sstevel@tonic-gate
20547c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM;
20557c478bd9Sstevel@tonic-gate /* if there hasn't been a sasl_sever_init() fail */
20567c478bd9Sstevel@tonic-gate gctx = conn->gctx;
20577c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT;
20587c478bd9Sstevel@tonic-gate
20597c478bd9Sstevel@tonic-gate (void)_load_server_plugins(gctx);
20607c478bd9Sstevel@tonic-gate mechlist = gctx->mechlist;
20617c478bd9Sstevel@tonic-gate #else
20627c478bd9Sstevel@tonic-gate /* if there hasn't been a sasl_sever_init() fail */
20637c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT;
20647c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM;
20657c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
20667c478bd9Sstevel@tonic-gate if (conn->type != SASL_CONN_SERVER) PARAMERROR(conn);
20677c478bd9Sstevel@tonic-gate
20687c478bd9Sstevel@tonic-gate if (! result)
20697c478bd9Sstevel@tonic-gate PARAMERROR(conn);
20707c478bd9Sstevel@tonic-gate
20717c478bd9Sstevel@tonic-gate if (plen != NULL)
20727c478bd9Sstevel@tonic-gate *plen = 0;
20737c478bd9Sstevel@tonic-gate if (pcount != NULL)
20747c478bd9Sstevel@tonic-gate *pcount = 0;
20757c478bd9Sstevel@tonic-gate
20767c478bd9Sstevel@tonic-gate if (sep) {
20777c478bd9Sstevel@tonic-gate mysep = sep;
20787c478bd9Sstevel@tonic-gate } else {
20797c478bd9Sstevel@tonic-gate mysep = " ";
20807c478bd9Sstevel@tonic-gate }
20817c478bd9Sstevel@tonic-gate
20827c478bd9Sstevel@tonic-gate if (! mechlist || mechlist->mech_length <= 0)
20837c478bd9Sstevel@tonic-gate INTERROR(conn, SASL_NOMECH);
20847c478bd9Sstevel@tonic-gate
20857c478bd9Sstevel@tonic-gate resultlen = (prefix ? strlen(prefix) : 0)
20867c478bd9Sstevel@tonic-gate + (strlen(mysep) * (mechlist->mech_length - 1))
20877c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
20887c478bd9Sstevel@tonic-gate + mech_names_len(gctx)
20897c478bd9Sstevel@tonic-gate #else
20907c478bd9Sstevel@tonic-gate + mech_names_len()
20917c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
20927c478bd9Sstevel@tonic-gate + (suffix ? strlen(suffix) : 0)
20937c478bd9Sstevel@tonic-gate + 1;
20947c478bd9Sstevel@tonic-gate ret = _buf_alloc(&conn->mechlist_buf,
20957c478bd9Sstevel@tonic-gate &conn->mechlist_buf_len, resultlen);
20967c478bd9Sstevel@tonic-gate if(ret != SASL_OK) MEMERROR(conn);
20977c478bd9Sstevel@tonic-gate
20987c478bd9Sstevel@tonic-gate if (prefix)
20997c478bd9Sstevel@tonic-gate strcpy (conn->mechlist_buf,prefix);
21007c478bd9Sstevel@tonic-gate else
21017c478bd9Sstevel@tonic-gate *(conn->mechlist_buf) = '\0';
21027c478bd9Sstevel@tonic-gate
21037c478bd9Sstevel@tonic-gate listptr = mechlist->mech_list;
21047c478bd9Sstevel@tonic-gate
21057c478bd9Sstevel@tonic-gate flag = 0;
21067c478bd9Sstevel@tonic-gate /* make list */
21077c478bd9Sstevel@tonic-gate for (lup = 0; lup < mechlist->mech_length; lup++) {
21087c478bd9Sstevel@tonic-gate /* currently, we don't use the "user" parameter for anything */
21097c478bd9Sstevel@tonic-gate if (mech_permitted(conn, listptr)) {
21107c478bd9Sstevel@tonic-gate if (pcount != NULL)
21117c478bd9Sstevel@tonic-gate (*pcount)++;
21127c478bd9Sstevel@tonic-gate
21137c478bd9Sstevel@tonic-gate /* print seperator */
21147c478bd9Sstevel@tonic-gate if (flag) {
21157c478bd9Sstevel@tonic-gate strcat(conn->mechlist_buf, mysep);
21167c478bd9Sstevel@tonic-gate } else {
21177c478bd9Sstevel@tonic-gate flag = 1;
21187c478bd9Sstevel@tonic-gate }
21197c478bd9Sstevel@tonic-gate
21207c478bd9Sstevel@tonic-gate /* now print the mechanism name */
21217c478bd9Sstevel@tonic-gate strcat(conn->mechlist_buf, listptr->plug->mech_name);
21227c478bd9Sstevel@tonic-gate }
21237c478bd9Sstevel@tonic-gate
21247c478bd9Sstevel@tonic-gate listptr = listptr->next;
21257c478bd9Sstevel@tonic-gate }
21267c478bd9Sstevel@tonic-gate
21277c478bd9Sstevel@tonic-gate if (suffix)
21287c478bd9Sstevel@tonic-gate strcat(conn->mechlist_buf,suffix);
21297c478bd9Sstevel@tonic-gate
21307c478bd9Sstevel@tonic-gate if (plen!=NULL)
21317c478bd9Sstevel@tonic-gate *plen=strlen(conn->mechlist_buf);
21327c478bd9Sstevel@tonic-gate
21337c478bd9Sstevel@tonic-gate *result = conn->mechlist_buf;
21347c478bd9Sstevel@tonic-gate
21357c478bd9Sstevel@tonic-gate return SASL_OK;
21367c478bd9Sstevel@tonic-gate }
21377c478bd9Sstevel@tonic-gate
21387c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
21397c478bd9Sstevel@tonic-gate sasl_string_list_t *_sasl_server_mechs(_sasl_global_context_t *gctx)
21407c478bd9Sstevel@tonic-gate #else
21417c478bd9Sstevel@tonic-gate sasl_string_list_t *_sasl_server_mechs(void)
21427c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
21437c478bd9Sstevel@tonic-gate {
21447c478bd9Sstevel@tonic-gate mechanism_t *listptr;
21457c478bd9Sstevel@tonic-gate sasl_string_list_t *retval = NULL, *next=NULL;
21467c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
21477c478bd9Sstevel@tonic-gate mech_list_t *mechlist = gctx->mechlist;
21487c478bd9Sstevel@tonic-gate
21497c478bd9Sstevel@tonic-gate if(!gctx->sasl_server_active) return NULL;
21507c478bd9Sstevel@tonic-gate #else
21517c478bd9Sstevel@tonic-gate if(!_sasl_server_active) return NULL;
21527c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
21537c478bd9Sstevel@tonic-gate
21547c478bd9Sstevel@tonic-gate /* make list */
21557c478bd9Sstevel@tonic-gate for (listptr = mechlist->mech_list; listptr; listptr = listptr->next) {
21567c478bd9Sstevel@tonic-gate next = sasl_ALLOC(sizeof(sasl_string_list_t));
21577c478bd9Sstevel@tonic-gate
21587c478bd9Sstevel@tonic-gate if(!next && !retval) return NULL;
21597c478bd9Sstevel@tonic-gate else if(!next) {
21607c478bd9Sstevel@tonic-gate next = retval->next;
21617c478bd9Sstevel@tonic-gate do {
21627c478bd9Sstevel@tonic-gate sasl_FREE(retval);
21637c478bd9Sstevel@tonic-gate retval = next;
21647c478bd9Sstevel@tonic-gate next = retval->next;
21657c478bd9Sstevel@tonic-gate } while(next);
21667c478bd9Sstevel@tonic-gate return NULL;
21677c478bd9Sstevel@tonic-gate }
21687c478bd9Sstevel@tonic-gate
21697c478bd9Sstevel@tonic-gate next->d = listptr->plug->mech_name;
21707c478bd9Sstevel@tonic-gate
21717c478bd9Sstevel@tonic-gate if(!retval) {
21727c478bd9Sstevel@tonic-gate next->next = NULL;
21737c478bd9Sstevel@tonic-gate retval = next;
21747c478bd9Sstevel@tonic-gate } else {
21757c478bd9Sstevel@tonic-gate next->next = retval;
21767c478bd9Sstevel@tonic-gate retval = next;
21777c478bd9Sstevel@tonic-gate }
21787c478bd9Sstevel@tonic-gate }
21797c478bd9Sstevel@tonic-gate
21807c478bd9Sstevel@tonic-gate return retval;
21817c478bd9Sstevel@tonic-gate }
21827c478bd9Sstevel@tonic-gate
21837c478bd9Sstevel@tonic-gate #define EOSTR(s,n) (((s)[n] == '\0') || ((s)[n] == ' ') || ((s)[n] == '\t'))
21847c478bd9Sstevel@tonic-gate static int is_mech(const char *t, const char *m)
21857c478bd9Sstevel@tonic-gate {
21867c478bd9Sstevel@tonic-gate int sl = strlen(m);
21877c478bd9Sstevel@tonic-gate return ((!strncasecmp(m, t, sl)) && EOSTR(t, sl));
21887c478bd9Sstevel@tonic-gate }
21897c478bd9Sstevel@tonic-gate
21907c478bd9Sstevel@tonic-gate /* returns OK if it's valid */
21917c478bd9Sstevel@tonic-gate static int _sasl_checkpass(sasl_conn_t *conn,
21927c478bd9Sstevel@tonic-gate const char *user,
21937c478bd9Sstevel@tonic-gate unsigned userlen __attribute__((unused)),
21947c478bd9Sstevel@tonic-gate const char *pass,
21957c478bd9Sstevel@tonic-gate unsigned passlen __attribute__((unused)))
21967c478bd9Sstevel@tonic-gate {
21977c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;
21987c478bd9Sstevel@tonic-gate int result;
21997c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt;
22007c478bd9Sstevel@tonic-gate sasl_server_userdb_checkpass_t *checkpass_cb;
22017c478bd9Sstevel@tonic-gate void *context;
22027c478bd9Sstevel@tonic-gate const char *mlist = NULL, *mech = NULL;
22037c478bd9Sstevel@tonic-gate struct sasl_verify_password_s *v;
22047c478bd9Sstevel@tonic-gate const char *service = conn->service;
22057c478bd9Sstevel@tonic-gate
22067c478bd9Sstevel@tonic-gate /* call userdb callback function, if available */
22077c478bd9Sstevel@tonic-gate result = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_CHECKPASS,
22087c478bd9Sstevel@tonic-gate &checkpass_cb, &context);
22097c478bd9Sstevel@tonic-gate if(result == SASL_OK && checkpass_cb) {
22107c478bd9Sstevel@tonic-gate result = checkpass_cb(conn, context, user, pass, strlen(pass),
22117c478bd9Sstevel@tonic-gate s_conn->sparams->propctx);
22127c478bd9Sstevel@tonic-gate if(result == SASL_OK)
22137c478bd9Sstevel@tonic-gate return SASL_OK;
22147c478bd9Sstevel@tonic-gate }
22157c478bd9Sstevel@tonic-gate
22167c478bd9Sstevel@tonic-gate /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */
22177c478bd9Sstevel@tonic-gate if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
22187c478bd9Sstevel@tonic-gate == SASL_OK) {
22197c478bd9Sstevel@tonic-gate getopt(context, NULL, "pwcheck_method", &mlist, NULL);
22207c478bd9Sstevel@tonic-gate }
22217c478bd9Sstevel@tonic-gate
22227c478bd9Sstevel@tonic-gate if(!mlist) mlist = DEFAULT_CHECKPASS_MECH;
22237c478bd9Sstevel@tonic-gate
22247c478bd9Sstevel@tonic-gate result = SASL_NOMECH;
22257c478bd9Sstevel@tonic-gate
22267c478bd9Sstevel@tonic-gate mech = mlist;
22277c478bd9Sstevel@tonic-gate while (*mech && result != SASL_OK) {
22287c478bd9Sstevel@tonic-gate for (v = _sasl_verify_password; v->name; v++) {
22297c478bd9Sstevel@tonic-gate if(is_mech(mech, v->name)) {
22307c478bd9Sstevel@tonic-gate result = v->verify(conn, user, pass, service,
22317c478bd9Sstevel@tonic-gate s_conn->user_realm);
22327c478bd9Sstevel@tonic-gate break;
22337c478bd9Sstevel@tonic-gate }
22347c478bd9Sstevel@tonic-gate }
22357c478bd9Sstevel@tonic-gate if (result != SASL_OK) {
22367c478bd9Sstevel@tonic-gate /* skip to next mech in list */
22377c478bd9Sstevel@tonic-gate while (*mech && !isspace((int) *mech)) mech++;
22387c478bd9Sstevel@tonic-gate while (*mech && isspace((int) *mech)) mech++;
22397c478bd9Sstevel@tonic-gate }
22407c478bd9Sstevel@tonic-gate }
22417c478bd9Sstevel@tonic-gate
22427c478bd9Sstevel@tonic-gate if (result == SASL_NOMECH) {
22437c478bd9Sstevel@tonic-gate /* no mechanism available ?!? */
22447c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, "unknown password verifier %s", mech);
22457c478bd9Sstevel@tonic-gate }
22467c478bd9Sstevel@tonic-gate
22477c478bd9Sstevel@tonic-gate if (result != SASL_OK)
22487c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
22497c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, gettext("checkpass failed"));
22507c478bd9Sstevel@tonic-gate #else
22517c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, "checkpass failed");
22527c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
22537c478bd9Sstevel@tonic-gate
22547c478bd9Sstevel@tonic-gate RETURN(conn, result);
22557c478bd9Sstevel@tonic-gate }
22567c478bd9Sstevel@tonic-gate
22577c478bd9Sstevel@tonic-gate /* check if a plaintext password is valid
22587c478bd9Sstevel@tonic-gate * if user is NULL, check if plaintext passwords are enabled
22597c478bd9Sstevel@tonic-gate * inputs:
22607c478bd9Sstevel@tonic-gate * user -- user to query in current user_domain
22617c478bd9Sstevel@tonic-gate * userlen -- length of username, 0 = strlen(user)
22627c478bd9Sstevel@tonic-gate * pass -- plaintext password to check
22637c478bd9Sstevel@tonic-gate * passlen -- length of password, 0 = strlen(pass)
22647c478bd9Sstevel@tonic-gate * returns
22657c478bd9Sstevel@tonic-gate * SASL_OK -- success
22667c478bd9Sstevel@tonic-gate * SASL_NOMECH -- mechanism not supported
22677c478bd9Sstevel@tonic-gate * SASL_NOVERIFY -- user found, but no verifier
22687c478bd9Sstevel@tonic-gate * SASL_NOUSER -- user not found
22697c478bd9Sstevel@tonic-gate */
22707c478bd9Sstevel@tonic-gate int sasl_checkpass(sasl_conn_t *conn,
22717c478bd9Sstevel@tonic-gate const char *user,
22727c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
22737c478bd9Sstevel@tonic-gate unsigned userlen,
22747c478bd9Sstevel@tonic-gate #else /* _SUN_SDK_ */
22757c478bd9Sstevel@tonic-gate unsigned userlen __attribute__((unused)),
22767c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
22777c478bd9Sstevel@tonic-gate const char *pass,
22787c478bd9Sstevel@tonic-gate unsigned passlen)
22797c478bd9Sstevel@tonic-gate {
22807c478bd9Sstevel@tonic-gate int result;
22817c478bd9Sstevel@tonic-gate
22827c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
22837c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx =
22847c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
22857c478bd9Sstevel@tonic-gate
22867c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT;
22877c478bd9Sstevel@tonic-gate
22887c478bd9Sstevel@tonic-gate /* A NULL user means the caller is checking if plaintext authentication
22897c478bd9Sstevel@tonic-gate * is enabled. But if no connection context is supplied, we have no
22907c478bd9Sstevel@tonic-gate * appropriate policy to check against. So for consistant global
22917c478bd9Sstevel@tonic-gate * behavior we always say plaintext is enabled in this case.
22927c478bd9Sstevel@tonic-gate */
22937c478bd9Sstevel@tonic-gate if (!user && !conn) return SASL_OK;
22947c478bd9Sstevel@tonic-gate
22957c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM;
22967c478bd9Sstevel@tonic-gate
22977c478bd9Sstevel@tonic-gate /* Check connection security policy to see if plaintext password
22987c478bd9Sstevel@tonic-gate * authentication is permitted.
22997c478bd9Sstevel@tonic-gate *
23007c478bd9Sstevel@tonic-gate * XXX TODO FIXME:
23017c478bd9Sstevel@tonic-gate * This should call mech_permitted with the PLAIN mechanism,
23027c478bd9Sstevel@tonic-gate * since all plaintext mechanisms should fall under the same
23037c478bd9Sstevel@tonic-gate * security policy guidelines. But to keep code changes and
23047c478bd9Sstevel@tonic-gate * risk to a minimum at this juncture, we do the minimal
23057c478bd9Sstevel@tonic-gate * security strength and plaintext policy checks which are
23067c478bd9Sstevel@tonic-gate * most likely to be deployed and useful in the field.
23077c478bd9Sstevel@tonic-gate */
23087c478bd9Sstevel@tonic-gate if (conn->props.min_ssf > conn->external.ssf)
23097c478bd9Sstevel@tonic-gate RETURN(conn, SASL_TOOWEAK);
23107c478bd9Sstevel@tonic-gate if ((conn->props.security_flags & SASL_SEC_NOPLAINTEXT) != 0
23117c478bd9Sstevel@tonic-gate && conn->external.ssf == 0)
23127c478bd9Sstevel@tonic-gate RETURN(conn, SASL_ENCRYPT);
23137c478bd9Sstevel@tonic-gate
23147c478bd9Sstevel@tonic-gate if (!user)
23157c478bd9Sstevel@tonic-gate return SASL_OK;
23167c478bd9Sstevel@tonic-gate #else
23177c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT;
23187c478bd9Sstevel@tonic-gate
23197c478bd9Sstevel@tonic-gate /* check if it's just a query if we are enabled */
23207c478bd9Sstevel@tonic-gate if (!user)
23217c478bd9Sstevel@tonic-gate return SASL_OK;
23227c478bd9Sstevel@tonic-gate
23237c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM;
23247c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
23257c478bd9Sstevel@tonic-gate
23267c478bd9Sstevel@tonic-gate /* check params */
23277c478bd9Sstevel@tonic-gate if (pass == NULL)
23287c478bd9Sstevel@tonic-gate PARAMERROR(conn);
23297c478bd9Sstevel@tonic-gate
23307c478bd9Sstevel@tonic-gate /* canonicalize the username */
23317c478bd9Sstevel@tonic-gate result = _sasl_canon_user(conn, user, 0,
23327c478bd9Sstevel@tonic-gate SASL_CU_AUTHID | SASL_CU_AUTHZID,
23337c478bd9Sstevel@tonic-gate &(conn->oparams));
23347c478bd9Sstevel@tonic-gate if(result != SASL_OK) RETURN(conn, result);
23357c478bd9Sstevel@tonic-gate user = conn->oparams.user;
23367c478bd9Sstevel@tonic-gate
23377c478bd9Sstevel@tonic-gate /* Check the password */
23387c478bd9Sstevel@tonic-gate result = _sasl_checkpass(conn, user, strlen(user), pass, strlen(pass));
23397c478bd9Sstevel@tonic-gate
23407c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
23417c478bd9Sstevel@tonic-gate if (result == SASL_OK) {
23427c478bd9Sstevel@tonic-gate result = do_authorization((sasl_server_conn_t *) conn);
23437c478bd9Sstevel@tonic-gate }
23447c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
23457c478bd9Sstevel@tonic-gate
23467c478bd9Sstevel@tonic-gate if (result == SASL_OK)
23477c478bd9Sstevel@tonic-gate result = _sasl_transition(conn, pass, passlen);
23487c478bd9Sstevel@tonic-gate
23497c478bd9Sstevel@tonic-gate RETURN(conn,result);
23507c478bd9Sstevel@tonic-gate }
23517c478bd9Sstevel@tonic-gate
23527c478bd9Sstevel@tonic-gate /* check if a user exists on server
23537c478bd9Sstevel@tonic-gate * conn -- connection context (may be NULL, used to hold last error)
23547c478bd9Sstevel@tonic-gate * service -- registered name of the service using SASL (e.g. "imap")
23557c478bd9Sstevel@tonic-gate * user_realm -- permits multiple user realms on server, NULL = default
23567c478bd9Sstevel@tonic-gate * user -- NUL terminated user name
23577c478bd9Sstevel@tonic-gate *
23587c478bd9Sstevel@tonic-gate * returns:
23597c478bd9Sstevel@tonic-gate * SASL_OK -- success
23607c478bd9Sstevel@tonic-gate * SASL_DISABLED -- account disabled [FIXME: currently not detected]
23617c478bd9Sstevel@tonic-gate * SASL_NOUSER -- user not found
23627c478bd9Sstevel@tonic-gate * SASL_NOVERIFY -- user found, but no usable mechanism [FIXME: not supported]
23637c478bd9Sstevel@tonic-gate * SASL_NOMECH -- no mechanisms enabled
23647c478bd9Sstevel@tonic-gate */
23657c478bd9Sstevel@tonic-gate int sasl_user_exists(sasl_conn_t *conn,
23667c478bd9Sstevel@tonic-gate const char *service,
23677c478bd9Sstevel@tonic-gate const char *user_realm,
23687c478bd9Sstevel@tonic-gate const char *user)
23697c478bd9Sstevel@tonic-gate {
23707c478bd9Sstevel@tonic-gate int result=SASL_NOMECH;
23717c478bd9Sstevel@tonic-gate const char *mlist = NULL, *mech = NULL;
23727c478bd9Sstevel@tonic-gate void *context;
23737c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt;
23747c478bd9Sstevel@tonic-gate struct sasl_verify_password_s *v;
23757c478bd9Sstevel@tonic-gate
23767c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
23777c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx =
23787c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
23797c478bd9Sstevel@tonic-gate
23807c478bd9Sstevel@tonic-gate /* check params */
23817c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT;
23827c478bd9Sstevel@tonic-gate #else
23837c478bd9Sstevel@tonic-gate /* check params */
23847c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT;
23857c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
23867c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM;
23877c478bd9Sstevel@tonic-gate if (!user || conn->type != SASL_CONN_SERVER)
23887c478bd9Sstevel@tonic-gate PARAMERROR(conn);
23897c478bd9Sstevel@tonic-gate
23907c478bd9Sstevel@tonic-gate if(!service) service = conn->service;
23917c478bd9Sstevel@tonic-gate
23927c478bd9Sstevel@tonic-gate /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */
23937c478bd9Sstevel@tonic-gate if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context)
23947c478bd9Sstevel@tonic-gate == SASL_OK) {
23957c478bd9Sstevel@tonic-gate getopt(context, NULL, "pwcheck_method", &mlist, NULL);
23967c478bd9Sstevel@tonic-gate }
23977c478bd9Sstevel@tonic-gate
23987c478bd9Sstevel@tonic-gate if(!mlist) mlist = DEFAULT_CHECKPASS_MECH;
23997c478bd9Sstevel@tonic-gate
24007c478bd9Sstevel@tonic-gate result = SASL_NOMECH;
24017c478bd9Sstevel@tonic-gate
24027c478bd9Sstevel@tonic-gate mech = mlist;
24037c478bd9Sstevel@tonic-gate while (*mech && result != SASL_OK) {
24047c478bd9Sstevel@tonic-gate for (v = _sasl_verify_password; v->name; v++) {
24057c478bd9Sstevel@tonic-gate if(is_mech(mech, v->name)) {
24067c478bd9Sstevel@tonic-gate result = v->verify(conn, user, NULL, service, user_realm);
24077c478bd9Sstevel@tonic-gate break;
24087c478bd9Sstevel@tonic-gate }
24097c478bd9Sstevel@tonic-gate }
24107c478bd9Sstevel@tonic-gate if (result != SASL_OK) {
24117c478bd9Sstevel@tonic-gate /* skip to next mech in list */
24127c478bd9Sstevel@tonic-gate while (*mech && !isspace((int) *mech)) mech++;
24137c478bd9Sstevel@tonic-gate while (*mech && isspace((int) *mech)) mech++;
24147c478bd9Sstevel@tonic-gate }
24157c478bd9Sstevel@tonic-gate }
24167c478bd9Sstevel@tonic-gate
24177c478bd9Sstevel@tonic-gate /* Screen out the SASL_BADPARAM response
24187c478bd9Sstevel@tonic-gate * we'll get from not giving a password */
24197c478bd9Sstevel@tonic-gate if(result == SASL_BADPARAM) {
24207c478bd9Sstevel@tonic-gate result = SASL_OK;
24217c478bd9Sstevel@tonic-gate }
24227c478bd9Sstevel@tonic-gate
24237c478bd9Sstevel@tonic-gate if (result == SASL_NOMECH) {
24247c478bd9Sstevel@tonic-gate /* no mechanism available ?!? */
24257c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, "no plaintext password verifier?");
24267c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
24277c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, "no plaintext password verifier?");
24287c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
24297c478bd9Sstevel@tonic-gate }
24307c478bd9Sstevel@tonic-gate
24317c478bd9Sstevel@tonic-gate RETURN(conn, result);
24327c478bd9Sstevel@tonic-gate }
24337c478bd9Sstevel@tonic-gate
24347c478bd9Sstevel@tonic-gate /* check if an apop exchange is valid
24357c478bd9Sstevel@tonic-gate * (note this is an optional part of the SASL API)
24367c478bd9Sstevel@tonic-gate * if challenge is NULL, just check if APOP is enabled
24377c478bd9Sstevel@tonic-gate * inputs:
24387c478bd9Sstevel@tonic-gate * challenge -- challenge which was sent to client
24397c478bd9Sstevel@tonic-gate * challen -- length of challenge, 0 = strlen(challenge)
24407c478bd9Sstevel@tonic-gate * response -- client response, "<user> <digest>" (RFC 1939)
24417c478bd9Sstevel@tonic-gate * resplen -- length of response, 0 = strlen(response)
24427c478bd9Sstevel@tonic-gate * returns
24437c478bd9Sstevel@tonic-gate * SASL_OK -- success
24447c478bd9Sstevel@tonic-gate * SASL_BADAUTH -- authentication failed
24457c478bd9Sstevel@tonic-gate * SASL_BADPARAM -- missing challenge
24467c478bd9Sstevel@tonic-gate * SASL_BADPROT -- protocol error (e.g., response in wrong format)
24477c478bd9Sstevel@tonic-gate * SASL_NOVERIFY -- user found, but no verifier
24487c478bd9Sstevel@tonic-gate * SASL_NOMECH -- mechanism not supported
24497c478bd9Sstevel@tonic-gate * SASL_NOUSER -- user not found
24507c478bd9Sstevel@tonic-gate */
24517c478bd9Sstevel@tonic-gate int sasl_checkapop(sasl_conn_t *conn,
24527c478bd9Sstevel@tonic-gate #ifdef DO_SASL_CHECKAPOP
24537c478bd9Sstevel@tonic-gate const char *challenge,
24547c478bd9Sstevel@tonic-gate unsigned challen __attribute__((unused)),
24557c478bd9Sstevel@tonic-gate const char *response,
24567c478bd9Sstevel@tonic-gate unsigned resplen __attribute__((unused)))
24577c478bd9Sstevel@tonic-gate #else
24587c478bd9Sstevel@tonic-gate const char *challenge __attribute__((unused)),
24597c478bd9Sstevel@tonic-gate unsigned challen __attribute__((unused)),
24607c478bd9Sstevel@tonic-gate const char *response __attribute__((unused)),
24617c478bd9Sstevel@tonic-gate unsigned resplen __attribute__((unused)))
24627c478bd9Sstevel@tonic-gate #endif
24637c478bd9Sstevel@tonic-gate {
24647c478bd9Sstevel@tonic-gate #ifdef DO_SASL_CHECKAPOP
24657c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn;
24667c478bd9Sstevel@tonic-gate char *user, *user_end;
24677c478bd9Sstevel@tonic-gate const char *password_request[] = { SASL_AUX_PASSWORD, NULL };
24687c478bd9Sstevel@tonic-gate size_t user_len;
24697c478bd9Sstevel@tonic-gate int result;
24707c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
24717c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx =
24727c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx;
24737c478bd9Sstevel@tonic-gate
24747c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0)
24757c478bd9Sstevel@tonic-gate return SASL_NOTINIT;
24767c478bd9Sstevel@tonic-gate #else
24777c478bd9Sstevel@tonic-gate if (_sasl_server_active==0)
24787c478bd9Sstevel@tonic-gate return SASL_NOTINIT;
24797c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
24807c478bd9Sstevel@tonic-gate
24817c478bd9Sstevel@tonic-gate /* check if it's just a query if we are enabled */
24827c478bd9Sstevel@tonic-gate if(!challenge)
24837c478bd9Sstevel@tonic-gate return SASL_OK;
24847c478bd9Sstevel@tonic-gate
24857c478bd9Sstevel@tonic-gate /* check params */
24867c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM;
24877c478bd9Sstevel@tonic-gate if (!response)
24887c478bd9Sstevel@tonic-gate PARAMERROR(conn);
24897c478bd9Sstevel@tonic-gate
24907c478bd9Sstevel@tonic-gate /* Parse out username and digest.
24917c478bd9Sstevel@tonic-gate *
24927c478bd9Sstevel@tonic-gate * Per RFC 1939, response must be "<user> <digest>", where
24937c478bd9Sstevel@tonic-gate * <digest> is a 16-octet value which is sent in hexadecimal
24947c478bd9Sstevel@tonic-gate * format, using lower-case ASCII characters.
24957c478bd9Sstevel@tonic-gate */
24967c478bd9Sstevel@tonic-gate user_end = strrchr(response, ' ');
24977c478bd9Sstevel@tonic-gate if (!user_end || strspn(user_end + 1, "0123456789abcdef") != 32)
24987c478bd9Sstevel@tonic-gate {
24997c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
25007c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, gettext("Bad Digest"));
25017c478bd9Sstevel@tonic-gate #else
25027c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "Bad Digest");
25037c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
25047c478bd9Sstevel@tonic-gate RETURN(conn,SASL_BADPROT);
25057c478bd9Sstevel@tonic-gate }
25067c478bd9Sstevel@tonic-gate
25077c478bd9Sstevel@tonic-gate user_len = (size_t)(user_end - response);
25087c478bd9Sstevel@tonic-gate user = sasl_ALLOC(user_len + 1);
25097c478bd9Sstevel@tonic-gate memcpy(user, response, user_len);
25107c478bd9Sstevel@tonic-gate user[user_len] = '\0';
25117c478bd9Sstevel@tonic-gate
25127c478bd9Sstevel@tonic-gate result = prop_request(s_conn->sparams->propctx, password_request);
25137c478bd9Sstevel@tonic-gate if(result != SASL_OK)
25147c478bd9Sstevel@tonic-gate {
25157c478bd9Sstevel@tonic-gate sasl_FREE(user);
25167c478bd9Sstevel@tonic-gate RETURN(conn, result);
25177c478bd9Sstevel@tonic-gate }
25187c478bd9Sstevel@tonic-gate
25197c478bd9Sstevel@tonic-gate /* Cannonify it */
25207c478bd9Sstevel@tonic-gate result = _sasl_canon_user(conn, user, user_len,
25217c478bd9Sstevel@tonic-gate SASL_CU_AUTHID | SASL_CU_AUTHZID,
25227c478bd9Sstevel@tonic-gate &(conn->oparams));
25237c478bd9Sstevel@tonic-gate sasl_FREE(user);
25247c478bd9Sstevel@tonic-gate
25257c478bd9Sstevel@tonic-gate if(result != SASL_OK) RETURN(conn, result);
25267c478bd9Sstevel@tonic-gate
25277c478bd9Sstevel@tonic-gate /* Do APOP verification */
25287c478bd9Sstevel@tonic-gate result = _sasl_auxprop_verify_apop(conn, conn->oparams.authid,
25297c478bd9Sstevel@tonic-gate challenge, user_end + 1, s_conn->user_realm);
25307c478bd9Sstevel@tonic-gate
25317c478bd9Sstevel@tonic-gate /* If verification failed, we don't want to encourage getprop to work */
25327c478bd9Sstevel@tonic-gate if(result != SASL_OK) {
25337c478bd9Sstevel@tonic-gate conn->oparams.user = NULL;
25347c478bd9Sstevel@tonic-gate conn->oparams.authid = NULL;
25357c478bd9Sstevel@tonic-gate }
25367c478bd9Sstevel@tonic-gate
25377c478bd9Sstevel@tonic-gate RETURN(conn, result);
25387c478bd9Sstevel@tonic-gate #else /* sasl_checkapop was disabled at compile time */
25397c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG,
25407c478bd9Sstevel@tonic-gate "sasl_checkapop called, but was disabled at compile time");
25417c478bd9Sstevel@tonic-gate RETURN(conn, SASL_NOMECH);
25427c478bd9Sstevel@tonic-gate #endif /* DO_SASL_CHECKAPOP */
25437c478bd9Sstevel@tonic-gate }
25447c478bd9Sstevel@tonic-gate
2545