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 #pragma ident "%Z%%M% %I% %E% SMI" 67c478bd9Sstevel@tonic-gate 77c478bd9Sstevel@tonic-gate /* SASL server API implementation 87c478bd9Sstevel@tonic-gate * Rob Siemborski 97c478bd9Sstevel@tonic-gate * Tim Martin 107c478bd9Sstevel@tonic-gate * $Id: server.c,v 1.123 2003/04/16 19:36:01 rjs3 Exp $ 117c478bd9Sstevel@tonic-gate */ 127c478bd9Sstevel@tonic-gate /* 137c478bd9Sstevel@tonic-gate * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. 147c478bd9Sstevel@tonic-gate * 157c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 167c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 177c478bd9Sstevel@tonic-gate * are met: 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 207c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 217c478bd9Sstevel@tonic-gate * 227c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 237c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 247c478bd9Sstevel@tonic-gate * the documentation and/or other materials provided with the 257c478bd9Sstevel@tonic-gate * distribution. 267c478bd9Sstevel@tonic-gate * 277c478bd9Sstevel@tonic-gate * 3. The name "Carnegie Mellon University" must not be used to 287c478bd9Sstevel@tonic-gate * endorse or promote products derived from this software without 297c478bd9Sstevel@tonic-gate * prior written permission. For permission or any other legal 307c478bd9Sstevel@tonic-gate * details, please contact 317c478bd9Sstevel@tonic-gate * Office of Technology Transfer 327c478bd9Sstevel@tonic-gate * Carnegie Mellon University 337c478bd9Sstevel@tonic-gate * 5000 Forbes Avenue 347c478bd9Sstevel@tonic-gate * Pittsburgh, PA 15213-3890 357c478bd9Sstevel@tonic-gate * (412) 268-4387, fax: (412) 268-7395 367c478bd9Sstevel@tonic-gate * tech-transfer@andrew.cmu.edu 377c478bd9Sstevel@tonic-gate * 387c478bd9Sstevel@tonic-gate * 4. Redistributions of any form whatsoever must retain the following 397c478bd9Sstevel@tonic-gate * acknowledgment: 407c478bd9Sstevel@tonic-gate * "This product includes software developed by Computing Services 417c478bd9Sstevel@tonic-gate * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 447c478bd9Sstevel@tonic-gate * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 457c478bd9Sstevel@tonic-gate * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 467c478bd9Sstevel@tonic-gate * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 477c478bd9Sstevel@tonic-gate * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 487c478bd9Sstevel@tonic-gate * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 497c478bd9Sstevel@tonic-gate * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate /* local functions/structs don't start with sasl 537c478bd9Sstevel@tonic-gate */ 547c478bd9Sstevel@tonic-gate #include <config.h> 557c478bd9Sstevel@tonic-gate #include <errno.h> 567c478bd9Sstevel@tonic-gate #include <stdio.h> 577c478bd9Sstevel@tonic-gate #include <stdlib.h> 587c478bd9Sstevel@tonic-gate #include <limits.h> 597c478bd9Sstevel@tonic-gate #ifndef macintosh 607c478bd9Sstevel@tonic-gate #include <sys/types.h> 617c478bd9Sstevel@tonic-gate #include <sys/stat.h> 627c478bd9Sstevel@tonic-gate #endif 637c478bd9Sstevel@tonic-gate #include <fcntl.h> 647c478bd9Sstevel@tonic-gate #include <string.h> 657c478bd9Sstevel@tonic-gate #include <ctype.h> 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #include "sasl.h" 687c478bd9Sstevel@tonic-gate #include "saslint.h" 697c478bd9Sstevel@tonic-gate #include "saslplug.h" 707c478bd9Sstevel@tonic-gate #include "saslutil.h" 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_ 737c478bd9Sstevel@tonic-gate #ifdef sun 747c478bd9Sstevel@tonic-gate /* gotta define gethostname ourselves on suns */ 757c478bd9Sstevel@tonic-gate extern int gethostname(char *, int); 767c478bd9Sstevel@tonic-gate #endif 777c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */ 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate #define DEFAULT_CHECKPASS_MECH "auxprop" 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate /* Contains functions: 827c478bd9Sstevel@tonic-gate * 837c478bd9Sstevel@tonic-gate * sasl_server_init 847c478bd9Sstevel@tonic-gate * sasl_server_new 857c478bd9Sstevel@tonic-gate * sasl_listmech 867c478bd9Sstevel@tonic-gate * sasl_server_start 877c478bd9Sstevel@tonic-gate * sasl_server_step 887c478bd9Sstevel@tonic-gate * sasl_checkpass 897c478bd9Sstevel@tonic-gate * sasl_checkapop 907c478bd9Sstevel@tonic-gate * sasl_user_exists 917c478bd9Sstevel@tonic-gate * sasl_setpass 927c478bd9Sstevel@tonic-gate */ 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 957c478bd9Sstevel@tonic-gate int _is_sasl_server_active(_sasl_global_context_t *gctx) 967c478bd9Sstevel@tonic-gate { 977c478bd9Sstevel@tonic-gate return gctx->sasl_server_active; 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(init_server_mutex); 1017c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(server_active_mutex); 1027c478bd9Sstevel@tonic-gate /* 1037c478bd9Sstevel@tonic-gate * server_plug_mutex ensures only one server plugin is init'ed at a time 1047c478bd9Sstevel@tonic-gate * If a plugin is loaded more than once, the glob_context may be overwritten 1057c478bd9Sstevel@tonic-gate * which may lead to a memory leak. We keep glob_context with each mech 1067c478bd9Sstevel@tonic-gate * to avoid this problem. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(server_plug_mutex); 1097c478bd9Sstevel@tonic-gate #else 1107c478bd9Sstevel@tonic-gate /* if we've initialized the server sucessfully */ 1117c478bd9Sstevel@tonic-gate static int _sasl_server_active = 0; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* For access by other modules */ 1147c478bd9Sstevel@tonic-gate int _is_sasl_server_active(void) { return _sasl_server_active; } 1157c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate static int _sasl_checkpass(sasl_conn_t *conn, 1187c478bd9Sstevel@tonic-gate const char *user, unsigned userlen, 1197c478bd9Sstevel@tonic-gate const char *pass, unsigned passlen); 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_ 1227c478bd9Sstevel@tonic-gate static mech_list_t *mechlist = NULL; /* global var which holds the list */ 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate static sasl_global_callbacks_t global_callbacks; 1257c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */ 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* set the password for a user 1287c478bd9Sstevel@tonic-gate * conn -- SASL connection 1297c478bd9Sstevel@tonic-gate * user -- user name 1307c478bd9Sstevel@tonic-gate * pass -- plaintext password, may be NULL to remove user 1317c478bd9Sstevel@tonic-gate * passlen -- length of password, 0 = strlen(pass) 1327c478bd9Sstevel@tonic-gate * oldpass -- NULL will sometimes work 1337c478bd9Sstevel@tonic-gate * oldpasslen -- length of password, 0 = strlen(oldpass) 1347c478bd9Sstevel@tonic-gate * flags -- see flags below 1357c478bd9Sstevel@tonic-gate * 1367c478bd9Sstevel@tonic-gate * returns: 1377c478bd9Sstevel@tonic-gate * SASL_NOCHANGE -- proper entry already exists 1387c478bd9Sstevel@tonic-gate * SASL_NOMECH -- no authdb supports password setting as configured 1397c478bd9Sstevel@tonic-gate * SASL_NOVERIFY -- user exists, but no settable password present 1407c478bd9Sstevel@tonic-gate * SASL_DISABLED -- account disabled 1417c478bd9Sstevel@tonic-gate * SASL_PWLOCK -- password locked 1427c478bd9Sstevel@tonic-gate * SASL_WEAKPASS -- password too weak for security policy 1437c478bd9Sstevel@tonic-gate * SASL_NOUSERPASS -- user-supplied passwords not permitted 1447c478bd9Sstevel@tonic-gate * SASL_FAIL -- OS error 1457c478bd9Sstevel@tonic-gate * SASL_BADPARAM -- password too long 1467c478bd9Sstevel@tonic-gate * SASL_OK -- successful 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate int sasl_setpass(sasl_conn_t *conn, 1507c478bd9Sstevel@tonic-gate const char *user, 1517c478bd9Sstevel@tonic-gate const char *pass, unsigned passlen, 1527c478bd9Sstevel@tonic-gate const char *oldpass, 1537c478bd9Sstevel@tonic-gate unsigned oldpasslen, 1547c478bd9Sstevel@tonic-gate unsigned flags) 1557c478bd9Sstevel@tonic-gate { 1567c478bd9Sstevel@tonic-gate int result=SASL_OK, tmpresult; 1577c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn; 1587c478bd9Sstevel@tonic-gate sasl_server_userdb_setpass_t *setpass_cb = NULL; 1597c478bd9Sstevel@tonic-gate void *context = NULL; 1607c478bd9Sstevel@tonic-gate mechanism_t *m; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 1637c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = 1647c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx; 1657c478bd9Sstevel@tonic-gate mech_list_t *mechlist = gctx == NULL ? NULL : gctx->mechlist; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate if (!gctx->sasl_server_active || !mechlist) return SASL_NOTINIT; 1687c478bd9Sstevel@tonic-gate #else 1697c478bd9Sstevel@tonic-gate if (!_sasl_server_active || !mechlist) return SASL_NOTINIT; 1707c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* check params */ 1737c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM; 1747c478bd9Sstevel@tonic-gate if (conn->type != SASL_CONN_SERVER) PARAMERROR(conn); 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate if ((!(flags & SASL_SET_DISABLE) && passlen == 0) 1777c478bd9Sstevel@tonic-gate || ((flags & SASL_SET_CREATE) && (flags & SASL_SET_DISABLE))) 1787c478bd9Sstevel@tonic-gate PARAMERROR(conn); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* call userdb callback function */ 1817c478bd9Sstevel@tonic-gate result = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_SETPASS, 1827c478bd9Sstevel@tonic-gate &setpass_cb, &context); 1837c478bd9Sstevel@tonic-gate if(result == SASL_OK && setpass_cb) { 1847c478bd9Sstevel@tonic-gate tmpresult = setpass_cb(conn, context, user, pass, passlen, 1857c478bd9Sstevel@tonic-gate s_conn->sparams->propctx, flags); 1867c478bd9Sstevel@tonic-gate if(tmpresult != SASL_OK) { 1877c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, 1887c478bd9Sstevel@tonic-gate "setpass callback failed for %s: %z", 1897c478bd9Sstevel@tonic-gate user, tmpresult); 1907c478bd9Sstevel@tonic-gate } else { 1917c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_NOTE, 1927c478bd9Sstevel@tonic-gate "setpass callback succeeded for %s", user); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate } else { 1957c478bd9Sstevel@tonic-gate result = SASL_OK; 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* now we let the mechanisms set their secrets */ 1997c478bd9Sstevel@tonic-gate for (m = mechlist->mech_list; m; m = m->next) { 2007c478bd9Sstevel@tonic-gate if (!m->plug->setpass) { 2017c478bd9Sstevel@tonic-gate /* can't set pass for this mech */ 2027c478bd9Sstevel@tonic-gate continue; 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 2057c478bd9Sstevel@tonic-gate tmpresult = m->plug->setpass(m->glob_context, 2067c478bd9Sstevel@tonic-gate #else 2077c478bd9Sstevel@tonic-gate tmpresult = m->plug->setpass(m->plug->glob_context, 2087c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 2097c478bd9Sstevel@tonic-gate ((sasl_server_conn_t *)conn)->sparams, 2107c478bd9Sstevel@tonic-gate user, 2117c478bd9Sstevel@tonic-gate pass, 2127c478bd9Sstevel@tonic-gate passlen, 2137c478bd9Sstevel@tonic-gate oldpass, oldpasslen, 2147c478bd9Sstevel@tonic-gate flags); 2157c478bd9Sstevel@tonic-gate if (tmpresult == SASL_OK) { 2167c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_NOTE, 2177c478bd9Sstevel@tonic-gate "%s: set secret for %s", m->plug->mech_name, user); 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate m->condition = SASL_OK; /* if we previously thought the 2207c478bd9Sstevel@tonic-gate mechanism didn't have any user secrets 2217c478bd9Sstevel@tonic-gate we now think it does */ 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate } else if (tmpresult == SASL_NOCHANGE) { 2247c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_NOTE, 2257c478bd9Sstevel@tonic-gate "%s: secret not changed for %s", m->plug->mech_name, user); 2267c478bd9Sstevel@tonic-gate } else { 2277c478bd9Sstevel@tonic-gate result = tmpresult; 2287c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, 2297c478bd9Sstevel@tonic-gate "%s: failed to set secret for %s: %z (%m)", 2307c478bd9Sstevel@tonic-gate m->plug->mech_name, user, tmpresult, 2317c478bd9Sstevel@tonic-gate #ifndef WIN32 2327c478bd9Sstevel@tonic-gate errno 2337c478bd9Sstevel@tonic-gate #else 2347c478bd9Sstevel@tonic-gate GetLastError() 2357c478bd9Sstevel@tonic-gate #endif 2367c478bd9Sstevel@tonic-gate ); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate RETURN(conn, result); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 2447c478bd9Sstevel@tonic-gate static void 2457c478bd9Sstevel@tonic-gate server_dispose_mech_contexts(sasl_conn_t *pconn) 2467c478bd9Sstevel@tonic-gate { 2477c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn= (sasl_server_conn_t *) pconn; 2487c478bd9Sstevel@tonic-gate context_list_t *cur, *cur_next; 2497c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = pconn->gctx; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate for(cur = s_conn->mech_contexts; cur; cur=cur_next) { 2527c478bd9Sstevel@tonic-gate cur_next = cur->next; 2537c478bd9Sstevel@tonic-gate if(cur->context) 2547c478bd9Sstevel@tonic-gate cur->mech->plug->mech_dispose(cur->context, s_conn->sparams->utils); 2557c478bd9Sstevel@tonic-gate sasl_FREE(cur); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate s_conn->mech_contexts = NULL; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* local mechanism which disposes of server */ 2627c478bd9Sstevel@tonic-gate static void server_dispose(sasl_conn_t *pconn) 2637c478bd9Sstevel@tonic-gate { 2647c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn= (sasl_server_conn_t *) pconn; 2657c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 2667c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = pconn->gctx; 2677c478bd9Sstevel@tonic-gate #else 2687c478bd9Sstevel@tonic-gate context_list_t *cur, *cur_next; 2697c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate if (s_conn->mech 2727c478bd9Sstevel@tonic-gate && s_conn->mech->plug->mech_dispose) { 2737c478bd9Sstevel@tonic-gate s_conn->mech->plug->mech_dispose(pconn->context, 2747c478bd9Sstevel@tonic-gate s_conn->sparams->utils); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate pconn->context = NULL; 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 2797c478bd9Sstevel@tonic-gate server_dispose_mech_contexts(pconn); 2807c478bd9Sstevel@tonic-gate #else 2817c478bd9Sstevel@tonic-gate for(cur = s_conn->mech_contexts; cur; cur=cur_next) { 2827c478bd9Sstevel@tonic-gate cur_next = cur->next; 2837c478bd9Sstevel@tonic-gate if(cur->context) 2847c478bd9Sstevel@tonic-gate cur->mech->plug->mech_dispose(cur->context, s_conn->sparams->utils); 2857c478bd9Sstevel@tonic-gate sasl_FREE(cur); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate s_conn->mech_contexts = NULL; 2887c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate _sasl_free_utils(&s_conn->sparams->utils); 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate if (s_conn->sparams->propctx) 2937c478bd9Sstevel@tonic-gate prop_dispose(&s_conn->sparams->propctx); 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate if (s_conn->user_realm) 2967c478bd9Sstevel@tonic-gate sasl_FREE(s_conn->user_realm); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if (s_conn->sparams) 2997c478bd9Sstevel@tonic-gate sasl_FREE(s_conn->sparams); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate _sasl_conn_dispose(pconn); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 3057c478bd9Sstevel@tonic-gate static int init_mechlist(_sasl_global_context_t *gctx) 3067c478bd9Sstevel@tonic-gate { 3077c478bd9Sstevel@tonic-gate mech_list_t *mechlist = gctx->mechlist; 3087c478bd9Sstevel@tonic-gate #else 3097c478bd9Sstevel@tonic-gate static int init_mechlist(void) 3107c478bd9Sstevel@tonic-gate { 3117c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 3127c478bd9Sstevel@tonic-gate sasl_utils_t *newutils = NULL; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate mechlist->mutex = sasl_MUTEX_ALLOC(); 3157c478bd9Sstevel@tonic-gate if(!mechlist->mutex) return SASL_FAIL; 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* set util functions - need to do rest */ 3187c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 3197c478bd9Sstevel@tonic-gate newutils = _sasl_alloc_utils(gctx, NULL, &gctx->server_global_callbacks); 3207c478bd9Sstevel@tonic-gate #else 3217c478bd9Sstevel@tonic-gate newutils = _sasl_alloc_utils(NULL, &global_callbacks); 3227c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 3237c478bd9Sstevel@tonic-gate if (newutils == NULL) 3247c478bd9Sstevel@tonic-gate return SASL_NOMEM; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate newutils->checkpass = &_sasl_checkpass; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate mechlist->utils = newutils; 3297c478bd9Sstevel@tonic-gate mechlist->mech_list=NULL; 3307c478bd9Sstevel@tonic-gate mechlist->mech_length=0; 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate return SASL_OK; 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 3367c478bd9Sstevel@tonic-gate static int load_mech(_sasl_global_context_t *gctx, const char *mechname) 3377c478bd9Sstevel@tonic-gate { 3387c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt; 3397c478bd9Sstevel@tonic-gate void *context; 3407c478bd9Sstevel@tonic-gate const char *mlist = NULL; 3417c478bd9Sstevel@tonic-gate const char *cp; 3427c478bd9Sstevel@tonic-gate size_t len; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* No sasl_conn_t was given to getcallback, so we provide the 3457c478bd9Sstevel@tonic-gate * global callbacks structure */ 3467c478bd9Sstevel@tonic-gate if (_sasl_getcallback(NULL, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) 3477c478bd9Sstevel@tonic-gate (void)getopt(&gctx->server_global_callbacks, NULL, 3487c478bd9Sstevel@tonic-gate "server_load_mech_list", &mlist, NULL); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (mlist == NULL) 3517c478bd9Sstevel@tonic-gate return (1); 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate len = strlen(mechname); 3547c478bd9Sstevel@tonic-gate while (*mlist && isspace((int) *mlist)) mlist++; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate while (*mlist) { 3577c478bd9Sstevel@tonic-gate for (cp = mlist; *cp && !isspace((int) *cp); cp++); 3587c478bd9Sstevel@tonic-gate if (((size_t) (cp - mlist) == len) && 3597c478bd9Sstevel@tonic-gate !strncasecmp(mlist, mechname, len)) 3607c478bd9Sstevel@tonic-gate break; 3617c478bd9Sstevel@tonic-gate mlist = cp; 3627c478bd9Sstevel@tonic-gate while (*mlist && isspace((int) *mlist)) mlist++; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate return (*mlist != '\0'); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate /* 3697c478bd9Sstevel@tonic-gate * parameters: 3707c478bd9Sstevel@tonic-gate * p - entry point 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate int sasl_server_add_plugin(const char *plugname, 3737c478bd9Sstevel@tonic-gate sasl_server_plug_init_t *p) 3747c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 3757c478bd9Sstevel@tonic-gate { 3767c478bd9Sstevel@tonic-gate return (_sasl_server_add_plugin(_sasl_gbl_ctx(), plugname, p)); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate int _sasl_server_add_plugin(void *ctx, 3807c478bd9Sstevel@tonic-gate const char *plugname, 3817c478bd9Sstevel@tonic-gate sasl_server_plug_init_t *p) 3827c478bd9Sstevel@tonic-gate { 3837c478bd9Sstevel@tonic-gate int nplug = 0; 3847c478bd9Sstevel@tonic-gate int i; 3857c478bd9Sstevel@tonic-gate mechanism_t *m; 3867c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx; 3877c478bd9Sstevel@tonic-gate mech_list_t *mechlist = gctx->mechlist; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */ 3907c478bd9Sstevel@tonic-gate /* CRYPT DELETE START */ 3917c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 3927c478bd9Sstevel@tonic-gate int sun_reg; 3937c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 3947c478bd9Sstevel@tonic-gate /* CRYPT DELETE END */ 3957c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */ 3967c478bd9Sstevel@tonic-gate #else 3977c478bd9Sstevel@tonic-gate { 3987c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 3997c478bd9Sstevel@tonic-gate int plugcount; 4007c478bd9Sstevel@tonic-gate sasl_server_plug_t *pluglist; 4017c478bd9Sstevel@tonic-gate mechanism_t *mech; 4027c478bd9Sstevel@tonic-gate sasl_server_plug_init_t *entry_point; 4037c478bd9Sstevel@tonic-gate int result; 4047c478bd9Sstevel@tonic-gate int version; 4057c478bd9Sstevel@tonic-gate int lupe; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if(!plugname || !p) return SASL_BADPARAM; 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 4107c478bd9Sstevel@tonic-gate if (mechlist == NULL) return SASL_BADPARAM; 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /* Check to see if this plugin has already been registered */ 4137c478bd9Sstevel@tonic-gate m = mechlist->mech_list; 4147c478bd9Sstevel@tonic-gate for (i = 0; i < mechlist->mech_length; i++) { 4157c478bd9Sstevel@tonic-gate if (strcmp(plugname, m->plugname) == 0) 4167c478bd9Sstevel@tonic-gate return SASL_OK; 4177c478bd9Sstevel@tonic-gate m = m->next; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate result = LOCK_MUTEX(&server_plug_mutex); 4217c478bd9Sstevel@tonic-gate if (result != SASL_OK) 4227c478bd9Sstevel@tonic-gate return result; 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 4257c478bd9Sstevel@tonic-gate entry_point = (sasl_server_plug_init_t *)p; 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate /* call into the shared library asking for information about it */ 4287c478bd9Sstevel@tonic-gate /* version is filled in with the version of the plugin */ 4297c478bd9Sstevel@tonic-gate result = entry_point(mechlist->utils, SASL_SERVER_PLUG_VERSION, &version, 4307c478bd9Sstevel@tonic-gate &pluglist, &plugcount); 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */ 4337c478bd9Sstevel@tonic-gate /* CRYPT DELETE START */ 4347c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 4357c478bd9Sstevel@tonic-gate sun_reg = _is_sun_reg(pluglist); 4367c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 4377c478bd9Sstevel@tonic-gate /* CRYPT DELETE END */ 4387c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */ 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 4417c478bd9Sstevel@tonic-gate if (result != SASL_OK) { 4427c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_plug_mutex); 4437c478bd9Sstevel@tonic-gate __sasl_log(gctx, gctx->server_global_callbacks.callbacks, 4447c478bd9Sstevel@tonic-gate SASL_LOG_DEBUG, 4457c478bd9Sstevel@tonic-gate "server add_plugin entry_point error %z", result); 4467c478bd9Sstevel@tonic-gate #else 4477c478bd9Sstevel@tonic-gate if ((result != SASL_OK) && (result != SASL_NOUSER)) { 4487c478bd9Sstevel@tonic-gate _sasl_log(NULL, SASL_LOG_DEBUG, 4497c478bd9Sstevel@tonic-gate "server add_plugin entry_point error %z\n", result); 4507c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 4517c478bd9Sstevel@tonic-gate return result; 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /* Make sure plugin is using the same SASL version as us */ 4557c478bd9Sstevel@tonic-gate if (version != SASL_SERVER_PLUG_VERSION) 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 4587c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_plug_mutex); 4597c478bd9Sstevel@tonic-gate __sasl_log(gctx, gctx->server_global_callbacks.callbacks, 4607c478bd9Sstevel@tonic-gate SASL_LOG_ERR, "version mismatch on plugin"); 4617c478bd9Sstevel@tonic-gate #else 4627c478bd9Sstevel@tonic-gate _sasl_log(NULL, SASL_LOG_ERR, 4637c478bd9Sstevel@tonic-gate "version mismatch on plugin"); 4647c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 4657c478bd9Sstevel@tonic-gate return SASL_BADVERS; 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 4687c478bd9Sstevel@tonic-gate /* Check plugins to make sure mech_name is non-NULL */ 4697c478bd9Sstevel@tonic-gate for (lupe=0;lupe < plugcount ;lupe++) { 4707c478bd9Sstevel@tonic-gate if (pluglist[lupe].mech_name == NULL) 4717c478bd9Sstevel@tonic-gate break; 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate if (lupe < plugcount) { 4747c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 4757c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_plug_mutex); 4767c478bd9Sstevel@tonic-gate __sasl_log(gctx, gctx->server_global_callbacks.callbacks, 4777c478bd9Sstevel@tonic-gate SASL_LOG_ERR, "invalid server plugin %s", plugname); 4787c478bd9Sstevel@tonic-gate #else 4797c478bd9Sstevel@tonic-gate _sasl_log(NULL, SASL_LOG_ERR, "invalid server plugin %s", plugname); 4807c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 4817c478bd9Sstevel@tonic-gate return SASL_BADPROT; 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate for (lupe=0;lupe < plugcount ;lupe++) 4867c478bd9Sstevel@tonic-gate { 4877c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 4887c478bd9Sstevel@tonic-gate if (!load_mech(gctx, pluglist->mech_name)) { 4897c478bd9Sstevel@tonic-gate pluglist++; 4907c478bd9Sstevel@tonic-gate continue; 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate nplug++; 4937c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 4947c478bd9Sstevel@tonic-gate mech = sasl_ALLOC(sizeof(mechanism_t)); 4957c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 4967c478bd9Sstevel@tonic-gate if (! mech) { 4977c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_plug_mutex); 4987c478bd9Sstevel@tonic-gate return SASL_NOMEM; 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate mech->glob_context = pluglist->glob_context; 5027c478bd9Sstevel@tonic-gate #else 5037c478bd9Sstevel@tonic-gate if (! mech) return SASL_NOMEM; 5047c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate mech->plug=pluglist++; 5077c478bd9Sstevel@tonic-gate if(_sasl_strdup(plugname, &mech->plugname, NULL) != SASL_OK) { 5087c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 5097c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_plug_mutex); 5107c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 5117c478bd9Sstevel@tonic-gate sasl_FREE(mech); 5127c478bd9Sstevel@tonic-gate return SASL_NOMEM; 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate mech->version = version; 5157c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 5167c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */ 5177c478bd9Sstevel@tonic-gate /* CRYPT DELETE START */ 5187c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 5197c478bd9Sstevel@tonic-gate mech->sun_reg = sun_reg; 5207c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 5217c478bd9Sstevel@tonic-gate /* CRYPT DELETE END */ 5227c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */ 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate /* whether this mech actually has any users in it's db */ 5257c478bd9Sstevel@tonic-gate mech->condition = SASL_OK; 5267c478bd9Sstevel@tonic-gate #else 5277c478bd9Sstevel@tonic-gate /* whether this mech actually has any users in it's db */ 5287c478bd9Sstevel@tonic-gate mech->condition = result; /* SASL_OK or SASL_NOUSER */ 5297c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate mech->next = mechlist->mech_list; 5327c478bd9Sstevel@tonic-gate mechlist->mech_list = mech; 5337c478bd9Sstevel@tonic-gate mechlist->mech_length++; 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 5377c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_plug_mutex); 5387c478bd9Sstevel@tonic-gate return (nplug == 0) ? SASL_NOMECH : SASL_OK; 5397c478bd9Sstevel@tonic-gate #else 5407c478bd9Sstevel@tonic-gate return SASL_OK; 5417c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 5457c478bd9Sstevel@tonic-gate static int server_done(_sasl_global_context_t *gctx) { 5467c478bd9Sstevel@tonic-gate mech_list_t *mechlist = gctx->mechlist; 5477c478bd9Sstevel@tonic-gate _sasl_path_info_t *path_info, *p; 5487c478bd9Sstevel@tonic-gate #else 5497c478bd9Sstevel@tonic-gate static int server_done(void) { 5507c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 5517c478bd9Sstevel@tonic-gate mechanism_t *m; 5527c478bd9Sstevel@tonic-gate mechanism_t *prevm; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 5557c478bd9Sstevel@tonic-gate if(!gctx->sasl_server_active) 5567c478bd9Sstevel@tonic-gate return SASL_NOTINIT; 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&server_active_mutex) < 0) { 5597c478bd9Sstevel@tonic-gate return (SASL_FAIL); 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate gctx->sasl_server_active--; 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate if(gctx->sasl_server_active) { 5647c478bd9Sstevel@tonic-gate /* Don't de-init yet! Our refcount is nonzero. */ 5657c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_active_mutex); 5667c478bd9Sstevel@tonic-gate return SASL_CONTINUE; 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate #else 5697c478bd9Sstevel@tonic-gate if(!_sasl_server_active) 5707c478bd9Sstevel@tonic-gate return SASL_NOTINIT; 5717c478bd9Sstevel@tonic-gate else 5727c478bd9Sstevel@tonic-gate _sasl_server_active--; 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate if(_sasl_server_active) { 5757c478bd9Sstevel@tonic-gate /* Don't de-init yet! Our refcount is nonzero. */ 5767c478bd9Sstevel@tonic-gate return SASL_CONTINUE; 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate if (mechlist != NULL) 5817c478bd9Sstevel@tonic-gate { 5827c478bd9Sstevel@tonic-gate m=mechlist->mech_list; /* m point to beginning of the list */ 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate while (m!=NULL) 5857c478bd9Sstevel@tonic-gate { 5867c478bd9Sstevel@tonic-gate prevm=m; 5877c478bd9Sstevel@tonic-gate m=m->next; 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate if (prevm->plug->mech_free) { 5907c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 5917c478bd9Sstevel@tonic-gate prevm->plug->mech_free(prevm->glob_context, 5927c478bd9Sstevel@tonic-gate #else 5937c478bd9Sstevel@tonic-gate prevm->plug->mech_free(prevm->plug->glob_context, 5947c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 5957c478bd9Sstevel@tonic-gate mechlist->utils); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate sasl_FREE(prevm->plugname); 5997c478bd9Sstevel@tonic-gate sasl_FREE(prevm); 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate _sasl_free_utils(&mechlist->utils); 6027c478bd9Sstevel@tonic-gate sasl_MUTEX_FREE(mechlist->mutex); 6037c478bd9Sstevel@tonic-gate sasl_FREE(mechlist); 6047c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 6057c478bd9Sstevel@tonic-gate gctx->mechlist = NULL; 6067c478bd9Sstevel@tonic-gate #else 6077c478bd9Sstevel@tonic-gate mechlist = NULL; 6087c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate /* Free the auxprop plugins */ 6127c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 6137c478bd9Sstevel@tonic-gate _sasl_auxprop_free(gctx); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate gctx->server_global_callbacks.callbacks = NULL; 6167c478bd9Sstevel@tonic-gate gctx->server_global_callbacks.appname = NULL; 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate p = gctx->splug_path_info; 6197c478bd9Sstevel@tonic-gate while((path_info = p) != NULL) { 6207c478bd9Sstevel@tonic-gate sasl_FREE(path_info->path); 6217c478bd9Sstevel@tonic-gate p = path_info->next; 6227c478bd9Sstevel@tonic-gate sasl_FREE(path_info); 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate gctx->splug_path_info = NULL; 6257c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_active_mutex); 6267c478bd9Sstevel@tonic-gate #else 6277c478bd9Sstevel@tonic-gate _sasl_auxprop_free(); 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate global_callbacks.callbacks = NULL; 6307c478bd9Sstevel@tonic-gate global_callbacks.appname = NULL; 6317c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate return SASL_OK; 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate static int server_idle(sasl_conn_t *conn) 6377c478bd9Sstevel@tonic-gate { 6387c478bd9Sstevel@tonic-gate mechanism_t *m; 6397c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 6407c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx; 6417c478bd9Sstevel@tonic-gate mech_list_t *mechlist; 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate if (conn == NULL) 6447c478bd9Sstevel@tonic-gate gctx = _sasl_gbl_ctx(); 6457c478bd9Sstevel@tonic-gate else 6467c478bd9Sstevel@tonic-gate gctx = conn->gctx; 6477c478bd9Sstevel@tonic-gate mechlist = gctx->mechlist; 6487c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 6497c478bd9Sstevel@tonic-gate if (! mechlist) 6507c478bd9Sstevel@tonic-gate return 0; 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate for (m = mechlist->mech_list; 6537c478bd9Sstevel@tonic-gate m!=NULL; 6547c478bd9Sstevel@tonic-gate m = m->next) 6557c478bd9Sstevel@tonic-gate if (m->plug->idle 6567c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 6577c478bd9Sstevel@tonic-gate && m->plug->idle(m->glob_context, 6587c478bd9Sstevel@tonic-gate #else 6597c478bd9Sstevel@tonic-gate && m->plug->idle(m->plug->glob_context, 6607c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 6617c478bd9Sstevel@tonic-gate conn, 6627c478bd9Sstevel@tonic-gate conn ? ((sasl_server_conn_t *)conn)->sparams : NULL)) 6637c478bd9Sstevel@tonic-gate return 1; 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate return 0; 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 6697c478bd9Sstevel@tonic-gate static int load_config(_sasl_global_context_t *gctx, 6707c478bd9Sstevel@tonic-gate const sasl_callback_t *verifyfile_cb) 6717c478bd9Sstevel@tonic-gate { 6727c478bd9Sstevel@tonic-gate int result; 6737c478bd9Sstevel@tonic-gate const char *conf_to_config = NULL; 6747c478bd9Sstevel@tonic-gate const char *conf_file = NULL; 6757c478bd9Sstevel@tonic-gate int conf_len; 6767c478bd9Sstevel@tonic-gate sasl_global_callbacks_t global_callbacks = gctx->server_global_callbacks; 6777c478bd9Sstevel@tonic-gate char *alloc_file_name=NULL; 6787c478bd9Sstevel@tonic-gate int len; 6797c478bd9Sstevel@tonic-gate const sasl_callback_t *getconf_cb=NULL; 6807c478bd9Sstevel@tonic-gate struct stat buf; 6817c478bd9Sstevel@tonic-gate int full_file = 0; 6827c478bd9Sstevel@tonic-gate int file_exists = 0; 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate /* get the path to the plugins; for now the config file will reside there */ 6857c478bd9Sstevel@tonic-gate getconf_cb = _sasl_find_getconf_callback(global_callbacks.callbacks); 6867c478bd9Sstevel@tonic-gate if (getconf_cb==NULL) return SASL_BADPARAM; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate result = ((sasl_getpath_t *)(getconf_cb->proc))(getconf_cb->context, 6897c478bd9Sstevel@tonic-gate &conf_to_config); 6907c478bd9Sstevel@tonic-gate if (result!=SASL_OK) goto done; 6917c478bd9Sstevel@tonic-gate if (conf_to_config == NULL) conf_to_config = ""; 6927c478bd9Sstevel@tonic-gate else { 6937c478bd9Sstevel@tonic-gate if (stat(conf_to_config, &buf)) 6947c478bd9Sstevel@tonic-gate goto process_file; 6957c478bd9Sstevel@tonic-gate full_file = !S_ISDIR(buf.st_mode); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate if (!full_file) { 6997c478bd9Sstevel@tonic-gate conf_len = strlen(conf_to_config); 7007c478bd9Sstevel@tonic-gate len = strlen(conf_to_config)+2+ strlen(global_callbacks.appname)+5+1; 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate if (len > PATH_MAX ) { 7037c478bd9Sstevel@tonic-gate result = SASL_FAIL; 7047c478bd9Sstevel@tonic-gate goto done; 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate /* construct the filename for the config file */ 7087c478bd9Sstevel@tonic-gate alloc_file_name = sasl_ALLOC(len); 7097c478bd9Sstevel@tonic-gate if (! alloc_file_name) { 7107c478bd9Sstevel@tonic-gate result = SASL_NOMEM; 7117c478bd9Sstevel@tonic-gate goto done; 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate snprintf(alloc_file_name, len, "%.*s/%s.conf", conf_len, conf_to_config, 7157c478bd9Sstevel@tonic-gate global_callbacks.appname); 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate conf_file = full_file ? conf_to_config : alloc_file_name; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate if (full_file || stat(conf_file, &buf) == 0) 7217c478bd9Sstevel@tonic-gate file_exists = S_ISREG(buf.st_mode); 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate process_file: 7247c478bd9Sstevel@tonic-gate /* Check to see if anything has changed */ 7257c478bd9Sstevel@tonic-gate if (file_exists && gctx->config_path != NULL && 7267c478bd9Sstevel@tonic-gate strcmp(conf_file, gctx->config_path) == 0 && 7277c478bd9Sstevel@tonic-gate gctx->config_last_read == buf.st_mtime) { 7287c478bd9Sstevel@tonic-gate /* File has not changed */ 7297c478bd9Sstevel@tonic-gate goto done; 7307c478bd9Sstevel@tonic-gate } else if (gctx->config_path == NULL) { 7317c478bd9Sstevel@tonic-gate /* No new file, nothing has changed */ 7327c478bd9Sstevel@tonic-gate if (!file_exists) 7337c478bd9Sstevel@tonic-gate goto done; 7347c478bd9Sstevel@tonic-gate } else { 7357c478bd9Sstevel@tonic-gate sasl_config_free(gctx); 7367c478bd9Sstevel@tonic-gate if (!file_exists) { 7377c478bd9Sstevel@tonic-gate gctx->config_path = NULL; 7387c478bd9Sstevel@tonic-gate goto done; 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate gctx->config_last_read = buf.st_mtime; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate /* Ask the application if it's safe to use this file */ 7447c478bd9Sstevel@tonic-gate result = ((sasl_verifyfile_t *)(verifyfile_cb->proc))(verifyfile_cb->context, 7457c478bd9Sstevel@tonic-gate conf_file, SASL_VRFY_CONF); 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate /* returns continue if this file is to be skipped */ 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate /* returns SASL_CONTINUE if doesn't exist 7507c478bd9Sstevel@tonic-gate * if doesn't exist we can continue using default behavior 7517c478bd9Sstevel@tonic-gate */ 7527c478bd9Sstevel@tonic-gate if (result==SASL_OK) 7537c478bd9Sstevel@tonic-gate result=sasl_config_init(gctx, conf_file); 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate done: 7567c478bd9Sstevel@tonic-gate if (alloc_file_name) sasl_FREE(alloc_file_name); 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate return result; 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate #else 7617c478bd9Sstevel@tonic-gate static int load_config(const sasl_callback_t *verifyfile_cb) 7627c478bd9Sstevel@tonic-gate { 7637c478bd9Sstevel@tonic-gate int result; 7647c478bd9Sstevel@tonic-gate const char *path_to_config=NULL; 7657c478bd9Sstevel@tonic-gate const char *c; 7667c478bd9Sstevel@tonic-gate unsigned path_len; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate char *config_filename=NULL; 7697c478bd9Sstevel@tonic-gate int len; 7707c478bd9Sstevel@tonic-gate const sasl_callback_t *getpath_cb=NULL; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* get the path to the plugins; for now the config file will reside there */ 7737c478bd9Sstevel@tonic-gate getpath_cb=_sasl_find_getpath_callback( global_callbacks.callbacks ); 7747c478bd9Sstevel@tonic-gate if (getpath_cb==NULL) return SASL_BADPARAM; 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate /* getpath_cb->proc MUST be a sasl_getpath_t; if only c had a type 7777c478bd9Sstevel@tonic-gate system */ 7787c478bd9Sstevel@tonic-gate result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context, 7797c478bd9Sstevel@tonic-gate &path_to_config); 7807c478bd9Sstevel@tonic-gate if (result!=SASL_OK) goto done; 7817c478bd9Sstevel@tonic-gate if (path_to_config == NULL) path_to_config = ""; 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate c = strchr(path_to_config, PATHS_DELIMITER); 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate /* length = length of path + '/' + length of appname + ".conf" + 1 7867c478bd9Sstevel@tonic-gate for '\0' */ 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate if(c != NULL) 7897c478bd9Sstevel@tonic-gate path_len = c - path_to_config; 7907c478bd9Sstevel@tonic-gate else 7917c478bd9Sstevel@tonic-gate path_len = strlen(path_to_config); 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate len = path_len + 2 + strlen(global_callbacks.appname) + 5 + 1; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate if (len > PATH_MAX ) { 7967c478bd9Sstevel@tonic-gate result = SASL_FAIL; 7977c478bd9Sstevel@tonic-gate goto done; 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate /* construct the filename for the config file */ 8017c478bd9Sstevel@tonic-gate config_filename = sasl_ALLOC(len); 8027c478bd9Sstevel@tonic-gate if (! config_filename) { 8037c478bd9Sstevel@tonic-gate result = SASL_NOMEM; 8047c478bd9Sstevel@tonic-gate goto done; 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate snprintf(config_filename, len, "%.*s/%s.conf", path_len, path_to_config, 8087c478bd9Sstevel@tonic-gate global_callbacks.appname); 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate /* Ask the application if it's safe to use this file */ 8117c478bd9Sstevel@tonic-gate result = ((sasl_verifyfile_t *)(verifyfile_cb->proc))(verifyfile_cb->context, 8127c478bd9Sstevel@tonic-gate config_filename, SASL_VRFY_CONF); 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate /* returns continue if this file is to be skipped */ 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate /* returns SASL_CONTINUE if doesn't exist 8177c478bd9Sstevel@tonic-gate * if doesn't exist we can continue using default behavior 8187c478bd9Sstevel@tonic-gate */ 8197c478bd9Sstevel@tonic-gate if (result==SASL_OK) 8207c478bd9Sstevel@tonic-gate result=sasl_config_init(config_filename); 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate done: 8237c478bd9Sstevel@tonic-gate if (config_filename) sasl_FREE(config_filename); 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate return result; 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate /* 8307c478bd9Sstevel@tonic-gate * Verify that all the callbacks are valid 8317c478bd9Sstevel@tonic-gate */ 8327c478bd9Sstevel@tonic-gate static int verify_server_callbacks(const sasl_callback_t *callbacks) 8337c478bd9Sstevel@tonic-gate { 8347c478bd9Sstevel@tonic-gate if (callbacks == NULL) return SASL_OK; 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate while (callbacks->id != SASL_CB_LIST_END) { 8377c478bd9Sstevel@tonic-gate if (callbacks->proc==NULL) return SASL_FAIL; 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate callbacks++; 8407c478bd9Sstevel@tonic-gate } 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate return SASL_OK; 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_ 8467c478bd9Sstevel@tonic-gate static char *grab_field(char *line, char **eofield) 8477c478bd9Sstevel@tonic-gate { 8487c478bd9Sstevel@tonic-gate int d = 0; 8497c478bd9Sstevel@tonic-gate char *field; 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate while (isspace((int) *line)) line++; 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate /* find end of field */ 8547c478bd9Sstevel@tonic-gate while (line[d] && !isspace(((int) line[d]))) d++; 8557c478bd9Sstevel@tonic-gate field = sasl_ALLOC(d + 1); 8567c478bd9Sstevel@tonic-gate if (!field) { return NULL; } 8577c478bd9Sstevel@tonic-gate memcpy(field, line, d); 8587c478bd9Sstevel@tonic-gate field[d] = '\0'; 8597c478bd9Sstevel@tonic-gate *eofield = line + d; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate return field; 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate struct secflag_map_s { 8657c478bd9Sstevel@tonic-gate char *name; 8667c478bd9Sstevel@tonic-gate int value; 8677c478bd9Sstevel@tonic-gate }; 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate struct secflag_map_s secflag_map[] = { 8707c478bd9Sstevel@tonic-gate { "noplaintext", SASL_SEC_NOPLAINTEXT }, 8717c478bd9Sstevel@tonic-gate { "noactive", SASL_SEC_NOACTIVE }, 8727c478bd9Sstevel@tonic-gate { "nodictionary", SASL_SEC_NODICTIONARY }, 8737c478bd9Sstevel@tonic-gate { "forward_secrecy", SASL_SEC_FORWARD_SECRECY }, 8747c478bd9Sstevel@tonic-gate { "noanonymous", SASL_SEC_NOANONYMOUS }, 8757c478bd9Sstevel@tonic-gate { "pass_credentials", SASL_SEC_PASS_CREDENTIALS }, 8767c478bd9Sstevel@tonic-gate { "mutual_auth", SASL_SEC_MUTUAL_AUTH }, 8777c478bd9Sstevel@tonic-gate { NULL, 0x0 } 8787c478bd9Sstevel@tonic-gate }; 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate static int parse_mechlist_file(const char *mechlistfile) 8817c478bd9Sstevel@tonic-gate { 8827c478bd9Sstevel@tonic-gate FILE *f; 8837c478bd9Sstevel@tonic-gate char buf[1024]; 8847c478bd9Sstevel@tonic-gate char *t, *ptr; 8857c478bd9Sstevel@tonic-gate int r = 0; 8867c478bd9Sstevel@tonic-gate 887*004388ebScasper f = fopen(mechlistfile, "rF"); 8887c478bd9Sstevel@tonic-gate if (!f) return SASL_FAIL; 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate r = SASL_OK; 8917c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof(buf), f) != NULL) { 8927c478bd9Sstevel@tonic-gate mechanism_t *n = sasl_ALLOC(sizeof(mechanism_t)); 8937c478bd9Sstevel@tonic-gate sasl_server_plug_t *nplug; 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate if (n == NULL) { r = SASL_NOMEM; break; } 8967c478bd9Sstevel@tonic-gate n->version = SASL_SERVER_PLUG_VERSION; 8977c478bd9Sstevel@tonic-gate n->condition = SASL_CONTINUE; 8987c478bd9Sstevel@tonic-gate nplug = sasl_ALLOC(sizeof(sasl_server_plug_t)); 8997c478bd9Sstevel@tonic-gate if (nplug == NULL) { r = SASL_NOMEM; break; } 9007c478bd9Sstevel@tonic-gate memset(nplug, 0, sizeof(sasl_server_plug_t)); 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate /* each line is: 9037c478bd9Sstevel@tonic-gate plugin-file WS mech_name WS max_ssf *(WS security_flag) RET 9047c478bd9Sstevel@tonic-gate */ 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate /* grab file */ 9077c478bd9Sstevel@tonic-gate n->f = grab_field(buf, &ptr); 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate /* grab mech_name */ 9107c478bd9Sstevel@tonic-gate nplug->mech_name = grab_field(ptr, &ptr); 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate /* grab max_ssf */ 9137c478bd9Sstevel@tonic-gate nplug->max_ssf = strtol(ptr, &ptr, 10); 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate /* grab security flags */ 9167c478bd9Sstevel@tonic-gate while (*ptr != '\n') { 9177c478bd9Sstevel@tonic-gate struct secflag_map_s *map; 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate /* read security flag */ 9207c478bd9Sstevel@tonic-gate t = grab_field(ptr, &ptr); 9217c478bd9Sstevel@tonic-gate map = secflag_map; 9227c478bd9Sstevel@tonic-gate while (map->name) { 9237c478bd9Sstevel@tonic-gate if (!strcasecmp(t, map->name)) { 9247c478bd9Sstevel@tonic-gate nplug->security_flags |= map->value; 9257c478bd9Sstevel@tonic-gate break; 9267c478bd9Sstevel@tonic-gate } 9277c478bd9Sstevel@tonic-gate map++; 9287c478bd9Sstevel@tonic-gate } 9297c478bd9Sstevel@tonic-gate if (!map->name) { 9307c478bd9Sstevel@tonic-gate _sasl_log(NULL, SASL_LOG_ERR, 9317c478bd9Sstevel@tonic-gate "%s: couldn't identify flag '%s'", 9327c478bd9Sstevel@tonic-gate nplug->mech_name, t); 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate free(t); 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate /* insert mechanism into mechlist */ 9387c478bd9Sstevel@tonic-gate n->plug = nplug; 9397c478bd9Sstevel@tonic-gate n->next = mechlist->mech_list; 9407c478bd9Sstevel@tonic-gate mechlist->mech_list = n; 9417c478bd9Sstevel@tonic-gate mechlist->mech_length++; 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate fclose(f); 9457c478bd9Sstevel@tonic-gate return r; 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */ 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 9507c478bd9Sstevel@tonic-gate static int _load_server_plugins(_sasl_global_context_t *gctx) 9517c478bd9Sstevel@tonic-gate { 9527c478bd9Sstevel@tonic-gate int ret; 9537c478bd9Sstevel@tonic-gate const add_plugin_list_t _ep_list[] = { 9547c478bd9Sstevel@tonic-gate { "sasl_server_plug_init", (add_plugin_t *)_sasl_server_add_plugin }, 9557c478bd9Sstevel@tonic-gate { "sasl_auxprop_plug_init", (add_plugin_t *)_sasl_auxprop_add_plugin }, 9567c478bd9Sstevel@tonic-gate { "sasl_canonuser_init", (add_plugin_t *)_sasl_canonuser_add_plugin }, 9577c478bd9Sstevel@tonic-gate { NULL, NULL } 9587c478bd9Sstevel@tonic-gate }; 9597c478bd9Sstevel@tonic-gate const sasl_callback_t *callbacks = gctx->server_global_callbacks.callbacks; 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate ret = _sasl_load_plugins(gctx, 1, _ep_list, 9627c478bd9Sstevel@tonic-gate _sasl_find_getpath_callback(callbacks), 9637c478bd9Sstevel@tonic-gate _sasl_find_verifyfile_callback(callbacks)); 9647c478bd9Sstevel@tonic-gate return (ret); 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate /* initialize server drivers, done once per process 9697c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 9707c478bd9Sstevel@tonic-gate * callbacks -- callbacks for all server connections 9717c478bd9Sstevel@tonic-gate * appname -- name of calling application (for config) 9727c478bd9Sstevel@tonic-gate #else 9737c478bd9Sstevel@tonic-gate * callbacks -- callbacks for all server connections; must include 9747c478bd9Sstevel@tonic-gate * getopt callback 9757c478bd9Sstevel@tonic-gate * appname -- name of calling application (for lower level logging) 9767c478bd9Sstevel@tonic-gate * results: 9777c478bd9Sstevel@tonic-gate * state -- server state 9787c478bd9Sstevel@tonic-gate #endif 9797c478bd9Sstevel@tonic-gate * returns: 9807c478bd9Sstevel@tonic-gate * SASL_OK -- success 9817c478bd9Sstevel@tonic-gate * SASL_BADPARAM -- error in config file 9827c478bd9Sstevel@tonic-gate * SASL_NOMEM -- memory failure 9837c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_ 9847c478bd9Sstevel@tonic-gate * SASL_BADVERS -- Mechanism version mismatch 9857c478bd9Sstevel@tonic-gate #endif 9867c478bd9Sstevel@tonic-gate */ 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate int sasl_server_init(const sasl_callback_t *callbacks, 9897c478bd9Sstevel@tonic-gate const char *appname) 9907c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 9917c478bd9Sstevel@tonic-gate { 9927c478bd9Sstevel@tonic-gate return _sasl_server_init(NULL, callbacks, appname); 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate int _sasl_server_init(void *ctx, const sasl_callback_t *callbacks, 9967c478bd9Sstevel@tonic-gate const char *appname) 9977c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 9987c478bd9Sstevel@tonic-gate { 9997c478bd9Sstevel@tonic-gate int ret; 10007c478bd9Sstevel@tonic-gate const sasl_callback_t *vf; 10017c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 10027c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx; 10037c478bd9Sstevel@tonic-gate #else 10047c478bd9Sstevel@tonic-gate const char *pluginfile = NULL; 10057c478bd9Sstevel@tonic-gate #ifdef PIC 10067c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt; 10077c478bd9Sstevel@tonic-gate void *context; 10087c478bd9Sstevel@tonic-gate #endif 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate const add_plugin_list_t ep_list[] = { 10117c478bd9Sstevel@tonic-gate { "sasl_server_plug_init", (add_plugin_t *)sasl_server_add_plugin }, 10127c478bd9Sstevel@tonic-gate { "sasl_auxprop_plug_init", (add_plugin_t *)sasl_auxprop_add_plugin }, 10137c478bd9Sstevel@tonic-gate { "sasl_canonuser_init", (add_plugin_t *)sasl_canonuser_add_plugin }, 10147c478bd9Sstevel@tonic-gate { NULL, NULL } 10157c478bd9Sstevel@tonic-gate }; 10167c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate /* we require the appname to be non-null and short enough to be a path */ 10197c478bd9Sstevel@tonic-gate if (!appname || strlen(appname) >= PATH_MAX) 10207c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 10237c478bd9Sstevel@tonic-gate /* Process only one _sasl_server_init() at a time */ 10247c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&init_server_mutex) < 0) 10257c478bd9Sstevel@tonic-gate return (SASL_FAIL); 10267c478bd9Sstevel@tonic-gate if (LOCK_MUTEX(&server_active_mutex) < 0) 10277c478bd9Sstevel@tonic-gate return (SASL_FAIL); 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active) { 10307c478bd9Sstevel@tonic-gate /* We're already active, just increase our refcount */ 10317c478bd9Sstevel@tonic-gate /* xxx do something with the callback structure? */ 10327c478bd9Sstevel@tonic-gate gctx->sasl_server_active++; 10337c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_active_mutex); 10347c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_server_mutex); 10357c478bd9Sstevel@tonic-gate return SASL_OK; 10367c478bd9Sstevel@tonic-gate } 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate ret = _sasl_common_init(gctx, &gctx->server_global_callbacks, 1); 10397c478bd9Sstevel@tonic-gate if (ret != SASL_OK) { 10407c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_active_mutex); 10417c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_server_mutex); 10427c478bd9Sstevel@tonic-gate return ret; 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate #else 10457c478bd9Sstevel@tonic-gate if (_sasl_server_active) { 10467c478bd9Sstevel@tonic-gate /* We're already active, just increase our refcount */ 10477c478bd9Sstevel@tonic-gate /* xxx do something with the callback structure? */ 10487c478bd9Sstevel@tonic-gate _sasl_server_active++; 10497c478bd9Sstevel@tonic-gate return SASL_OK; 10507c478bd9Sstevel@tonic-gate } 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate ret = _sasl_common_init(&global_callbacks); 10537c478bd9Sstevel@tonic-gate if (ret != SASL_OK) 10547c478bd9Sstevel@tonic-gate return ret; 10557c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate /* verify that the callbacks look ok */ 10587c478bd9Sstevel@tonic-gate ret = verify_server_callbacks(callbacks); 10597c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 10607c478bd9Sstevel@tonic-gate if (ret != SASL_OK) { 10617c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_active_mutex); 10627c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_server_mutex); 10637c478bd9Sstevel@tonic-gate return ret; 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate gctx->server_global_callbacks.callbacks = callbacks; 10677c478bd9Sstevel@tonic-gate gctx->server_global_callbacks.appname = appname; 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate /* If we fail now, we have to call server_done */ 10707c478bd9Sstevel@tonic-gate gctx->sasl_server_active = 1; 10717c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&server_active_mutex); 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate /* allocate mechlist and set it to empty */ 10747c478bd9Sstevel@tonic-gate gctx->mechlist = sasl_ALLOC(sizeof(mech_list_t)); 10757c478bd9Sstevel@tonic-gate if (gctx->mechlist == NULL) { 10767c478bd9Sstevel@tonic-gate server_done(gctx); 10777c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_server_mutex); 10787c478bd9Sstevel@tonic-gate return SASL_NOMEM; 10797c478bd9Sstevel@tonic-gate } 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate ret = init_mechlist(gctx); 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate if (ret != SASL_OK) { 10847c478bd9Sstevel@tonic-gate server_done(gctx); 10857c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_server_mutex); 10867c478bd9Sstevel@tonic-gate return ret; 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate #else 10897c478bd9Sstevel@tonic-gate if (ret != SASL_OK) 10907c478bd9Sstevel@tonic-gate return ret; 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate global_callbacks.callbacks = callbacks; 10937c478bd9Sstevel@tonic-gate global_callbacks.appname = appname; 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate /* If we fail now, we have to call server_done */ 10967c478bd9Sstevel@tonic-gate _sasl_server_active = 1; 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate /* allocate mechlist and set it to empty */ 10997c478bd9Sstevel@tonic-gate mechlist = sasl_ALLOC(sizeof(mech_list_t)); 11007c478bd9Sstevel@tonic-gate if (mechlist == NULL) { 11017c478bd9Sstevel@tonic-gate server_done(); 11027c478bd9Sstevel@tonic-gate return SASL_NOMEM; 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate ret = init_mechlist(); 11067c478bd9Sstevel@tonic-gate if (ret != SASL_OK) { 11077c478bd9Sstevel@tonic-gate server_done(); 11087c478bd9Sstevel@tonic-gate return ret; 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate vf = _sasl_find_verifyfile_callback(callbacks); 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate /* load config file if applicable */ 11157c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 11167c478bd9Sstevel@tonic-gate ret = load_config(gctx, vf); 11177c478bd9Sstevel@tonic-gate if ((ret != SASL_OK) && (ret != SASL_CONTINUE)) { 11187c478bd9Sstevel@tonic-gate server_done(gctx); 11197c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_server_mutex); 11207c478bd9Sstevel@tonic-gate #else 11217c478bd9Sstevel@tonic-gate ret = load_config(vf); 11227c478bd9Sstevel@tonic-gate if ((ret != SASL_OK) && (ret != SASL_CONTINUE)) { 11237c478bd9Sstevel@tonic-gate server_done(); 11247c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 11257c478bd9Sstevel@tonic-gate return ret; 11267c478bd9Sstevel@tonic-gate } 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate /* load internal plugins */ 11297c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 11307c478bd9Sstevel@tonic-gate _sasl_server_add_plugin(gctx, "EXTERNAL", &external_server_plug_init); 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate /* NOTE: plugin_list option not supported in SUN SDK */ 11337c478bd9Sstevel@tonic-gate { 11347c478bd9Sstevel@tonic-gate #else 11357c478bd9Sstevel@tonic-gate sasl_server_add_plugin("EXTERNAL", &external_server_plug_init); 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate #ifdef PIC 11387c478bd9Sstevel@tonic-gate /* delayed loading of plugins? (DSO only, as it doesn't 11397c478bd9Sstevel@tonic-gate * make much [any] sense to delay in the static library case) */ 11407c478bd9Sstevel@tonic-gate if (_sasl_getcallback(NULL, SASL_CB_GETOPT, &getopt, &context) 11417c478bd9Sstevel@tonic-gate == SASL_OK) { 11427c478bd9Sstevel@tonic-gate /* No sasl_conn_t was given to getcallback, so we provide the 11437c478bd9Sstevel@tonic-gate * global callbacks structure */ 11447c478bd9Sstevel@tonic-gate ret = getopt(&global_callbacks, NULL, "plugin_list", &pluginfile, NULL); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate #endif 11477c478bd9Sstevel@tonic-gate 11487c478bd9Sstevel@tonic-gate if (pluginfile != NULL) { 11497c478bd9Sstevel@tonic-gate /* this file should contain a list of plugins available. 11507c478bd9Sstevel@tonic-gate we'll load on demand. */ 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate /* Ask the application if it's safe to use this file */ 11537c478bd9Sstevel@tonic-gate ret = ((sasl_verifyfile_t *)(vf->proc))(vf->context, 11547c478bd9Sstevel@tonic-gate pluginfile, 11557c478bd9Sstevel@tonic-gate SASL_VRFY_CONF); 11567c478bd9Sstevel@tonic-gate if (ret != SASL_OK) { 11577c478bd9Sstevel@tonic-gate _sasl_log(NULL, SASL_LOG_ERR, 11587c478bd9Sstevel@tonic-gate "unable to load plugin list %s: %z", pluginfile, ret); 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate if (ret == SASL_OK) { 11627c478bd9Sstevel@tonic-gate ret = parse_mechlist_file(pluginfile); 11637c478bd9Sstevel@tonic-gate } 11647c478bd9Sstevel@tonic-gate } else { 11657c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 11667c478bd9Sstevel@tonic-gate /* load all plugins now */ 11677c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 11687c478bd9Sstevel@tonic-gate ret = _load_server_plugins(gctx); 11697c478bd9Sstevel@tonic-gate #else 11707c478bd9Sstevel@tonic-gate ret = _sasl_load_plugins(ep_list, 11717c478bd9Sstevel@tonic-gate _sasl_find_getpath_callback(callbacks), 11727c478bd9Sstevel@tonic-gate _sasl_find_verifyfile_callback(callbacks)); 11737c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 11777c478bd9Sstevel@tonic-gate if (ret == SASL_OK) 11787c478bd9Sstevel@tonic-gate ret = _sasl_build_mechlist(gctx); 11797c478bd9Sstevel@tonic-gate if (ret == SASL_OK) { 11807c478bd9Sstevel@tonic-gate gctx->sasl_server_cleanup_hook = &server_done; 11817c478bd9Sstevel@tonic-gate gctx->sasl_server_idle_hook = &server_idle; 11827c478bd9Sstevel@tonic-gate } else { 11837c478bd9Sstevel@tonic-gate server_done(gctx); 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate UNLOCK_MUTEX(&init_server_mutex); 11867c478bd9Sstevel@tonic-gate #else 11877c478bd9Sstevel@tonic-gate if (ret == SASL_OK) { 11887c478bd9Sstevel@tonic-gate _sasl_server_cleanup_hook = &server_done; 11897c478bd9Sstevel@tonic-gate _sasl_server_idle_hook = &server_idle; 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate ret = _sasl_build_mechlist(); 11927c478bd9Sstevel@tonic-gate } else { 11937c478bd9Sstevel@tonic-gate server_done(); 11947c478bd9Sstevel@tonic-gate } 11957c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate return ret; 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate /* 12017c478bd9Sstevel@tonic-gate * Once we have the users plaintext password we 12027c478bd9Sstevel@tonic-gate * may want to transition them. That is put entries 12037c478bd9Sstevel@tonic-gate * for them in the passwd database for other 12047c478bd9Sstevel@tonic-gate * stronger mechanism 12057c478bd9Sstevel@tonic-gate * 12067c478bd9Sstevel@tonic-gate * for example PLAIN -> CRAM-MD5 12077c478bd9Sstevel@tonic-gate */ 12087c478bd9Sstevel@tonic-gate static int 12097c478bd9Sstevel@tonic-gate _sasl_transition(sasl_conn_t * conn, 12107c478bd9Sstevel@tonic-gate const char * pass, 12117c478bd9Sstevel@tonic-gate unsigned passlen) 12127c478bd9Sstevel@tonic-gate { 12137c478bd9Sstevel@tonic-gate const char *dotrans = "n"; 12147c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt; 12157c478bd9Sstevel@tonic-gate int result = SASL_OK; 12167c478bd9Sstevel@tonic-gate void *context; 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate if (! conn) 12197c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate if (! conn->oparams.authid) 12227c478bd9Sstevel@tonic-gate PARAMERROR(conn); 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate /* check if this is enabled: default to false */ 12257c478bd9Sstevel@tonic-gate if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) 12267c478bd9Sstevel@tonic-gate { 12277c478bd9Sstevel@tonic-gate getopt(context, NULL, "auto_transition", &dotrans, NULL); 12287c478bd9Sstevel@tonic-gate if (dotrans == NULL) dotrans = "n"; 12297c478bd9Sstevel@tonic-gate } 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate if (*dotrans == '1' || *dotrans == 'y' || 12327c478bd9Sstevel@tonic-gate (*dotrans == 'o' && dotrans[1] == 'n') || *dotrans == 't') { 12337c478bd9Sstevel@tonic-gate /* ok, it's on! */ 12347c478bd9Sstevel@tonic-gate result = sasl_setpass(conn, 12357c478bd9Sstevel@tonic-gate conn->oparams.authid, 12367c478bd9Sstevel@tonic-gate pass, 12377c478bd9Sstevel@tonic-gate passlen, 12387c478bd9Sstevel@tonic-gate NULL, 0, 0); 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate RETURN(conn,result); 12427c478bd9Sstevel@tonic-gate } 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate /* create context for a single SASL connection 12467c478bd9Sstevel@tonic-gate * service -- registered name of the service using SASL (e.g. "imap") 12477c478bd9Sstevel@tonic-gate * serverFQDN -- Fully qualified domain name of server. NULL means use 12487c478bd9Sstevel@tonic-gate * gethostname() or equivalent. 12497c478bd9Sstevel@tonic-gate * Useful for multi-homed servers. 12507c478bd9Sstevel@tonic-gate * user_realm -- permits multiple user realms on server, NULL = default 12517c478bd9Sstevel@tonic-gate * iplocalport -- server IPv4/IPv6 domain literal string with port 12527c478bd9Sstevel@tonic-gate * (if NULL, then mechanisms requiring IPaddr are disabled) 12537c478bd9Sstevel@tonic-gate * ipremoteport -- client IPv4/IPv6 domain literal string with port 12547c478bd9Sstevel@tonic-gate * (if NULL, then mechanisms requiring IPaddr are disabled) 12557c478bd9Sstevel@tonic-gate * callbacks -- callbacks (e.g., authorization, lang, new getopt context) 12567c478bd9Sstevel@tonic-gate * flags -- usage flags (see above) 12577c478bd9Sstevel@tonic-gate * returns: 12587c478bd9Sstevel@tonic-gate * pconn -- new connection context 12597c478bd9Sstevel@tonic-gate * 12607c478bd9Sstevel@tonic-gate * returns: 12617c478bd9Sstevel@tonic-gate * SASL_OK -- success 12627c478bd9Sstevel@tonic-gate * SASL_NOMEM -- not enough memory 12637c478bd9Sstevel@tonic-gate */ 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate int sasl_server_new(const char *service, 12667c478bd9Sstevel@tonic-gate const char *serverFQDN, 12677c478bd9Sstevel@tonic-gate const char *user_realm, 12687c478bd9Sstevel@tonic-gate const char *iplocalport, 12697c478bd9Sstevel@tonic-gate const char *ipremoteport, 12707c478bd9Sstevel@tonic-gate const sasl_callback_t *callbacks, 12717c478bd9Sstevel@tonic-gate unsigned flags, 12727c478bd9Sstevel@tonic-gate sasl_conn_t **pconn) 12737c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 12747c478bd9Sstevel@tonic-gate { 12757c478bd9Sstevel@tonic-gate return _sasl_server_new(NULL, service, serverFQDN, user_realm, iplocalport, 12767c478bd9Sstevel@tonic-gate ipremoteport, callbacks, flags, pconn); 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate int _sasl_server_new(void *ctx, 12807c478bd9Sstevel@tonic-gate const char *service, 12817c478bd9Sstevel@tonic-gate const char *serverFQDN, 12827c478bd9Sstevel@tonic-gate const char *user_realm, 12837c478bd9Sstevel@tonic-gate const char *iplocalport, 12847c478bd9Sstevel@tonic-gate const char *ipremoteport, 12857c478bd9Sstevel@tonic-gate const sasl_callback_t *callbacks, 12867c478bd9Sstevel@tonic-gate unsigned flags, 12877c478bd9Sstevel@tonic-gate sasl_conn_t **pconn) 12887c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 12897c478bd9Sstevel@tonic-gate { 12907c478bd9Sstevel@tonic-gate int result; 12917c478bd9Sstevel@tonic-gate sasl_server_conn_t *serverconn; 12927c478bd9Sstevel@tonic-gate sasl_utils_t *utils; 12937c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt; 12947c478bd9Sstevel@tonic-gate void *context; 12957c478bd9Sstevel@tonic-gate const char *log_level; 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 12987c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = (ctx == NULL) ? _sasl_gbl_ctx() : ctx; 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT; 13017c478bd9Sstevel@tonic-gate #else 13027c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT; 13037c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 13047c478bd9Sstevel@tonic-gate if (! pconn) return SASL_FAIL; 13057c478bd9Sstevel@tonic-gate if (! service) return SASL_FAIL; 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate *pconn=sasl_ALLOC(sizeof(sasl_server_conn_t)); 13087c478bd9Sstevel@tonic-gate if (*pconn==NULL) return SASL_NOMEM; 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate memset(*pconn, 0, sizeof(sasl_server_conn_t)); 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 13137c478bd9Sstevel@tonic-gate (*pconn)->gctx = gctx; 13147c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate serverconn = (sasl_server_conn_t *)*pconn; 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate /* make sparams */ 13197c478bd9Sstevel@tonic-gate serverconn->sparams=sasl_ALLOC(sizeof(sasl_server_params_t)); 13207c478bd9Sstevel@tonic-gate if (serverconn->sparams==NULL) 13217c478bd9Sstevel@tonic-gate MEMERROR(*pconn); 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate memset(serverconn->sparams, 0, sizeof(sasl_server_params_t)); 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate (*pconn)->destroy_conn = &server_dispose; 13267c478bd9Sstevel@tonic-gate result = _sasl_conn_init(*pconn, service, flags, SASL_CONN_SERVER, 13277c478bd9Sstevel@tonic-gate &server_idle, serverFQDN, 13287c478bd9Sstevel@tonic-gate iplocalport, ipremoteport, 13297c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 13307c478bd9Sstevel@tonic-gate callbacks, &gctx->server_global_callbacks); 13317c478bd9Sstevel@tonic-gate #else 13327c478bd9Sstevel@tonic-gate callbacks, &global_callbacks); 13337c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 13347c478bd9Sstevel@tonic-gate if (result != SASL_OK) 13357c478bd9Sstevel@tonic-gate goto done_error; 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate /* set util functions - need to do rest */ 13397c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 13407c478bd9Sstevel@tonic-gate utils=_sasl_alloc_utils(gctx, *pconn, &gctx->server_global_callbacks); 13417c478bd9Sstevel@tonic-gate #else 13427c478bd9Sstevel@tonic-gate utils=_sasl_alloc_utils(*pconn, &global_callbacks); 13437c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 13447c478bd9Sstevel@tonic-gate if (!utils) { 13457c478bd9Sstevel@tonic-gate result = SASL_NOMEM; 13467c478bd9Sstevel@tonic-gate goto done_error; 13477c478bd9Sstevel@tonic-gate } 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 13507c478bd9Sstevel@tonic-gate utils->checkpass = &_sasl_checkpass; 13517c478bd9Sstevel@tonic-gate #else /* _SUN_SDK_ */ 13527c478bd9Sstevel@tonic-gate utils->checkpass = &sasl_checkpass; 13537c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate /* Setup the propctx -> We'll assume the default size */ 13567c478bd9Sstevel@tonic-gate serverconn->sparams->propctx=prop_new(0); 13577c478bd9Sstevel@tonic-gate if(!serverconn->sparams->propctx) { 13587c478bd9Sstevel@tonic-gate result = SASL_NOMEM; 13597c478bd9Sstevel@tonic-gate goto done_error; 13607c478bd9Sstevel@tonic-gate } 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate serverconn->sparams->service = (*pconn)->service; 13637c478bd9Sstevel@tonic-gate serverconn->sparams->servicelen = strlen((*pconn)->service); 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 13667c478bd9Sstevel@tonic-gate serverconn->sparams->appname = gctx->server_global_callbacks.appname; 13677c478bd9Sstevel@tonic-gate serverconn->sparams->applen = strlen(gctx->server_global_callbacks.appname); 13687c478bd9Sstevel@tonic-gate #else 13697c478bd9Sstevel@tonic-gate serverconn->sparams->appname = global_callbacks.appname; 13707c478bd9Sstevel@tonic-gate serverconn->sparams->applen = strlen(global_callbacks.appname); 13717c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate serverconn->sparams->serverFQDN = (*pconn)->serverFQDN; 13747c478bd9Sstevel@tonic-gate serverconn->sparams->slen = strlen((*pconn)->serverFQDN); 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate if (user_realm) { 13777c478bd9Sstevel@tonic-gate result = _sasl_strdup(user_realm, &serverconn->user_realm, NULL); 13787c478bd9Sstevel@tonic-gate serverconn->sparams->urlen = strlen(user_realm); 13797c478bd9Sstevel@tonic-gate serverconn->sparams->user_realm = serverconn->user_realm; 13807c478bd9Sstevel@tonic-gate } else { 13817c478bd9Sstevel@tonic-gate serverconn->user_realm = NULL; 13827c478bd9Sstevel@tonic-gate /* the sparams is already zeroed */ 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 13867c478bd9Sstevel@tonic-gate serverconn->sparams->iplocalport = (*pconn)->iplocalport; 13877c478bd9Sstevel@tonic-gate serverconn->sparams->iploclen = strlen((*pconn)->iplocalport); 13887c478bd9Sstevel@tonic-gate serverconn->sparams->ipremoteport = (*pconn)->ipremoteport; 13897c478bd9Sstevel@tonic-gate serverconn->sparams->ipremlen = strlen((*pconn)->ipremoteport); 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate serverconn->sparams->callbacks = callbacks; 13927c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate log_level = NULL; 13957c478bd9Sstevel@tonic-gate if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { 13967c478bd9Sstevel@tonic-gate getopt(context, NULL, "log_level", &log_level, NULL); 13977c478bd9Sstevel@tonic-gate } 13987c478bd9Sstevel@tonic-gate serverconn->sparams->log_level = log_level ? atoi(log_level) : SASL_LOG_ERR; 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate serverconn->sparams->utils = utils; 14017c478bd9Sstevel@tonic-gate serverconn->sparams->transition = &_sasl_transition; 14027c478bd9Sstevel@tonic-gate serverconn->sparams->canon_user = &_sasl_canon_user; 14037c478bd9Sstevel@tonic-gate serverconn->sparams->props = serverconn->base.props; 14047c478bd9Sstevel@tonic-gate serverconn->sparams->flags = flags; 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate if(result == SASL_OK) return SASL_OK; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate done_error: 14097c478bd9Sstevel@tonic-gate _sasl_conn_dispose(*pconn); 14107c478bd9Sstevel@tonic-gate sasl_FREE(*pconn); 14117c478bd9Sstevel@tonic-gate *pconn = NULL; 14127c478bd9Sstevel@tonic-gate return result; 14137c478bd9Sstevel@tonic-gate } 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate /* 14167c478bd9Sstevel@tonic-gate * The rule is: 14177c478bd9Sstevel@tonic-gate * IF mech strength + external strength < min ssf THEN FAIL 14187c478bd9Sstevel@tonic-gate * We also have to look at the security properties and make sure 14197c478bd9Sstevel@tonic-gate * that this mechanism has everything we want 14207c478bd9Sstevel@tonic-gate */ 14217c478bd9Sstevel@tonic-gate static int mech_permitted(sasl_conn_t *conn, 14227c478bd9Sstevel@tonic-gate mechanism_t *mech) 14237c478bd9Sstevel@tonic-gate { 14247c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn = (sasl_server_conn_t *)conn; 14257c478bd9Sstevel@tonic-gate const sasl_server_plug_t *plug; 14267c478bd9Sstevel@tonic-gate int myflags; 14277c478bd9Sstevel@tonic-gate context_list_t *cur; 14287c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt; 14297c478bd9Sstevel@tonic-gate void *context; 14307c478bd9Sstevel@tonic-gate sasl_ssf_t minssf = 0; 14317c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 14327c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx; 14337c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate if(!conn) return 0; 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 14387c478bd9Sstevel@tonic-gate gctx = conn->gctx; 14397c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate if(! mech || ! mech->plug) { 14427c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 14437c478bd9Sstevel@tonic-gate if(conn) _sasl_log(conn, SASL_LOG_WARN, "Parameter error"); 14447c478bd9Sstevel@tonic-gate #else 14457c478bd9Sstevel@tonic-gate PARAMERROR(conn); 14467c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 14477c478bd9Sstevel@tonic-gate return 0; 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate plug = mech->plug; 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate /* get the list of allowed mechanisms (default = all) */ 14537c478bd9Sstevel@tonic-gate if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) 14547c478bd9Sstevel@tonic-gate == SASL_OK) { 14557c478bd9Sstevel@tonic-gate const char *mlist = NULL; 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate getopt(context, NULL, "mech_list", &mlist, NULL); 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate /* if we have a list, check the plugin against it */ 14607c478bd9Sstevel@tonic-gate if (mlist) { 14617c478bd9Sstevel@tonic-gate const char *cp; 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate while (*mlist) { 14647c478bd9Sstevel@tonic-gate for (cp = mlist; *cp && !isspace((int) *cp); cp++); 14657c478bd9Sstevel@tonic-gate if (((size_t) (cp - mlist) == strlen(plug->mech_name)) && 14667c478bd9Sstevel@tonic-gate !strncasecmp(mlist, plug->mech_name, 14677c478bd9Sstevel@tonic-gate strlen(plug->mech_name))) { 14687c478bd9Sstevel@tonic-gate break; 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate mlist = cp; 14717c478bd9Sstevel@tonic-gate while (*mlist && isspace((int) *mlist)) mlist++; 14727c478bd9Sstevel@tonic-gate } 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate if (!*mlist) return 0; /* reached EOS -> not in our list */ 14757c478bd9Sstevel@tonic-gate } 14767c478bd9Sstevel@tonic-gate } 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate /* setup parameters for the call to mech_avail */ 14797c478bd9Sstevel@tonic-gate s_conn->sparams->serverFQDN=conn->serverFQDN; 14807c478bd9Sstevel@tonic-gate s_conn->sparams->service=conn->service; 14817c478bd9Sstevel@tonic-gate s_conn->sparams->user_realm=s_conn->user_realm; 14827c478bd9Sstevel@tonic-gate s_conn->sparams->props=conn->props; 14837c478bd9Sstevel@tonic-gate s_conn->sparams->external_ssf=conn->external.ssf; 14847c478bd9Sstevel@tonic-gate 14857c478bd9Sstevel@tonic-gate /* Check if we have banished this one already */ 14867c478bd9Sstevel@tonic-gate for(cur = s_conn->mech_contexts; cur; cur=cur->next) { 14877c478bd9Sstevel@tonic-gate if(cur->mech == mech) { 14887c478bd9Sstevel@tonic-gate /* If it's not mech_avail'd, then stop now */ 14897c478bd9Sstevel@tonic-gate if(!cur->context) return 0; 14907c478bd9Sstevel@tonic-gate break; 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate } 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */ 14957c478bd9Sstevel@tonic-gate /* CRYPT DELETE START */ 14967c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 14977c478bd9Sstevel@tonic-gate if (!mech->sun_reg) { 14987c478bd9Sstevel@tonic-gate s_conn->sparams->props.min_ssf = 0; 14997c478bd9Sstevel@tonic-gate s_conn->sparams->props.max_ssf = 0; 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate s_conn->base.sun_reg = mech->sun_reg; 15027c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 15037c478bd9Sstevel@tonic-gate /* CRYPT DELETE END */ 15047c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */ 15057c478bd9Sstevel@tonic-gate if (conn->props.min_ssf < conn->external.ssf) { 15067c478bd9Sstevel@tonic-gate minssf = 0; 15077c478bd9Sstevel@tonic-gate } else { 15087c478bd9Sstevel@tonic-gate minssf = conn->props.min_ssf - conn->external.ssf; 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate /* Generic mechanism */ 15127c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */ 15137c478bd9Sstevel@tonic-gate /* CRYPT DELETE START */ 15147c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 15157c478bd9Sstevel@tonic-gate /* If not SUN supplied mech, it has no strength */ 15167c478bd9Sstevel@tonic-gate if (plug->max_ssf < minssf || (minssf > 0 && !mech->sun_reg)) { 15177c478bd9Sstevel@tonic-gate #else 15187c478bd9Sstevel@tonic-gate /* CRYPT DELETE END */ 15197c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */ 15207c478bd9Sstevel@tonic-gate if (plug->max_ssf < minssf) { 15217c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */ 15227c478bd9Sstevel@tonic-gate /* CRYPT DELETE START */ 15237c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 15247c478bd9Sstevel@tonic-gate /* CRYPT DELETE END */ 15257c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */ 15267c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 15277c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, 15287c478bd9Sstevel@tonic-gate gettext("mech %s is too weak"), plug->mech_name); 15297c478bd9Sstevel@tonic-gate #else 15307c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, 15317c478bd9Sstevel@tonic-gate "mech %s is too weak", plug->mech_name); 15327c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 15337c478bd9Sstevel@tonic-gate return 0; /* too weak */ 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate 15367c478bd9Sstevel@tonic-gate context = NULL; 15377c478bd9Sstevel@tonic-gate if(plug->mech_avail 15387c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 15397c478bd9Sstevel@tonic-gate && plug->mech_avail(mech->glob_context, 15407c478bd9Sstevel@tonic-gate #else 15417c478bd9Sstevel@tonic-gate && plug->mech_avail(plug->glob_context, 15427c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 15437c478bd9Sstevel@tonic-gate s_conn->sparams, (void **)&context) != SASL_OK ) { 15447c478bd9Sstevel@tonic-gate /* Mark this mech as no good for this connection */ 15457c478bd9Sstevel@tonic-gate cur = sasl_ALLOC(sizeof(context_list_t)); 15467c478bd9Sstevel@tonic-gate if(!cur) { 15477c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 15487c478bd9Sstevel@tonic-gate if(conn) _sasl_log(conn, SASL_LOG_WARN, "Out of Memory"); 15497c478bd9Sstevel@tonic-gate #else 15507c478bd9Sstevel@tonic-gate MEMERROR(conn); 15517c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 15527c478bd9Sstevel@tonic-gate return 0; 15537c478bd9Sstevel@tonic-gate } 15547c478bd9Sstevel@tonic-gate cur->context = NULL; 15557c478bd9Sstevel@tonic-gate cur->mech = mech; 15567c478bd9Sstevel@tonic-gate cur->next = s_conn->mech_contexts; 15577c478bd9Sstevel@tonic-gate s_conn->mech_contexts = cur; 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate /* Error should be set by mech_avail call */ 15607c478bd9Sstevel@tonic-gate return 0; 15617c478bd9Sstevel@tonic-gate } else if(context) { 15627c478bd9Sstevel@tonic-gate /* Save this context */ 15637c478bd9Sstevel@tonic-gate cur = sasl_ALLOC(sizeof(context_list_t)); 15647c478bd9Sstevel@tonic-gate if(!cur) { 15657c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 15667c478bd9Sstevel@tonic-gate if(conn) _sasl_log(conn, SASL_LOG_WARN, "Out of Memory"); 15677c478bd9Sstevel@tonic-gate #else 15687c478bd9Sstevel@tonic-gate MEMERROR(conn); 15697c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 15707c478bd9Sstevel@tonic-gate return 0; 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate cur->context = context; 15737c478bd9Sstevel@tonic-gate cur->mech = mech; 15747c478bd9Sstevel@tonic-gate cur->next = s_conn->mech_contexts; 15757c478bd9Sstevel@tonic-gate s_conn->mech_contexts = cur; 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate /* Generic mechanism */ 15797c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */ 15807c478bd9Sstevel@tonic-gate /* CRYPT DELETE START */ 15817c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 15827c478bd9Sstevel@tonic-gate /* If not SUN supplied mech, it has no strength */ 15837c478bd9Sstevel@tonic-gate if (plug->max_ssf < minssf || (minssf > 0 && !mech->sun_reg)) { 15847c478bd9Sstevel@tonic-gate #else 15857c478bd9Sstevel@tonic-gate /* CRYPT DELETE END */ 15867c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */ 15877c478bd9Sstevel@tonic-gate if (plug->max_ssf < minssf) { 15887c478bd9Sstevel@tonic-gate /* EXPORT DELETE START */ 15897c478bd9Sstevel@tonic-gate /* CRYPT DELETE START */ 15907c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 15917c478bd9Sstevel@tonic-gate /* CRYPT DELETE END */ 15927c478bd9Sstevel@tonic-gate /* EXPORT DELETE END */ 15937c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 15947c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, gettext("too weak")); 15957c478bd9Sstevel@tonic-gate #else 15967c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, "too weak"); 15977c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 15987c478bd9Sstevel@tonic-gate return 0; /* too weak */ 15997c478bd9Sstevel@tonic-gate } 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_ 16027c478bd9Sstevel@tonic-gate /* if there are no users in the secrets database we can't use this 16037c478bd9Sstevel@tonic-gate mechanism */ 16047c478bd9Sstevel@tonic-gate if (mech->condition == SASL_NOUSER) { 16057c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "no users in secrets db"); 16067c478bd9Sstevel@tonic-gate return 0; 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */ 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate /* Can it meet our features? */ 16117c478bd9Sstevel@tonic-gate if ((conn->flags & SASL_NEED_PROXY) && 16127c478bd9Sstevel@tonic-gate !(plug->features & SASL_FEAT_ALLOWS_PROXY)) { 16137c478bd9Sstevel@tonic-gate return 0; 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate /* security properties---if there are any flags that differ and are 16177c478bd9Sstevel@tonic-gate in what the connection are requesting, then fail */ 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate /* special case plaintext */ 16207c478bd9Sstevel@tonic-gate myflags = conn->props.security_flags; 16217c478bd9Sstevel@tonic-gate 16227c478bd9Sstevel@tonic-gate /* if there's an external layer this is no longer plaintext */ 16237c478bd9Sstevel@tonic-gate if ((conn->props.min_ssf <= conn->external.ssf) && 16247c478bd9Sstevel@tonic-gate (conn->external.ssf > 1)) { 16257c478bd9Sstevel@tonic-gate myflags &= ~SASL_SEC_NOPLAINTEXT; 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate /* do we want to special case SASL_SEC_PASS_CREDENTIALS? nah.. */ 16297c478bd9Sstevel@tonic-gate if (((myflags ^ plug->security_flags) & myflags) != 0) { 16307c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 16317c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, 16327c478bd9Sstevel@tonic-gate gettext("security flags do not match required")); 16337c478bd9Sstevel@tonic-gate #else 16347c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, 16357c478bd9Sstevel@tonic-gate "security flags do not match required"); 16367c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 16377c478bd9Sstevel@tonic-gate return 0; 16387c478bd9Sstevel@tonic-gate } 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate /* Check Features */ 16417c478bd9Sstevel@tonic-gate if(plug->features & SASL_FEAT_GETSECRET) { 16427c478bd9Sstevel@tonic-gate /* We no longer support sasl_server_{get,put}secret */ 16437c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 16447c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, 16457c478bd9Sstevel@tonic-gate "mech %s requires unprovided secret facility", 16467c478bd9Sstevel@tonic-gate plug->mech_name); 16477c478bd9Sstevel@tonic-gate #else 16487c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, 16497c478bd9Sstevel@tonic-gate "mech %s requires unprovided secret facility", 16507c478bd9Sstevel@tonic-gate plug->mech_name); 16517c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 16527c478bd9Sstevel@tonic-gate return 0; 16537c478bd9Sstevel@tonic-gate } 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate return 1; 16567c478bd9Sstevel@tonic-gate } 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate /* 16597c478bd9Sstevel@tonic-gate * make the authorization 16607c478bd9Sstevel@tonic-gate * 16617c478bd9Sstevel@tonic-gate */ 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate static int do_authorization(sasl_server_conn_t *s_conn) 16647c478bd9Sstevel@tonic-gate { 16657c478bd9Sstevel@tonic-gate int ret; 16667c478bd9Sstevel@tonic-gate sasl_authorize_t *authproc; 16677c478bd9Sstevel@tonic-gate void *auth_context; 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate /* now let's see if authname is allowed to proxy for username! */ 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate /* check the proxy callback */ 16727c478bd9Sstevel@tonic-gate if (_sasl_getcallback(&s_conn->base, SASL_CB_PROXY_POLICY, 16737c478bd9Sstevel@tonic-gate &authproc, &auth_context) != SASL_OK) { 16747c478bd9Sstevel@tonic-gate INTERROR(&s_conn->base, SASL_NOAUTHZ); 16757c478bd9Sstevel@tonic-gate } 16767c478bd9Sstevel@tonic-gate 16777c478bd9Sstevel@tonic-gate ret = authproc(&(s_conn->base), auth_context, 16787c478bd9Sstevel@tonic-gate s_conn->base.oparams.user, s_conn->base.oparams.ulen, 16797c478bd9Sstevel@tonic-gate s_conn->base.oparams.authid, s_conn->base.oparams.alen, 16807c478bd9Sstevel@tonic-gate s_conn->user_realm, 16817c478bd9Sstevel@tonic-gate (s_conn->user_realm ? strlen(s_conn->user_realm) : 0), 16827c478bd9Sstevel@tonic-gate s_conn->sparams->propctx); 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate RETURN(&s_conn->base, ret); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate /* start a mechanism exchange within a connection context 16897c478bd9Sstevel@tonic-gate * mech -- the mechanism name client requested 16907c478bd9Sstevel@tonic-gate * clientin -- client initial response (NUL terminated), NULL if empty 16917c478bd9Sstevel@tonic-gate * clientinlen -- length of initial response 16927c478bd9Sstevel@tonic-gate * serverout -- initial server challenge, NULL if done 16937c478bd9Sstevel@tonic-gate * (library handles freeing this string) 16947c478bd9Sstevel@tonic-gate * serveroutlen -- length of initial server challenge 16957c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 16967c478bd9Sstevel@tonic-gate * conn -- the sasl connection 16977c478bd9Sstevel@tonic-gate #else 16987c478bd9Sstevel@tonic-gate * output: 16997c478bd9Sstevel@tonic-gate * pconn -- the connection negotiation state on success 17007c478bd9Sstevel@tonic-gate #endif 17017c478bd9Sstevel@tonic-gate * 17027c478bd9Sstevel@tonic-gate * Same returns as sasl_server_step() or 17037c478bd9Sstevel@tonic-gate * SASL_NOMECH if mechanism not available. 17047c478bd9Sstevel@tonic-gate */ 17057c478bd9Sstevel@tonic-gate int sasl_server_start(sasl_conn_t *conn, 17067c478bd9Sstevel@tonic-gate const char *mech, 17077c478bd9Sstevel@tonic-gate const char *clientin, 17087c478bd9Sstevel@tonic-gate unsigned clientinlen, 17097c478bd9Sstevel@tonic-gate const char **serverout, 17107c478bd9Sstevel@tonic-gate unsigned *serveroutlen) 17117c478bd9Sstevel@tonic-gate { 17127c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn=(sasl_server_conn_t *) conn; 17137c478bd9Sstevel@tonic-gate int result; 17147c478bd9Sstevel@tonic-gate context_list_t *cur, **prev; 17157c478bd9Sstevel@tonic-gate mechanism_t *m; 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 17187c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = 17197c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx; 17207c478bd9Sstevel@tonic-gate mech_list_t *mechlist; 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT; 17237c478bd9Sstevel@tonic-gate if (! conn) 17247c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate (void)_load_server_plugins(gctx); 17277c478bd9Sstevel@tonic-gate mechlist = gctx->mechlist; 17287c478bd9Sstevel@tonic-gate m=mechlist->mech_list; 17297c478bd9Sstevel@tonic-gate result = load_config(gctx, _sasl_find_verifyfile_callback( 17307c478bd9Sstevel@tonic-gate gctx->server_global_callbacks.callbacks)); 17317c478bd9Sstevel@tonic-gate if (result != SASL_OK) 17327c478bd9Sstevel@tonic-gate return (result); 17337c478bd9Sstevel@tonic-gate #else 17347c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT; 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate /* make sure mech is valid mechanism 17377c478bd9Sstevel@tonic-gate if not return appropriate error */ 17387c478bd9Sstevel@tonic-gate m=mechlist->mech_list; 17397c478bd9Sstevel@tonic-gate 17407c478bd9Sstevel@tonic-gate /* check parameters */ 17417c478bd9Sstevel@tonic-gate if(!conn) return SASL_BADPARAM; 17427c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 17437c478bd9Sstevel@tonic-gate 17447c478bd9Sstevel@tonic-gate if (!mech || ((clientin==NULL) && (clientinlen>0))) 17457c478bd9Sstevel@tonic-gate PARAMERROR(conn); 17467c478bd9Sstevel@tonic-gate 17477c478bd9Sstevel@tonic-gate if(serverout) *serverout = NULL; 17487c478bd9Sstevel@tonic-gate if(serveroutlen) *serveroutlen = 0; 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate while (m!=NULL) 17517c478bd9Sstevel@tonic-gate { 17527c478bd9Sstevel@tonic-gate if ( strcasecmp(mech,m->plug->mech_name)==0) 17537c478bd9Sstevel@tonic-gate { 17547c478bd9Sstevel@tonic-gate break; 17557c478bd9Sstevel@tonic-gate } 17567c478bd9Sstevel@tonic-gate m=m->next; 17577c478bd9Sstevel@tonic-gate } 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate if (m==NULL) { 17607c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 17617c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, gettext("Couldn't find mech %s"), mech); 17627c478bd9Sstevel@tonic-gate #else 17637c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "Couldn't find mech %s", mech); 17647c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 17657c478bd9Sstevel@tonic-gate result = SASL_NOMECH; 17667c478bd9Sstevel@tonic-gate goto done; 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 17707c478bd9Sstevel@tonic-gate server_dispose_mech_contexts(conn); 17717c478bd9Sstevel@tonic-gate #endif /*_SUN_SDK_ */ 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate /* Make sure that we're willing to use this mech */ 17747c478bd9Sstevel@tonic-gate if (! mech_permitted(conn, m)) { 17757c478bd9Sstevel@tonic-gate result = SASL_NOMECH; 17767c478bd9Sstevel@tonic-gate goto done; 17777c478bd9Sstevel@tonic-gate } 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 17807c478bd9Sstevel@tonic-gate if(conn->context) { 17817c478bd9Sstevel@tonic-gate s_conn->mech->plug->mech_dispose(conn->context, s_conn->sparams->utils); 17827c478bd9Sstevel@tonic-gate conn->context = NULL; 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate memset(&conn->oparams, 0, sizeof(sasl_out_params_t)); 17857c478bd9Sstevel@tonic-gate #else 17867c478bd9Sstevel@tonic-gate if (m->condition == SASL_CONTINUE) { 17877c478bd9Sstevel@tonic-gate sasl_server_plug_init_t *entry_point; 17887c478bd9Sstevel@tonic-gate void *library = NULL; 17897c478bd9Sstevel@tonic-gate sasl_server_plug_t *pluglist; 17907c478bd9Sstevel@tonic-gate int version, plugcount; 17917c478bd9Sstevel@tonic-gate int l = 0; 17927c478bd9Sstevel@tonic-gate 17937c478bd9Sstevel@tonic-gate /* need to load this plugin */ 17947c478bd9Sstevel@tonic-gate result = _sasl_get_plugin(m->f, 17957c478bd9Sstevel@tonic-gate _sasl_find_verifyfile_callback(global_callbacks.callbacks), 17967c478bd9Sstevel@tonic-gate &library); 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate if (result == SASL_OK) { 17997c478bd9Sstevel@tonic-gate result = _sasl_locate_entry(library, "sasl_server_plug_init", 18007c478bd9Sstevel@tonic-gate (void **)&entry_point); 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate if (result == SASL_OK) { 18047c478bd9Sstevel@tonic-gate result = entry_point(mechlist->utils, SASL_SERVER_PLUG_VERSION, 18057c478bd9Sstevel@tonic-gate &version, &pluglist, &plugcount); 18067c478bd9Sstevel@tonic-gate } 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate if (result == SASL_OK) { 18097c478bd9Sstevel@tonic-gate /* find the correct mechanism in this plugin */ 18107c478bd9Sstevel@tonic-gate for (l = 0; l < plugcount; l++) { 18117c478bd9Sstevel@tonic-gate if (!strcasecmp(pluglist[l].mech_name, 18127c478bd9Sstevel@tonic-gate m->plug->mech_name)) break; 18137c478bd9Sstevel@tonic-gate } 18147c478bd9Sstevel@tonic-gate if (l == plugcount) { 18157c478bd9Sstevel@tonic-gate result = SASL_NOMECH; 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate } 18187c478bd9Sstevel@tonic-gate if (result == SASL_OK) { 18197c478bd9Sstevel@tonic-gate /* check that the parameters are the same */ 18207c478bd9Sstevel@tonic-gate if ((pluglist[l].max_ssf != m->plug->max_ssf) || 18217c478bd9Sstevel@tonic-gate (pluglist[l].security_flags != m->plug->security_flags)) { 18227c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, 18237c478bd9Sstevel@tonic-gate "%s: security parameters don't match mechlist file", 18247c478bd9Sstevel@tonic-gate pluglist[l].mech_name); 18257c478bd9Sstevel@tonic-gate result = SASL_NOMECH; 18267c478bd9Sstevel@tonic-gate } 18277c478bd9Sstevel@tonic-gate } 18287c478bd9Sstevel@tonic-gate if (result == SASL_OK) { 18297c478bd9Sstevel@tonic-gate /* copy mechlist over */ 18307c478bd9Sstevel@tonic-gate sasl_FREE((sasl_server_plug_t *) m->plug); 18317c478bd9Sstevel@tonic-gate m->plug = &pluglist[l]; 18327c478bd9Sstevel@tonic-gate m->condition = SASL_OK; 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate if (result != SASL_OK) { 18367c478bd9Sstevel@tonic-gate /* The library will eventually be freed, don't sweat it */ 18377c478bd9Sstevel@tonic-gate RETURN(conn, result); 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate } 18407c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */ 18417c478bd9Sstevel@tonic-gate 18427c478bd9Sstevel@tonic-gate /* We used to setup sparams HERE, but now it's done 18437c478bd9Sstevel@tonic-gate inside of mech_permitted (which is called above) */ 18447c478bd9Sstevel@tonic-gate prev = &s_conn->mech_contexts; 18457c478bd9Sstevel@tonic-gate for(cur = *prev; cur; prev=&cur->next,cur=cur->next) { 18467c478bd9Sstevel@tonic-gate if(cur->mech == m) { 18477c478bd9Sstevel@tonic-gate if(!cur->context) { 18487c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 18497c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, 18507c478bd9Sstevel@tonic-gate "Got past mech_permitted with a disallowed mech!"); 18517c478bd9Sstevel@tonic-gate #else 18527c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, 18537c478bd9Sstevel@tonic-gate "Got past mech_permitted with a disallowed mech!"); 18547c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 18557c478bd9Sstevel@tonic-gate return SASL_NOMECH; 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate /* If we find it, we need to pull cur out of the 18587c478bd9Sstevel@tonic-gate list so it won't be freed later! */ 18597c478bd9Sstevel@tonic-gate (*prev)->next = cur->next; 18607c478bd9Sstevel@tonic-gate conn->context = cur->context; 18617c478bd9Sstevel@tonic-gate sasl_FREE(cur); 18627c478bd9Sstevel@tonic-gate } 18637c478bd9Sstevel@tonic-gate } 18647c478bd9Sstevel@tonic-gate 18657c478bd9Sstevel@tonic-gate s_conn->mech = m; 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate if(!conn->context) { 18687c478bd9Sstevel@tonic-gate /* Note that we don't hand over a new challenge */ 18697c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 18707c478bd9Sstevel@tonic-gate result = s_conn->mech->plug->mech_new(s_conn->mech->glob_context, 18717c478bd9Sstevel@tonic-gate #else 18727c478bd9Sstevel@tonic-gate result = s_conn->mech->plug->mech_new(s_conn->mech->plug->glob_context, 18737c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 18747c478bd9Sstevel@tonic-gate s_conn->sparams, 18757c478bd9Sstevel@tonic-gate NULL, 18767c478bd9Sstevel@tonic-gate 0, 18777c478bd9Sstevel@tonic-gate &(conn->context)); 18787c478bd9Sstevel@tonic-gate } else { 18797c478bd9Sstevel@tonic-gate /* the work was already done by mech_avail! */ 18807c478bd9Sstevel@tonic-gate result = SASL_OK; 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate if (result == SASL_OK) { 18847c478bd9Sstevel@tonic-gate if(clientin) { 18857c478bd9Sstevel@tonic-gate if(s_conn->mech->plug->features & SASL_FEAT_SERVER_FIRST) { 18867c478bd9Sstevel@tonic-gate /* Remote sent first, but mechanism does not support it. 18877c478bd9Sstevel@tonic-gate * RFC 2222 says we fail at this point. */ 18887c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 18897c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, 18907c478bd9Sstevel@tonic-gate "Remote sent first but mech does not allow it."); 18917c478bd9Sstevel@tonic-gate #else 18927c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, 18937c478bd9Sstevel@tonic-gate "Remote sent first but mech does not allow it."); 18947c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 18957c478bd9Sstevel@tonic-gate result = SASL_BADPROT; 18967c478bd9Sstevel@tonic-gate } else { 18977c478bd9Sstevel@tonic-gate /* Mech wants client-first, so let them have it */ 18987c478bd9Sstevel@tonic-gate result = sasl_server_step(conn, 18997c478bd9Sstevel@tonic-gate clientin, clientinlen, 19007c478bd9Sstevel@tonic-gate serverout, serveroutlen); 19017c478bd9Sstevel@tonic-gate } 19027c478bd9Sstevel@tonic-gate } else { 19037c478bd9Sstevel@tonic-gate if(s_conn->mech->plug->features & SASL_FEAT_WANT_CLIENT_FIRST) { 19047c478bd9Sstevel@tonic-gate /* Mech wants client first anyway, so we should do that */ 19057c478bd9Sstevel@tonic-gate *serverout = ""; 19067c478bd9Sstevel@tonic-gate *serveroutlen = 0; 19077c478bd9Sstevel@tonic-gate result = SASL_CONTINUE; 19087c478bd9Sstevel@tonic-gate } else { 19097c478bd9Sstevel@tonic-gate /* Mech wants server-first, so let them have it */ 19107c478bd9Sstevel@tonic-gate result = sasl_server_step(conn, 19117c478bd9Sstevel@tonic-gate clientin, clientinlen, 19127c478bd9Sstevel@tonic-gate serverout, serveroutlen); 19137c478bd9Sstevel@tonic-gate } 19147c478bd9Sstevel@tonic-gate } 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate 19177c478bd9Sstevel@tonic-gate done: 19187c478bd9Sstevel@tonic-gate if( result != SASL_OK 19197c478bd9Sstevel@tonic-gate && result != SASL_CONTINUE 19207c478bd9Sstevel@tonic-gate && result != SASL_INTERACT) { 19217c478bd9Sstevel@tonic-gate if(conn->context) { 19227c478bd9Sstevel@tonic-gate s_conn->mech->plug->mech_dispose(conn->context, 19237c478bd9Sstevel@tonic-gate s_conn->sparams->utils); 19247c478bd9Sstevel@tonic-gate conn->context = NULL; 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate 19287c478bd9Sstevel@tonic-gate RETURN(conn,result); 19297c478bd9Sstevel@tonic-gate } 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate /* perform one step of the SASL exchange 19337c478bd9Sstevel@tonic-gate * inputlen & input -- client data 19347c478bd9Sstevel@tonic-gate * NULL on first step if no optional client step 19357c478bd9Sstevel@tonic-gate * outputlen & output -- set to the server data to transmit 19367c478bd9Sstevel@tonic-gate * to the client in the next step 19377c478bd9Sstevel@tonic-gate * (library handles freeing this) 19387c478bd9Sstevel@tonic-gate * 19397c478bd9Sstevel@tonic-gate * returns: 19407c478bd9Sstevel@tonic-gate * SASL_OK -- exchange is complete. 19417c478bd9Sstevel@tonic-gate * SASL_CONTINUE -- indicates another step is necessary. 19427c478bd9Sstevel@tonic-gate * SASL_TRANS -- entry for user exists, but not for mechanism 19437c478bd9Sstevel@tonic-gate * and transition is possible 19447c478bd9Sstevel@tonic-gate * SASL_BADPARAM -- service name needed 19457c478bd9Sstevel@tonic-gate * SASL_BADPROT -- invalid input from client 19467c478bd9Sstevel@tonic-gate * ... 19477c478bd9Sstevel@tonic-gate */ 19487c478bd9Sstevel@tonic-gate 19497c478bd9Sstevel@tonic-gate int sasl_server_step(sasl_conn_t *conn, 19507c478bd9Sstevel@tonic-gate const char *clientin, 19517c478bd9Sstevel@tonic-gate unsigned clientinlen, 19527c478bd9Sstevel@tonic-gate const char **serverout, 19537c478bd9Sstevel@tonic-gate unsigned *serveroutlen) 19547c478bd9Sstevel@tonic-gate { 19557c478bd9Sstevel@tonic-gate int ret; 19567c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn; /* cast */ 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 19597c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = 19607c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx; 19617c478bd9Sstevel@tonic-gate 19627c478bd9Sstevel@tonic-gate /* check parameters */ 19637c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT; 19647c478bd9Sstevel@tonic-gate #else 19657c478bd9Sstevel@tonic-gate /* check parameters */ 19667c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT; 19677c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 19687c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM; 19697c478bd9Sstevel@tonic-gate if ((clientin==NULL) && (clientinlen>0)) 19707c478bd9Sstevel@tonic-gate PARAMERROR(conn); 19717c478bd9Sstevel@tonic-gate 19727c478bd9Sstevel@tonic-gate /* If we've already done the last send, return! */ 19737c478bd9Sstevel@tonic-gate if(s_conn->sent_last == 1) { 19747c478bd9Sstevel@tonic-gate return SASL_OK; 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate /* Don't do another step if the plugin told us that we're done */ 19787c478bd9Sstevel@tonic-gate if (conn->oparams.doneflag) { 19797c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, "attempting server step after doneflag"); 19807c478bd9Sstevel@tonic-gate return SASL_FAIL; 19817c478bd9Sstevel@tonic-gate } 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate if(serverout) *serverout = NULL; 19847c478bd9Sstevel@tonic-gate if(serveroutlen) *serveroutlen = 0; 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate ret = s_conn->mech->plug->mech_step(conn->context, 19877c478bd9Sstevel@tonic-gate s_conn->sparams, 19887c478bd9Sstevel@tonic-gate clientin, 19897c478bd9Sstevel@tonic-gate clientinlen, 19907c478bd9Sstevel@tonic-gate serverout, 19917c478bd9Sstevel@tonic-gate serveroutlen, 19927c478bd9Sstevel@tonic-gate &conn->oparams); 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate if (ret == SASL_OK) { 19957c478bd9Sstevel@tonic-gate ret = do_authorization(s_conn); 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate if (ret == SASL_OK) { 19997c478bd9Sstevel@tonic-gate /* if we're done, we need to watch out for the following: 20007c478bd9Sstevel@tonic-gate * 1. the mech does server-send-last 20017c478bd9Sstevel@tonic-gate * 2. the protocol does not 20027c478bd9Sstevel@tonic-gate * 20037c478bd9Sstevel@tonic-gate * in this case, return SASL_CONTINUE and remember we are done. 20047c478bd9Sstevel@tonic-gate */ 20057c478bd9Sstevel@tonic-gate if(*serverout && !(conn->flags & SASL_SUCCESS_DATA)) { 20067c478bd9Sstevel@tonic-gate s_conn->sent_last = 1; 20077c478bd9Sstevel@tonic-gate ret = SASL_CONTINUE; 20087c478bd9Sstevel@tonic-gate } 20097c478bd9Sstevel@tonic-gate if(!conn->oparams.maxoutbuf) { 20107c478bd9Sstevel@tonic-gate conn->oparams.maxoutbuf = conn->props.maxbufsize; 20117c478bd9Sstevel@tonic-gate } 20127c478bd9Sstevel@tonic-gate 20137c478bd9Sstevel@tonic-gate if(conn->oparams.user == NULL || conn->oparams.authid == NULL) { 20147c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 20157c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, 20167c478bd9Sstevel@tonic-gate "mech did not call canon_user for both authzid " 20177c478bd9Sstevel@tonic-gate "and authid"); 20187c478bd9Sstevel@tonic-gate #else 20197c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, 20207c478bd9Sstevel@tonic-gate "mech did not call canon_user for both authzid " \ 20217c478bd9Sstevel@tonic-gate "and authid"); 20227c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 20237c478bd9Sstevel@tonic-gate ret = SASL_BADPROT; 20247c478bd9Sstevel@tonic-gate } 20257c478bd9Sstevel@tonic-gate } 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate if( ret != SASL_OK 20287c478bd9Sstevel@tonic-gate && ret != SASL_CONTINUE 20297c478bd9Sstevel@tonic-gate && ret != SASL_INTERACT) { 20307c478bd9Sstevel@tonic-gate if(conn->context) { 20317c478bd9Sstevel@tonic-gate s_conn->mech->plug->mech_dispose(conn->context, 20327c478bd9Sstevel@tonic-gate s_conn->sparams->utils); 20337c478bd9Sstevel@tonic-gate conn->context = NULL; 20347c478bd9Sstevel@tonic-gate } 20357c478bd9Sstevel@tonic-gate } 20367c478bd9Sstevel@tonic-gate 20377c478bd9Sstevel@tonic-gate RETURN(conn, ret); 20387c478bd9Sstevel@tonic-gate } 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate /* returns the length of all the mechanisms 20417c478bd9Sstevel@tonic-gate * added up 20427c478bd9Sstevel@tonic-gate */ 20437c478bd9Sstevel@tonic-gate 20447c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 20457c478bd9Sstevel@tonic-gate static unsigned mech_names_len(_sasl_global_context_t *gctx) 20467c478bd9Sstevel@tonic-gate { 20477c478bd9Sstevel@tonic-gate mech_list_t *mechlist = gctx->mechlist; 20487c478bd9Sstevel@tonic-gate #else 20497c478bd9Sstevel@tonic-gate static unsigned mech_names_len() 20507c478bd9Sstevel@tonic-gate { 20517c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 20527c478bd9Sstevel@tonic-gate mechanism_t *listptr; 20537c478bd9Sstevel@tonic-gate unsigned result = 0; 20547c478bd9Sstevel@tonic-gate 20557c478bd9Sstevel@tonic-gate for (listptr = mechlist->mech_list; 20567c478bd9Sstevel@tonic-gate listptr; 20577c478bd9Sstevel@tonic-gate listptr = listptr->next) 20587c478bd9Sstevel@tonic-gate result += strlen(listptr->plug->mech_name); 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate return result; 20617c478bd9Sstevel@tonic-gate } 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate /* This returns a list of mechanisms in a NUL-terminated string 20647c478bd9Sstevel@tonic-gate * 20657c478bd9Sstevel@tonic-gate * The default behavior is to seperate with spaces if sep==NULL 20667c478bd9Sstevel@tonic-gate */ 20677c478bd9Sstevel@tonic-gate int _sasl_server_listmech(sasl_conn_t *conn, 20687c478bd9Sstevel@tonic-gate const char *user __attribute__((unused)), 20697c478bd9Sstevel@tonic-gate const char *prefix, 20707c478bd9Sstevel@tonic-gate const char *sep, 20717c478bd9Sstevel@tonic-gate const char *suffix, 20727c478bd9Sstevel@tonic-gate const char **result, 20737c478bd9Sstevel@tonic-gate unsigned *plen, 20747c478bd9Sstevel@tonic-gate int *pcount) 20757c478bd9Sstevel@tonic-gate { 20767c478bd9Sstevel@tonic-gate int lup; 20777c478bd9Sstevel@tonic-gate mechanism_t *listptr; 20787c478bd9Sstevel@tonic-gate int ret; 20797c478bd9Sstevel@tonic-gate int resultlen; 20807c478bd9Sstevel@tonic-gate int flag; 20817c478bd9Sstevel@tonic-gate const char *mysep; 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 20847c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx; 20857c478bd9Sstevel@tonic-gate mech_list_t *mechlist; 20867c478bd9Sstevel@tonic-gate 20877c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM; 20887c478bd9Sstevel@tonic-gate /* if there hasn't been a sasl_sever_init() fail */ 20897c478bd9Sstevel@tonic-gate gctx = conn->gctx; 20907c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT; 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate (void)_load_server_plugins(gctx); 20937c478bd9Sstevel@tonic-gate mechlist = gctx->mechlist; 20947c478bd9Sstevel@tonic-gate #else 20957c478bd9Sstevel@tonic-gate /* if there hasn't been a sasl_sever_init() fail */ 20967c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT; 20977c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM; 20987c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 20997c478bd9Sstevel@tonic-gate if (conn->type != SASL_CONN_SERVER) PARAMERROR(conn); 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate if (! result) 21027c478bd9Sstevel@tonic-gate PARAMERROR(conn); 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate if (plen != NULL) 21057c478bd9Sstevel@tonic-gate *plen = 0; 21067c478bd9Sstevel@tonic-gate if (pcount != NULL) 21077c478bd9Sstevel@tonic-gate *pcount = 0; 21087c478bd9Sstevel@tonic-gate 21097c478bd9Sstevel@tonic-gate if (sep) { 21107c478bd9Sstevel@tonic-gate mysep = sep; 21117c478bd9Sstevel@tonic-gate } else { 21127c478bd9Sstevel@tonic-gate mysep = " "; 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate if (! mechlist || mechlist->mech_length <= 0) 21167c478bd9Sstevel@tonic-gate INTERROR(conn, SASL_NOMECH); 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate resultlen = (prefix ? strlen(prefix) : 0) 21197c478bd9Sstevel@tonic-gate + (strlen(mysep) * (mechlist->mech_length - 1)) 21207c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 21217c478bd9Sstevel@tonic-gate + mech_names_len(gctx) 21227c478bd9Sstevel@tonic-gate #else 21237c478bd9Sstevel@tonic-gate + mech_names_len() 21247c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 21257c478bd9Sstevel@tonic-gate + (suffix ? strlen(suffix) : 0) 21267c478bd9Sstevel@tonic-gate + 1; 21277c478bd9Sstevel@tonic-gate ret = _buf_alloc(&conn->mechlist_buf, 21287c478bd9Sstevel@tonic-gate &conn->mechlist_buf_len, resultlen); 21297c478bd9Sstevel@tonic-gate if(ret != SASL_OK) MEMERROR(conn); 21307c478bd9Sstevel@tonic-gate 21317c478bd9Sstevel@tonic-gate if (prefix) 21327c478bd9Sstevel@tonic-gate strcpy (conn->mechlist_buf,prefix); 21337c478bd9Sstevel@tonic-gate else 21347c478bd9Sstevel@tonic-gate *(conn->mechlist_buf) = '\0'; 21357c478bd9Sstevel@tonic-gate 21367c478bd9Sstevel@tonic-gate listptr = mechlist->mech_list; 21377c478bd9Sstevel@tonic-gate 21387c478bd9Sstevel@tonic-gate flag = 0; 21397c478bd9Sstevel@tonic-gate /* make list */ 21407c478bd9Sstevel@tonic-gate for (lup = 0; lup < mechlist->mech_length; lup++) { 21417c478bd9Sstevel@tonic-gate /* currently, we don't use the "user" parameter for anything */ 21427c478bd9Sstevel@tonic-gate if (mech_permitted(conn, listptr)) { 21437c478bd9Sstevel@tonic-gate if (pcount != NULL) 21447c478bd9Sstevel@tonic-gate (*pcount)++; 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate /* print seperator */ 21477c478bd9Sstevel@tonic-gate if (flag) { 21487c478bd9Sstevel@tonic-gate strcat(conn->mechlist_buf, mysep); 21497c478bd9Sstevel@tonic-gate } else { 21507c478bd9Sstevel@tonic-gate flag = 1; 21517c478bd9Sstevel@tonic-gate } 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate /* now print the mechanism name */ 21547c478bd9Sstevel@tonic-gate strcat(conn->mechlist_buf, listptr->plug->mech_name); 21557c478bd9Sstevel@tonic-gate } 21567c478bd9Sstevel@tonic-gate 21577c478bd9Sstevel@tonic-gate listptr = listptr->next; 21587c478bd9Sstevel@tonic-gate } 21597c478bd9Sstevel@tonic-gate 21607c478bd9Sstevel@tonic-gate if (suffix) 21617c478bd9Sstevel@tonic-gate strcat(conn->mechlist_buf,suffix); 21627c478bd9Sstevel@tonic-gate 21637c478bd9Sstevel@tonic-gate if (plen!=NULL) 21647c478bd9Sstevel@tonic-gate *plen=strlen(conn->mechlist_buf); 21657c478bd9Sstevel@tonic-gate 21667c478bd9Sstevel@tonic-gate *result = conn->mechlist_buf; 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate return SASL_OK; 21697c478bd9Sstevel@tonic-gate } 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 21727c478bd9Sstevel@tonic-gate sasl_string_list_t *_sasl_server_mechs(_sasl_global_context_t *gctx) 21737c478bd9Sstevel@tonic-gate #else 21747c478bd9Sstevel@tonic-gate sasl_string_list_t *_sasl_server_mechs(void) 21757c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 21767c478bd9Sstevel@tonic-gate { 21777c478bd9Sstevel@tonic-gate mechanism_t *listptr; 21787c478bd9Sstevel@tonic-gate sasl_string_list_t *retval = NULL, *next=NULL; 21797c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 21807c478bd9Sstevel@tonic-gate mech_list_t *mechlist = gctx->mechlist; 21817c478bd9Sstevel@tonic-gate 21827c478bd9Sstevel@tonic-gate if(!gctx->sasl_server_active) return NULL; 21837c478bd9Sstevel@tonic-gate #else 21847c478bd9Sstevel@tonic-gate if(!_sasl_server_active) return NULL; 21857c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 21867c478bd9Sstevel@tonic-gate 21877c478bd9Sstevel@tonic-gate /* make list */ 21887c478bd9Sstevel@tonic-gate for (listptr = mechlist->mech_list; listptr; listptr = listptr->next) { 21897c478bd9Sstevel@tonic-gate next = sasl_ALLOC(sizeof(sasl_string_list_t)); 21907c478bd9Sstevel@tonic-gate 21917c478bd9Sstevel@tonic-gate if(!next && !retval) return NULL; 21927c478bd9Sstevel@tonic-gate else if(!next) { 21937c478bd9Sstevel@tonic-gate next = retval->next; 21947c478bd9Sstevel@tonic-gate do { 21957c478bd9Sstevel@tonic-gate sasl_FREE(retval); 21967c478bd9Sstevel@tonic-gate retval = next; 21977c478bd9Sstevel@tonic-gate next = retval->next; 21987c478bd9Sstevel@tonic-gate } while(next); 21997c478bd9Sstevel@tonic-gate return NULL; 22007c478bd9Sstevel@tonic-gate } 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate next->d = listptr->plug->mech_name; 22037c478bd9Sstevel@tonic-gate 22047c478bd9Sstevel@tonic-gate if(!retval) { 22057c478bd9Sstevel@tonic-gate next->next = NULL; 22067c478bd9Sstevel@tonic-gate retval = next; 22077c478bd9Sstevel@tonic-gate } else { 22087c478bd9Sstevel@tonic-gate next->next = retval; 22097c478bd9Sstevel@tonic-gate retval = next; 22107c478bd9Sstevel@tonic-gate } 22117c478bd9Sstevel@tonic-gate } 22127c478bd9Sstevel@tonic-gate 22137c478bd9Sstevel@tonic-gate return retval; 22147c478bd9Sstevel@tonic-gate } 22157c478bd9Sstevel@tonic-gate 22167c478bd9Sstevel@tonic-gate #define EOSTR(s,n) (((s)[n] == '\0') || ((s)[n] == ' ') || ((s)[n] == '\t')) 22177c478bd9Sstevel@tonic-gate static int is_mech(const char *t, const char *m) 22187c478bd9Sstevel@tonic-gate { 22197c478bd9Sstevel@tonic-gate int sl = strlen(m); 22207c478bd9Sstevel@tonic-gate return ((!strncasecmp(m, t, sl)) && EOSTR(t, sl)); 22217c478bd9Sstevel@tonic-gate } 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate /* returns OK if it's valid */ 22247c478bd9Sstevel@tonic-gate static int _sasl_checkpass(sasl_conn_t *conn, 22257c478bd9Sstevel@tonic-gate const char *user, 22267c478bd9Sstevel@tonic-gate unsigned userlen __attribute__((unused)), 22277c478bd9Sstevel@tonic-gate const char *pass, 22287c478bd9Sstevel@tonic-gate unsigned passlen __attribute__((unused))) 22297c478bd9Sstevel@tonic-gate { 22307c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn; 22317c478bd9Sstevel@tonic-gate int result; 22327c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt; 22337c478bd9Sstevel@tonic-gate sasl_server_userdb_checkpass_t *checkpass_cb; 22347c478bd9Sstevel@tonic-gate void *context; 22357c478bd9Sstevel@tonic-gate const char *mlist = NULL, *mech = NULL; 22367c478bd9Sstevel@tonic-gate struct sasl_verify_password_s *v; 22377c478bd9Sstevel@tonic-gate const char *service = conn->service; 22387c478bd9Sstevel@tonic-gate 22397c478bd9Sstevel@tonic-gate /* call userdb callback function, if available */ 22407c478bd9Sstevel@tonic-gate result = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_CHECKPASS, 22417c478bd9Sstevel@tonic-gate &checkpass_cb, &context); 22427c478bd9Sstevel@tonic-gate if(result == SASL_OK && checkpass_cb) { 22437c478bd9Sstevel@tonic-gate result = checkpass_cb(conn, context, user, pass, strlen(pass), 22447c478bd9Sstevel@tonic-gate s_conn->sparams->propctx); 22457c478bd9Sstevel@tonic-gate if(result == SASL_OK) 22467c478bd9Sstevel@tonic-gate return SASL_OK; 22477c478bd9Sstevel@tonic-gate } 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */ 22507c478bd9Sstevel@tonic-gate if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) 22517c478bd9Sstevel@tonic-gate == SASL_OK) { 22527c478bd9Sstevel@tonic-gate getopt(context, NULL, "pwcheck_method", &mlist, NULL); 22537c478bd9Sstevel@tonic-gate } 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate if(!mlist) mlist = DEFAULT_CHECKPASS_MECH; 22567c478bd9Sstevel@tonic-gate 22577c478bd9Sstevel@tonic-gate result = SASL_NOMECH; 22587c478bd9Sstevel@tonic-gate 22597c478bd9Sstevel@tonic-gate mech = mlist; 22607c478bd9Sstevel@tonic-gate while (*mech && result != SASL_OK) { 22617c478bd9Sstevel@tonic-gate for (v = _sasl_verify_password; v->name; v++) { 22627c478bd9Sstevel@tonic-gate if(is_mech(mech, v->name)) { 22637c478bd9Sstevel@tonic-gate result = v->verify(conn, user, pass, service, 22647c478bd9Sstevel@tonic-gate s_conn->user_realm); 22657c478bd9Sstevel@tonic-gate break; 22667c478bd9Sstevel@tonic-gate } 22677c478bd9Sstevel@tonic-gate } 22687c478bd9Sstevel@tonic-gate if (result != SASL_OK) { 22697c478bd9Sstevel@tonic-gate /* skip to next mech in list */ 22707c478bd9Sstevel@tonic-gate while (*mech && !isspace((int) *mech)) mech++; 22717c478bd9Sstevel@tonic-gate while (*mech && isspace((int) *mech)) mech++; 22727c478bd9Sstevel@tonic-gate } 22737c478bd9Sstevel@tonic-gate } 22747c478bd9Sstevel@tonic-gate 22757c478bd9Sstevel@tonic-gate if (result == SASL_NOMECH) { 22767c478bd9Sstevel@tonic-gate /* no mechanism available ?!? */ 22777c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, "unknown password verifier %s", mech); 22787c478bd9Sstevel@tonic-gate } 22797c478bd9Sstevel@tonic-gate 22807c478bd9Sstevel@tonic-gate if (result != SASL_OK) 22817c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 22827c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, gettext("checkpass failed")); 22837c478bd9Sstevel@tonic-gate #else 22847c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, "checkpass failed"); 22857c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 22867c478bd9Sstevel@tonic-gate 22877c478bd9Sstevel@tonic-gate RETURN(conn, result); 22887c478bd9Sstevel@tonic-gate } 22897c478bd9Sstevel@tonic-gate 22907c478bd9Sstevel@tonic-gate /* check if a plaintext password is valid 22917c478bd9Sstevel@tonic-gate * if user is NULL, check if plaintext passwords are enabled 22927c478bd9Sstevel@tonic-gate * inputs: 22937c478bd9Sstevel@tonic-gate * user -- user to query in current user_domain 22947c478bd9Sstevel@tonic-gate * userlen -- length of username, 0 = strlen(user) 22957c478bd9Sstevel@tonic-gate * pass -- plaintext password to check 22967c478bd9Sstevel@tonic-gate * passlen -- length of password, 0 = strlen(pass) 22977c478bd9Sstevel@tonic-gate * returns 22987c478bd9Sstevel@tonic-gate * SASL_OK -- success 22997c478bd9Sstevel@tonic-gate * SASL_NOMECH -- mechanism not supported 23007c478bd9Sstevel@tonic-gate * SASL_NOVERIFY -- user found, but no verifier 23017c478bd9Sstevel@tonic-gate * SASL_NOUSER -- user not found 23027c478bd9Sstevel@tonic-gate */ 23037c478bd9Sstevel@tonic-gate int sasl_checkpass(sasl_conn_t *conn, 23047c478bd9Sstevel@tonic-gate const char *user, 23057c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 23067c478bd9Sstevel@tonic-gate unsigned userlen, 23077c478bd9Sstevel@tonic-gate #else /* _SUN_SDK_ */ 23087c478bd9Sstevel@tonic-gate unsigned userlen __attribute__((unused)), 23097c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 23107c478bd9Sstevel@tonic-gate const char *pass, 23117c478bd9Sstevel@tonic-gate unsigned passlen) 23127c478bd9Sstevel@tonic-gate { 23137c478bd9Sstevel@tonic-gate int result; 23147c478bd9Sstevel@tonic-gate 23157c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 23167c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = 23177c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx; 23187c478bd9Sstevel@tonic-gate 23197c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT; 23207c478bd9Sstevel@tonic-gate 23217c478bd9Sstevel@tonic-gate /* A NULL user means the caller is checking if plaintext authentication 23227c478bd9Sstevel@tonic-gate * is enabled. But if no connection context is supplied, we have no 23237c478bd9Sstevel@tonic-gate * appropriate policy to check against. So for consistant global 23247c478bd9Sstevel@tonic-gate * behavior we always say plaintext is enabled in this case. 23257c478bd9Sstevel@tonic-gate */ 23267c478bd9Sstevel@tonic-gate if (!user && !conn) return SASL_OK; 23277c478bd9Sstevel@tonic-gate 23287c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM; 23297c478bd9Sstevel@tonic-gate 23307c478bd9Sstevel@tonic-gate /* Check connection security policy to see if plaintext password 23317c478bd9Sstevel@tonic-gate * authentication is permitted. 23327c478bd9Sstevel@tonic-gate * 23337c478bd9Sstevel@tonic-gate * XXX TODO FIXME: 23347c478bd9Sstevel@tonic-gate * This should call mech_permitted with the PLAIN mechanism, 23357c478bd9Sstevel@tonic-gate * since all plaintext mechanisms should fall under the same 23367c478bd9Sstevel@tonic-gate * security policy guidelines. But to keep code changes and 23377c478bd9Sstevel@tonic-gate * risk to a minimum at this juncture, we do the minimal 23387c478bd9Sstevel@tonic-gate * security strength and plaintext policy checks which are 23397c478bd9Sstevel@tonic-gate * most likely to be deployed and useful in the field. 23407c478bd9Sstevel@tonic-gate */ 23417c478bd9Sstevel@tonic-gate if (conn->props.min_ssf > conn->external.ssf) 23427c478bd9Sstevel@tonic-gate RETURN(conn, SASL_TOOWEAK); 23437c478bd9Sstevel@tonic-gate if ((conn->props.security_flags & SASL_SEC_NOPLAINTEXT) != 0 23447c478bd9Sstevel@tonic-gate && conn->external.ssf == 0) 23457c478bd9Sstevel@tonic-gate RETURN(conn, SASL_ENCRYPT); 23467c478bd9Sstevel@tonic-gate 23477c478bd9Sstevel@tonic-gate if (!user) 23487c478bd9Sstevel@tonic-gate return SASL_OK; 23497c478bd9Sstevel@tonic-gate #else 23507c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT; 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate /* check if it's just a query if we are enabled */ 23537c478bd9Sstevel@tonic-gate if (!user) 23547c478bd9Sstevel@tonic-gate return SASL_OK; 23557c478bd9Sstevel@tonic-gate 23567c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM; 23577c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 23587c478bd9Sstevel@tonic-gate 23597c478bd9Sstevel@tonic-gate /* check params */ 23607c478bd9Sstevel@tonic-gate if (pass == NULL) 23617c478bd9Sstevel@tonic-gate PARAMERROR(conn); 23627c478bd9Sstevel@tonic-gate 23637c478bd9Sstevel@tonic-gate /* canonicalize the username */ 23647c478bd9Sstevel@tonic-gate result = _sasl_canon_user(conn, user, 0, 23657c478bd9Sstevel@tonic-gate SASL_CU_AUTHID | SASL_CU_AUTHZID, 23667c478bd9Sstevel@tonic-gate &(conn->oparams)); 23677c478bd9Sstevel@tonic-gate if(result != SASL_OK) RETURN(conn, result); 23687c478bd9Sstevel@tonic-gate user = conn->oparams.user; 23697c478bd9Sstevel@tonic-gate 23707c478bd9Sstevel@tonic-gate /* Check the password */ 23717c478bd9Sstevel@tonic-gate result = _sasl_checkpass(conn, user, strlen(user), pass, strlen(pass)); 23727c478bd9Sstevel@tonic-gate 23737c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 23747c478bd9Sstevel@tonic-gate if (result == SASL_OK) { 23757c478bd9Sstevel@tonic-gate result = do_authorization((sasl_server_conn_t *) conn); 23767c478bd9Sstevel@tonic-gate } 23777c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 23787c478bd9Sstevel@tonic-gate 23797c478bd9Sstevel@tonic-gate if (result == SASL_OK) 23807c478bd9Sstevel@tonic-gate result = _sasl_transition(conn, pass, passlen); 23817c478bd9Sstevel@tonic-gate 23827c478bd9Sstevel@tonic-gate RETURN(conn,result); 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate /* check if a user exists on server 23867c478bd9Sstevel@tonic-gate * conn -- connection context (may be NULL, used to hold last error) 23877c478bd9Sstevel@tonic-gate * service -- registered name of the service using SASL (e.g. "imap") 23887c478bd9Sstevel@tonic-gate * user_realm -- permits multiple user realms on server, NULL = default 23897c478bd9Sstevel@tonic-gate * user -- NUL terminated user name 23907c478bd9Sstevel@tonic-gate * 23917c478bd9Sstevel@tonic-gate * returns: 23927c478bd9Sstevel@tonic-gate * SASL_OK -- success 23937c478bd9Sstevel@tonic-gate * SASL_DISABLED -- account disabled [FIXME: currently not detected] 23947c478bd9Sstevel@tonic-gate * SASL_NOUSER -- user not found 23957c478bd9Sstevel@tonic-gate * SASL_NOVERIFY -- user found, but no usable mechanism [FIXME: not supported] 23967c478bd9Sstevel@tonic-gate * SASL_NOMECH -- no mechanisms enabled 23977c478bd9Sstevel@tonic-gate */ 23987c478bd9Sstevel@tonic-gate int sasl_user_exists(sasl_conn_t *conn, 23997c478bd9Sstevel@tonic-gate const char *service, 24007c478bd9Sstevel@tonic-gate const char *user_realm, 24017c478bd9Sstevel@tonic-gate const char *user) 24027c478bd9Sstevel@tonic-gate { 24037c478bd9Sstevel@tonic-gate int result=SASL_NOMECH; 24047c478bd9Sstevel@tonic-gate const char *mlist = NULL, *mech = NULL; 24057c478bd9Sstevel@tonic-gate void *context; 24067c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt; 24077c478bd9Sstevel@tonic-gate struct sasl_verify_password_s *v; 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 24107c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = 24117c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx; 24127c478bd9Sstevel@tonic-gate 24137c478bd9Sstevel@tonic-gate /* check params */ 24147c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) return SASL_NOTINIT; 24157c478bd9Sstevel@tonic-gate #else 24167c478bd9Sstevel@tonic-gate /* check params */ 24177c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) return SASL_NOTINIT; 24187c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 24197c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM; 24207c478bd9Sstevel@tonic-gate if (!user || conn->type != SASL_CONN_SERVER) 24217c478bd9Sstevel@tonic-gate PARAMERROR(conn); 24227c478bd9Sstevel@tonic-gate 24237c478bd9Sstevel@tonic-gate if(!service) service = conn->service; 24247c478bd9Sstevel@tonic-gate 24257c478bd9Sstevel@tonic-gate /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */ 24267c478bd9Sstevel@tonic-gate if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) 24277c478bd9Sstevel@tonic-gate == SASL_OK) { 24287c478bd9Sstevel@tonic-gate getopt(context, NULL, "pwcheck_method", &mlist, NULL); 24297c478bd9Sstevel@tonic-gate } 24307c478bd9Sstevel@tonic-gate 24317c478bd9Sstevel@tonic-gate if(!mlist) mlist = DEFAULT_CHECKPASS_MECH; 24327c478bd9Sstevel@tonic-gate 24337c478bd9Sstevel@tonic-gate result = SASL_NOMECH; 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate mech = mlist; 24367c478bd9Sstevel@tonic-gate while (*mech && result != SASL_OK) { 24377c478bd9Sstevel@tonic-gate for (v = _sasl_verify_password; v->name; v++) { 24387c478bd9Sstevel@tonic-gate if(is_mech(mech, v->name)) { 24397c478bd9Sstevel@tonic-gate result = v->verify(conn, user, NULL, service, user_realm); 24407c478bd9Sstevel@tonic-gate break; 24417c478bd9Sstevel@tonic-gate } 24427c478bd9Sstevel@tonic-gate } 24437c478bd9Sstevel@tonic-gate if (result != SASL_OK) { 24447c478bd9Sstevel@tonic-gate /* skip to next mech in list */ 24457c478bd9Sstevel@tonic-gate while (*mech && !isspace((int) *mech)) mech++; 24467c478bd9Sstevel@tonic-gate while (*mech && isspace((int) *mech)) mech++; 24477c478bd9Sstevel@tonic-gate } 24487c478bd9Sstevel@tonic-gate } 24497c478bd9Sstevel@tonic-gate 24507c478bd9Sstevel@tonic-gate /* Screen out the SASL_BADPARAM response 24517c478bd9Sstevel@tonic-gate * we'll get from not giving a password */ 24527c478bd9Sstevel@tonic-gate if(result == SASL_BADPARAM) { 24537c478bd9Sstevel@tonic-gate result = SASL_OK; 24547c478bd9Sstevel@tonic-gate } 24557c478bd9Sstevel@tonic-gate 24567c478bd9Sstevel@tonic-gate if (result == SASL_NOMECH) { 24577c478bd9Sstevel@tonic-gate /* no mechanism available ?!? */ 24587c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, "no plaintext password verifier?"); 24597c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_ 24607c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, "no plaintext password verifier?"); 24617c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */ 24627c478bd9Sstevel@tonic-gate } 24637c478bd9Sstevel@tonic-gate 24647c478bd9Sstevel@tonic-gate RETURN(conn, result); 24657c478bd9Sstevel@tonic-gate } 24667c478bd9Sstevel@tonic-gate 24677c478bd9Sstevel@tonic-gate /* check if an apop exchange is valid 24687c478bd9Sstevel@tonic-gate * (note this is an optional part of the SASL API) 24697c478bd9Sstevel@tonic-gate * if challenge is NULL, just check if APOP is enabled 24707c478bd9Sstevel@tonic-gate * inputs: 24717c478bd9Sstevel@tonic-gate * challenge -- challenge which was sent to client 24727c478bd9Sstevel@tonic-gate * challen -- length of challenge, 0 = strlen(challenge) 24737c478bd9Sstevel@tonic-gate * response -- client response, "<user> <digest>" (RFC 1939) 24747c478bd9Sstevel@tonic-gate * resplen -- length of response, 0 = strlen(response) 24757c478bd9Sstevel@tonic-gate * returns 24767c478bd9Sstevel@tonic-gate * SASL_OK -- success 24777c478bd9Sstevel@tonic-gate * SASL_BADAUTH -- authentication failed 24787c478bd9Sstevel@tonic-gate * SASL_BADPARAM -- missing challenge 24797c478bd9Sstevel@tonic-gate * SASL_BADPROT -- protocol error (e.g., response in wrong format) 24807c478bd9Sstevel@tonic-gate * SASL_NOVERIFY -- user found, but no verifier 24817c478bd9Sstevel@tonic-gate * SASL_NOMECH -- mechanism not supported 24827c478bd9Sstevel@tonic-gate * SASL_NOUSER -- user not found 24837c478bd9Sstevel@tonic-gate */ 24847c478bd9Sstevel@tonic-gate int sasl_checkapop(sasl_conn_t *conn, 24857c478bd9Sstevel@tonic-gate #ifdef DO_SASL_CHECKAPOP 24867c478bd9Sstevel@tonic-gate const char *challenge, 24877c478bd9Sstevel@tonic-gate unsigned challen __attribute__((unused)), 24887c478bd9Sstevel@tonic-gate const char *response, 24897c478bd9Sstevel@tonic-gate unsigned resplen __attribute__((unused))) 24907c478bd9Sstevel@tonic-gate #else 24917c478bd9Sstevel@tonic-gate const char *challenge __attribute__((unused)), 24927c478bd9Sstevel@tonic-gate unsigned challen __attribute__((unused)), 24937c478bd9Sstevel@tonic-gate const char *response __attribute__((unused)), 24947c478bd9Sstevel@tonic-gate unsigned resplen __attribute__((unused))) 24957c478bd9Sstevel@tonic-gate #endif 24967c478bd9Sstevel@tonic-gate { 24977c478bd9Sstevel@tonic-gate #ifdef DO_SASL_CHECKAPOP 24987c478bd9Sstevel@tonic-gate sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn; 24997c478bd9Sstevel@tonic-gate char *user, *user_end; 25007c478bd9Sstevel@tonic-gate const char *password_request[] = { SASL_AUX_PASSWORD, NULL }; 25017c478bd9Sstevel@tonic-gate size_t user_len; 25027c478bd9Sstevel@tonic-gate int result; 25037c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 25047c478bd9Sstevel@tonic-gate _sasl_global_context_t *gctx = 25057c478bd9Sstevel@tonic-gate (conn == NULL) ? _sasl_gbl_ctx() : conn->gctx; 25067c478bd9Sstevel@tonic-gate 25077c478bd9Sstevel@tonic-gate if (gctx->sasl_server_active==0) 25087c478bd9Sstevel@tonic-gate return SASL_NOTINIT; 25097c478bd9Sstevel@tonic-gate #else 25107c478bd9Sstevel@tonic-gate if (_sasl_server_active==0) 25117c478bd9Sstevel@tonic-gate return SASL_NOTINIT; 25127c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 25137c478bd9Sstevel@tonic-gate 25147c478bd9Sstevel@tonic-gate /* check if it's just a query if we are enabled */ 25157c478bd9Sstevel@tonic-gate if(!challenge) 25167c478bd9Sstevel@tonic-gate return SASL_OK; 25177c478bd9Sstevel@tonic-gate 25187c478bd9Sstevel@tonic-gate /* check params */ 25197c478bd9Sstevel@tonic-gate if (!conn) return SASL_BADPARAM; 25207c478bd9Sstevel@tonic-gate if (!response) 25217c478bd9Sstevel@tonic-gate PARAMERROR(conn); 25227c478bd9Sstevel@tonic-gate 25237c478bd9Sstevel@tonic-gate /* Parse out username and digest. 25247c478bd9Sstevel@tonic-gate * 25257c478bd9Sstevel@tonic-gate * Per RFC 1939, response must be "<user> <digest>", where 25267c478bd9Sstevel@tonic-gate * <digest> is a 16-octet value which is sent in hexadecimal 25277c478bd9Sstevel@tonic-gate * format, using lower-case ASCII characters. 25287c478bd9Sstevel@tonic-gate */ 25297c478bd9Sstevel@tonic-gate user_end = strrchr(response, ' '); 25307c478bd9Sstevel@tonic-gate if (!user_end || strspn(user_end + 1, "0123456789abcdef") != 32) 25317c478bd9Sstevel@tonic-gate { 25327c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 25337c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, gettext("Bad Digest")); 25347c478bd9Sstevel@tonic-gate #else 25357c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "Bad Digest"); 25367c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 25377c478bd9Sstevel@tonic-gate RETURN(conn,SASL_BADPROT); 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate 25407c478bd9Sstevel@tonic-gate user_len = (size_t)(user_end - response); 25417c478bd9Sstevel@tonic-gate user = sasl_ALLOC(user_len + 1); 25427c478bd9Sstevel@tonic-gate memcpy(user, response, user_len); 25437c478bd9Sstevel@tonic-gate user[user_len] = '\0'; 25447c478bd9Sstevel@tonic-gate 25457c478bd9Sstevel@tonic-gate result = prop_request(s_conn->sparams->propctx, password_request); 25467c478bd9Sstevel@tonic-gate if(result != SASL_OK) 25477c478bd9Sstevel@tonic-gate { 25487c478bd9Sstevel@tonic-gate sasl_FREE(user); 25497c478bd9Sstevel@tonic-gate RETURN(conn, result); 25507c478bd9Sstevel@tonic-gate } 25517c478bd9Sstevel@tonic-gate 25527c478bd9Sstevel@tonic-gate /* Cannonify it */ 25537c478bd9Sstevel@tonic-gate result = _sasl_canon_user(conn, user, user_len, 25547c478bd9Sstevel@tonic-gate SASL_CU_AUTHID | SASL_CU_AUTHZID, 25557c478bd9Sstevel@tonic-gate &(conn->oparams)); 25567c478bd9Sstevel@tonic-gate sasl_FREE(user); 25577c478bd9Sstevel@tonic-gate 25587c478bd9Sstevel@tonic-gate if(result != SASL_OK) RETURN(conn, result); 25597c478bd9Sstevel@tonic-gate 25607c478bd9Sstevel@tonic-gate /* Do APOP verification */ 25617c478bd9Sstevel@tonic-gate result = _sasl_auxprop_verify_apop(conn, conn->oparams.authid, 25627c478bd9Sstevel@tonic-gate challenge, user_end + 1, s_conn->user_realm); 25637c478bd9Sstevel@tonic-gate 25647c478bd9Sstevel@tonic-gate /* If verification failed, we don't want to encourage getprop to work */ 25657c478bd9Sstevel@tonic-gate if(result != SASL_OK) { 25667c478bd9Sstevel@tonic-gate conn->oparams.user = NULL; 25677c478bd9Sstevel@tonic-gate conn->oparams.authid = NULL; 25687c478bd9Sstevel@tonic-gate } 25697c478bd9Sstevel@tonic-gate 25707c478bd9Sstevel@tonic-gate RETURN(conn, result); 25717c478bd9Sstevel@tonic-gate #else /* sasl_checkapop was disabled at compile time */ 25727c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, 25737c478bd9Sstevel@tonic-gate "sasl_checkapop called, but was disabled at compile time"); 25747c478bd9Sstevel@tonic-gate RETURN(conn, SASL_NOMECH); 25757c478bd9Sstevel@tonic-gate #endif /* DO_SASL_CHECKAPOP */ 25767c478bd9Sstevel@tonic-gate } 25777c478bd9Sstevel@tonic-gate 2578