xref: /illumos-gate/usr/src/lib/libsasl/lib/external.c (revision 1da57d551424de5a9d469760be7c4b4d4f10a755)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /* SASL server API implementation
7*7c478bd9Sstevel@tonic-gate  * Rob Siemborski
8*7c478bd9Sstevel@tonic-gate  * Tim Martin
9*7c478bd9Sstevel@tonic-gate  * $Id: external.c,v 1.19 2003/04/08 17:30:54 rjs3 Exp $
10*7c478bd9Sstevel@tonic-gate  */
11*7c478bd9Sstevel@tonic-gate /*
12*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
15*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
16*7c478bd9Sstevel@tonic-gate  * are met:
17*7c478bd9Sstevel@tonic-gate  *
18*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
19*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
20*7c478bd9Sstevel@tonic-gate  *
21*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
22*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
23*7c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
24*7c478bd9Sstevel@tonic-gate  *    distribution.
25*7c478bd9Sstevel@tonic-gate  *
26*7c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
27*7c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
28*7c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
29*7c478bd9Sstevel@tonic-gate  *    details, please contact
30*7c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
31*7c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
32*7c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
33*7c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
34*7c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
35*7c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
36*7c478bd9Sstevel@tonic-gate  *
37*7c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
38*7c478bd9Sstevel@tonic-gate  *    acknowledgment:
39*7c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
40*7c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
41*7c478bd9Sstevel@tonic-gate  *
42*7c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
43*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
44*7c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
45*7c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46*7c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
47*7c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
48*7c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49*7c478bd9Sstevel@tonic-gate  */
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #include <config.h>
52*7c478bd9Sstevel@tonic-gate #include <stdio.h>
53*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
54*7c478bd9Sstevel@tonic-gate #include <limits.h>
55*7c478bd9Sstevel@tonic-gate #include <ctype.h>
56*7c478bd9Sstevel@tonic-gate #include <string.h>
57*7c478bd9Sstevel@tonic-gate #include <sasl.h>
58*7c478bd9Sstevel@tonic-gate #include <saslplug.h>
59*7c478bd9Sstevel@tonic-gate #include "saslint.h"
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate #include <plugin_common.h>
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate /*****************************  Common Section  *****************************/
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
66*7c478bd9Sstevel@tonic-gate static const char plugin_id[] = "$Id: external.c,v 1.19 2003/04/08 17:30:54 rjs3 Exp $";
67*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate /*****************************  Server Section  *****************************/
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate static int
external_server_mech_new(void * glob_context,sasl_server_params_t * sparams,const char * challenge,unsigned challen,void ** conn_context)72*7c478bd9Sstevel@tonic-gate external_server_mech_new(void *glob_context __attribute__((unused)),
73*7c478bd9Sstevel@tonic-gate 			 sasl_server_params_t *sparams,
74*7c478bd9Sstevel@tonic-gate 			 const char *challenge __attribute__((unused)),
75*7c478bd9Sstevel@tonic-gate 			 unsigned challen __attribute__((unused)),
76*7c478bd9Sstevel@tonic-gate 			 void **conn_context)
77*7c478bd9Sstevel@tonic-gate {
78*7c478bd9Sstevel@tonic-gate     if (!conn_context
79*7c478bd9Sstevel@tonic-gate 	|| !sparams
80*7c478bd9Sstevel@tonic-gate 	|| !sparams->utils
81*7c478bd9Sstevel@tonic-gate 	|| !sparams->utils->conn)
82*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate     if (!sparams->utils->conn->external.auth_id)
85*7c478bd9Sstevel@tonic-gate 	return SASL_NOMECH;
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate     *conn_context = NULL;
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate     return SASL_OK;
90*7c478bd9Sstevel@tonic-gate }
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate static int
external_server_mech_step(void * conn_context,sasl_server_params_t * sparams,const char * clientin,unsigned clientinlen,const char ** serverout,unsigned * serveroutlen,sasl_out_params_t * oparams)93*7c478bd9Sstevel@tonic-gate external_server_mech_step(void *conn_context __attribute__((unused)),
94*7c478bd9Sstevel@tonic-gate 			  sasl_server_params_t *sparams,
95*7c478bd9Sstevel@tonic-gate 			  const char *clientin,
96*7c478bd9Sstevel@tonic-gate 			  unsigned clientinlen,
97*7c478bd9Sstevel@tonic-gate 			  const char **serverout,
98*7c478bd9Sstevel@tonic-gate 			  unsigned *serveroutlen,
99*7c478bd9Sstevel@tonic-gate 			  sasl_out_params_t *oparams)
100*7c478bd9Sstevel@tonic-gate {
101*7c478bd9Sstevel@tonic-gate     int result;
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate     if (!sparams
104*7c478bd9Sstevel@tonic-gate 	|| !sparams->utils
105*7c478bd9Sstevel@tonic-gate 	|| !sparams->utils->conn
106*7c478bd9Sstevel@tonic-gate 	|| !sparams->utils->getcallback
107*7c478bd9Sstevel@tonic-gate 	|| !serverout
108*7c478bd9Sstevel@tonic-gate 	|| !serveroutlen
109*7c478bd9Sstevel@tonic-gate 	|| !oparams)
110*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate     if (!sparams->utils->conn->external.auth_id)
113*7c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate     if ((sparams->props.security_flags & SASL_SEC_NOANONYMOUS) &&
116*7c478bd9Sstevel@tonic-gate 	(!strcmp(sparams->utils->conn->external.auth_id, "anonymous"))) {
117*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
118*7c478bd9Sstevel@tonic-gate 	sasl_seterror(sparams->utils->conn,0,
119*7c478bd9Sstevel@tonic-gate 		gettext("anonymous login not allowed"));
120*7c478bd9Sstevel@tonic-gate #else
121*7c478bd9Sstevel@tonic-gate 	sasl_seterror(sparams->utils->conn,0,"anonymous login not allowed");
122*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
123*7c478bd9Sstevel@tonic-gate 	return SASL_NOAUTHZ;
124*7c478bd9Sstevel@tonic-gate     }
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate     *serverout = NULL;
127*7c478bd9Sstevel@tonic-gate     *serveroutlen = 0;
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate     if (!clientin) {
130*7c478bd9Sstevel@tonic-gate 	/* No initial data; we're in a protocol which doesn't support it.
131*7c478bd9Sstevel@tonic-gate 	 * So we let the server app know that we need some... */
132*7c478bd9Sstevel@tonic-gate 	return SASL_CONTINUE;
133*7c478bd9Sstevel@tonic-gate     }
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate     if (clientinlen) {		/* if we have a non-zero authorization id */
136*7c478bd9Sstevel@tonic-gate 	/* The user's trying to authorize as someone they didn't
137*7c478bd9Sstevel@tonic-gate 	 * authenticate as */
138*7c478bd9Sstevel@tonic-gate 	result = sparams->canon_user(sparams->utils->conn,
139*7c478bd9Sstevel@tonic-gate 				     clientin, 0, SASL_CU_AUTHZID, oparams);
140*7c478bd9Sstevel@tonic-gate 	if(result != SASL_OK) return result;
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	result = sparams->canon_user(sparams->utils->conn,
143*7c478bd9Sstevel@tonic-gate 				     sparams->utils->conn->external.auth_id, 0,
144*7c478bd9Sstevel@tonic-gate 				     SASL_CU_AUTHID, oparams);
145*7c478bd9Sstevel@tonic-gate     } else {
146*7c478bd9Sstevel@tonic-gate 	result = sparams->canon_user(sparams->utils->conn,
147*7c478bd9Sstevel@tonic-gate 				     sparams->utils->conn->external.auth_id, 0,
148*7c478bd9Sstevel@tonic-gate 				     SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams);
149*7c478bd9Sstevel@tonic-gate     }
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate     if (result != SASL_OK) return result;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate     /* set oparams */
154*7c478bd9Sstevel@tonic-gate     oparams->doneflag = 1;
155*7c478bd9Sstevel@tonic-gate     oparams->mech_ssf = 0;
156*7c478bd9Sstevel@tonic-gate     oparams->maxoutbuf = 0;
157*7c478bd9Sstevel@tonic-gate     oparams->encode_context = NULL;
158*7c478bd9Sstevel@tonic-gate     oparams->encode = NULL;
159*7c478bd9Sstevel@tonic-gate     oparams->decode_context = NULL;
160*7c478bd9Sstevel@tonic-gate     oparams->decode = NULL;
161*7c478bd9Sstevel@tonic-gate     oparams->param_version = 0;
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate     return SASL_OK;
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate static int
external_server_mech_avail(void * glob_context,sasl_server_params_t * sparams,void ** conn_context)167*7c478bd9Sstevel@tonic-gate external_server_mech_avail(void *glob_context __attribute__((unused)),
168*7c478bd9Sstevel@tonic-gate 			   sasl_server_params_t *sparams,
169*7c478bd9Sstevel@tonic-gate 			   void **conn_context __attribute__((unused)))
170*7c478bd9Sstevel@tonic-gate {
171*7c478bd9Sstevel@tonic-gate     if (!sparams->utils->conn->external.auth_id)
172*7c478bd9Sstevel@tonic-gate 	return SASL_NOMECH;
173*7c478bd9Sstevel@tonic-gate     return SASL_OK;
174*7c478bd9Sstevel@tonic-gate }
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate static sasl_server_plug_t external_server_plugins[] =
177*7c478bd9Sstevel@tonic-gate {
178*7c478bd9Sstevel@tonic-gate     {
179*7c478bd9Sstevel@tonic-gate 	"EXTERNAL",			/* mech_name */
180*7c478bd9Sstevel@tonic-gate 	0,				/* max_ssf */
181*7c478bd9Sstevel@tonic-gate 	SASL_SEC_NOPLAINTEXT
182*7c478bd9Sstevel@tonic-gate 	| SASL_SEC_NOANONYMOUS
183*7c478bd9Sstevel@tonic-gate 	| SASL_SEC_NODICTIONARY,	/* security_flags */
184*7c478bd9Sstevel@tonic-gate 	SASL_FEAT_WANT_CLIENT_FIRST
185*7c478bd9Sstevel@tonic-gate 	| SASL_FEAT_ALLOWS_PROXY,	/* features */
186*7c478bd9Sstevel@tonic-gate 	NULL,				/* glob_context */
187*7c478bd9Sstevel@tonic-gate 	&external_server_mech_new,	/* mech_new */
188*7c478bd9Sstevel@tonic-gate 	&external_server_mech_step,	/* mech_step */
189*7c478bd9Sstevel@tonic-gate 	NULL,				/* mech_dispose */
190*7c478bd9Sstevel@tonic-gate 	NULL,				/* mech_free */
191*7c478bd9Sstevel@tonic-gate 	NULL,				/* setpass */
192*7c478bd9Sstevel@tonic-gate 	NULL,				/* user_query */
193*7c478bd9Sstevel@tonic-gate 	NULL,				/* idle */
194*7c478bd9Sstevel@tonic-gate 	&external_server_mech_avail,	/* mech_avail */
195*7c478bd9Sstevel@tonic-gate 	NULL				/* spare */
196*7c478bd9Sstevel@tonic-gate     }
197*7c478bd9Sstevel@tonic-gate };
198*7c478bd9Sstevel@tonic-gate 
external_server_plug_init(const sasl_utils_t * utils,int max_version,int * out_version,sasl_server_plug_t ** pluglist,int * plugcount)199*7c478bd9Sstevel@tonic-gate int external_server_plug_init(const sasl_utils_t *utils,
200*7c478bd9Sstevel@tonic-gate 			      int max_version,
201*7c478bd9Sstevel@tonic-gate 			      int *out_version,
202*7c478bd9Sstevel@tonic-gate 			      sasl_server_plug_t **pluglist,
203*7c478bd9Sstevel@tonic-gate 			      int *plugcount)
204*7c478bd9Sstevel@tonic-gate {
205*7c478bd9Sstevel@tonic-gate     if (!out_version || !pluglist || !plugcount)
206*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate     if (max_version != SASL_SERVER_PLUG_VERSION) {
209*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
210*7c478bd9Sstevel@tonic-gate 	utils->log(utils->conn, SASL_LOG_ERR, "EXTERNAL version mismatch");
211*7c478bd9Sstevel@tonic-gate #else
212*7c478bd9Sstevel@tonic-gate 	SETERROR( utils, "EXTERNAL version mismatch" );
213*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
214*7c478bd9Sstevel@tonic-gate 	return SASL_BADVERS;
215*7c478bd9Sstevel@tonic-gate     }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate     *out_version = SASL_SERVER_PLUG_VERSION;
218*7c478bd9Sstevel@tonic-gate     *pluglist = external_server_plugins;
219*7c478bd9Sstevel@tonic-gate     *plugcount = 1;
220*7c478bd9Sstevel@tonic-gate     return SASL_OK;
221*7c478bd9Sstevel@tonic-gate }
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate /*****************************  Client Section  *****************************/
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate typedef struct client_context
226*7c478bd9Sstevel@tonic-gate {
227*7c478bd9Sstevel@tonic-gate     char *out_buf;
228*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
229*7c478bd9Sstevel@tonic-gate     unsigned out_buf_len;
230*7c478bd9Sstevel@tonic-gate #else
231*7c478bd9Sstevel@tonic-gate     size_t out_buf_len;
232*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
233*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
234*7c478bd9Sstevel@tonic-gate     void *h;
235*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
236*7c478bd9Sstevel@tonic-gate } client_context_t;
237*7c478bd9Sstevel@tonic-gate 
external_client_mech_new(void * glob_context,sasl_client_params_t * params,void ** conn_context)238*7c478bd9Sstevel@tonic-gate static int external_client_mech_new(void *glob_context __attribute__((unused)),
239*7c478bd9Sstevel@tonic-gate 				    sasl_client_params_t *params,
240*7c478bd9Sstevel@tonic-gate 				    void **conn_context)
241*7c478bd9Sstevel@tonic-gate {
242*7c478bd9Sstevel@tonic-gate     client_context_t *text;
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate     if (!params
245*7c478bd9Sstevel@tonic-gate 	|| !params->utils
246*7c478bd9Sstevel@tonic-gate 	|| !params->utils->conn
247*7c478bd9Sstevel@tonic-gate 	|| !conn_context)
248*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate     if (!params->utils->conn->external.auth_id)
251*7c478bd9Sstevel@tonic-gate 	return SASL_NOMECH;
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
254*7c478bd9Sstevel@tonic-gate     text = params->utils->malloc(sizeof(client_context_t));
255*7c478bd9Sstevel@tonic-gate #else
256*7c478bd9Sstevel@tonic-gate     text = sasl_ALLOC(sizeof(client_context_t));
257*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
258*7c478bd9Sstevel@tonic-gate     if(!text) return SASL_NOMEM;
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate     memset(text, 0, sizeof(client_context_t));
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate     *conn_context = text;
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate     return SASL_OK;
265*7c478bd9Sstevel@tonic-gate }
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate static int
external_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)268*7c478bd9Sstevel@tonic-gate external_client_mech_step(void *conn_context,
269*7c478bd9Sstevel@tonic-gate 			  sasl_client_params_t *params,
270*7c478bd9Sstevel@tonic-gate 			  const char *serverin __attribute__((unused)),
271*7c478bd9Sstevel@tonic-gate 			  unsigned serverinlen,
272*7c478bd9Sstevel@tonic-gate 			  sasl_interact_t **prompt_need,
273*7c478bd9Sstevel@tonic-gate 			  const char **clientout,
274*7c478bd9Sstevel@tonic-gate 			  unsigned *clientoutlen,
275*7c478bd9Sstevel@tonic-gate 			  sasl_out_params_t *oparams)
276*7c478bd9Sstevel@tonic-gate {
277*7c478bd9Sstevel@tonic-gate     client_context_t *text = (client_context_t *)conn_context;
278*7c478bd9Sstevel@tonic-gate     const char *user = NULL;
279*7c478bd9Sstevel@tonic-gate     int user_result = SASL_OK;
280*7c478bd9Sstevel@tonic-gate     int result;
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate     if (!params
283*7c478bd9Sstevel@tonic-gate 	|| !params->utils
284*7c478bd9Sstevel@tonic-gate 	|| !params->utils->conn
285*7c478bd9Sstevel@tonic-gate 	|| !params->utils->getcallback
286*7c478bd9Sstevel@tonic-gate 	|| !clientout
287*7c478bd9Sstevel@tonic-gate 	|| !clientoutlen
288*7c478bd9Sstevel@tonic-gate 	|| !oparams)
289*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate     if (!params->utils->conn->external.auth_id)
292*7c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate     if (serverinlen != 0)
295*7c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate     *clientout = NULL;
298*7c478bd9Sstevel@tonic-gate     *clientoutlen = 0;
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate     /* try to get the userid */
301*7c478bd9Sstevel@tonic-gate     if (user == NULL) {
302*7c478bd9Sstevel@tonic-gate 	user_result = _plug_get_userid(params->utils, &user, prompt_need);
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	if ((user_result != SASL_OK) && (user_result != SASL_INTERACT))
305*7c478bd9Sstevel@tonic-gate 	    return user_result;
306*7c478bd9Sstevel@tonic-gate     }
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate     /* free prompts we got */
309*7c478bd9Sstevel@tonic-gate     if (prompt_need && *prompt_need) {
310*7c478bd9Sstevel@tonic-gate 	params->utils->free(*prompt_need);
311*7c478bd9Sstevel@tonic-gate 	*prompt_need = NULL;
312*7c478bd9Sstevel@tonic-gate     }
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate     /* if there are prompts not filled in */
315*7c478bd9Sstevel@tonic-gate     if (user_result == SASL_INTERACT) {
316*7c478bd9Sstevel@tonic-gate 	/* make the prompt list */
317*7c478bd9Sstevel@tonic-gate 	int result =
318*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
319*7c478bd9Sstevel@tonic-gate 	    _plug_make_prompts(params->utils, &text->h, prompt_need,
320*7c478bd9Sstevel@tonic-gate 			       user_result == SASL_INTERACT ?
321*7c478bd9Sstevel@tonic-gate 			       convert_prompt(params->utils, &text->h,
322*7c478bd9Sstevel@tonic-gate 			       gettext("Please enter your authorization name"))
323*7c478bd9Sstevel@tonic-gate 				 : NULL,
324*7c478bd9Sstevel@tonic-gate #else
325*7c478bd9Sstevel@tonic-gate 	    _plug_make_prompts(params->utils, prompt_need,
326*7c478bd9Sstevel@tonic-gate 			       user_result == SASL_INTERACT ?
327*7c478bd9Sstevel@tonic-gate 			       "Please enter your authorization name" : NULL,
328*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
329*7c478bd9Sstevel@tonic-gate 			       "",
330*7c478bd9Sstevel@tonic-gate 			       NULL, NULL,
331*7c478bd9Sstevel@tonic-gate 			       NULL, NULL,
332*7c478bd9Sstevel@tonic-gate 			       NULL, NULL, NULL,
333*7c478bd9Sstevel@tonic-gate 			       NULL, NULL, NULL);
334*7c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) return result;
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	return SASL_INTERACT;
337*7c478bd9Sstevel@tonic-gate     }
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate     *clientoutlen = user ? strlen(user) : 0;
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
342*7c478bd9Sstevel@tonic-gate     result = _plug_buf_alloc(params->utils, &text->out_buf,
343*7c478bd9Sstevel@tonic-gate         &text->out_buf_len, *clientoutlen + 1);
344*7c478bd9Sstevel@tonic-gate #else
345*7c478bd9Sstevel@tonic-gate     result = _buf_alloc(&text->out_buf, &text->out_buf_len, *clientoutlen + 1);
346*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate     if (result != SASL_OK) return result;
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate     if (user && *user) {
351*7c478bd9Sstevel@tonic-gate 	result = params->canon_user(params->utils->conn,
352*7c478bd9Sstevel@tonic-gate 				    user, 0, SASL_CU_AUTHZID, oparams);
353*7c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) return result;
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 	result = params->canon_user(params->utils->conn,
356*7c478bd9Sstevel@tonic-gate 				    params->utils->conn->external.auth_id, 0,
357*7c478bd9Sstevel@tonic-gate 				    SASL_CU_AUTHID, oparams);
358*7c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) return result;
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	memcpy(text->out_buf, user, *clientoutlen);
361*7c478bd9Sstevel@tonic-gate     } else {
362*7c478bd9Sstevel@tonic-gate 	result = params->canon_user(params->utils->conn,
363*7c478bd9Sstevel@tonic-gate 				    params->utils->conn->external.auth_id, 0,
364*7c478bd9Sstevel@tonic-gate 				    SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams);
365*7c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) return result;
366*7c478bd9Sstevel@tonic-gate     }
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate     text->out_buf[*clientoutlen] = '\0';
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate     *clientout = text->out_buf;
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate     /* set oparams */
373*7c478bd9Sstevel@tonic-gate     oparams->doneflag = 1;
374*7c478bd9Sstevel@tonic-gate     oparams->mech_ssf = 0;
375*7c478bd9Sstevel@tonic-gate     oparams->maxoutbuf = 0;
376*7c478bd9Sstevel@tonic-gate     oparams->encode_context = NULL;
377*7c478bd9Sstevel@tonic-gate     oparams->encode = NULL;
378*7c478bd9Sstevel@tonic-gate     oparams->decode_context = NULL;
379*7c478bd9Sstevel@tonic-gate     oparams->decode = NULL;
380*7c478bd9Sstevel@tonic-gate     oparams->param_version = 0;
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate     return SASL_OK;
383*7c478bd9Sstevel@tonic-gate }
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate static void
external_client_mech_dispose(void * conn_context,const sasl_utils_t * utils)386*7c478bd9Sstevel@tonic-gate external_client_mech_dispose(void *conn_context,
387*7c478bd9Sstevel@tonic-gate 			     const sasl_utils_t *utils __attribute__((unused)))
388*7c478bd9Sstevel@tonic-gate {
389*7c478bd9Sstevel@tonic-gate     client_context_t *text = (client_context_t *) conn_context;
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate     if (!text) return;
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
394*7c478bd9Sstevel@tonic-gate     convert_prompt(utils, &text->h, NULL);
395*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
398*7c478bd9Sstevel@tonic-gate     if(text->out_buf) utils->free(text->out_buf);
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate     utils->free(text);
401*7c478bd9Sstevel@tonic-gate #else
402*7c478bd9Sstevel@tonic-gate     if(text->out_buf) sasl_FREE(text->out_buf);
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate     sasl_FREE(text);
405*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
406*7c478bd9Sstevel@tonic-gate }
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
409*7c478bd9Sstevel@tonic-gate static const unsigned long external_required_prompts[] = {
410*7c478bd9Sstevel@tonic-gate #else
411*7c478bd9Sstevel@tonic-gate static const long external_required_prompts[] = {
412*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
413*7c478bd9Sstevel@tonic-gate     SASL_CB_LIST_END
414*7c478bd9Sstevel@tonic-gate };
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate static sasl_client_plug_t external_client_plugins[] =
417*7c478bd9Sstevel@tonic-gate {
418*7c478bd9Sstevel@tonic-gate     {
419*7c478bd9Sstevel@tonic-gate 	"EXTERNAL",			/* mech_name */
420*7c478bd9Sstevel@tonic-gate 	0,				/* max_ssf */
421*7c478bd9Sstevel@tonic-gate 	SASL_SEC_NOPLAINTEXT
422*7c478bd9Sstevel@tonic-gate 	| SASL_SEC_NOANONYMOUS
423*7c478bd9Sstevel@tonic-gate 	| SASL_SEC_NODICTIONARY,	/* security_flags */
424*7c478bd9Sstevel@tonic-gate 	SASL_FEAT_WANT_CLIENT_FIRST
425*7c478bd9Sstevel@tonic-gate 	| SASL_FEAT_ALLOWS_PROXY,	/* features */
426*7c478bd9Sstevel@tonic-gate 	external_required_prompts,	/* required_prompts */
427*7c478bd9Sstevel@tonic-gate 	NULL,				/* glob_context */
428*7c478bd9Sstevel@tonic-gate 	&external_client_mech_new,	/* mech_new */
429*7c478bd9Sstevel@tonic-gate 	&external_client_mech_step,	/* mech_step */
430*7c478bd9Sstevel@tonic-gate 	&external_client_mech_dispose,	/* mech_dispose */
431*7c478bd9Sstevel@tonic-gate 	NULL,				/* mech_free */
432*7c478bd9Sstevel@tonic-gate 	NULL,				/* idle */
433*7c478bd9Sstevel@tonic-gate 	NULL,				/* spare */
434*7c478bd9Sstevel@tonic-gate 	NULL				/* spare */
435*7c478bd9Sstevel@tonic-gate     }
436*7c478bd9Sstevel@tonic-gate };
437*7c478bd9Sstevel@tonic-gate 
external_client_plug_init(const sasl_utils_t * utils,int max_version,int * out_version,sasl_client_plug_t ** pluglist,int * plugcount)438*7c478bd9Sstevel@tonic-gate int external_client_plug_init(const sasl_utils_t *utils,
439*7c478bd9Sstevel@tonic-gate 			      int max_version,
440*7c478bd9Sstevel@tonic-gate 			      int *out_version,
441*7c478bd9Sstevel@tonic-gate 			      sasl_client_plug_t **pluglist,
442*7c478bd9Sstevel@tonic-gate 			      int *plugcount)
443*7c478bd9Sstevel@tonic-gate {
444*7c478bd9Sstevel@tonic-gate     if (!utils || !out_version || !pluglist || !plugcount)
445*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate     if (max_version != SASL_CLIENT_PLUG_VERSION) {
448*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
449*7c478bd9Sstevel@tonic-gate 	utils->log(utils->conn, SASL_LOG_ERR, "EXTERNAL version mismatch");
450*7c478bd9Sstevel@tonic-gate #else
451*7c478bd9Sstevel@tonic-gate 	SETERROR( utils, "EXTERNAL version mismatch" );
452*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
453*7c478bd9Sstevel@tonic-gate 	return SASL_BADVERS;
454*7c478bd9Sstevel@tonic-gate     }
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate     *out_version = SASL_CLIENT_PLUG_VERSION;
457*7c478bd9Sstevel@tonic-gate     *pluglist = external_client_plugins;
458*7c478bd9Sstevel@tonic-gate     *plugcount = 1;
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate     return SASL_OK;
461*7c478bd9Sstevel@tonic-gate }
462