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