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