1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2003 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: checkpw.c,v 1.62 2003/03/19 18:25:27 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 #include <config.h> 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate /* checkpw stuff */ 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #include <stdio.h> 57*7c478bd9Sstevel@tonic-gate #include "sasl.h" 58*7c478bd9Sstevel@tonic-gate #include "saslutil.h" 59*7c478bd9Sstevel@tonic-gate #include "saslplug.h" 60*7c478bd9Sstevel@tonic-gate #include "saslint.h" 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #include <assert.h> 63*7c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H 64*7c478bd9Sstevel@tonic-gate #include <unistd.h> 65*7c478bd9Sstevel@tonic-gate #endif 66*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 67*7c478bd9Sstevel@tonic-gate #ifdef USE_DOORS 68*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 69*7c478bd9Sstevel@tonic-gate #include <door.h> 70*7c478bd9Sstevel@tonic-gate #endif 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate #ifndef WIN32 75*7c478bd9Sstevel@tonic-gate #include <strings.h> 76*7c478bd9Sstevel@tonic-gate #include <netdb.h> 77*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 78*7c478bd9Sstevel@tonic-gate #include <sys/un.h> 79*7c478bd9Sstevel@tonic-gate #else 80*7c478bd9Sstevel@tonic-gate #include <string.h> 81*7c478bd9Sstevel@tonic-gate #endif 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 84*7c478bd9Sstevel@tonic-gate #include <ctype.h> 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate #ifdef HAVE_PWD_H 87*7c478bd9Sstevel@tonic-gate #include <pwd.h> 88*7c478bd9Sstevel@tonic-gate #endif /* HAVE_PWD_H */ 89*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SHADOW_H 90*7c478bd9Sstevel@tonic-gate #include <shadow.h> 91*7c478bd9Sstevel@tonic-gate #endif /* HAVE_SHADOW_H */ 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate #if defined(HAVE_PWCHECK) || defined(HAVE_SASLAUTHD) 94*7c478bd9Sstevel@tonic-gate # include <errno.h> 95*7c478bd9Sstevel@tonic-gate # include <sys/types.h> 96*7c478bd9Sstevel@tonic-gate # include <sys/socket.h> 97*7c478bd9Sstevel@tonic-gate # include <sys/un.h> 98*7c478bd9Sstevel@tonic-gate # ifdef HAVE_UNISTD_H 99*7c478bd9Sstevel@tonic-gate # include <unistd.h> 100*7c478bd9Sstevel@tonic-gate # endif 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate extern int errno; 103*7c478bd9Sstevel@tonic-gate #endif 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* we store the following secret to check plaintext passwords: 107*7c478bd9Sstevel@tonic-gate * 108*7c478bd9Sstevel@tonic-gate * <salt> \0 <secret> 109*7c478bd9Sstevel@tonic-gate * 110*7c478bd9Sstevel@tonic-gate * where <secret> = MD5(<salt>, "sasldb", <pass>) 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 113*7c478bd9Sstevel@tonic-gate static int _sasl_make_plain_secret(const sasl_utils_t *utils, const char *salt, 114*7c478bd9Sstevel@tonic-gate const char *passwd, size_t passlen, 115*7c478bd9Sstevel@tonic-gate sasl_secret_t **secret) 116*7c478bd9Sstevel@tonic-gate #else 117*7c478bd9Sstevel@tonic-gate static int _sasl_make_plain_secret(const char *salt, 118*7c478bd9Sstevel@tonic-gate const char *passwd, size_t passlen, 119*7c478bd9Sstevel@tonic-gate sasl_secret_t **secret) 120*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 121*7c478bd9Sstevel@tonic-gate { 122*7c478bd9Sstevel@tonic-gate MD5_CTX ctx; 123*7c478bd9Sstevel@tonic-gate unsigned sec_len = 16 + 1 + 16; /* salt + "\0" + hash */ 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 126*7c478bd9Sstevel@tonic-gate *secret = (sasl_secret_t *)utils->malloc(sizeof(sasl_secret_t) + 127*7c478bd9Sstevel@tonic-gate sec_len * sizeof(char)); 128*7c478bd9Sstevel@tonic-gate #else 129*7c478bd9Sstevel@tonic-gate *secret = (sasl_secret_t *) sasl_ALLOC(sizeof(sasl_secret_t) + 130*7c478bd9Sstevel@tonic-gate sec_len * sizeof(char)); 131*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 132*7c478bd9Sstevel@tonic-gate if (*secret == NULL) { 133*7c478bd9Sstevel@tonic-gate return SASL_NOMEM; 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate _sasl_MD5Init(&ctx); 137*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&ctx, salt, 16); 138*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&ctx, "sasldb", 6); 139*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&ctx, passwd, passlen); 140*7c478bd9Sstevel@tonic-gate memcpy((*secret)->data, salt, 16); 141*7c478bd9Sstevel@tonic-gate (*secret)->data[16] = '\0'; 142*7c478bd9Sstevel@tonic-gate _sasl_MD5Final((*secret)->data + 17, &ctx); 143*7c478bd9Sstevel@tonic-gate (*secret)->len = sec_len; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate return SASL_OK; 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* erase & dispose of a sasl_secret_t 149*7c478bd9Sstevel@tonic-gate */ 150*7c478bd9Sstevel@tonic-gate static int auxprop_verify_password(sasl_conn_t *conn, 151*7c478bd9Sstevel@tonic-gate const char *userstr, 152*7c478bd9Sstevel@tonic-gate const char *passwd, 153*7c478bd9Sstevel@tonic-gate const char *service __attribute__((unused)), 154*7c478bd9Sstevel@tonic-gate const char *user_realm __attribute__((unused))) 155*7c478bd9Sstevel@tonic-gate { 156*7c478bd9Sstevel@tonic-gate int ret = SASL_FAIL; 157*7c478bd9Sstevel@tonic-gate char *userid = NULL; 158*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_ 159*7c478bd9Sstevel@tonic-gate char *realm = NULL; 160*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */ 161*7c478bd9Sstevel@tonic-gate int result = SASL_OK; 162*7c478bd9Sstevel@tonic-gate sasl_server_conn_t *sconn = (sasl_server_conn_t *)conn; 163*7c478bd9Sstevel@tonic-gate const char *password_request[] = { SASL_AUX_PASSWORD, 164*7c478bd9Sstevel@tonic-gate "*cmusaslsecretPLAIN", 165*7c478bd9Sstevel@tonic-gate NULL }; 166*7c478bd9Sstevel@tonic-gate struct propval auxprop_values[3]; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate if (!conn || !userstr) 169*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* We need to clear any previous results and re-canonify to 172*7c478bd9Sstevel@tonic-gate * ensure correctness */ 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate prop_clear(sconn->sparams->propctx, 0); 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* ensure its requested */ 177*7c478bd9Sstevel@tonic-gate result = prop_request(sconn->sparams->propctx, password_request); 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate if(result != SASL_OK) return result; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate result = _sasl_canon_user(conn, userstr, 0, 182*7c478bd9Sstevel@tonic-gate SASL_CU_AUTHID | SASL_CU_AUTHZID, 183*7c478bd9Sstevel@tonic-gate &(conn->oparams)); 184*7c478bd9Sstevel@tonic-gate if(result != SASL_OK) return result; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate result = prop_getnames(sconn->sparams->propctx, password_request, 187*7c478bd9Sstevel@tonic-gate auxprop_values); 188*7c478bd9Sstevel@tonic-gate if(result < 0) 189*7c478bd9Sstevel@tonic-gate return result; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate if((!auxprop_values[0].name 192*7c478bd9Sstevel@tonic-gate || !auxprop_values[0].values || !auxprop_values[0].values[0]) 193*7c478bd9Sstevel@tonic-gate && (!auxprop_values[1].name 194*7c478bd9Sstevel@tonic-gate || !auxprop_values[1].values || !auxprop_values[1].values[0])) 195*7c478bd9Sstevel@tonic-gate return SASL_NOUSER; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /* It is possible for us to get useful information out of just 198*7c478bd9Sstevel@tonic-gate * the lookup, so we won't check that we have a password until now */ 199*7c478bd9Sstevel@tonic-gate if(!passwd) { 200*7c478bd9Sstevel@tonic-gate ret = SASL_BADPARAM; 201*7c478bd9Sstevel@tonic-gate goto done; 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* At the point this has been called, the username has been canonified 205*7c478bd9Sstevel@tonic-gate * and we've done the auxprop lookup. This should be easy. */ 206*7c478bd9Sstevel@tonic-gate if(auxprop_values[0].name 207*7c478bd9Sstevel@tonic-gate && auxprop_values[0].values 208*7c478bd9Sstevel@tonic-gate && auxprop_values[0].values[0] 209*7c478bd9Sstevel@tonic-gate && !strcmp(auxprop_values[0].values[0], passwd)) { 210*7c478bd9Sstevel@tonic-gate /* We have a plaintext version and it matched! */ 211*7c478bd9Sstevel@tonic-gate return SASL_OK; 212*7c478bd9Sstevel@tonic-gate } else if(auxprop_values[1].name 213*7c478bd9Sstevel@tonic-gate && auxprop_values[1].values 214*7c478bd9Sstevel@tonic-gate && auxprop_values[1].values[0]) { 215*7c478bd9Sstevel@tonic-gate const char *db_secret = auxprop_values[1].values[0]; 216*7c478bd9Sstevel@tonic-gate sasl_secret_t *construct; 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 219*7c478bd9Sstevel@tonic-gate ret = _sasl_make_plain_secret(sconn->sparams->utils, db_secret, 220*7c478bd9Sstevel@tonic-gate passwd, strlen(passwd), 221*7c478bd9Sstevel@tonic-gate &construct); 222*7c478bd9Sstevel@tonic-gate #else 223*7c478bd9Sstevel@tonic-gate ret = _sasl_make_plain_secret(db_secret, passwd, 224*7c478bd9Sstevel@tonic-gate strlen(passwd), 225*7c478bd9Sstevel@tonic-gate &construct); 226*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 227*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) { 228*7c478bd9Sstevel@tonic-gate goto done; 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate if (!memcmp(db_secret, construct->data, construct->len)) { 232*7c478bd9Sstevel@tonic-gate /* password verified! */ 233*7c478bd9Sstevel@tonic-gate ret = SASL_OK; 234*7c478bd9Sstevel@tonic-gate } else { 235*7c478bd9Sstevel@tonic-gate /* passwords do not match */ 236*7c478bd9Sstevel@tonic-gate ret = SASL_BADAUTH; 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 240*7c478bd9Sstevel@tonic-gate sconn->sparams->utils->free(construct); 241*7c478bd9Sstevel@tonic-gate #else 242*7c478bd9Sstevel@tonic-gate sasl_FREE(construct); 243*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 244*7c478bd9Sstevel@tonic-gate } else { 245*7c478bd9Sstevel@tonic-gate /* passwords do not match */ 246*7c478bd9Sstevel@tonic-gate ret = SASL_BADAUTH; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate done: 250*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 251*7c478bd9Sstevel@tonic-gate if (userid) sconn->sparams->utils->free(userid); 252*7c478bd9Sstevel@tonic-gate #else 253*7c478bd9Sstevel@tonic-gate if (userid) sasl_FREE(userid); 254*7c478bd9Sstevel@tonic-gate if (realm) sasl_FREE(realm); 255*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* We're not going to erase the property here because other people 258*7c478bd9Sstevel@tonic-gate * may want it */ 259*7c478bd9Sstevel@tonic-gate return ret; 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate #ifdef DO_SASL_CHECKAPOP 263*7c478bd9Sstevel@tonic-gate int _sasl_auxprop_verify_apop(sasl_conn_t *conn, 264*7c478bd9Sstevel@tonic-gate const char *userstr, 265*7c478bd9Sstevel@tonic-gate const char *challenge, 266*7c478bd9Sstevel@tonic-gate const char *response, 267*7c478bd9Sstevel@tonic-gate const char *user_realm __attribute__((unused))) 268*7c478bd9Sstevel@tonic-gate { 269*7c478bd9Sstevel@tonic-gate int ret = SASL_BADAUTH; 270*7c478bd9Sstevel@tonic-gate char *userid = NULL; 271*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_ 272*7c478bd9Sstevel@tonic-gate char *realm = NULL; 273*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */ 274*7c478bd9Sstevel@tonic-gate unsigned char digest[16]; 275*7c478bd9Sstevel@tonic-gate char digeststr[33]; 276*7c478bd9Sstevel@tonic-gate const char *password_request[] = { SASL_AUX_PASSWORD, NULL }; 277*7c478bd9Sstevel@tonic-gate struct propval auxprop_values[2]; 278*7c478bd9Sstevel@tonic-gate sasl_server_conn_t *sconn = (sasl_server_conn_t *)conn; 279*7c478bd9Sstevel@tonic-gate MD5_CTX ctx; 280*7c478bd9Sstevel@tonic-gate int i; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if (!conn || !userstr || !challenge || !response) 283*7c478bd9Sstevel@tonic-gate PARAMERROR(conn) 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* We've done the auxprop lookup already (in our caller) */ 286*7c478bd9Sstevel@tonic-gate /* sadly, APOP has no provision for storing secrets */ 287*7c478bd9Sstevel@tonic-gate ret = prop_getnames(sconn->sparams->propctx, password_request, 288*7c478bd9Sstevel@tonic-gate auxprop_values); 289*7c478bd9Sstevel@tonic-gate if(ret < 0) { 290*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 291*7c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_ERR, "could not perform password lookup"); 292*7c478bd9Sstevel@tonic-gate #else 293*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "could not perform password lookup"); 294*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 295*7c478bd9Sstevel@tonic-gate goto done; 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate if(!auxprop_values[0].name || 299*7c478bd9Sstevel@tonic-gate !auxprop_values[0].values || 300*7c478bd9Sstevel@tonic-gate !auxprop_values[0].values[0]) { 301*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 302*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, gettext("could not find password")); 303*7c478bd9Sstevel@tonic-gate #else 304*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "could not find password"); 305*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 306*7c478bd9Sstevel@tonic-gate ret = SASL_NOUSER; 307*7c478bd9Sstevel@tonic-gate goto done; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate _sasl_MD5Init(&ctx); 311*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&ctx, challenge, strlen(challenge)); 312*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&ctx, auxprop_values[0].values[0], 313*7c478bd9Sstevel@tonic-gate strlen(auxprop_values[0].values[0])); 314*7c478bd9Sstevel@tonic-gate _sasl_MD5Final(digest, &ctx); 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* convert digest from binary to ASCII hex */ 317*7c478bd9Sstevel@tonic-gate for (i = 0; i < 16; i++) 318*7c478bd9Sstevel@tonic-gate sprintf(digeststr + (i*2), "%02x", digest[i]); 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate if (!strncasecmp(digeststr, response, 32)) { 321*7c478bd9Sstevel@tonic-gate /* password verified! */ 322*7c478bd9Sstevel@tonic-gate ret = SASL_OK; 323*7c478bd9Sstevel@tonic-gate } else { 324*7c478bd9Sstevel@tonic-gate /* passwords do not match */ 325*7c478bd9Sstevel@tonic-gate ret = SASL_BADAUTH; 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate done: 329*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 330*7c478bd9Sstevel@tonic-gate if (ret == SASL_BADAUTH) sasl_seterror(conn, SASL_NOLOG, 331*7c478bd9Sstevel@tonic-gate gettext("login incorrect")); 332*7c478bd9Sstevel@tonic-gate #else 333*7c478bd9Sstevel@tonic-gate if (ret == SASL_BADAUTH) sasl_seterror(conn, SASL_NOLOG, 334*7c478bd9Sstevel@tonic-gate "login incorrect"); 335*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 336*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 337*7c478bd9Sstevel@tonic-gate if (userid) sconn->sparams->utils->free(userid); 338*7c478bd9Sstevel@tonic-gate #else 339*7c478bd9Sstevel@tonic-gate if (userid) sasl_FREE(userid); 340*7c478bd9Sstevel@tonic-gate if (realm) sasl_FREE(realm); 341*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate return ret; 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate #endif /* DO_SASL_CHECKAPOP */ 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate #if defined(HAVE_PWCHECK) || defined(HAVE_SASLAUTHD) 348*7c478bd9Sstevel@tonic-gate /* 349*7c478bd9Sstevel@tonic-gate * Keep calling the writev() system call with 'fd', 'iov', and 'iovcnt' 350*7c478bd9Sstevel@tonic-gate * until all the data is written out or an error occurs. 351*7c478bd9Sstevel@tonic-gate */ 352*7c478bd9Sstevel@tonic-gate static int retry_writev(int fd, struct iovec *iov, int iovcnt) 353*7c478bd9Sstevel@tonic-gate { 354*7c478bd9Sstevel@tonic-gate int n; 355*7c478bd9Sstevel@tonic-gate int i; 356*7c478bd9Sstevel@tonic-gate int written = 0; 357*7c478bd9Sstevel@tonic-gate static int iov_max = 358*7c478bd9Sstevel@tonic-gate #ifdef MAXIOV 359*7c478bd9Sstevel@tonic-gate MAXIOV 360*7c478bd9Sstevel@tonic-gate #else 361*7c478bd9Sstevel@tonic-gate #ifdef IOV_MAX 362*7c478bd9Sstevel@tonic-gate IOV_MAX 363*7c478bd9Sstevel@tonic-gate #else 364*7c478bd9Sstevel@tonic-gate 8192 365*7c478bd9Sstevel@tonic-gate #endif 366*7c478bd9Sstevel@tonic-gate #endif 367*7c478bd9Sstevel@tonic-gate ; 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate for (;;) { 370*7c478bd9Sstevel@tonic-gate while (iovcnt && iov[0].iov_len == 0) { 371*7c478bd9Sstevel@tonic-gate iov++; 372*7c478bd9Sstevel@tonic-gate iovcnt--; 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate if (!iovcnt) return written; 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate n = writev(fd, iov, iovcnt > iov_max ? iov_max : iovcnt); 378*7c478bd9Sstevel@tonic-gate if (n == -1) { 379*7c478bd9Sstevel@tonic-gate if (errno == EINVAL && iov_max > 10) { 380*7c478bd9Sstevel@tonic-gate iov_max /= 2; 381*7c478bd9Sstevel@tonic-gate continue; 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate if (errno == EINTR) continue; 384*7c478bd9Sstevel@tonic-gate return -1; 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate written += n; 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate for (i = 0; i < iovcnt; i++) { 390*7c478bd9Sstevel@tonic-gate if (iov[i].iov_len > (unsigned) n) { 391*7c478bd9Sstevel@tonic-gate iov[i].iov_base = (char *)iov[i].iov_base + n; 392*7c478bd9Sstevel@tonic-gate iov[i].iov_len -= n; 393*7c478bd9Sstevel@tonic-gate break; 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate n -= iov[i].iov_len; 396*7c478bd9Sstevel@tonic-gate iov[i].iov_len = 0; 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate if (i == iovcnt) return written; 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate #endif 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate #ifdef HAVE_PWCHECK 406*7c478bd9Sstevel@tonic-gate /* pwcheck daemon-authenticated login */ 407*7c478bd9Sstevel@tonic-gate static int pwcheck_verify_password(sasl_conn_t *conn, 408*7c478bd9Sstevel@tonic-gate const char *userid, 409*7c478bd9Sstevel@tonic-gate const char *passwd, 410*7c478bd9Sstevel@tonic-gate const char *service __attribute__((unused)), 411*7c478bd9Sstevel@tonic-gate const char *user_realm 412*7c478bd9Sstevel@tonic-gate __attribute__((unused))) 413*7c478bd9Sstevel@tonic-gate { 414*7c478bd9Sstevel@tonic-gate int s; 415*7c478bd9Sstevel@tonic-gate struct sockaddr_un srvaddr; 416*7c478bd9Sstevel@tonic-gate int r; 417*7c478bd9Sstevel@tonic-gate struct iovec iov[10]; 418*7c478bd9Sstevel@tonic-gate static char response[1024]; 419*7c478bd9Sstevel@tonic-gate unsigned start, n; 420*7c478bd9Sstevel@tonic-gate char pwpath[1024]; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate if (strlen(PWCHECKDIR)+8+1 > sizeof(pwpath)) return SASL_FAIL; 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate strcpy(pwpath, PWCHECKDIR); 425*7c478bd9Sstevel@tonic-gate strcat(pwpath, "/pwcheck"); 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate s = socket(AF_UNIX, SOCK_STREAM, 0); 428*7c478bd9Sstevel@tonic-gate if (s == -1) return errno; 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate memset((char *)&srvaddr, 0, sizeof(srvaddr)); 431*7c478bd9Sstevel@tonic-gate srvaddr.sun_family = AF_UNIX; 432*7c478bd9Sstevel@tonic-gate strncpy(srvaddr.sun_path, pwpath, sizeof(srvaddr.sun_path)); 433*7c478bd9Sstevel@tonic-gate r = connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr)); 434*7c478bd9Sstevel@tonic-gate if (r == -1) { 435*7c478bd9Sstevel@tonic-gate sasl_seterror(conn,0,"cannot connect to pwcheck server"); 436*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate iov[0].iov_base = (char *)userid; 440*7c478bd9Sstevel@tonic-gate iov[0].iov_len = strlen(userid)+1; 441*7c478bd9Sstevel@tonic-gate iov[1].iov_base = (char *)passwd; 442*7c478bd9Sstevel@tonic-gate iov[1].iov_len = strlen(passwd)+1; 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate retry_writev(s, iov, 2); 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate start = 0; 447*7c478bd9Sstevel@tonic-gate while (start < sizeof(response) - 1) { 448*7c478bd9Sstevel@tonic-gate n = read(s, response+start, sizeof(response) - 1 - start); 449*7c478bd9Sstevel@tonic-gate if (n < 1) break; 450*7c478bd9Sstevel@tonic-gate start += n; 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate close(s); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate if (start > 1 && !strncmp(response, "OK", 2)) { 456*7c478bd9Sstevel@tonic-gate return SASL_OK; 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate response[start] = '\0'; 460*7c478bd9Sstevel@tonic-gate sasl_seterror(conn,0,response); 461*7c478bd9Sstevel@tonic-gate return SASL_BADAUTH; 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate #endif 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SASLAUTHD 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate /* 469*7c478bd9Sstevel@tonic-gate * Keep calling the read() system call with 'fd', 'buf', and 'nbyte' 470*7c478bd9Sstevel@tonic-gate * until all the data is read in or an error occurs. 471*7c478bd9Sstevel@tonic-gate */ 472*7c478bd9Sstevel@tonic-gate static int retry_read(int fd, void *buf0, unsigned nbyte) 473*7c478bd9Sstevel@tonic-gate { 474*7c478bd9Sstevel@tonic-gate int n; 475*7c478bd9Sstevel@tonic-gate int nread = 0; 476*7c478bd9Sstevel@tonic-gate char *buf = buf0; 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate if (nbyte == 0) return 0; 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate for (;;) { 481*7c478bd9Sstevel@tonic-gate n = read(fd, buf, nbyte); 482*7c478bd9Sstevel@tonic-gate if (n == -1 || n == 0) { 483*7c478bd9Sstevel@tonic-gate if (errno == EINTR || errno == EAGAIN) continue; 484*7c478bd9Sstevel@tonic-gate return -1; 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate nread += n; 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate if (nread >= (int) nbyte) return nread; 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate buf += n; 492*7c478bd9Sstevel@tonic-gate nbyte -= n; 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate /* saslauthd-authenticated login */ 497*7c478bd9Sstevel@tonic-gate static int saslauthd_verify_password(sasl_conn_t *conn, 498*7c478bd9Sstevel@tonic-gate const char *userid, 499*7c478bd9Sstevel@tonic-gate const char *passwd, 500*7c478bd9Sstevel@tonic-gate const char *service, 501*7c478bd9Sstevel@tonic-gate const char *user_realm) 502*7c478bd9Sstevel@tonic-gate { 503*7c478bd9Sstevel@tonic-gate char response[1024]; 504*7c478bd9Sstevel@tonic-gate char query[8192]; 505*7c478bd9Sstevel@tonic-gate char *query_end = query; 506*7c478bd9Sstevel@tonic-gate int s; 507*7c478bd9Sstevel@tonic-gate struct sockaddr_un srvaddr; 508*7c478bd9Sstevel@tonic-gate sasl_getopt_t *getopt; 509*7c478bd9Sstevel@tonic-gate void *context; 510*7c478bd9Sstevel@tonic-gate char pwpath[sizeof(srvaddr.sun_path)]; 511*7c478bd9Sstevel@tonic-gate const char *p = NULL; 512*7c478bd9Sstevel@tonic-gate #ifdef USE_DOORS 513*7c478bd9Sstevel@tonic-gate door_arg_t arg; 514*7c478bd9Sstevel@tonic-gate #endif 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate /* check to see if the user configured a rundir */ 517*7c478bd9Sstevel@tonic-gate if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { 518*7c478bd9Sstevel@tonic-gate getopt(context, NULL, "saslauthd_path", &p, NULL); 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate if (p) { 521*7c478bd9Sstevel@tonic-gate strncpy(pwpath, p, sizeof(pwpath)); 522*7c478bd9Sstevel@tonic-gate } else { 523*7c478bd9Sstevel@tonic-gate if (strlen(PATH_SASLAUTHD_RUNDIR) + 4 + 1 > sizeof(pwpath)) 524*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate strcpy(pwpath, PATH_SASLAUTHD_RUNDIR); 527*7c478bd9Sstevel@tonic-gate strcat(pwpath, "/mux"); 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate /* 531*7c478bd9Sstevel@tonic-gate * build request of the form: 532*7c478bd9Sstevel@tonic-gate * 533*7c478bd9Sstevel@tonic-gate * count authid count password count service count realm 534*7c478bd9Sstevel@tonic-gate */ 535*7c478bd9Sstevel@tonic-gate { 536*7c478bd9Sstevel@tonic-gate unsigned short u_len, p_len, s_len, r_len; 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate u_len = (strlen(userid)); 539*7c478bd9Sstevel@tonic-gate p_len = (strlen(passwd)); 540*7c478bd9Sstevel@tonic-gate s_len = (strlen(service)); 541*7c478bd9Sstevel@tonic-gate r_len = ((user_realm ? strlen(user_realm) : 0)); 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate if (u_len + p_len + s_len + r_len + 30 > (unsigned short) sizeof(query)) { 544*7c478bd9Sstevel@tonic-gate /* request just too damn big */ 545*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "saslauthd request too large"); 546*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate u_len = htons(u_len); 550*7c478bd9Sstevel@tonic-gate p_len = htons(p_len); 551*7c478bd9Sstevel@tonic-gate s_len = htons(s_len); 552*7c478bd9Sstevel@tonic-gate r_len = htons(r_len); 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate memcpy(query_end, &u_len, sizeof(unsigned short)); 555*7c478bd9Sstevel@tonic-gate query_end += sizeof(unsigned short); 556*7c478bd9Sstevel@tonic-gate while (*userid) *query_end++ = *userid++; 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate memcpy(query_end, &p_len, sizeof(unsigned short)); 559*7c478bd9Sstevel@tonic-gate query_end += sizeof(unsigned short); 560*7c478bd9Sstevel@tonic-gate while (*passwd) *query_end++ = *passwd++; 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate memcpy(query_end, &s_len, sizeof(unsigned short)); 563*7c478bd9Sstevel@tonic-gate query_end += sizeof(unsigned short); 564*7c478bd9Sstevel@tonic-gate while (*service) *query_end++ = *service++; 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate memcpy(query_end, &r_len, sizeof(unsigned short)); 567*7c478bd9Sstevel@tonic-gate query_end += sizeof(unsigned short); 568*7c478bd9Sstevel@tonic-gate if (user_realm) while (*user_realm) *query_end++ = *user_realm++; 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate #ifdef USE_DOORS 572*7c478bd9Sstevel@tonic-gate s = open(pwpath, O_RDONLY); 573*7c478bd9Sstevel@tonic-gate if (s < 0) { 574*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "cannot open door to saslauthd server: %m", errno); 575*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate arg.data_ptr = query; 579*7c478bd9Sstevel@tonic-gate arg.data_size = query_end - query; 580*7c478bd9Sstevel@tonic-gate arg.desc_ptr = NULL; 581*7c478bd9Sstevel@tonic-gate arg.desc_num = 0; 582*7c478bd9Sstevel@tonic-gate arg.rbuf = response; 583*7c478bd9Sstevel@tonic-gate arg.rsize = sizeof(response); 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate door_call(s, &arg); 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate if (arg.data_ptr != response || arg.data_size >= sizeof(response)) { 588*7c478bd9Sstevel@tonic-gate /* oh damn, we got back a really long response */ 589*7c478bd9Sstevel@tonic-gate munmap(arg.rbuf, arg.rsize); 590*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "saslauthd sent an overly long response"); 591*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate response[arg.data_size] = '\0'; 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate close(s); 596*7c478bd9Sstevel@tonic-gate #else 597*7c478bd9Sstevel@tonic-gate /* unix sockets */ 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate s = socket(AF_UNIX, SOCK_STREAM, 0); 600*7c478bd9Sstevel@tonic-gate if (s == -1) { 601*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "cannot create socket for saslauthd: %m", errno); 602*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate memset((char *)&srvaddr, 0, sizeof(srvaddr)); 606*7c478bd9Sstevel@tonic-gate srvaddr.sun_family = AF_UNIX; 607*7c478bd9Sstevel@tonic-gate strncpy(srvaddr.sun_path, pwpath, sizeof(srvaddr.sun_path)); 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate { 610*7c478bd9Sstevel@tonic-gate int r = connect(s, (struct sockaddr *) &srvaddr, sizeof(srvaddr)); 611*7c478bd9Sstevel@tonic-gate if (r == -1) { 612*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "cannot connect to saslauthd server: %m", errno); 613*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate { 618*7c478bd9Sstevel@tonic-gate struct iovec iov[8]; 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate iov[0].iov_len = query_end - query; 621*7c478bd9Sstevel@tonic-gate iov[0].iov_base = query; 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate if (retry_writev(s, iov, 1) == -1) { 624*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "write failed"); 625*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate { 630*7c478bd9Sstevel@tonic-gate unsigned short count = 0; 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate /* 633*7c478bd9Sstevel@tonic-gate * read response of the form: 634*7c478bd9Sstevel@tonic-gate * 635*7c478bd9Sstevel@tonic-gate * count result 636*7c478bd9Sstevel@tonic-gate */ 637*7c478bd9Sstevel@tonic-gate if (retry_read(s, &count, sizeof(count)) < (int) sizeof(count)) { 638*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "size read failed"); 639*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 640*7c478bd9Sstevel@tonic-gate } 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate count = ntohs(count); 643*7c478bd9Sstevel@tonic-gate if (count < 2) { /* MUST have at least "OK" or "NO" */ 644*7c478bd9Sstevel@tonic-gate close(s); 645*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "bad response from saslauthd"); 646*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate count = (int)sizeof(response) < count ? sizeof(response) : count; 650*7c478bd9Sstevel@tonic-gate if (retry_read(s, response, count) < count) { 651*7c478bd9Sstevel@tonic-gate close(s); 652*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, 0, "read failed"); 653*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate response[count] = '\0'; 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate close(s); 659*7c478bd9Sstevel@tonic-gate #endif /* USE_DOORS */ 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate if (!strncmp(response, "OK", 2)) { 662*7c478bd9Sstevel@tonic-gate return SASL_OK; 663*7c478bd9Sstevel@tonic-gate } 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate sasl_seterror(conn, SASL_NOLOG, "authentication failed"); 666*7c478bd9Sstevel@tonic-gate return SASL_BADAUTH; 667*7c478bd9Sstevel@tonic-gate } 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate #endif 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate #ifdef HAVE_ALWAYSTRUE 672*7c478bd9Sstevel@tonic-gate static int always_true(sasl_conn_t *conn, 673*7c478bd9Sstevel@tonic-gate const char *userstr, 674*7c478bd9Sstevel@tonic-gate const char *passwd __attribute__((unused)), 675*7c478bd9Sstevel@tonic-gate const char *service __attribute__((unused)), 676*7c478bd9Sstevel@tonic-gate const char *user_realm __attribute__((unused))) 677*7c478bd9Sstevel@tonic-gate { 678*7c478bd9Sstevel@tonic-gate _sasl_log(conn, SASL_LOG_WARN, "AlwaysTrue Password Verifier Verified: %s", 679*7c478bd9Sstevel@tonic-gate userstr); 680*7c478bd9Sstevel@tonic-gate return SASL_OK; 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate #endif 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate struct sasl_verify_password_s _sasl_verify_password[] = { 685*7c478bd9Sstevel@tonic-gate { "auxprop", &auxprop_verify_password }, 686*7c478bd9Sstevel@tonic-gate #ifdef HAVE_PWCHECK 687*7c478bd9Sstevel@tonic-gate { "pwcheck", &pwcheck_verify_password }, 688*7c478bd9Sstevel@tonic-gate #endif 689*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SASLAUTHD 690*7c478bd9Sstevel@tonic-gate { "saslauthd", &saslauthd_verify_password }, 691*7c478bd9Sstevel@tonic-gate #endif 692*7c478bd9Sstevel@tonic-gate #ifdef HAVE_ALWAYSTRUE 693*7c478bd9Sstevel@tonic-gate { "alwaystrue", &always_true }, 694*7c478bd9Sstevel@tonic-gate #endif 695*7c478bd9Sstevel@tonic-gate { NULL, NULL } 696*7c478bd9Sstevel@tonic-gate }; 697