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 /* Plain SASL plugin
77c478bd9Sstevel@tonic-gate  * Rob Siemborski
8*1da57d55SToomas Soome  * Tim Martin
97c478bd9Sstevel@tonic-gate  * $Id: plain.c,v 1.61 2003/03/26 17:18:04 rjs3 Exp $
107c478bd9Sstevel@tonic-gate  */
117c478bd9Sstevel@tonic-gate 
12*1da57d55SToomas Soome /*
137c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
147c478bd9Sstevel@tonic-gate  *
157c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
167c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
177c478bd9Sstevel@tonic-gate  * are met:
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
20*1da57d55SToomas Soome  *    notice, this list of conditions and the following disclaimer.
217c478bd9Sstevel@tonic-gate  *
227c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
237c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
247c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
257c478bd9Sstevel@tonic-gate  *    distribution.
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
287c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
297c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
30*1da57d55SToomas Soome  *    details, please contact
317c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
327c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
337c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
347c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
357c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
367c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
397c478bd9Sstevel@tonic-gate  *    acknowledgment:
407c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
417c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
427c478bd9Sstevel@tonic-gate  *
437c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
447c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
457c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
467c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
477c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
487c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
497c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #include <config.h>
537c478bd9Sstevel@tonic-gate #include <stdio.h>
54*1da57d55SToomas Soome #include <string.h>
557c478bd9Sstevel@tonic-gate #include <sasl.h>
567c478bd9Sstevel@tonic-gate #include <saslplug.h>
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #include "plugin_common.h"
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
617c478bd9Sstevel@tonic-gate #ifdef WIN32
627c478bd9Sstevel@tonic-gate /* This must be after sasl.h */
637c478bd9Sstevel@tonic-gate # include "saslPLAIN.h"
647c478bd9Sstevel@tonic-gate #endif /* WIN32 */
657c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
667c478bd9Sstevel@tonic-gate 
67*1da57d55SToomas Soome #ifdef macintosh
68*1da57d55SToomas Soome #include <sasl_plain_plugin_decl.h>
69*1da57d55SToomas Soome #endif
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*****************************  Common Section  *****************************/
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
747c478bd9Sstevel@tonic-gate static const char plugin_id[] = "$Id: plain.c,v 1.61 2003/03/26 17:18:04 rjs3 Exp $";
757c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /*****************************  Server Section  *****************************/
787c478bd9Sstevel@tonic-gate 
plain_server_mech_new(void * glob_context,sasl_server_params_t * sparams,const char * challenge,unsigned challen,void ** conn_context)79*1da57d55SToomas Soome static int plain_server_mech_new(void *glob_context __attribute__((unused)),
807c478bd9Sstevel@tonic-gate 				 sasl_server_params_t *sparams,
817c478bd9Sstevel@tonic-gate 				 const char *challenge __attribute__((unused)),
827c478bd9Sstevel@tonic-gate 				 unsigned challen __attribute__((unused)),
837c478bd9Sstevel@tonic-gate 				 void **conn_context)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate     /* holds state are in */
867c478bd9Sstevel@tonic-gate     if (!conn_context) {
877c478bd9Sstevel@tonic-gate 	PARAMERROR( sparams->utils );
887c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
897c478bd9Sstevel@tonic-gate     }
90*1da57d55SToomas Soome 
917c478bd9Sstevel@tonic-gate     *conn_context = NULL;
92*1da57d55SToomas Soome 
937c478bd9Sstevel@tonic-gate     return SASL_OK;
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate 
plain_server_mech_step(void * conn_context,sasl_server_params_t * params,const char * clientin,unsigned clientinlen,const char ** serverout,unsigned * serveroutlen,sasl_out_params_t * oparams)967c478bd9Sstevel@tonic-gate static int plain_server_mech_step(void *conn_context __attribute__((unused)),
977c478bd9Sstevel@tonic-gate 				  sasl_server_params_t *params,
987c478bd9Sstevel@tonic-gate 				  const char *clientin,
997c478bd9Sstevel@tonic-gate 				  unsigned clientinlen,
1007c478bd9Sstevel@tonic-gate 				  const char **serverout,
1017c478bd9Sstevel@tonic-gate 				  unsigned *serveroutlen,
1027c478bd9Sstevel@tonic-gate 				  sasl_out_params_t *oparams)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate     const char *author;
1057c478bd9Sstevel@tonic-gate     const char *authen;
1067c478bd9Sstevel@tonic-gate     const char *password;
1077c478bd9Sstevel@tonic-gate     size_t password_len;
1087c478bd9Sstevel@tonic-gate     unsigned lup=0;
1097c478bd9Sstevel@tonic-gate     int result;
110*1da57d55SToomas Soome     char *passcopy;
111*1da57d55SToomas Soome 
1127c478bd9Sstevel@tonic-gate     *serverout = NULL;
1137c478bd9Sstevel@tonic-gate     *serveroutlen = 0;
114*1da57d55SToomas Soome 
1157c478bd9Sstevel@tonic-gate     /* should have received author-id NUL authen-id NUL password */
116*1da57d55SToomas Soome 
1177c478bd9Sstevel@tonic-gate     /* get author */
1187c478bd9Sstevel@tonic-gate     author = clientin;
1197c478bd9Sstevel@tonic-gate     while ((lup < clientinlen) && (clientin[lup] != 0)) ++lup;
120*1da57d55SToomas Soome 
1217c478bd9Sstevel@tonic-gate     if (lup >= clientinlen) {
1227c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1237c478bd9Sstevel@tonic-gate 	params->utils->log(params->utils->conn, SASL_LOG_ERR,
1247c478bd9Sstevel@tonic-gate 		"Can only find author (no password)");
1257c478bd9Sstevel@tonic-gate #else
1267c478bd9Sstevel@tonic-gate 	SETERROR(params->utils, "Can only find author (no password)");
1277c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1287c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
1297c478bd9Sstevel@tonic-gate     }
130*1da57d55SToomas Soome 
1317c478bd9Sstevel@tonic-gate     /* get authen */
1327c478bd9Sstevel@tonic-gate     ++lup;
1337c478bd9Sstevel@tonic-gate     authen = clientin + lup;
1347c478bd9Sstevel@tonic-gate     while ((lup < clientinlen) && (clientin[lup] != 0)) ++lup;
135*1da57d55SToomas Soome 
1367c478bd9Sstevel@tonic-gate     if (lup >= clientinlen) {
1377c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1387c478bd9Sstevel@tonic-gate 	params->utils->log(params->utils->conn, SASL_LOG_ERR,
1397c478bd9Sstevel@tonic-gate 			"Can only find author/en (no password)");
1407c478bd9Sstevel@tonic-gate #else
1417c478bd9Sstevel@tonic-gate 	params->utils->seterror(params->utils->conn, 0,
1427c478bd9Sstevel@tonic-gate 				"Can only find author/en (no password)");
1437c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1447c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
1457c478bd9Sstevel@tonic-gate     }
146*1da57d55SToomas Soome 
1477c478bd9Sstevel@tonic-gate     /* get password */
1487c478bd9Sstevel@tonic-gate     lup++;
1497c478bd9Sstevel@tonic-gate     password = clientin + lup;
1507c478bd9Sstevel@tonic-gate     while ((lup < clientinlen) && (clientin[lup] != 0)) ++lup;
151*1da57d55SToomas Soome 
1527c478bd9Sstevel@tonic-gate     password_len = clientin + lup - password;
153*1da57d55SToomas Soome 
1547c478bd9Sstevel@tonic-gate     if (lup != clientinlen) {
1557c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
1567c478bd9Sstevel@tonic-gate 	params->utils->log(params->utils->conn, SASL_LOG_ERR,
1577c478bd9Sstevel@tonic-gate 		"Got more data than we were expecting in the PLAIN plugin");
1587c478bd9Sstevel@tonic-gate #else
1597c478bd9Sstevel@tonic-gate 	SETERROR(params->utils,
1607c478bd9Sstevel@tonic-gate 		 "Got more data than we were expecting in the PLAIN plugin\n");
1617c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1627c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
1637c478bd9Sstevel@tonic-gate     }
164*1da57d55SToomas Soome 
1657c478bd9Sstevel@tonic-gate     /* this kinda sucks. we need password to be null terminated
1667c478bd9Sstevel@tonic-gate        but we can't assume there is an allocated byte at the end
1677c478bd9Sstevel@tonic-gate        of password so we have to copy it */
168*1da57d55SToomas Soome     passcopy = params->utils->malloc(password_len + 1);
1697c478bd9Sstevel@tonic-gate     if (passcopy == NULL) {
1707c478bd9Sstevel@tonic-gate 	MEMERROR(params->utils);
1717c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
1727c478bd9Sstevel@tonic-gate     }
173*1da57d55SToomas Soome 
1747c478bd9Sstevel@tonic-gate     strncpy(passcopy, password, password_len);
1757c478bd9Sstevel@tonic-gate     passcopy[password_len] = '\0';
176*1da57d55SToomas Soome 
1777c478bd9Sstevel@tonic-gate     /* Canonicalize userid first, so that password verification is only
1787c478bd9Sstevel@tonic-gate      * against the canonical id */
1797c478bd9Sstevel@tonic-gate     if (!author || !*author)
1807c478bd9Sstevel@tonic-gate 	author = authen;
181*1da57d55SToomas Soome 
1827c478bd9Sstevel@tonic-gate     result = params->canon_user(params->utils->conn,
1837c478bd9Sstevel@tonic-gate 				authen, 0, SASL_CU_AUTHID, oparams);
1847c478bd9Sstevel@tonic-gate     if (result != SASL_OK) {
1857c478bd9Sstevel@tonic-gate 	_plug_free_string(params->utils, &passcopy);
1867c478bd9Sstevel@tonic-gate 	return result;
1877c478bd9Sstevel@tonic-gate     }
188*1da57d55SToomas Soome 
1897c478bd9Sstevel@tonic-gate     /* verify password - return sasl_ok on success*/
1907c478bd9Sstevel@tonic-gate     result = params->utils->checkpass(params->utils->conn,
1917c478bd9Sstevel@tonic-gate 				      oparams->authid, oparams->alen,
1927c478bd9Sstevel@tonic-gate 				      passcopy, password_len);
193*1da57d55SToomas Soome 
1947c478bd9Sstevel@tonic-gate     _plug_free_string(params->utils, &passcopy);
195*1da57d55SToomas Soome 
1967c478bd9Sstevel@tonic-gate     if (result != SASL_OK) {
1977c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
1987c478bd9Sstevel@tonic-gate 	params->utils->seterror(params->utils->conn, 0,
1997c478bd9Sstevel@tonic-gate 				gettext("Password verification failed"));
2007c478bd9Sstevel@tonic-gate #else
2017c478bd9Sstevel@tonic-gate 	params->utils->seterror(params->utils->conn, 0,
2027c478bd9Sstevel@tonic-gate 				"Password verification failed");
2037c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
2047c478bd9Sstevel@tonic-gate 	return result;
2057c478bd9Sstevel@tonic-gate     }
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate     /* Canonicalize and store the authorization ID */
2087c478bd9Sstevel@tonic-gate     /* We need to do this after calling verify_user just in case verify_user
2097c478bd9Sstevel@tonic-gate      * needed to get auxprops itself */
2107c478bd9Sstevel@tonic-gate     result = params->canon_user(params->utils->conn,
2117c478bd9Sstevel@tonic-gate 				author, 0, SASL_CU_AUTHZID, oparams);
2127c478bd9Sstevel@tonic-gate     if (result != SASL_OK) return result;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate     /* Transition? */
2157c478bd9Sstevel@tonic-gate     if (params->transition) {
2167c478bd9Sstevel@tonic-gate 	params->transition(params->utils->conn, password, password_len);
2177c478bd9Sstevel@tonic-gate     }
218*1da57d55SToomas Soome 
2197c478bd9Sstevel@tonic-gate     /* set oparams */
2207c478bd9Sstevel@tonic-gate     oparams->doneflag = 1;
2217c478bd9Sstevel@tonic-gate     oparams->mech_ssf = 0;
2227c478bd9Sstevel@tonic-gate     oparams->maxoutbuf = 0;
2237c478bd9Sstevel@tonic-gate     oparams->encode_context = NULL;
2247c478bd9Sstevel@tonic-gate     oparams->encode = NULL;
2257c478bd9Sstevel@tonic-gate     oparams->decode_context = NULL;
2267c478bd9Sstevel@tonic-gate     oparams->decode = NULL;
2277c478bd9Sstevel@tonic-gate     oparams->param_version = 0;
228*1da57d55SToomas Soome 
2297c478bd9Sstevel@tonic-gate     return SASL_OK;
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate 
232*1da57d55SToomas Soome static sasl_server_plug_t plain_server_plugins[] =
2337c478bd9Sstevel@tonic-gate {
2347c478bd9Sstevel@tonic-gate     {
2357c478bd9Sstevel@tonic-gate 	"PLAIN",			/* mech_name */
2367c478bd9Sstevel@tonic-gate 	0,				/* max_ssf */
2377c478bd9Sstevel@tonic-gate 	SASL_SEC_NOANONYMOUS,		/* security_flags */
2387c478bd9Sstevel@tonic-gate 	SASL_FEAT_WANT_CLIENT_FIRST
2397c478bd9Sstevel@tonic-gate 	| SASL_FEAT_ALLOWS_PROXY,	/* features */
2407c478bd9Sstevel@tonic-gate 	NULL,				/* glob_context */
2417c478bd9Sstevel@tonic-gate 	&plain_server_mech_new,		/* mech_new */
2427c478bd9Sstevel@tonic-gate 	&plain_server_mech_step,	/* mech_step */
2437c478bd9Sstevel@tonic-gate 	NULL,				/* mech_dispose */
2447c478bd9Sstevel@tonic-gate 	NULL,				/* mech_free */
2457c478bd9Sstevel@tonic-gate 	NULL,				/* setpass */
2467c478bd9Sstevel@tonic-gate 	NULL,				/* user_query */
2477c478bd9Sstevel@tonic-gate 	NULL,				/* idle */
2487c478bd9Sstevel@tonic-gate 	NULL,				/* mech_avail */
2497c478bd9Sstevel@tonic-gate 	NULL				/* spare */
2507c478bd9Sstevel@tonic-gate     }
2517c478bd9Sstevel@tonic-gate };
2527c478bd9Sstevel@tonic-gate 
plain_server_plug_init(const sasl_utils_t * utils,int maxversion,int * out_version,sasl_server_plug_t ** pluglist,int * plugcount)2537c478bd9Sstevel@tonic-gate int plain_server_plug_init(const sasl_utils_t *utils,
2547c478bd9Sstevel@tonic-gate 			   int maxversion,
2557c478bd9Sstevel@tonic-gate 			   int *out_version,
2567c478bd9Sstevel@tonic-gate 			   sasl_server_plug_t **pluglist,
2577c478bd9Sstevel@tonic-gate 			   int *plugcount)
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate     if (maxversion < SASL_SERVER_PLUG_VERSION) {
2607c478bd9Sstevel@tonic-gate 	SETERROR(utils, "PLAIN version mismatch");
2617c478bd9Sstevel@tonic-gate 	return SASL_BADVERS;
2627c478bd9Sstevel@tonic-gate     }
263*1da57d55SToomas Soome 
2647c478bd9Sstevel@tonic-gate     *out_version = SASL_SERVER_PLUG_VERSION;
2657c478bd9Sstevel@tonic-gate     *pluglist = plain_server_plugins;
266*1da57d55SToomas Soome     *plugcount = 1;
267*1da57d55SToomas Soome 
2687c478bd9Sstevel@tonic-gate     return SASL_OK;
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate /*****************************  Client Section  *****************************/
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate typedef struct client_context {
2747c478bd9Sstevel@tonic-gate     char *out_buf;
2757c478bd9Sstevel@tonic-gate     unsigned out_buf_len;
2767c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
2777c478bd9Sstevel@tonic-gate     void *h;
2787c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
2797c478bd9Sstevel@tonic-gate } client_context_t;
2807c478bd9Sstevel@tonic-gate 
plain_client_mech_new(void * glob_context,sasl_client_params_t * params,void ** conn_context)2817c478bd9Sstevel@tonic-gate static int plain_client_mech_new(void *glob_context __attribute__((unused)),
2827c478bd9Sstevel@tonic-gate 				 sasl_client_params_t *params,
2837c478bd9Sstevel@tonic-gate 				 void **conn_context)
2847c478bd9Sstevel@tonic-gate {
2857c478bd9Sstevel@tonic-gate     client_context_t *text;
286*1da57d55SToomas Soome 
2877c478bd9Sstevel@tonic-gate     /* holds state are in */
2887c478bd9Sstevel@tonic-gate     text = params->utils->malloc(sizeof(client_context_t));
2897c478bd9Sstevel@tonic-gate     if (text == NULL) {
2907c478bd9Sstevel@tonic-gate 	MEMERROR( params->utils );
2917c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
2927c478bd9Sstevel@tonic-gate     }
293*1da57d55SToomas Soome 
2947c478bd9Sstevel@tonic-gate     memset(text, 0, sizeof(client_context_t));
295*1da57d55SToomas Soome 
2967c478bd9Sstevel@tonic-gate     *conn_context = text;
297*1da57d55SToomas Soome 
2987c478bd9Sstevel@tonic-gate     return SASL_OK;
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate 
plain_client_mech_step(void * conn_context,sasl_client_params_t * params,const char * serverin,unsigned serverinlen,sasl_interact_t ** prompt_need,const char ** clientout,unsigned * clientoutlen,sasl_out_params_t * oparams)3017c478bd9Sstevel@tonic-gate static int plain_client_mech_step(void *conn_context,
3027c478bd9Sstevel@tonic-gate 				  sasl_client_params_t *params,
3037c478bd9Sstevel@tonic-gate 				  const char *serverin __attribute__((unused)),
3047c478bd9Sstevel@tonic-gate 				  unsigned serverinlen __attribute__((unused)),
3057c478bd9Sstevel@tonic-gate 				  sasl_interact_t **prompt_need,
3067c478bd9Sstevel@tonic-gate 				  const char **clientout,
3077c478bd9Sstevel@tonic-gate 				  unsigned *clientoutlen,
3087c478bd9Sstevel@tonic-gate 				  sasl_out_params_t *oparams)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate     client_context_t *text = (client_context_t *) conn_context;
3117c478bd9Sstevel@tonic-gate     const char *user = NULL, *authid = NULL;
3127c478bd9Sstevel@tonic-gate     sasl_secret_t *password = NULL;
3137c478bd9Sstevel@tonic-gate     unsigned int free_password = 0; /* set if we need to free password */
3147c478bd9Sstevel@tonic-gate     int user_result = SASL_OK;
3157c478bd9Sstevel@tonic-gate     int auth_result = SASL_OK;
3167c478bd9Sstevel@tonic-gate     int pass_result = SASL_OK;
3177c478bd9Sstevel@tonic-gate     int result;
318*1da57d55SToomas Soome 
3197c478bd9Sstevel@tonic-gate     *clientout = NULL;
3207c478bd9Sstevel@tonic-gate     *clientoutlen = 0;
321*1da57d55SToomas Soome 
3227c478bd9Sstevel@tonic-gate     /* doesn't really matter how the server responds */
323*1da57d55SToomas Soome 
3247c478bd9Sstevel@tonic-gate     /* check if sec layer strong enough */
3257c478bd9Sstevel@tonic-gate     if (params->props.min_ssf > params->external_ssf) {
3267c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
3277c478bd9Sstevel@tonic-gate 	SETERROR( params->utils, gettext("SSF requested of PLAIN plugin"));
3287c478bd9Sstevel@tonic-gate #else
3297c478bd9Sstevel@tonic-gate 	SETERROR( params->utils, "SSF requested of PLAIN plugin");
3307c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
3317c478bd9Sstevel@tonic-gate 	return SASL_TOOWEAK;
3327c478bd9Sstevel@tonic-gate     }
333*1da57d55SToomas Soome 
334*1da57d55SToomas Soome     /* try to get the authid */
3357c478bd9Sstevel@tonic-gate     if (oparams->authid == NULL) {
3367c478bd9Sstevel@tonic-gate 	auth_result = _plug_get_authid(params->utils, &authid, prompt_need);
337*1da57d55SToomas Soome 
3387c478bd9Sstevel@tonic-gate 	if ((auth_result != SASL_OK) && (auth_result != SASL_INTERACT))
3397c478bd9Sstevel@tonic-gate 	    return auth_result;
340*1da57d55SToomas Soome     }
341*1da57d55SToomas Soome 
3427c478bd9Sstevel@tonic-gate     /* try to get the userid */
3437c478bd9Sstevel@tonic-gate     if (oparams->user == NULL) {
3447c478bd9Sstevel@tonic-gate 	user_result = _plug_get_userid(params->utils, &user, prompt_need);
345*1da57d55SToomas Soome 
3467c478bd9Sstevel@tonic-gate 	if ((user_result != SASL_OK) && (user_result != SASL_INTERACT))
3477c478bd9Sstevel@tonic-gate 	    return user_result;
3487c478bd9Sstevel@tonic-gate     }
349*1da57d55SToomas Soome 
3507c478bd9Sstevel@tonic-gate     /* try to get the password */
3517c478bd9Sstevel@tonic-gate     if (password == NULL) {
3527c478bd9Sstevel@tonic-gate 	pass_result = _plug_get_password(params->utils, &password,
3537c478bd9Sstevel@tonic-gate 					 &free_password, prompt_need);
354*1da57d55SToomas Soome 
3557c478bd9Sstevel@tonic-gate 	if ((pass_result != SASL_OK) && (pass_result != SASL_INTERACT))
3567c478bd9Sstevel@tonic-gate 	    return pass_result;
3577c478bd9Sstevel@tonic-gate     }
358*1da57d55SToomas Soome 
3597c478bd9Sstevel@tonic-gate     /* free prompts we got */
3607c478bd9Sstevel@tonic-gate     if (prompt_need && *prompt_need) {
3617c478bd9Sstevel@tonic-gate 	params->utils->free(*prompt_need);
3627c478bd9Sstevel@tonic-gate 	*prompt_need = NULL;
3637c478bd9Sstevel@tonic-gate     }
364*1da57d55SToomas Soome 
3657c478bd9Sstevel@tonic-gate     /* if there are prompts not filled in */
3667c478bd9Sstevel@tonic-gate     if ((user_result == SASL_INTERACT) || (auth_result == SASL_INTERACT) ||
3677c478bd9Sstevel@tonic-gate 	(pass_result == SASL_INTERACT)) {
3687c478bd9Sstevel@tonic-gate 	/* make the prompt list */
3697c478bd9Sstevel@tonic-gate 	result =
3707c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
3717c478bd9Sstevel@tonic-gate 	    _plug_make_prompts(params->utils, &text->h, prompt_need,
3727c478bd9Sstevel@tonic-gate 			       user_result == SASL_INTERACT ?
3737c478bd9Sstevel@tonic-gate 			       convert_prompt(params->utils, &text->h,
3747c478bd9Sstevel@tonic-gate 				gettext("Please enter your authorization name"))
3757c478bd9Sstevel@tonic-gate 					: NULL,
3767c478bd9Sstevel@tonic-gate 			       NULL,
3777c478bd9Sstevel@tonic-gate 			       auth_result == SASL_INTERACT ?
3787c478bd9Sstevel@tonic-gate 			       convert_prompt(params->utils, &text->h,
3797c478bd9Sstevel@tonic-gate 			gettext("Please enter your authentication name"))
3807c478bd9Sstevel@tonic-gate 					: NULL,
3817c478bd9Sstevel@tonic-gate 			       NULL,
3827c478bd9Sstevel@tonic-gate 			       pass_result == SASL_INTERACT ?
3837c478bd9Sstevel@tonic-gate 			       convert_prompt(params->utils, &text->h,
3847c478bd9Sstevel@tonic-gate 				gettext("Please enter your password")) : NULL,
3857c478bd9Sstevel@tonic-gate 				NULL,
3867c478bd9Sstevel@tonic-gate 			       NULL, NULL, NULL,
3877c478bd9Sstevel@tonic-gate 			       NULL, NULL, NULL);
3887c478bd9Sstevel@tonic-gate #else
3897c478bd9Sstevel@tonic-gate 	    _plug_make_prompts(params->utils, prompt_need,
3907c478bd9Sstevel@tonic-gate 			       user_result == SASL_INTERACT ?
3917c478bd9Sstevel@tonic-gate 			       "Please enter your authorization name" : NULL,
3927c478bd9Sstevel@tonic-gate 			       NULL,
3937c478bd9Sstevel@tonic-gate 			       auth_result == SASL_INTERACT ?
3947c478bd9Sstevel@tonic-gate 			       "Please enter your authentication name" : NULL,
3957c478bd9Sstevel@tonic-gate 			       NULL,
3967c478bd9Sstevel@tonic-gate 			       pass_result == SASL_INTERACT ?
3977c478bd9Sstevel@tonic-gate 			       "Please enter your password" : NULL, NULL,
3987c478bd9Sstevel@tonic-gate 			       NULL, NULL, NULL,
3997c478bd9Sstevel@tonic-gate 			       NULL, NULL, NULL);
4007c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
4017c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) goto cleanup;
402*1da57d55SToomas Soome 
4037c478bd9Sstevel@tonic-gate 	return SASL_INTERACT;
4047c478bd9Sstevel@tonic-gate     }
405*1da57d55SToomas Soome 
4067c478bd9Sstevel@tonic-gate     if (!password) {
4077c478bd9Sstevel@tonic-gate 	PARAMERROR(params->utils);
4087c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
4097c478bd9Sstevel@tonic-gate     }
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate     if (!user || !*user) {
4127c478bd9Sstevel@tonic-gate 	result = params->canon_user(params->utils->conn, authid, 0,
4137c478bd9Sstevel@tonic-gate 				    SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams);
4147c478bd9Sstevel@tonic-gate     }
4157c478bd9Sstevel@tonic-gate     else {
4167c478bd9Sstevel@tonic-gate 	result = params->canon_user(params->utils->conn, user, 0,
4177c478bd9Sstevel@tonic-gate 				    SASL_CU_AUTHZID, oparams);
4187c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) goto cleanup;
419*1da57d55SToomas Soome 
4207c478bd9Sstevel@tonic-gate 	result = params->canon_user(params->utils->conn, authid, 0,
4217c478bd9Sstevel@tonic-gate 				    SASL_CU_AUTHID, oparams);
4227c478bd9Sstevel@tonic-gate     }
4237c478bd9Sstevel@tonic-gate     if (result != SASL_OK) goto cleanup;
424*1da57d55SToomas Soome 
4257c478bd9Sstevel@tonic-gate     /* send authorized id NUL authentication id NUL password */
4267c478bd9Sstevel@tonic-gate     *clientoutlen = (oparams->ulen + 1
4277c478bd9Sstevel@tonic-gate 		     + oparams->alen + 1
4287c478bd9Sstevel@tonic-gate 		     + password->len);
429*1da57d55SToomas Soome 
4307c478bd9Sstevel@tonic-gate     /* remember the extra NUL on the end for stupid clients */
4317c478bd9Sstevel@tonic-gate     result = _plug_buf_alloc(params->utils, &(text->out_buf),
4327c478bd9Sstevel@tonic-gate 			     &(text->out_buf_len), *clientoutlen + 1);
4337c478bd9Sstevel@tonic-gate     if (result != SASL_OK) goto cleanup;
434*1da57d55SToomas Soome 
4357c478bd9Sstevel@tonic-gate     memset(text->out_buf, 0, *clientoutlen + 1);
4367c478bd9Sstevel@tonic-gate     memcpy(text->out_buf, oparams->user, oparams->ulen);
4377c478bd9Sstevel@tonic-gate     memcpy(text->out_buf + oparams->ulen + 1, oparams->authid, oparams->alen);
4387c478bd9Sstevel@tonic-gate     memcpy(text->out_buf + oparams->ulen + oparams->alen + 2,
4397c478bd9Sstevel@tonic-gate 	   password->data, password->len);
440*1da57d55SToomas Soome 
4417c478bd9Sstevel@tonic-gate     *clientout = text->out_buf;
442*1da57d55SToomas Soome 
4437c478bd9Sstevel@tonic-gate     /* set oparams */
4447c478bd9Sstevel@tonic-gate     oparams->doneflag = 1;
4457c478bd9Sstevel@tonic-gate     oparams->mech_ssf = 0;
4467c478bd9Sstevel@tonic-gate     oparams->maxoutbuf = 0;
4477c478bd9Sstevel@tonic-gate     oparams->encode_context = NULL;
4487c478bd9Sstevel@tonic-gate     oparams->encode = NULL;
4497c478bd9Sstevel@tonic-gate     oparams->decode_context = NULL;
4507c478bd9Sstevel@tonic-gate     oparams->decode = NULL;
4517c478bd9Sstevel@tonic-gate     oparams->param_version = 0;
452*1da57d55SToomas Soome 
4537c478bd9Sstevel@tonic-gate     result = SASL_OK;
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate   cleanup:
4567c478bd9Sstevel@tonic-gate     /* free sensitive info */
4577c478bd9Sstevel@tonic-gate     if (free_password) _plug_free_secret(params->utils, &password);
458*1da57d55SToomas Soome 
4597c478bd9Sstevel@tonic-gate     return result;
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate 
plain_client_mech_dispose(void * conn_context,const sasl_utils_t * utils)4627c478bd9Sstevel@tonic-gate static void plain_client_mech_dispose(void *conn_context,
4637c478bd9Sstevel@tonic-gate 				      const sasl_utils_t *utils)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate     client_context_t *text = (client_context_t *) conn_context;
466*1da57d55SToomas Soome 
4677c478bd9Sstevel@tonic-gate     if (!text) return;
468*1da57d55SToomas Soome 
4697c478bd9Sstevel@tonic-gate     if (text->out_buf) utils->free(text->out_buf);
4707c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
4717c478bd9Sstevel@tonic-gate     convert_prompt(utils, &text->h, NULL);
4727c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
473*1da57d55SToomas Soome 
4747c478bd9Sstevel@tonic-gate     utils->free(text);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate 
477*1da57d55SToomas Soome static sasl_client_plug_t plain_client_plugins[] =
4787c478bd9Sstevel@tonic-gate {
4797c478bd9Sstevel@tonic-gate     {
4807c478bd9Sstevel@tonic-gate 	"PLAIN",			/* mech_name */
4817c478bd9Sstevel@tonic-gate 	0,				/* max_ssf */
4827c478bd9Sstevel@tonic-gate 	SASL_SEC_NOANONYMOUS,		/* security_flags */
4837c478bd9Sstevel@tonic-gate 	SASL_FEAT_WANT_CLIENT_FIRST
4847c478bd9Sstevel@tonic-gate 	| SASL_FEAT_ALLOWS_PROXY,	/* features */
4857c478bd9Sstevel@tonic-gate 	NULL,				/* required_prompts */
4867c478bd9Sstevel@tonic-gate 	NULL,				/* glob_context */
4877c478bd9Sstevel@tonic-gate 	&plain_client_mech_new,		/* mech_new */
4887c478bd9Sstevel@tonic-gate 	&plain_client_mech_step,	/* mech_step */
4897c478bd9Sstevel@tonic-gate 	&plain_client_mech_dispose,	/* mech_dispose */
4907c478bd9Sstevel@tonic-gate 	NULL,				/* mech_free */
4917c478bd9Sstevel@tonic-gate 	NULL,				/* idle */
4927c478bd9Sstevel@tonic-gate 	NULL,				/* spare */
4937c478bd9Sstevel@tonic-gate 	NULL				/* spare */
4947c478bd9Sstevel@tonic-gate     }
4957c478bd9Sstevel@tonic-gate };
4967c478bd9Sstevel@tonic-gate 
plain_client_plug_init(sasl_utils_t * utils,int maxversion,int * out_version,sasl_client_plug_t ** pluglist,int * plugcount)4977c478bd9Sstevel@tonic-gate int plain_client_plug_init(sasl_utils_t *utils,
4987c478bd9Sstevel@tonic-gate 			   int maxversion,
4997c478bd9Sstevel@tonic-gate 			   int *out_version,
5007c478bd9Sstevel@tonic-gate 			   sasl_client_plug_t **pluglist,
5017c478bd9Sstevel@tonic-gate 			   int *plugcount)
5027c478bd9Sstevel@tonic-gate {
5037c478bd9Sstevel@tonic-gate     if (maxversion < SASL_CLIENT_PLUG_VERSION) {
5047c478bd9Sstevel@tonic-gate 	SETERROR(utils, "PLAIN version mismatch");
5057c478bd9Sstevel@tonic-gate 	return SASL_BADVERS;
5067c478bd9Sstevel@tonic-gate     }
507*1da57d55SToomas Soome 
5087c478bd9Sstevel@tonic-gate     *out_version = SASL_CLIENT_PLUG_VERSION;
5097c478bd9Sstevel@tonic-gate     *pluglist = plain_client_plugins;
5107c478bd9Sstevel@tonic-gate     *plugcount = 1;
511*1da57d55SToomas Soome 
5127c478bd9Sstevel@tonic-gate     return SASL_OK;
5137c478bd9Sstevel@tonic-gate }
514