xref: /illumos-gate/usr/src/lib/libsasl/lib/checkpw.c (revision 1da57d55)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /* SASL server API implementation
77c478bd9Sstevel@tonic-gate  * Rob Siemborski
87c478bd9Sstevel@tonic-gate  * Tim Martin
97c478bd9Sstevel@tonic-gate  * $Id: checkpw.c,v 1.62 2003/03/19 18:25:27 rjs3 Exp $
107c478bd9Sstevel@tonic-gate  */
11*1da57d55SToomas Soome /*
127c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
157c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
167c478bd9Sstevel@tonic-gate  * are met:
177c478bd9Sstevel@tonic-gate  *
187c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
19*1da57d55SToomas Soome  *    notice, this list of conditions and the following disclaimer.
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
227c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
237c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
247c478bd9Sstevel@tonic-gate  *    distribution.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
277c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
287c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
29*1da57d55SToomas Soome  *    details, please contact
307c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
317c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
327c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
337c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
347c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
357c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
387c478bd9Sstevel@tonic-gate  *    acknowledgment:
397c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
407c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
437c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
447c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
457c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
467c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
477c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
487c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #include <config.h>
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /* checkpw stuff */
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #include <stdio.h>
567c478bd9Sstevel@tonic-gate #include "sasl.h"
577c478bd9Sstevel@tonic-gate #include "saslutil.h"
587c478bd9Sstevel@tonic-gate #include "saslplug.h"
597c478bd9Sstevel@tonic-gate #include "saslint.h"
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #include <assert.h>
627c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H
637c478bd9Sstevel@tonic-gate #include <unistd.h>
647c478bd9Sstevel@tonic-gate #endif
657c478bd9Sstevel@tonic-gate #include <fcntl.h>
667c478bd9Sstevel@tonic-gate #ifdef USE_DOORS
677c478bd9Sstevel@tonic-gate #include <sys/mman.h>
687c478bd9Sstevel@tonic-gate #include <door.h>
697c478bd9Sstevel@tonic-gate #endif
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #include <stdlib.h>
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #ifndef WIN32
747c478bd9Sstevel@tonic-gate #include <strings.h>
757c478bd9Sstevel@tonic-gate #include <netdb.h>
767c478bd9Sstevel@tonic-gate #include <netinet/in.h>
777c478bd9Sstevel@tonic-gate #include <sys/un.h>
787c478bd9Sstevel@tonic-gate #else
797c478bd9Sstevel@tonic-gate #include <string.h>
807c478bd9Sstevel@tonic-gate #endif
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate #include <sys/types.h>
837c478bd9Sstevel@tonic-gate #include <ctype.h>
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate #ifdef HAVE_PWD_H
867c478bd9Sstevel@tonic-gate #include <pwd.h>
877c478bd9Sstevel@tonic-gate #endif /* HAVE_PWD_H */
887c478bd9Sstevel@tonic-gate #ifdef HAVE_SHADOW_H
897c478bd9Sstevel@tonic-gate #include <shadow.h>
907c478bd9Sstevel@tonic-gate #endif /* HAVE_SHADOW_H */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #if defined(HAVE_PWCHECK) || defined(HAVE_SASLAUTHD)
937c478bd9Sstevel@tonic-gate # include <errno.h>
947c478bd9Sstevel@tonic-gate # include <sys/types.h>
957c478bd9Sstevel@tonic-gate # include <sys/socket.h>
967c478bd9Sstevel@tonic-gate # include <sys/un.h>
977c478bd9Sstevel@tonic-gate # ifdef HAVE_UNISTD_H
987c478bd9Sstevel@tonic-gate #  include <unistd.h>
997c478bd9Sstevel@tonic-gate # endif
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate extern int errno;
1027c478bd9Sstevel@tonic-gate #endif
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /* we store the following secret to check plaintext passwords:
1067c478bd9Sstevel@tonic-gate  *
1077c478bd9Sstevel@tonic-gate  * <salt> \0 <secret>
1087c478bd9Sstevel@tonic-gate  *
1097c478bd9Sstevel@tonic-gate  * where <secret> = MD5(<salt>, "sasldb", <pass>)
1107c478bd9Sstevel@tonic-gate  */
1117c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
_sasl_make_plain_secret(const sasl_utils_t * utils,const char * salt,const char * passwd,size_t passlen,sasl_secret_t ** secret)1127c478bd9Sstevel@tonic-gate static int _sasl_make_plain_secret(const sasl_utils_t *utils, const char *salt,
1137c478bd9Sstevel@tonic-gate 				const char *passwd, size_t passlen,
1147c478bd9Sstevel@tonic-gate 				sasl_secret_t **secret)
1157c478bd9Sstevel@tonic-gate #else
116*1da57d55SToomas Soome static int _sasl_make_plain_secret(const char *salt,
1177c478bd9Sstevel@tonic-gate 				   const char *passwd, size_t passlen,
1187c478bd9Sstevel@tonic-gate 				   sasl_secret_t **secret)
1197c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate     MD5_CTX ctx;
1227c478bd9Sstevel@tonic-gate     unsigned sec_len = 16 + 1 + 16; /* salt + "\0" + hash */
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1257c478bd9Sstevel@tonic-gate     *secret = (sasl_secret_t *)utils->malloc(sizeof(sasl_secret_t) +
1267c478bd9Sstevel@tonic-gate 					sec_len * sizeof(char));
1277c478bd9Sstevel@tonic-gate #else
1287c478bd9Sstevel@tonic-gate     *secret = (sasl_secret_t *) sasl_ALLOC(sizeof(sasl_secret_t) +
1297c478bd9Sstevel@tonic-gate 					   sec_len * sizeof(char));
1307c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1317c478bd9Sstevel@tonic-gate     if (*secret == NULL) {
1327c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
1337c478bd9Sstevel@tonic-gate     }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate     _sasl_MD5Init(&ctx);
1367c478bd9Sstevel@tonic-gate     _sasl_MD5Update(&ctx, salt, 16);
1377c478bd9Sstevel@tonic-gate     _sasl_MD5Update(&ctx, "sasldb", 6);
1387c478bd9Sstevel@tonic-gate     _sasl_MD5Update(&ctx, passwd, passlen);
1397c478bd9Sstevel@tonic-gate     memcpy((*secret)->data, salt, 16);
1407c478bd9Sstevel@tonic-gate     (*secret)->data[16] = '\0';
1417c478bd9Sstevel@tonic-gate     _sasl_MD5Final((*secret)->data + 17, &ctx);
1427c478bd9Sstevel@tonic-gate     (*secret)->len = sec_len;
143*1da57d55SToomas Soome 
1447c478bd9Sstevel@tonic-gate     return SASL_OK;
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate /* erase & dispose of a sasl_secret_t
1487c478bd9Sstevel@tonic-gate  */
auxprop_verify_password(sasl_conn_t * conn,const char * userstr,const char * passwd,const char * service,const char * user_realm)1497c478bd9Sstevel@tonic-gate static int auxprop_verify_password(sasl_conn_t *conn,
1507c478bd9Sstevel@tonic-gate 				   const char *userstr,
1517c478bd9Sstevel@tonic-gate 				   const char *passwd,
1527c478bd9Sstevel@tonic-gate 				   const char *service __attribute__((unused)),
1537c478bd9Sstevel@tonic-gate 				   const char *user_realm __attribute__((unused)))
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate     int ret = SASL_FAIL;
1567c478bd9Sstevel@tonic-gate     char *userid = NULL;
1577c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1587c478bd9Sstevel@tonic-gate     char *realm = NULL;
1597c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1607c478bd9Sstevel@tonic-gate     int result = SASL_OK;
1617c478bd9Sstevel@tonic-gate     sasl_server_conn_t *sconn = (sasl_server_conn_t *)conn;
1627c478bd9Sstevel@tonic-gate     const char *password_request[] = { SASL_AUX_PASSWORD,
1637c478bd9Sstevel@tonic-gate 				       "*cmusaslsecretPLAIN",
1647c478bd9Sstevel@tonic-gate 				       NULL };
1657c478bd9Sstevel@tonic-gate     struct propval auxprop_values[3];
166*1da57d55SToomas Soome 
1677c478bd9Sstevel@tonic-gate     if (!conn || !userstr)
1687c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
1697c478bd9Sstevel@tonic-gate 
170*1da57d55SToomas Soome     /* We need to clear any previous results and re-canonify to
1717c478bd9Sstevel@tonic-gate      * ensure correctness */
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate     prop_clear(sconn->sparams->propctx, 0);
174*1da57d55SToomas Soome 
1757c478bd9Sstevel@tonic-gate     /* ensure its requested */
1767c478bd9Sstevel@tonic-gate     result = prop_request(sconn->sparams->propctx, password_request);
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate     if(result != SASL_OK) return result;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate     result = _sasl_canon_user(conn, userstr, 0,
1817c478bd9Sstevel@tonic-gate 			      SASL_CU_AUTHID | SASL_CU_AUTHZID,
1827c478bd9Sstevel@tonic-gate 			      &(conn->oparams));
1837c478bd9Sstevel@tonic-gate     if(result != SASL_OK) return result;
184*1da57d55SToomas Soome 
1857c478bd9Sstevel@tonic-gate     result = prop_getnames(sconn->sparams->propctx, password_request,
1867c478bd9Sstevel@tonic-gate 			   auxprop_values);
1877c478bd9Sstevel@tonic-gate     if(result < 0)
1887c478bd9Sstevel@tonic-gate 	return result;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate     if((!auxprop_values[0].name
1917c478bd9Sstevel@tonic-gate          || !auxprop_values[0].values || !auxprop_values[0].values[0])
1927c478bd9Sstevel@tonic-gate        && (!auxprop_values[1].name
1937c478bd9Sstevel@tonic-gate          || !auxprop_values[1].values || !auxprop_values[1].values[0]))
1947c478bd9Sstevel@tonic-gate 	    return SASL_NOUSER;
195*1da57d55SToomas Soome 
1967c478bd9Sstevel@tonic-gate     /* It is possible for us to get useful information out of just
1977c478bd9Sstevel@tonic-gate      * the lookup, so we won't check that we have a password until now */
1987c478bd9Sstevel@tonic-gate     if(!passwd) {
1997c478bd9Sstevel@tonic-gate 	ret = SASL_BADPARAM;
2007c478bd9Sstevel@tonic-gate 	goto done;
2017c478bd9Sstevel@tonic-gate     }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate     /* At the point this has been called, the username has been canonified
2047c478bd9Sstevel@tonic-gate      * and we've done the auxprop lookup.  This should be easy. */
2057c478bd9Sstevel@tonic-gate     if(auxprop_values[0].name
2067c478bd9Sstevel@tonic-gate        && auxprop_values[0].values
2077c478bd9Sstevel@tonic-gate        && auxprop_values[0].values[0]
2087c478bd9Sstevel@tonic-gate        && !strcmp(auxprop_values[0].values[0], passwd)) {
2097c478bd9Sstevel@tonic-gate 	/* We have a plaintext version and it matched! */
2107c478bd9Sstevel@tonic-gate 	return SASL_OK;
2117c478bd9Sstevel@tonic-gate     } else if(auxprop_values[1].name
2127c478bd9Sstevel@tonic-gate 	      && auxprop_values[1].values
2137c478bd9Sstevel@tonic-gate 	      && auxprop_values[1].values[0]) {
2147c478bd9Sstevel@tonic-gate 	const char *db_secret = auxprop_values[1].values[0];
2157c478bd9Sstevel@tonic-gate 	sasl_secret_t *construct;
216*1da57d55SToomas Soome 
2177c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2187c478bd9Sstevel@tonic-gate 	ret = _sasl_make_plain_secret(sconn->sparams->utils, db_secret,
2197c478bd9Sstevel@tonic-gate 				passwd, strlen(passwd),
2207c478bd9Sstevel@tonic-gate 				&construct);
2217c478bd9Sstevel@tonic-gate #else
2227c478bd9Sstevel@tonic-gate 	ret = _sasl_make_plain_secret(db_secret, passwd,
2237c478bd9Sstevel@tonic-gate 				      strlen(passwd),
2247c478bd9Sstevel@tonic-gate 				      &construct);
2257c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2267c478bd9Sstevel@tonic-gate 	if (ret != SASL_OK) {
2277c478bd9Sstevel@tonic-gate 	    goto done;
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (!memcmp(db_secret, construct->data, construct->len)) {
2317c478bd9Sstevel@tonic-gate 	    /* password verified! */
2327c478bd9Sstevel@tonic-gate 	    ret = SASL_OK;
2337c478bd9Sstevel@tonic-gate 	} else {
2347c478bd9Sstevel@tonic-gate 	    /* passwords do not match */
2357c478bd9Sstevel@tonic-gate 	    ret = SASL_BADAUTH;
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2397c478bd9Sstevel@tonic-gate 	sconn->sparams->utils->free(construct);
2407c478bd9Sstevel@tonic-gate #else
2417c478bd9Sstevel@tonic-gate 	sasl_FREE(construct);
2427c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2437c478bd9Sstevel@tonic-gate     } else {
2447c478bd9Sstevel@tonic-gate 	/* passwords do not match */
2457c478bd9Sstevel@tonic-gate 	ret = SASL_BADAUTH;
2467c478bd9Sstevel@tonic-gate     }
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate  done:
2497c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2507c478bd9Sstevel@tonic-gate     if (userid) sconn->sparams->utils->free(userid);
2517c478bd9Sstevel@tonic-gate #else
2527c478bd9Sstevel@tonic-gate     if (userid) sasl_FREE(userid);
2537c478bd9Sstevel@tonic-gate     if (realm)  sasl_FREE(realm);
2547c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate     /* We're not going to erase the property here because other people
2577c478bd9Sstevel@tonic-gate      * may want it */
2587c478bd9Sstevel@tonic-gate     return ret;
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate #ifdef DO_SASL_CHECKAPOP
_sasl_auxprop_verify_apop(sasl_conn_t * conn,const char * userstr,const char * challenge,const char * response,const char * user_realm)2627c478bd9Sstevel@tonic-gate int _sasl_auxprop_verify_apop(sasl_conn_t *conn,
2637c478bd9Sstevel@tonic-gate 			      const char *userstr,
2647c478bd9Sstevel@tonic-gate 			      const char *challenge,
2657c478bd9Sstevel@tonic-gate 			      const char *response,
2667c478bd9Sstevel@tonic-gate 			      const char *user_realm __attribute__((unused)))
2677c478bd9Sstevel@tonic-gate {
2687c478bd9Sstevel@tonic-gate     int ret = SASL_BADAUTH;
2697c478bd9Sstevel@tonic-gate     char *userid = NULL;
2707c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
2717c478bd9Sstevel@tonic-gate     char *realm = NULL;
2727c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
2737c478bd9Sstevel@tonic-gate     unsigned char digest[16];
2747c478bd9Sstevel@tonic-gate     char digeststr[33];
2757c478bd9Sstevel@tonic-gate     const char *password_request[] = { SASL_AUX_PASSWORD, NULL };
2767c478bd9Sstevel@tonic-gate     struct propval auxprop_values[2];
2777c478bd9Sstevel@tonic-gate     sasl_server_conn_t *sconn = (sasl_server_conn_t *)conn;
2787c478bd9Sstevel@tonic-gate     MD5_CTX ctx;
2797c478bd9Sstevel@tonic-gate     int i;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate     if (!conn || !userstr || !challenge || !response)
2827c478bd9Sstevel@tonic-gate        PARAMERROR(conn)
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate     /* We've done the auxprop lookup already (in our caller) */
2857c478bd9Sstevel@tonic-gate     /* sadly, APOP has no provision for storing secrets */
2867c478bd9Sstevel@tonic-gate     ret = prop_getnames(sconn->sparams->propctx, password_request,
2877c478bd9Sstevel@tonic-gate 			auxprop_values);
2887c478bd9Sstevel@tonic-gate     if(ret < 0) {
2897c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2907c478bd9Sstevel@tonic-gate 	_sasl_log(conn, SASL_LOG_ERR, "could not perform password lookup");
2917c478bd9Sstevel@tonic-gate #else
2927c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, "could not perform password lookup");
2937c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2947c478bd9Sstevel@tonic-gate 	goto done;
2957c478bd9Sstevel@tonic-gate     }
296*1da57d55SToomas Soome 
2977c478bd9Sstevel@tonic-gate     if(!auxprop_values[0].name ||
2987c478bd9Sstevel@tonic-gate        !auxprop_values[0].values ||
2997c478bd9Sstevel@tonic-gate        !auxprop_values[0].values[0]) {
3007c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
3017c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, gettext("could not find password"));
3027c478bd9Sstevel@tonic-gate #else
3037c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, "could not find password");
3047c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
3057c478bd9Sstevel@tonic-gate 	ret = SASL_NOUSER;
3067c478bd9Sstevel@tonic-gate 	goto done;
3077c478bd9Sstevel@tonic-gate     }
308*1da57d55SToomas Soome 
3097c478bd9Sstevel@tonic-gate     _sasl_MD5Init(&ctx);
3107c478bd9Sstevel@tonic-gate     _sasl_MD5Update(&ctx, challenge, strlen(challenge));
3117c478bd9Sstevel@tonic-gate     _sasl_MD5Update(&ctx, auxprop_values[0].values[0],
3127c478bd9Sstevel@tonic-gate 		    strlen(auxprop_values[0].values[0]));
3137c478bd9Sstevel@tonic-gate     _sasl_MD5Final(digest, &ctx);
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate     /* convert digest from binary to ASCII hex */
3167c478bd9Sstevel@tonic-gate     for (i = 0; i < 16; i++)
3177c478bd9Sstevel@tonic-gate       sprintf(digeststr + (i*2), "%02x", digest[i]);
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate     if (!strncasecmp(digeststr, response, 32)) {
3207c478bd9Sstevel@tonic-gate       /* password verified! */
3217c478bd9Sstevel@tonic-gate       ret = SASL_OK;
3227c478bd9Sstevel@tonic-gate     } else {
3237c478bd9Sstevel@tonic-gate       /* passwords do not match */
3247c478bd9Sstevel@tonic-gate       ret = SASL_BADAUTH;
3257c478bd9Sstevel@tonic-gate     }
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate  done:
3287c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
3297c478bd9Sstevel@tonic-gate     if (ret == SASL_BADAUTH) sasl_seterror(conn, SASL_NOLOG,
3307c478bd9Sstevel@tonic-gate 					   gettext("login incorrect"));
3317c478bd9Sstevel@tonic-gate #else
3327c478bd9Sstevel@tonic-gate     if (ret == SASL_BADAUTH) sasl_seterror(conn, SASL_NOLOG,
3337c478bd9Sstevel@tonic-gate 					   "login incorrect");
3347c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
3357c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
3367c478bd9Sstevel@tonic-gate     if (userid) sconn->sparams->utils->free(userid);
3377c478bd9Sstevel@tonic-gate #else
3387c478bd9Sstevel@tonic-gate     if (userid) sasl_FREE(userid);
3397c478bd9Sstevel@tonic-gate     if (realm)  sasl_FREE(realm);
3407c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate     return ret;
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate #endif /* DO_SASL_CHECKAPOP */
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate #if defined(HAVE_PWCHECK) || defined(HAVE_SASLAUTHD)
3477c478bd9Sstevel@tonic-gate /*
3487c478bd9Sstevel@tonic-gate  * Keep calling the writev() system call with 'fd', 'iov', and 'iovcnt'
3497c478bd9Sstevel@tonic-gate  * until all the data is written out or an error occurs.
3507c478bd9Sstevel@tonic-gate  */
retry_writev(int fd,struct iovec * iov,int iovcnt)3517c478bd9Sstevel@tonic-gate static int retry_writev(int fd, struct iovec *iov, int iovcnt)
3527c478bd9Sstevel@tonic-gate {
3537c478bd9Sstevel@tonic-gate     int n;
3547c478bd9Sstevel@tonic-gate     int i;
3557c478bd9Sstevel@tonic-gate     int written = 0;
3567c478bd9Sstevel@tonic-gate     static int iov_max =
3577c478bd9Sstevel@tonic-gate #ifdef MAXIOV
3587c478bd9Sstevel@tonic-gate 	MAXIOV
3597c478bd9Sstevel@tonic-gate #else
3607c478bd9Sstevel@tonic-gate #ifdef IOV_MAX
3617c478bd9Sstevel@tonic-gate 	IOV_MAX
3627c478bd9Sstevel@tonic-gate #else
3637c478bd9Sstevel@tonic-gate 	8192
3647c478bd9Sstevel@tonic-gate #endif
3657c478bd9Sstevel@tonic-gate #endif
3667c478bd9Sstevel@tonic-gate 	;
367*1da57d55SToomas Soome 
3687c478bd9Sstevel@tonic-gate     for (;;) {
3697c478bd9Sstevel@tonic-gate 	while (iovcnt && iov[0].iov_len == 0) {
3707c478bd9Sstevel@tonic-gate 	    iov++;
3717c478bd9Sstevel@tonic-gate 	    iovcnt--;
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	if (!iovcnt) return written;
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	n = writev(fd, iov, iovcnt > iov_max ? iov_max : iovcnt);
3777c478bd9Sstevel@tonic-gate 	if (n == -1) {
3787c478bd9Sstevel@tonic-gate 	    if (errno == EINVAL && iov_max > 10) {
3797c478bd9Sstevel@tonic-gate 		iov_max /= 2;
3807c478bd9Sstevel@tonic-gate 		continue;
3817c478bd9Sstevel@tonic-gate 	    }
3827c478bd9Sstevel@tonic-gate 	    if (errno == EINTR) continue;
3837c478bd9Sstevel@tonic-gate 	    return -1;
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	written += n;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	for (i = 0; i < iovcnt; i++) {
3897c478bd9Sstevel@tonic-gate 	    if (iov[i].iov_len > (unsigned) n) {
3907c478bd9Sstevel@tonic-gate 		iov[i].iov_base = (char *)iov[i].iov_base + n;
3917c478bd9Sstevel@tonic-gate 		iov[i].iov_len -= n;
3927c478bd9Sstevel@tonic-gate 		break;
3937c478bd9Sstevel@tonic-gate 	    }
3947c478bd9Sstevel@tonic-gate 	    n -= iov[i].iov_len;
3957c478bd9Sstevel@tonic-gate 	    iov[i].iov_len = 0;
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	if (i == iovcnt) return written;
3997c478bd9Sstevel@tonic-gate     }
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate #endif
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate #ifdef HAVE_PWCHECK
4057c478bd9Sstevel@tonic-gate /* pwcheck daemon-authenticated login */
pwcheck_verify_password(sasl_conn_t * conn,const char * userid,const char * passwd,const char * service,const char * user_realm)4067c478bd9Sstevel@tonic-gate static int pwcheck_verify_password(sasl_conn_t *conn,
407*1da57d55SToomas Soome 				   const char *userid,
4087c478bd9Sstevel@tonic-gate 				   const char *passwd,
4097c478bd9Sstevel@tonic-gate 				   const char *service __attribute__((unused)),
410*1da57d55SToomas Soome 				   const char *user_realm
4117c478bd9Sstevel@tonic-gate 				               __attribute__((unused)))
4127c478bd9Sstevel@tonic-gate {
4137c478bd9Sstevel@tonic-gate     int s;
4147c478bd9Sstevel@tonic-gate     struct sockaddr_un srvaddr;
4157c478bd9Sstevel@tonic-gate     int r;
4167c478bd9Sstevel@tonic-gate     struct iovec iov[10];
4177c478bd9Sstevel@tonic-gate     static char response[1024];
4187c478bd9Sstevel@tonic-gate     unsigned start, n;
4197c478bd9Sstevel@tonic-gate     char pwpath[1024];
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate     if (strlen(PWCHECKDIR)+8+1 > sizeof(pwpath)) return SASL_FAIL;
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate     strcpy(pwpath, PWCHECKDIR);
4247c478bd9Sstevel@tonic-gate     strcat(pwpath, "/pwcheck");
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate     s = socket(AF_UNIX, SOCK_STREAM, 0);
4277c478bd9Sstevel@tonic-gate     if (s == -1) return errno;
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate     memset((char *)&srvaddr, 0, sizeof(srvaddr));
4307c478bd9Sstevel@tonic-gate     srvaddr.sun_family = AF_UNIX;
4317c478bd9Sstevel@tonic-gate     strncpy(srvaddr.sun_path, pwpath, sizeof(srvaddr.sun_path));
4327c478bd9Sstevel@tonic-gate     r = connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
4337c478bd9Sstevel@tonic-gate     if (r == -1) {
4347c478bd9Sstevel@tonic-gate 	sasl_seterror(conn,0,"cannot connect to pwcheck server");
4357c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
4367c478bd9Sstevel@tonic-gate     }
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate     iov[0].iov_base = (char *)userid;
4397c478bd9Sstevel@tonic-gate     iov[0].iov_len = strlen(userid)+1;
4407c478bd9Sstevel@tonic-gate     iov[1].iov_base = (char *)passwd;
4417c478bd9Sstevel@tonic-gate     iov[1].iov_len = strlen(passwd)+1;
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate     retry_writev(s, iov, 2);
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate     start = 0;
4467c478bd9Sstevel@tonic-gate     while (start < sizeof(response) - 1) {
4477c478bd9Sstevel@tonic-gate 	n = read(s, response+start, sizeof(response) - 1 - start);
4487c478bd9Sstevel@tonic-gate 	if (n < 1) break;
4497c478bd9Sstevel@tonic-gate 	start += n;
4507c478bd9Sstevel@tonic-gate     }
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate     close(s);
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate     if (start > 1 && !strncmp(response, "OK", 2)) {
4557c478bd9Sstevel@tonic-gate 	return SASL_OK;
4567c478bd9Sstevel@tonic-gate     }
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate     response[start] = '\0';
4597c478bd9Sstevel@tonic-gate     sasl_seterror(conn,0,response);
4607c478bd9Sstevel@tonic-gate     return SASL_BADAUTH;
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate #endif
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate #ifdef HAVE_SASLAUTHD
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate /*
4687c478bd9Sstevel@tonic-gate  * Keep calling the read() system call with 'fd', 'buf', and 'nbyte'
4697c478bd9Sstevel@tonic-gate  * until all the data is read in or an error occurs.
4707c478bd9Sstevel@tonic-gate  */
retry_read(int fd,void * buf0,unsigned nbyte)4717c478bd9Sstevel@tonic-gate static int retry_read(int fd, void *buf0, unsigned nbyte)
4727c478bd9Sstevel@tonic-gate {
4737c478bd9Sstevel@tonic-gate     int n;
4747c478bd9Sstevel@tonic-gate     int nread = 0;
4757c478bd9Sstevel@tonic-gate     char *buf = buf0;
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate     if (nbyte == 0) return 0;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate     for (;;) {
4807c478bd9Sstevel@tonic-gate 	n = read(fd, buf, nbyte);
4817c478bd9Sstevel@tonic-gate 	if (n == -1 || n == 0) {
4827c478bd9Sstevel@tonic-gate 	    if (errno == EINTR || errno == EAGAIN) continue;
4837c478bd9Sstevel@tonic-gate 	    return -1;
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	nread += n;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	if (nread >= (int) nbyte) return nread;
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	buf += n;
4917c478bd9Sstevel@tonic-gate 	nbyte -= n;
4927c478bd9Sstevel@tonic-gate     }
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate /* saslauthd-authenticated login */
saslauthd_verify_password(sasl_conn_t * conn,const char * userid,const char * passwd,const char * service,const char * user_realm)4967c478bd9Sstevel@tonic-gate static int saslauthd_verify_password(sasl_conn_t *conn,
497*1da57d55SToomas Soome 				     const char *userid,
4987c478bd9Sstevel@tonic-gate 				     const char *passwd,
4997c478bd9Sstevel@tonic-gate 				     const char *service,
5007c478bd9Sstevel@tonic-gate 				     const char *user_realm)
5017c478bd9Sstevel@tonic-gate {
5027c478bd9Sstevel@tonic-gate     char response[1024];
5037c478bd9Sstevel@tonic-gate     char query[8192];
5047c478bd9Sstevel@tonic-gate     char *query_end = query;
5057c478bd9Sstevel@tonic-gate     int s;
5067c478bd9Sstevel@tonic-gate     struct sockaddr_un srvaddr;
5077c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
5087c478bd9Sstevel@tonic-gate     void *context;
5097c478bd9Sstevel@tonic-gate     char pwpath[sizeof(srvaddr.sun_path)];
5107c478bd9Sstevel@tonic-gate     const char *p = NULL;
5117c478bd9Sstevel@tonic-gate #ifdef USE_DOORS
5127c478bd9Sstevel@tonic-gate     door_arg_t arg;
5137c478bd9Sstevel@tonic-gate #endif
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate     /* check to see if the user configured a rundir */
5167c478bd9Sstevel@tonic-gate     if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) {
5177c478bd9Sstevel@tonic-gate 	getopt(context, NULL, "saslauthd_path", &p, NULL);
5187c478bd9Sstevel@tonic-gate     }
5197c478bd9Sstevel@tonic-gate     if (p) {
5207c478bd9Sstevel@tonic-gate 	strncpy(pwpath, p, sizeof(pwpath));
5217c478bd9Sstevel@tonic-gate     } else {
5227c478bd9Sstevel@tonic-gate 	if (strlen(PATH_SASLAUTHD_RUNDIR) + 4 + 1 > sizeof(pwpath))
5237c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	strcpy(pwpath, PATH_SASLAUTHD_RUNDIR);
5267c478bd9Sstevel@tonic-gate 	strcat(pwpath, "/mux");
5277c478bd9Sstevel@tonic-gate     }
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate     /*
5307c478bd9Sstevel@tonic-gate      * build request of the form:
5317c478bd9Sstevel@tonic-gate      *
5327c478bd9Sstevel@tonic-gate      * count authid count password count service count realm
5337c478bd9Sstevel@tonic-gate      */
5347c478bd9Sstevel@tonic-gate     {
5357c478bd9Sstevel@tonic-gate  	unsigned short u_len, p_len, s_len, r_len;
536*1da57d55SToomas Soome 
5377c478bd9Sstevel@tonic-gate  	u_len = (strlen(userid));
5387c478bd9Sstevel@tonic-gate  	p_len = (strlen(passwd));
5397c478bd9Sstevel@tonic-gate 	s_len = (strlen(service));
5407c478bd9Sstevel@tonic-gate 	r_len = ((user_realm ? strlen(user_realm) : 0));
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	if (u_len + p_len + s_len + r_len + 30 > (unsigned short) sizeof(query)) {
5437c478bd9Sstevel@tonic-gate 	    /* request just too damn big */
5447c478bd9Sstevel@tonic-gate             sasl_seterror(conn, 0, "saslauthd request too large");
5457c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
5467c478bd9Sstevel@tonic-gate 	}
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	u_len = htons(u_len);
5497c478bd9Sstevel@tonic-gate 	p_len = htons(p_len);
5507c478bd9Sstevel@tonic-gate 	s_len = htons(s_len);
5517c478bd9Sstevel@tonic-gate 	r_len = htons(r_len);
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	memcpy(query_end, &u_len, sizeof(unsigned short));
5547c478bd9Sstevel@tonic-gate 	query_end += sizeof(unsigned short);
5557c478bd9Sstevel@tonic-gate 	while (*userid) *query_end++ = *userid++;
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	memcpy(query_end, &p_len, sizeof(unsigned short));
5587c478bd9Sstevel@tonic-gate 	query_end += sizeof(unsigned short);
5597c478bd9Sstevel@tonic-gate 	while (*passwd) *query_end++ = *passwd++;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	memcpy(query_end, &s_len, sizeof(unsigned short));
5627c478bd9Sstevel@tonic-gate 	query_end += sizeof(unsigned short);
5637c478bd9Sstevel@tonic-gate 	while (*service) *query_end++ = *service++;
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	memcpy(query_end, &r_len, sizeof(unsigned short));
5667c478bd9Sstevel@tonic-gate 	query_end += sizeof(unsigned short);
5677c478bd9Sstevel@tonic-gate 	if (user_realm) while (*user_realm) *query_end++ = *user_realm++;
5687c478bd9Sstevel@tonic-gate     }
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate #ifdef USE_DOORS
5717c478bd9Sstevel@tonic-gate     s = open(pwpath, O_RDONLY);
5727c478bd9Sstevel@tonic-gate     if (s < 0) {
5737c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, "cannot open door to saslauthd server: %m", errno);
5747c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
5757c478bd9Sstevel@tonic-gate     }
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate     arg.data_ptr = query;
5787c478bd9Sstevel@tonic-gate     arg.data_size = query_end - query;
5797c478bd9Sstevel@tonic-gate     arg.desc_ptr = NULL;
5807c478bd9Sstevel@tonic-gate     arg.desc_num = 0;
5817c478bd9Sstevel@tonic-gate     arg.rbuf = response;
5827c478bd9Sstevel@tonic-gate     arg.rsize = sizeof(response);
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate     door_call(s, &arg);
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate     if (arg.data_ptr != response || arg.data_size >= sizeof(response)) {
5877c478bd9Sstevel@tonic-gate 	/* oh damn, we got back a really long response */
5887c478bd9Sstevel@tonic-gate 	munmap(arg.rbuf, arg.rsize);
5897c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, "saslauthd sent an overly long response");
5907c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
5917c478bd9Sstevel@tonic-gate     }
5927c478bd9Sstevel@tonic-gate     response[arg.data_size] = '\0';
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate     close(s);
5957c478bd9Sstevel@tonic-gate #else
5967c478bd9Sstevel@tonic-gate     /* unix sockets */
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate     s = socket(AF_UNIX, SOCK_STREAM, 0);
5997c478bd9Sstevel@tonic-gate     if (s == -1) {
6007c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, "cannot create socket for saslauthd: %m", errno);
6017c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
6027c478bd9Sstevel@tonic-gate     }
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate     memset((char *)&srvaddr, 0, sizeof(srvaddr));
6057c478bd9Sstevel@tonic-gate     srvaddr.sun_family = AF_UNIX;
6067c478bd9Sstevel@tonic-gate     strncpy(srvaddr.sun_path, pwpath, sizeof(srvaddr.sun_path));
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate     {
6097c478bd9Sstevel@tonic-gate 	int r = connect(s, (struct sockaddr *) &srvaddr, sizeof(srvaddr));
6107c478bd9Sstevel@tonic-gate 	if (r == -1) {
6117c478bd9Sstevel@tonic-gate 	    sasl_seterror(conn, 0, "cannot connect to saslauthd server: %m", errno);
6127c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate     }
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate     {
6177c478bd9Sstevel@tonic-gate  	struct iovec iov[8];
618*1da57d55SToomas Soome 
6197c478bd9Sstevel@tonic-gate 	iov[0].iov_len = query_end - query;
6207c478bd9Sstevel@tonic-gate 	iov[0].iov_base = query;
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	if (retry_writev(s, iov, 1) == -1) {
6237c478bd9Sstevel@tonic-gate             sasl_seterror(conn, 0, "write failed");
6247c478bd9Sstevel@tonic-gate   	    return SASL_FAIL;
6257c478bd9Sstevel@tonic-gate   	}
6267c478bd9Sstevel@tonic-gate     }
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate     {
6297c478bd9Sstevel@tonic-gate 	unsigned short count = 0;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	/*
6327c478bd9Sstevel@tonic-gate 	 * read response of the form:
6337c478bd9Sstevel@tonic-gate 	 *
6347c478bd9Sstevel@tonic-gate 	 * count result
6357c478bd9Sstevel@tonic-gate 	 */
6367c478bd9Sstevel@tonic-gate 	if (retry_read(s, &count, sizeof(count)) < (int) sizeof(count)) {
6377c478bd9Sstevel@tonic-gate 	    sasl_seterror(conn, 0, "size read failed");
6387c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
6397c478bd9Sstevel@tonic-gate 	}
640*1da57d55SToomas Soome 
6417c478bd9Sstevel@tonic-gate 	count = ntohs(count);
6427c478bd9Sstevel@tonic-gate 	if (count < 2) { /* MUST have at least "OK" or "NO" */
6437c478bd9Sstevel@tonic-gate 	    close(s);
6447c478bd9Sstevel@tonic-gate 	    sasl_seterror(conn, 0, "bad response from saslauthd");
6457c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
6467c478bd9Sstevel@tonic-gate 	}
647*1da57d55SToomas Soome 
6487c478bd9Sstevel@tonic-gate 	count = (int)sizeof(response) < count ? sizeof(response) : count;
6497c478bd9Sstevel@tonic-gate 	if (retry_read(s, response, count) < count) {
6507c478bd9Sstevel@tonic-gate 	    close(s);
6517c478bd9Sstevel@tonic-gate 	    sasl_seterror(conn, 0, "read failed");
6527c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
6537c478bd9Sstevel@tonic-gate 	}
6547c478bd9Sstevel@tonic-gate 	response[count] = '\0';
6557c478bd9Sstevel@tonic-gate     }
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate     close(s);
6587c478bd9Sstevel@tonic-gate #endif /* USE_DOORS */
659*1da57d55SToomas Soome 
6607c478bd9Sstevel@tonic-gate     if (!strncmp(response, "OK", 2)) {
6617c478bd9Sstevel@tonic-gate 	return SASL_OK;
6627c478bd9Sstevel@tonic-gate     }
663*1da57d55SToomas Soome 
6647c478bd9Sstevel@tonic-gate     sasl_seterror(conn, SASL_NOLOG, "authentication failed");
6657c478bd9Sstevel@tonic-gate     return SASL_BADAUTH;
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate #endif
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate #ifdef HAVE_ALWAYSTRUE
always_true(sasl_conn_t * conn,const char * userstr,const char * passwd,const char * service,const char * user_realm)6717c478bd9Sstevel@tonic-gate static int always_true(sasl_conn_t *conn,
6727c478bd9Sstevel@tonic-gate 		       const char *userstr,
6737c478bd9Sstevel@tonic-gate 		       const char *passwd __attribute__((unused)),
6747c478bd9Sstevel@tonic-gate 		       const char *service __attribute__((unused)),
675*1da57d55SToomas Soome 		       const char *user_realm __attribute__((unused)))
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate     _sasl_log(conn, SASL_LOG_WARN, "AlwaysTrue Password Verifier Verified: %s",
6787c478bd9Sstevel@tonic-gate 	      userstr);
6797c478bd9Sstevel@tonic-gate     return SASL_OK;
6807c478bd9Sstevel@tonic-gate }
6817c478bd9Sstevel@tonic-gate #endif
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate struct sasl_verify_password_s _sasl_verify_password[] = {
6847c478bd9Sstevel@tonic-gate     { "auxprop", &auxprop_verify_password },
6857c478bd9Sstevel@tonic-gate #ifdef HAVE_PWCHECK
6867c478bd9Sstevel@tonic-gate     { "pwcheck", &pwcheck_verify_password },
6877c478bd9Sstevel@tonic-gate #endif
6887c478bd9Sstevel@tonic-gate #ifdef HAVE_SASLAUTHD
6897c478bd9Sstevel@tonic-gate     { "saslauthd", &saslauthd_verify_password },
6907c478bd9Sstevel@tonic-gate #endif
6917c478bd9Sstevel@tonic-gate #ifdef HAVE_ALWAYSTRUE
6927c478bd9Sstevel@tonic-gate     { "alwaystrue", &always_true },
693*1da57d55SToomas Soome #endif
6947c478bd9Sstevel@tonic-gate     { NULL, NULL }
6957c478bd9Sstevel@tonic-gate };
696