xref: /illumos-gate/usr/src/lib/libsasl/lib/canonusr.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
6*7c478bd9Sstevel@tonic-gate 
7*7c478bd9Sstevel@tonic-gate /* canonusr.c - user canonicalization support
8*7c478bd9Sstevel@tonic-gate  * Rob Siemborski
9*7c478bd9Sstevel@tonic-gate  * $Id: canonusr.c,v 1.12 2003/02/13 19:55:53 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 <sasl.h>
53*7c478bd9Sstevel@tonic-gate #include <string.h>
54*7c478bd9Sstevel@tonic-gate #include <ctype.h>
55*7c478bd9Sstevel@tonic-gate #include <prop.h>
56*7c478bd9Sstevel@tonic-gate #include <stdio.h>
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate #include "saslint.h"
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate typedef struct canonuser_plug_list
61*7c478bd9Sstevel@tonic-gate {
62*7c478bd9Sstevel@tonic-gate     struct canonuser_plug_list *next;
63*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
64*7c478bd9Sstevel@tonic-gate     char *name;
65*7c478bd9Sstevel@tonic-gate #else
66*7c478bd9Sstevel@tonic-gate     char name[PATH_MAX];
67*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
68*7c478bd9Sstevel@tonic-gate     const sasl_canonuser_plug_t *plug;
69*7c478bd9Sstevel@tonic-gate } canonuser_plug_list_t;
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
72*7c478bd9Sstevel@tonic-gate static canonuser_plug_list_t *canonuser_head = NULL;
73*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate /* default behavior:
76*7c478bd9Sstevel@tonic-gate  *                   eliminate leading & trailing whitespace,
77*7c478bd9Sstevel@tonic-gate  *                   null-terminate, and get into the outparams
78*7c478bd9Sstevel@tonic-gate  *
79*7c478bd9Sstevel@tonic-gate  *                   (handled by INTERNAL plugin) */
80*7c478bd9Sstevel@tonic-gate /* Also does auxprop lookups once username is canonoicalized */
81*7c478bd9Sstevel@tonic-gate /* a zero ulen or alen indicates that it is strlen(value) */
_sasl_canon_user(sasl_conn_t * conn,const char * user,unsigned ulen,unsigned flags,sasl_out_params_t * oparams)82*7c478bd9Sstevel@tonic-gate int _sasl_canon_user(sasl_conn_t *conn,
83*7c478bd9Sstevel@tonic-gate                      const char *user, unsigned ulen,
84*7c478bd9Sstevel@tonic-gate                      unsigned flags,
85*7c478bd9Sstevel@tonic-gate                      sasl_out_params_t *oparams)
86*7c478bd9Sstevel@tonic-gate {
87*7c478bd9Sstevel@tonic-gate     canonuser_plug_list_t *ptr;
88*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *sconn = NULL;
89*7c478bd9Sstevel@tonic-gate     sasl_client_conn_t *cconn = NULL;
90*7c478bd9Sstevel@tonic-gate     sasl_canon_user_t *cuser_cb;
91*7c478bd9Sstevel@tonic-gate     sasl_getopt_t *getopt;
92*7c478bd9Sstevel@tonic-gate     void *context;
93*7c478bd9Sstevel@tonic-gate     int result;
94*7c478bd9Sstevel@tonic-gate     const char *plugin_name = NULL;
95*7c478bd9Sstevel@tonic-gate     char *user_buf;
96*7c478bd9Sstevel@tonic-gate     unsigned *lenp;
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate     if(!conn) return SASL_BADPARAM;
99*7c478bd9Sstevel@tonic-gate     if(!user || !oparams) return SASL_BADPARAM;
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate     if(flags & SASL_CU_AUTHID) {
102*7c478bd9Sstevel@tonic-gate 	user_buf = conn->authid_buf;
103*7c478bd9Sstevel@tonic-gate 	lenp = &(oparams->alen);
104*7c478bd9Sstevel@tonic-gate     } else if (flags & SASL_CU_AUTHZID) {
105*7c478bd9Sstevel@tonic-gate 	user_buf = conn->user_buf;
106*7c478bd9Sstevel@tonic-gate 	lenp = &(oparams->ulen);
107*7c478bd9Sstevel@tonic-gate     } else {
108*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
109*7c478bd9Sstevel@tonic-gate     }
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate     if(conn->type == SASL_CONN_SERVER) sconn = (sasl_server_conn_t *)conn;
112*7c478bd9Sstevel@tonic-gate     else if(conn->type == SASL_CONN_CLIENT) cconn = (sasl_client_conn_t *)conn;
113*7c478bd9Sstevel@tonic-gate     else return SASL_FAIL;
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate     if(!ulen) ulen = (unsigned int)strlen(user);
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate     /* check to see if we have a callback to make*/
118*7c478bd9Sstevel@tonic-gate     result = _sasl_getcallback(conn, SASL_CB_CANON_USER,
119*7c478bd9Sstevel@tonic-gate 			       &cuser_cb, &context);
120*7c478bd9Sstevel@tonic-gate     if(result == SASL_OK && cuser_cb) {
121*7c478bd9Sstevel@tonic-gate 	result = cuser_cb(conn, context,
122*7c478bd9Sstevel@tonic-gate 			user, ulen,
123*7c478bd9Sstevel@tonic-gate 			flags, (conn->type == SASL_CONN_SERVER ?
124*7c478bd9Sstevel@tonic-gate 				((sasl_server_conn_t *)conn)->user_realm :
125*7c478bd9Sstevel@tonic-gate 				NULL),
126*7c478bd9Sstevel@tonic-gate 			user_buf, CANON_BUF_SIZE, lenp);
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 	if (result != SASL_OK) return result;
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	/* Point the input copy at the stored buffer */
132*7c478bd9Sstevel@tonic-gate 	user = user_buf;
133*7c478bd9Sstevel@tonic-gate 	ulen = *lenp;
134*7c478bd9Sstevel@tonic-gate     }
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate     /* which plugin are we supposed to use? */
137*7c478bd9Sstevel@tonic-gate     result = _sasl_getcallback(conn, SASL_CB_GETOPT,
138*7c478bd9Sstevel@tonic-gate 			       &getopt, &context);
139*7c478bd9Sstevel@tonic-gate     if(result == SASL_OK && getopt) {
140*7c478bd9Sstevel@tonic-gate 	getopt(context, NULL, "canon_user_plugin", &plugin_name, NULL);
141*7c478bd9Sstevel@tonic-gate     }
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate     if(!plugin_name) {
144*7c478bd9Sstevel@tonic-gate 	/* Use Defualt */
145*7c478bd9Sstevel@tonic-gate 	plugin_name = "INTERNAL";
146*7c478bd9Sstevel@tonic-gate     }
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
149*7c478bd9Sstevel@tonic-gate     for(ptr = conn->gctx->canonuser_head; ptr; ptr = ptr->next) {
150*7c478bd9Sstevel@tonic-gate #else
151*7c478bd9Sstevel@tonic-gate     for(ptr = canonuser_head; ptr; ptr = ptr->next) {
152*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
153*7c478bd9Sstevel@tonic-gate 	/* A match is if we match the internal name of the plugin, or if
154*7c478bd9Sstevel@tonic-gate 	 * we match the filename (old-style) */
155*7c478bd9Sstevel@tonic-gate 	if((ptr->plug->name && !strcmp(plugin_name, ptr->plug->name))
156*7c478bd9Sstevel@tonic-gate 	   || !strcmp(plugin_name, ptr->name)) break;
157*7c478bd9Sstevel@tonic-gate     }
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate     /* We clearly don't have this one! */
160*7c478bd9Sstevel@tonic-gate     if(!ptr) {
161*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
162*7c478bd9Sstevel@tonic-gate 	if (conn->type == SASL_CONN_CLIENT)
163*7c478bd9Sstevel@tonic-gate 		sasl_seterror(conn, 0,
164*7c478bd9Sstevel@tonic-gate 		      gettext("desired canon_user plugin %s not found"),
165*7c478bd9Sstevel@tonic-gate 		      plugin_name);
166*7c478bd9Sstevel@tonic-gate 	else
167*7c478bd9Sstevel@tonic-gate 		_sasl_log(conn, SASL_LOG_ERR,
168*7c478bd9Sstevel@tonic-gate 		      "desired canon_user plugin %s not found",
169*7c478bd9Sstevel@tonic-gate 		      plugin_name);
170*7c478bd9Sstevel@tonic-gate #else
171*7c478bd9Sstevel@tonic-gate 	sasl_seterror(conn, 0, "desired canon_user plugin %s not found",
172*7c478bd9Sstevel@tonic-gate 		      plugin_name);
173*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
174*7c478bd9Sstevel@tonic-gate 	return SASL_NOMECH;
175*7c478bd9Sstevel@tonic-gate     }
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate     if(sconn) {
178*7c478bd9Sstevel@tonic-gate 	/* we're a server */
179*7c478bd9Sstevel@tonic-gate 	result = ptr->plug->canon_user_server(ptr->plug->glob_context,
180*7c478bd9Sstevel@tonic-gate 					      sconn->sparams,
181*7c478bd9Sstevel@tonic-gate 					      user, ulen,
182*7c478bd9Sstevel@tonic-gate 					      flags,
183*7c478bd9Sstevel@tonic-gate 					      user_buf,
184*7c478bd9Sstevel@tonic-gate 					      CANON_BUF_SIZE, lenp);
185*7c478bd9Sstevel@tonic-gate     } else {
186*7c478bd9Sstevel@tonic-gate 	/* we're a client */
187*7c478bd9Sstevel@tonic-gate 	result = ptr->plug->canon_user_client(ptr->plug->glob_context,
188*7c478bd9Sstevel@tonic-gate 					      cconn->cparams,
189*7c478bd9Sstevel@tonic-gate 					      user, ulen,
190*7c478bd9Sstevel@tonic-gate 					      flags,
191*7c478bd9Sstevel@tonic-gate 					      user_buf,
192*7c478bd9Sstevel@tonic-gate 					      CANON_BUF_SIZE, lenp);
193*7c478bd9Sstevel@tonic-gate     }
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate     if(result != SASL_OK) return result;
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate     if((flags & SASL_CU_AUTHID) && (flags & SASL_CU_AUTHZID)) {
198*7c478bd9Sstevel@tonic-gate 	/* We did both, so we need to copy the result into
199*7c478bd9Sstevel@tonic-gate 	 * the buffer for the authzid from the buffer for the authid */
200*7c478bd9Sstevel@tonic-gate 	memcpy(conn->user_buf, conn->authid_buf, CANON_BUF_SIZE);
201*7c478bd9Sstevel@tonic-gate 	oparams->ulen = oparams->alen;
202*7c478bd9Sstevel@tonic-gate     }
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate     /* Set the appropriate oparams (lengths have already been set by lenp) */
205*7c478bd9Sstevel@tonic-gate     if(flags & SASL_CU_AUTHID) {
206*7c478bd9Sstevel@tonic-gate 	oparams->authid = conn->authid_buf;
207*7c478bd9Sstevel@tonic-gate     }
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate     if (flags & SASL_CU_AUTHZID) {
210*7c478bd9Sstevel@tonic-gate 	oparams->user = conn->user_buf;
211*7c478bd9Sstevel@tonic-gate     }
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate #ifndef macintosh
214*7c478bd9Sstevel@tonic-gate     /* do auxprop lookups (server only) */
215*7c478bd9Sstevel@tonic-gate     if(sconn) {
216*7c478bd9Sstevel@tonic-gate 	if(flags & SASL_CU_AUTHID) {
217*7c478bd9Sstevel@tonic-gate 	    _sasl_auxprop_lookup(sconn->sparams, 0,
218*7c478bd9Sstevel@tonic-gate 				 oparams->authid, oparams->alen);
219*7c478bd9Sstevel@tonic-gate 	}
220*7c478bd9Sstevel@tonic-gate 	if(flags & SASL_CU_AUTHZID) {
221*7c478bd9Sstevel@tonic-gate 	    _sasl_auxprop_lookup(sconn->sparams, SASL_AUXPROP_AUTHZID,
222*7c478bd9Sstevel@tonic-gate 				 oparams->user, oparams->ulen);
223*7c478bd9Sstevel@tonic-gate 	}
224*7c478bd9Sstevel@tonic-gate     }
225*7c478bd9Sstevel@tonic-gate #endif
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
229*7c478bd9Sstevel@tonic-gate     return (SASL_OK);
230*7c478bd9Sstevel@tonic-gate #else
231*7c478bd9Sstevel@tonic-gate     RETURN(conn, SASL_OK);
232*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
233*7c478bd9Sstevel@tonic-gate }
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
236*7c478bd9Sstevel@tonic-gate void _sasl_canonuser_free(_sasl_global_context_t *gctx)
237*7c478bd9Sstevel@tonic-gate {
238*7c478bd9Sstevel@tonic-gate     canonuser_plug_list_t *ptr, *ptr_next;
239*7c478bd9Sstevel@tonic-gate     const sasl_utils_t *sasl_global_utils = gctx->sasl_canonusr_global_utils;
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate     for(ptr = (canonuser_plug_list_t *)gctx->canonuser_head;
242*7c478bd9Sstevel@tonic-gate 		ptr; ptr = ptr_next) {
243*7c478bd9Sstevel@tonic-gate 	ptr_next = ptr->next;
244*7c478bd9Sstevel@tonic-gate 	if(ptr->plug->canon_user_free)
245*7c478bd9Sstevel@tonic-gate 	    ptr->plug->canon_user_free(ptr->plug->glob_context,
246*7c478bd9Sstevel@tonic-gate 				       sasl_global_utils);
247*7c478bd9Sstevel@tonic-gate 	sasl_FREE(ptr->name);
248*7c478bd9Sstevel@tonic-gate 	sasl_FREE(ptr);
249*7c478bd9Sstevel@tonic-gate     }
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate     gctx->canonuser_head = NULL;
252*7c478bd9Sstevel@tonic-gate }
253*7c478bd9Sstevel@tonic-gate #else
254*7c478bd9Sstevel@tonic-gate void _sasl_canonuser_free()
255*7c478bd9Sstevel@tonic-gate {
256*7c478bd9Sstevel@tonic-gate     canonuser_plug_list_t *ptr, *ptr_next;
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate     for(ptr = canonuser_head; ptr; ptr = ptr_next) {
259*7c478bd9Sstevel@tonic-gate 	ptr_next = ptr->next;
260*7c478bd9Sstevel@tonic-gate 	if(ptr->plug->canon_user_free)
261*7c478bd9Sstevel@tonic-gate 	    ptr->plug->canon_user_free(ptr->plug->glob_context,
262*7c478bd9Sstevel@tonic-gate 				       sasl_global_utils);
263*7c478bd9Sstevel@tonic-gate 	sasl_FREE(ptr);
264*7c478bd9Sstevel@tonic-gate     }
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate     canonuser_head = NULL;
267*7c478bd9Sstevel@tonic-gate }
268*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
271*7c478bd9Sstevel@tonic-gate int sasl_canonuser_add_plugin(const char *plugname,
272*7c478bd9Sstevel@tonic-gate                               sasl_canonuser_init_t *canonuserfunc)
273*7c478bd9Sstevel@tonic-gate {
274*7c478bd9Sstevel@tonic-gate     return (_sasl_canonuser_add_plugin(_sasl_gbl_ctx(), plugname,
275*7c478bd9Sstevel@tonic-gate         canonuserfunc));
276*7c478bd9Sstevel@tonic-gate }
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate int _sasl_canonuser_add_plugin(void *ctx,
279*7c478bd9Sstevel@tonic-gate                                const char *plugname,
280*7c478bd9Sstevel@tonic-gate                                sasl_canonuser_init_t *canonuserfunc)
281*7c478bd9Sstevel@tonic-gate #else
282*7c478bd9Sstevel@tonic-gate int sasl_canonuser_add_plugin(const char *plugname,
283*7c478bd9Sstevel@tonic-gate 			      sasl_canonuser_init_t *canonuserfunc)
284*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
285*7c478bd9Sstevel@tonic-gate {
286*7c478bd9Sstevel@tonic-gate     int result, out_version;
287*7c478bd9Sstevel@tonic-gate     canonuser_plug_list_t *new_item;
288*7c478bd9Sstevel@tonic-gate     sasl_canonuser_plug_t *plug;
289*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
290*7c478bd9Sstevel@tonic-gate     _sasl_global_context_t *gctx = ctx == NULL ? _sasl_gbl_ctx() : ctx;
291*7c478bd9Sstevel@tonic-gate     const sasl_utils_t *sasl_global_utils;
292*7c478bd9Sstevel@tonic-gate     canonuser_plug_list_t *l;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate   /* Check to see if this plugin has already been registered */
295*7c478bd9Sstevel@tonic-gate     for (l = gctx->canonuser_head; l != NULL; l = l->next) {
296*7c478bd9Sstevel@tonic-gate 	if (strcmp(plugname, l->name) == 0) {
297*7c478bd9Sstevel@tonic-gate 	    return SASL_OK;
298*7c478bd9Sstevel@tonic-gate 	}
299*7c478bd9Sstevel@tonic-gate     }
300*7c478bd9Sstevel@tonic-gate     sasl_global_utils = gctx->sasl_canonusr_global_utils;
301*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate     if(!plugname || strlen(plugname) > (PATH_MAX - 1)) {
304*7c478bd9Sstevel@tonic-gate 	sasl_seterror(NULL, 0,
305*7c478bd9Sstevel@tonic-gate 		      "bad plugname passed to sasl_canonuser_add_plugin\n");
306*7c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
307*7c478bd9Sstevel@tonic-gate     }
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate     result = canonuserfunc(sasl_global_utils, SASL_CANONUSER_PLUG_VERSION,
310*7c478bd9Sstevel@tonic-gate 			   &out_version, &plug, plugname);
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate     if(result != SASL_OK) {
313*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
314*7c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks == NULL ?
315*7c478bd9Sstevel@tonic-gate 	    	   gctx->client_global_callbacks.callbacks :
316*7c478bd9Sstevel@tonic-gate 	    	   gctx->server_global_callbacks.callbacks,
317*7c478bd9Sstevel@tonic-gate 		   SASL_LOG_ERR, "canonuserfunc error %i\n",result);
318*7c478bd9Sstevel@tonic-gate #else
319*7c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR, "canonuserfunc error %i\n",result);
320*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
321*7c478bd9Sstevel@tonic-gate 	return result;
322*7c478bd9Sstevel@tonic-gate     }
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate     if(!plug->canon_user_server && !plug->canon_user_client) {
325*7c478bd9Sstevel@tonic-gate 	/* We need atleast one of these implemented */
326*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
327*7c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks == NULL ?
328*7c478bd9Sstevel@tonic-gate 	    	   gctx->client_global_callbacks.callbacks :
329*7c478bd9Sstevel@tonic-gate 	    	   gctx->server_global_callbacks.callbacks, SASL_LOG_ERR,
330*7c478bd9Sstevel@tonic-gate 		   "canonuser plugin without either client or server side");
331*7c478bd9Sstevel@tonic-gate #else
332*7c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR,
333*7c478bd9Sstevel@tonic-gate 		  "canonuser plugin without either client or server side");
334*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
335*7c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
336*7c478bd9Sstevel@tonic-gate     }
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
339*7c478bd9Sstevel@tonic-gate     /* Check plugin to make sure name is non-NULL */
340*7c478bd9Sstevel@tonic-gate     if (plug->name == NULL) {
341*7c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks == NULL ?
342*7c478bd9Sstevel@tonic-gate 	    	   gctx->client_global_callbacks.callbacks :
343*7c478bd9Sstevel@tonic-gate 	    	   gctx->server_global_callbacks.callbacks,
344*7c478bd9Sstevel@tonic-gate 		   SASL_LOG_ERR, "invalid canonusr plugin %s", plugname);
345*7c478bd9Sstevel@tonic-gate 	return SASL_BADPROT;
346*7c478bd9Sstevel@tonic-gate     }
347*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate     new_item = sasl_ALLOC(sizeof(canonuser_plug_list_t));
350*7c478bd9Sstevel@tonic-gate     if(!new_item) return SASL_NOMEM;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
353*7c478bd9Sstevel@tonic-gate     if(_sasl_strdup(plugname, &new_item->name, NULL) != SASL_OK) {
354*7c478bd9Sstevel@tonic-gate 	sasl_FREE(new_item);
355*7c478bd9Sstevel@tonic-gate 	return SASL_NOMEM;
356*7c478bd9Sstevel@tonic-gate     }
357*7c478bd9Sstevel@tonic-gate #else
358*7c478bd9Sstevel@tonic-gate     strncpy(new_item->name, plugname, PATH_MAX);
359*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate     new_item->plug = plug;
362*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
363*7c478bd9Sstevel@tonic-gate     new_item->next = gctx->canonuser_head;
364*7c478bd9Sstevel@tonic-gate     gctx->canonuser_head = new_item;
365*7c478bd9Sstevel@tonic-gate #else
366*7c478bd9Sstevel@tonic-gate     new_item->next = canonuser_head;
367*7c478bd9Sstevel@tonic-gate     canonuser_head = new_item;
368*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate     return SASL_OK;
371*7c478bd9Sstevel@tonic-gate }
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate #ifdef MIN
374*7c478bd9Sstevel@tonic-gate #undef MIN
375*7c478bd9Sstevel@tonic-gate #endif
376*7c478bd9Sstevel@tonic-gate #define MIN(a,b) (((a) < (b))? (a):(b))
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate static int _canonuser_internal(const sasl_utils_t *utils,
379*7c478bd9Sstevel@tonic-gate 			       const char *user, unsigned ulen,
380*7c478bd9Sstevel@tonic-gate 			       unsigned flags __attribute__((unused)),
381*7c478bd9Sstevel@tonic-gate 			       char *out_user,
382*7c478bd9Sstevel@tonic-gate 			       unsigned out_umax, unsigned *out_ulen)
383*7c478bd9Sstevel@tonic-gate {
384*7c478bd9Sstevel@tonic-gate     unsigned i;
385*7c478bd9Sstevel@tonic-gate     char *in_buf, *userin;
386*7c478bd9Sstevel@tonic-gate     const char *begin_u;
387*7c478bd9Sstevel@tonic-gate     unsigned u_apprealm = 0;
388*7c478bd9Sstevel@tonic-gate     sasl_server_conn_t *sconn = NULL;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate     if(!utils || !user) return SASL_BADPARAM;
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
393*7c478bd9Sstevel@tonic-gate     in_buf = utils->malloc((ulen + 2) * sizeof(char));
394*7c478bd9Sstevel@tonic-gate #else
395*7c478bd9Sstevel@tonic-gate     in_buf = sasl_ALLOC((ulen + 2) * sizeof(char));
396*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
397*7c478bd9Sstevel@tonic-gate     if(!in_buf) return SASL_NOMEM;
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate     userin = in_buf;
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate     memcpy(userin, user, ulen);
402*7c478bd9Sstevel@tonic-gate     userin[ulen] = '\0';
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate     /* Strip User ID */
405*7c478bd9Sstevel@tonic-gate     for(i=0;isspace((int)userin[i]) && i<ulen;i++);
406*7c478bd9Sstevel@tonic-gate     begin_u = &(userin[i]);
407*7c478bd9Sstevel@tonic-gate     if(i>0) ulen -= i;
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate     for(;ulen > 0 && isspace((int)begin_u[ulen-1]); ulen--);
410*7c478bd9Sstevel@tonic-gate     if(begin_u == &(userin[ulen])) {
411*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
412*7c478bd9Sstevel@tonic-gate 	utils->free(in_buf);
413*7c478bd9Sstevel@tonic-gate #else
414*7c478bd9Sstevel@tonic-gate 	sasl_FREE(in_buf);
415*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
416*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
417*7c478bd9Sstevel@tonic-gate 	utils->seterror(utils->conn, 0, gettext("All-whitespace username."));
418*7c478bd9Sstevel@tonic-gate #else
419*7c478bd9Sstevel@tonic-gate 	utils->seterror(utils->conn, 0, "All-whitespace username.");
420*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
421*7c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
422*7c478bd9Sstevel@tonic-gate     }
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate     if(utils->conn && utils->conn->type == SASL_CONN_SERVER)
425*7c478bd9Sstevel@tonic-gate 	sconn = (sasl_server_conn_t *)utils->conn;
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate     /* Need to append realm if necessary (see sasl.h) */
428*7c478bd9Sstevel@tonic-gate     if(sconn && sconn->user_realm && !strchr(user, '@')) {
429*7c478bd9Sstevel@tonic-gate 	u_apprealm = strlen(sconn->user_realm) + 1;
430*7c478bd9Sstevel@tonic-gate     }
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate     /* Now Copy */
433*7c478bd9Sstevel@tonic-gate     memcpy(out_user, begin_u, MIN(ulen, out_umax));
434*7c478bd9Sstevel@tonic-gate     if(sconn && u_apprealm) {
435*7c478bd9Sstevel@tonic-gate 	if(ulen >= out_umax) return SASL_BUFOVER;
436*7c478bd9Sstevel@tonic-gate 	out_user[ulen] = '@';
437*7c478bd9Sstevel@tonic-gate 	memcpy(&(out_user[ulen+1]), sconn->user_realm,
438*7c478bd9Sstevel@tonic-gate 	       MIN(u_apprealm-1, out_umax-ulen-1));
439*7c478bd9Sstevel@tonic-gate     }
440*7c478bd9Sstevel@tonic-gate     out_user[MIN(ulen + u_apprealm,out_umax)] = '\0';
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate     if(ulen + u_apprealm > out_umax) return SASL_BUFOVER;
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate     if(out_ulen) *out_ulen = MIN(ulen + u_apprealm,out_umax);
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
447*7c478bd9Sstevel@tonic-gate     utils->free(in_buf);
448*7c478bd9Sstevel@tonic-gate #else
449*7c478bd9Sstevel@tonic-gate     sasl_FREE(in_buf);
450*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
451*7c478bd9Sstevel@tonic-gate     return SASL_OK;
452*7c478bd9Sstevel@tonic-gate }
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate static int _cu_internal_server(void *glob_context __attribute__((unused)),
455*7c478bd9Sstevel@tonic-gate 			       sasl_server_params_t *sparams,
456*7c478bd9Sstevel@tonic-gate 			       const char *user, unsigned ulen,
457*7c478bd9Sstevel@tonic-gate 			       unsigned flags,
458*7c478bd9Sstevel@tonic-gate 			       char *out_user,
459*7c478bd9Sstevel@tonic-gate 			       unsigned out_umax, unsigned *out_ulen)
460*7c478bd9Sstevel@tonic-gate {
461*7c478bd9Sstevel@tonic-gate     return _canonuser_internal(sparams->utils,
462*7c478bd9Sstevel@tonic-gate 			       user, ulen,
463*7c478bd9Sstevel@tonic-gate 			       flags, out_user, out_umax, out_ulen);
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate static int _cu_internal_client(void *glob_context __attribute__((unused)),
467*7c478bd9Sstevel@tonic-gate 			       sasl_client_params_t *cparams,
468*7c478bd9Sstevel@tonic-gate 			       const char *user, unsigned ulen,
469*7c478bd9Sstevel@tonic-gate 			       unsigned flags,
470*7c478bd9Sstevel@tonic-gate 			       char *out_user,
471*7c478bd9Sstevel@tonic-gate 			       unsigned out_umax, unsigned *out_ulen)
472*7c478bd9Sstevel@tonic-gate {
473*7c478bd9Sstevel@tonic-gate     return _canonuser_internal(cparams->utils,
474*7c478bd9Sstevel@tonic-gate 			       user, ulen,
475*7c478bd9Sstevel@tonic-gate 			       flags, out_user, out_umax, out_ulen);
476*7c478bd9Sstevel@tonic-gate }
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate static sasl_canonuser_plug_t canonuser_internal_plugin = {
479*7c478bd9Sstevel@tonic-gate         0, /* features */
480*7c478bd9Sstevel@tonic-gate 	0, /* spare */
481*7c478bd9Sstevel@tonic-gate 	NULL, /* glob_context */
482*7c478bd9Sstevel@tonic-gate 	"INTERNAL", /* name */
483*7c478bd9Sstevel@tonic-gate 	NULL, /* canon_user_free */
484*7c478bd9Sstevel@tonic-gate 	_cu_internal_server,
485*7c478bd9Sstevel@tonic-gate 	_cu_internal_client,
486*7c478bd9Sstevel@tonic-gate 	NULL,
487*7c478bd9Sstevel@tonic-gate 	NULL,
488*7c478bd9Sstevel@tonic-gate 	NULL
489*7c478bd9Sstevel@tonic-gate };
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate int internal_canonuser_init(const sasl_utils_t *utils __attribute__((unused)),
492*7c478bd9Sstevel@tonic-gate                             int max_version,
493*7c478bd9Sstevel@tonic-gate                             int *out_version,
494*7c478bd9Sstevel@tonic-gate                             sasl_canonuser_plug_t **plug,
495*7c478bd9Sstevel@tonic-gate                             const char *plugname __attribute__((unused)))
496*7c478bd9Sstevel@tonic-gate {
497*7c478bd9Sstevel@tonic-gate     if(!out_version || !plug) return SASL_BADPARAM;
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate     if(max_version < SASL_CANONUSER_PLUG_VERSION) return SASL_BADVERS;
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate     *out_version = SASL_CANONUSER_PLUG_VERSION;
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate     *plug = &canonuser_internal_plugin;
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate     return SASL_OK;
506*7c478bd9Sstevel@tonic-gate }
507