1*2871f9cfSDan McDonald /*
2*2871f9cfSDan McDonald * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
3*2871f9cfSDan McDonald */
4*2871f9cfSDan McDonald
5*2871f9cfSDan McDonald /* LOGIN is a PLAIN-like authenticator, but for older deployments. */
6*2871f9cfSDan McDonald
7*2871f9cfSDan McDonald /* Login SASL plugin
8*2871f9cfSDan McDonald * Rob Siemborski (SASLv2 Conversion)
9*2871f9cfSDan McDonald * contributed by Rainer Schoepf <schoepf@uni-mainz.de>
10*2871f9cfSDan McDonald * based on PLAIN, by Tim Martin <tmartin@andrew.cmu.edu>
11*2871f9cfSDan McDonald * $Id: login.c,v 1.25 2003/02/13 19:56:04 rjs3 Exp $
12*2871f9cfSDan McDonald */
13*2871f9cfSDan McDonald /*
14*2871f9cfSDan McDonald * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
15*2871f9cfSDan McDonald *
16*2871f9cfSDan McDonald * Redistribution and use in source and binary forms, with or without
17*2871f9cfSDan McDonald * modification, are permitted provided that the following conditions
18*2871f9cfSDan McDonald * are met:
19*2871f9cfSDan McDonald *
20*2871f9cfSDan McDonald * 1. Redistributions of source code must retain the above copyright
21*2871f9cfSDan McDonald * notice, this list of conditions and the following disclaimer.
22*2871f9cfSDan McDonald *
23*2871f9cfSDan McDonald * 2. Redistributions in binary form must reproduce the above copyright
24*2871f9cfSDan McDonald * notice, this list of conditions and the following disclaimer in
25*2871f9cfSDan McDonald * the documentation and/or other materials provided with the
26*2871f9cfSDan McDonald * distribution.
27*2871f9cfSDan McDonald *
28*2871f9cfSDan McDonald * 3. The name "Carnegie Mellon University" must not be used to
29*2871f9cfSDan McDonald * endorse or promote products derived from this software without
30*2871f9cfSDan McDonald * prior written permission. For permission or any other legal
31*2871f9cfSDan McDonald * details, please contact
32*2871f9cfSDan McDonald * Office of Technology Transfer
33*2871f9cfSDan McDonald * Carnegie Mellon University
34*2871f9cfSDan McDonald * 5000 Forbes Avenue
35*2871f9cfSDan McDonald * Pittsburgh, PA 15213-3890
36*2871f9cfSDan McDonald * (412) 268-4387, fax: (412) 268-7395
37*2871f9cfSDan McDonald * tech-transfer@andrew.cmu.edu
38*2871f9cfSDan McDonald *
39*2871f9cfSDan McDonald * 4. Redistributions of any form whatsoever must retain the following
40*2871f9cfSDan McDonald * acknowledgment:
41*2871f9cfSDan McDonald * "This product includes software developed by Computing Services
42*2871f9cfSDan McDonald * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
43*2871f9cfSDan McDonald *
44*2871f9cfSDan McDonald * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
45*2871f9cfSDan McDonald * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
46*2871f9cfSDan McDonald * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
47*2871f9cfSDan McDonald * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
48*2871f9cfSDan McDonald * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
49*2871f9cfSDan McDonald * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
50*2871f9cfSDan McDonald * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51*2871f9cfSDan McDonald */
52*2871f9cfSDan McDonald
53*2871f9cfSDan McDonald #include <config.h>
54*2871f9cfSDan McDonald #include <stdio.h>
55*2871f9cfSDan McDonald #include <ctype.h>
56*2871f9cfSDan McDonald #include <sasl.h>
57*2871f9cfSDan McDonald #include <saslplug.h>
58*2871f9cfSDan McDonald
59*2871f9cfSDan McDonald #include "plugin_common.h"
60*2871f9cfSDan McDonald
61*2871f9cfSDan McDonald #ifndef _SUN_SDK_
62*2871f9cfSDan McDonald #ifdef WIN32
63*2871f9cfSDan McDonald /* This must be after sasl.h */
64*2871f9cfSDan McDonald # include "saslLOGIN.h"
65*2871f9cfSDan McDonald #endif /* WIN32 */
66*2871f9cfSDan McDonald #endif /* !_SUN_SDK_ */
67*2871f9cfSDan McDonald
68*2871f9cfSDan McDonald /***************************** Common Section *****************************/
69*2871f9cfSDan McDonald
70*2871f9cfSDan McDonald #ifndef _SUN_SDK_
71*2871f9cfSDan McDonald static const char plugin_id[] = "$Id: login.c,v 1.25 2003/02/13 19:56:04 rjs3 Exp $";
72*2871f9cfSDan McDonald #endif /* !_SUN_SDK_ */
73*2871f9cfSDan McDonald
74*2871f9cfSDan McDonald /***************************** Server Section *****************************/
75*2871f9cfSDan McDonald
76*2871f9cfSDan McDonald typedef struct context {
77*2871f9cfSDan McDonald int state;
78*2871f9cfSDan McDonald
79*2871f9cfSDan McDonald char *username;
80*2871f9cfSDan McDonald size_t username_len;
81*2871f9cfSDan McDonald } server_context_t;
82*2871f9cfSDan McDonald
login_server_mech_new(void * glob_context,sasl_server_params_t * sparams,const char * challenge,unsigned challen,void ** conn_context)83*2871f9cfSDan McDonald static int login_server_mech_new(void *glob_context __attribute__((unused)),
84*2871f9cfSDan McDonald sasl_server_params_t *sparams,
85*2871f9cfSDan McDonald const char *challenge __attribute__((unused)),
86*2871f9cfSDan McDonald unsigned challen __attribute__((unused)),
87*2871f9cfSDan McDonald void **conn_context)
88*2871f9cfSDan McDonald {
89*2871f9cfSDan McDonald server_context_t *text;
90*2871f9cfSDan McDonald
91*2871f9cfSDan McDonald /* holds state are in */
92*2871f9cfSDan McDonald text = sparams->utils->malloc(sizeof(server_context_t));
93*2871f9cfSDan McDonald if (text == NULL) {
94*2871f9cfSDan McDonald MEMERROR( sparams->utils );
95*2871f9cfSDan McDonald return SASL_NOMEM;
96*2871f9cfSDan McDonald }
97*2871f9cfSDan McDonald
98*2871f9cfSDan McDonald memset(text, 0, sizeof(server_context_t));
99*2871f9cfSDan McDonald
100*2871f9cfSDan McDonald text->state = 1;
101*2871f9cfSDan McDonald
102*2871f9cfSDan McDonald *conn_context = text;
103*2871f9cfSDan McDonald
104*2871f9cfSDan McDonald return SASL_OK;
105*2871f9cfSDan McDonald }
106*2871f9cfSDan McDonald
107*2871f9cfSDan McDonald #define USERNAME_CHALLENGE "Username:"
108*2871f9cfSDan McDonald #define PASSWORD_CHALLENGE "Password:"
109*2871f9cfSDan McDonald
login_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)110*2871f9cfSDan McDonald static int login_server_mech_step(void *conn_context,
111*2871f9cfSDan McDonald sasl_server_params_t *params,
112*2871f9cfSDan McDonald const char *clientin,
113*2871f9cfSDan McDonald unsigned clientinlen,
114*2871f9cfSDan McDonald const char **serverout,
115*2871f9cfSDan McDonald unsigned *serveroutlen,
116*2871f9cfSDan McDonald sasl_out_params_t *oparams)
117*2871f9cfSDan McDonald {
118*2871f9cfSDan McDonald server_context_t *text = (server_context_t *) conn_context;
119*2871f9cfSDan McDonald
120*2871f9cfSDan McDonald *serverout = NULL;
121*2871f9cfSDan McDonald *serveroutlen = 0;
122*2871f9cfSDan McDonald
123*2871f9cfSDan McDonald switch (text->state) {
124*2871f9cfSDan McDonald
125*2871f9cfSDan McDonald case 1:
126*2871f9cfSDan McDonald text->state = 2;
127*2871f9cfSDan McDonald
128*2871f9cfSDan McDonald /* Check inlen, (possibly we have already the user name) */
129*2871f9cfSDan McDonald /* In this case fall through to state 2 */
130*2871f9cfSDan McDonald if (clientinlen == 0) {
131*2871f9cfSDan McDonald /* demand username */
132*2871f9cfSDan McDonald
133*2871f9cfSDan McDonald *serveroutlen = strlen(USERNAME_CHALLENGE);
134*2871f9cfSDan McDonald *serverout = USERNAME_CHALLENGE;
135*2871f9cfSDan McDonald
136*2871f9cfSDan McDonald return SASL_CONTINUE;
137*2871f9cfSDan McDonald }
138*2871f9cfSDan McDonald
139*2871f9cfSDan McDonald
140*2871f9cfSDan McDonald case 2:
141*2871f9cfSDan McDonald /* Catch really long usernames */
142*2871f9cfSDan McDonald if (clientinlen > 1024) {
143*2871f9cfSDan McDonald #ifdef _SUN_SDK_
144*2871f9cfSDan McDonald params->utils->log(params->utils->conn, SASL_LOG_ERR,
145*2871f9cfSDan McDonald "username too long (>1024 characters)");
146*2871f9cfSDan McDonald #else
147*2871f9cfSDan McDonald SETERROR(params->utils, "username too long (>1024 characters)");
148*2871f9cfSDan McDonald #endif /* _SUN_SDK_ */
149*2871f9cfSDan McDonald return SASL_BADPROT;
150*2871f9cfSDan McDonald }
151*2871f9cfSDan McDonald
152*2871f9cfSDan McDonald /* get username */
153*2871f9cfSDan McDonald text->username =
154*2871f9cfSDan McDonald params->utils->malloc(sizeof(sasl_secret_t) + clientinlen + 1);
155*2871f9cfSDan McDonald if (!text->username) {
156*2871f9cfSDan McDonald MEMERROR( params->utils );
157*2871f9cfSDan McDonald return SASL_NOMEM;
158*2871f9cfSDan McDonald }
159*2871f9cfSDan McDonald
160*2871f9cfSDan McDonald strncpy(text->username, clientin, clientinlen);
161*2871f9cfSDan McDonald text->username_len = clientinlen;
162*2871f9cfSDan McDonald text->username[clientinlen] = '\0';
163*2871f9cfSDan McDonald
164*2871f9cfSDan McDonald /* demand password */
165*2871f9cfSDan McDonald *serveroutlen = strlen(PASSWORD_CHALLENGE);
166*2871f9cfSDan McDonald *serverout = PASSWORD_CHALLENGE;
167*2871f9cfSDan McDonald
168*2871f9cfSDan McDonald text->state = 3;
169*2871f9cfSDan McDonald
170*2871f9cfSDan McDonald return SASL_CONTINUE;
171*2871f9cfSDan McDonald
172*2871f9cfSDan McDonald
173*2871f9cfSDan McDonald case 3: {
174*2871f9cfSDan McDonald sasl_secret_t *password;
175*2871f9cfSDan McDonald int result;
176*2871f9cfSDan McDonald
177*2871f9cfSDan McDonald /* Catch really long passwords */
178*2871f9cfSDan McDonald if (clientinlen > 1024) {
179*2871f9cfSDan McDonald #ifdef _SUN_SDK_
180*2871f9cfSDan McDonald params->utils->log(params->utils->conn, SASL_LOG_ERR,
181*2871f9cfSDan McDonald "clientinlen is > 1024 characters in LOGIN plugin");
182*2871f9cfSDan McDonald #else
183*2871f9cfSDan McDonald SETERROR(params->utils,
184*2871f9cfSDan McDonald "clientinlen is > 1024 characters in LOGIN plugin");
185*2871f9cfSDan McDonald #endif /* _SUN_SDK_ */
186*2871f9cfSDan McDonald return SASL_BADPROT;
187*2871f9cfSDan McDonald }
188*2871f9cfSDan McDonald
189*2871f9cfSDan McDonald /* get password */
190*2871f9cfSDan McDonald password =
191*2871f9cfSDan McDonald params->utils->malloc(sizeof(sasl_secret_t) + clientinlen + 1);
192*2871f9cfSDan McDonald if (!password) {
193*2871f9cfSDan McDonald MEMERROR(params->utils);
194*2871f9cfSDan McDonald return SASL_NOMEM;
195*2871f9cfSDan McDonald }
196*2871f9cfSDan McDonald
197*2871f9cfSDan McDonald strncpy((char *)password->data, clientin, clientinlen);
198*2871f9cfSDan McDonald password->data[clientinlen] = '\0';
199*2871f9cfSDan McDonald password->len = clientinlen;
200*2871f9cfSDan McDonald
201*2871f9cfSDan McDonald /* canonicalize username first, so that password verification is
202*2871f9cfSDan McDonald * done against the canonical id */
203*2871f9cfSDan McDonald result = params->canon_user(params->utils->conn, text->username,
204*2871f9cfSDan McDonald text->username_len,
205*2871f9cfSDan McDonald SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams);
206*2871f9cfSDan McDonald if (result != SASL_OK) {
207*2871f9cfSDan McDonald _plug_free_secret(params->utils, &password);
208*2871f9cfSDan McDonald return result;
209*2871f9cfSDan McDonald }
210*2871f9cfSDan McDonald
211*2871f9cfSDan McDonald /* verify_password - return sasl_ok on success */
212*2871f9cfSDan McDonald result = params->utils->checkpass(params->utils->conn,
213*2871f9cfSDan McDonald oparams->authid, oparams->alen,
214*2871f9cfSDan McDonald (char *)password->data, password->len);
215*2871f9cfSDan McDonald
216*2871f9cfSDan McDonald if (result != SASL_OK) {
217*2871f9cfSDan McDonald _plug_free_secret(params->utils, &password);
218*2871f9cfSDan McDonald return result;
219*2871f9cfSDan McDonald }
220*2871f9cfSDan McDonald
221*2871f9cfSDan McDonald if (params->transition) {
222*2871f9cfSDan McDonald params->transition(params->utils->conn,
223*2871f9cfSDan McDonald (char *)password->data, password->len);
224*2871f9cfSDan McDonald }
225*2871f9cfSDan McDonald
226*2871f9cfSDan McDonald _plug_free_secret(params->utils, &password);
227*2871f9cfSDan McDonald
228*2871f9cfSDan McDonald *serverout = NULL;
229*2871f9cfSDan McDonald *serveroutlen = 0;
230*2871f9cfSDan McDonald
231*2871f9cfSDan McDonald oparams->doneflag = 1;
232*2871f9cfSDan McDonald oparams->mech_ssf = 0;
233*2871f9cfSDan McDonald oparams->maxoutbuf = 0;
234*2871f9cfSDan McDonald oparams->encode_context = NULL;
235*2871f9cfSDan McDonald oparams->encode = NULL;
236*2871f9cfSDan McDonald oparams->decode_context = NULL;
237*2871f9cfSDan McDonald oparams->decode = NULL;
238*2871f9cfSDan McDonald oparams->param_version = 0;
239*2871f9cfSDan McDonald
240*2871f9cfSDan McDonald return SASL_OK;
241*2871f9cfSDan McDonald }
242*2871f9cfSDan McDonald
243*2871f9cfSDan McDonald
244*2871f9cfSDan McDonald default:
245*2871f9cfSDan McDonald params->utils->log(NULL, SASL_LOG_ERR,
246*2871f9cfSDan McDonald "Invalid LOGIN server step %d\n", text->state);
247*2871f9cfSDan McDonald return SASL_FAIL;
248*2871f9cfSDan McDonald }
249*2871f9cfSDan McDonald
250*2871f9cfSDan McDonald return SASL_FAIL; /* should never get here */
251*2871f9cfSDan McDonald }
252*2871f9cfSDan McDonald
login_server_mech_dispose(void * conn_context,const sasl_utils_t * utils)253*2871f9cfSDan McDonald static void login_server_mech_dispose(void *conn_context,
254*2871f9cfSDan McDonald const sasl_utils_t *utils)
255*2871f9cfSDan McDonald {
256*2871f9cfSDan McDonald server_context_t *text = (server_context_t *) conn_context;
257*2871f9cfSDan McDonald
258*2871f9cfSDan McDonald if (!text) return;
259*2871f9cfSDan McDonald
260*2871f9cfSDan McDonald if (text->username) utils->free(text->username);
261*2871f9cfSDan McDonald
262*2871f9cfSDan McDonald utils->free(text);
263*2871f9cfSDan McDonald }
264*2871f9cfSDan McDonald
265*2871f9cfSDan McDonald static sasl_server_plug_t login_server_plugins[] =
266*2871f9cfSDan McDonald {
267*2871f9cfSDan McDonald {
268*2871f9cfSDan McDonald "LOGIN", /* mech_name */
269*2871f9cfSDan McDonald 0, /* max_ssf */
270*2871f9cfSDan McDonald SASL_SEC_NOANONYMOUS, /* security_flags */
271*2871f9cfSDan McDonald 0, /* features */
272*2871f9cfSDan McDonald NULL, /* glob_context */
273*2871f9cfSDan McDonald &login_server_mech_new, /* mech_new */
274*2871f9cfSDan McDonald &login_server_mech_step, /* mech_step */
275*2871f9cfSDan McDonald &login_server_mech_dispose, /* mech_dispose */
276*2871f9cfSDan McDonald NULL, /* mech_free */
277*2871f9cfSDan McDonald NULL, /* setpass */
278*2871f9cfSDan McDonald NULL, /* user_query */
279*2871f9cfSDan McDonald NULL, /* idle */
280*2871f9cfSDan McDonald NULL, /* mech_avail */
281*2871f9cfSDan McDonald NULL /* spare */
282*2871f9cfSDan McDonald }
283*2871f9cfSDan McDonald };
284*2871f9cfSDan McDonald
login_server_plug_init(sasl_utils_t * utils,int maxversion,int * out_version,sasl_server_plug_t ** pluglist,int * plugcount)285*2871f9cfSDan McDonald int login_server_plug_init(sasl_utils_t *utils,
286*2871f9cfSDan McDonald int maxversion,
287*2871f9cfSDan McDonald int *out_version,
288*2871f9cfSDan McDonald sasl_server_plug_t **pluglist,
289*2871f9cfSDan McDonald int *plugcount)
290*2871f9cfSDan McDonald {
291*2871f9cfSDan McDonald if (maxversion < SASL_SERVER_PLUG_VERSION) {
292*2871f9cfSDan McDonald SETERROR(utils, "LOGIN version mismatch");
293*2871f9cfSDan McDonald return SASL_BADVERS;
294*2871f9cfSDan McDonald }
295*2871f9cfSDan McDonald
296*2871f9cfSDan McDonald *out_version = SASL_SERVER_PLUG_VERSION;
297*2871f9cfSDan McDonald *pluglist = login_server_plugins;
298*2871f9cfSDan McDonald *plugcount = 1;
299*2871f9cfSDan McDonald
300*2871f9cfSDan McDonald return SASL_OK;
301*2871f9cfSDan McDonald }
302*2871f9cfSDan McDonald
303*2871f9cfSDan McDonald /***************************** Client Section *****************************/
304*2871f9cfSDan McDonald
305*2871f9cfSDan McDonald typedef struct client_context {
306*2871f9cfSDan McDonald int state;
307*2871f9cfSDan McDonald
308*2871f9cfSDan McDonald #ifdef _INTEGRATED_SOLARIS_
309*2871f9cfSDan McDonald void *h;
310*2871f9cfSDan McDonald #endif /* _INTEGRATED_SOLARIS_ */
311*2871f9cfSDan McDonald sasl_secret_t *password;
312*2871f9cfSDan McDonald unsigned int free_password; /* set if we need to free password */
313*2871f9cfSDan McDonald } client_context_t;
314*2871f9cfSDan McDonald
login_client_mech_new(void * glob_context,sasl_client_params_t * params,void ** conn_context)315*2871f9cfSDan McDonald static int login_client_mech_new(void *glob_context __attribute__((unused)),
316*2871f9cfSDan McDonald sasl_client_params_t *params,
317*2871f9cfSDan McDonald void **conn_context)
318*2871f9cfSDan McDonald {
319*2871f9cfSDan McDonald client_context_t *text;
320*2871f9cfSDan McDonald
321*2871f9cfSDan McDonald /* holds state are in */
322*2871f9cfSDan McDonald text = params->utils->malloc(sizeof(client_context_t));
323*2871f9cfSDan McDonald if (text == NULL) {
324*2871f9cfSDan McDonald MEMERROR(params->utils);
325*2871f9cfSDan McDonald return SASL_NOMEM;
326*2871f9cfSDan McDonald }
327*2871f9cfSDan McDonald
328*2871f9cfSDan McDonald memset(text, 0, sizeof(client_context_t));
329*2871f9cfSDan McDonald
330*2871f9cfSDan McDonald text->state = 1;
331*2871f9cfSDan McDonald
332*2871f9cfSDan McDonald *conn_context = text;
333*2871f9cfSDan McDonald
334*2871f9cfSDan McDonald return SASL_OK;
335*2871f9cfSDan McDonald }
336*2871f9cfSDan McDonald
login_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)337*2871f9cfSDan McDonald static int login_client_mech_step(void *conn_context,
338*2871f9cfSDan McDonald sasl_client_params_t *params,
339*2871f9cfSDan McDonald const char *serverin __attribute__((unused)),
340*2871f9cfSDan McDonald unsigned serverinlen __attribute__((unused)),
341*2871f9cfSDan McDonald sasl_interact_t **prompt_need,
342*2871f9cfSDan McDonald const char **clientout,
343*2871f9cfSDan McDonald unsigned *clientoutlen,
344*2871f9cfSDan McDonald sasl_out_params_t *oparams)
345*2871f9cfSDan McDonald {
346*2871f9cfSDan McDonald client_context_t *text = (client_context_t *) conn_context;
347*2871f9cfSDan McDonald
348*2871f9cfSDan McDonald *clientout = NULL;
349*2871f9cfSDan McDonald *clientoutlen = 0;
350*2871f9cfSDan McDonald
351*2871f9cfSDan McDonald switch (text->state) {
352*2871f9cfSDan McDonald
353*2871f9cfSDan McDonald case 1: {
354*2871f9cfSDan McDonald const char *user;
355*2871f9cfSDan McDonald int auth_result = SASL_OK;
356*2871f9cfSDan McDonald int pass_result = SASL_OK;
357*2871f9cfSDan McDonald int result;
358*2871f9cfSDan McDonald
359*2871f9cfSDan McDonald /* check if sec layer strong enough */
360*2871f9cfSDan McDonald if (params->props.min_ssf > params->external_ssf) {
361*2871f9cfSDan McDonald #ifdef _INTEGRATED_SOLARIS_
362*2871f9cfSDan McDonald params->utils->log(params->utils->conn, SASL_LOG_ERR,
363*2871f9cfSDan McDonald gettext("SSF requested of LOGIN plugin"));
364*2871f9cfSDan McDonald #else
365*2871f9cfSDan McDonald SETERROR( params->utils, "SSF requested of LOGIN plugin");
366*2871f9cfSDan McDonald #endif /* _INTEGRATED_SOLARIS_ */
367*2871f9cfSDan McDonald return SASL_TOOWEAK;
368*2871f9cfSDan McDonald }
369*2871f9cfSDan McDonald
370*2871f9cfSDan McDonald /* try to get the userid */
371*2871f9cfSDan McDonald /* Note: we want to grab the authname and not the userid, which is
372*2871f9cfSDan McDonald * who we AUTHORIZE as, and will be the same as the authname
373*2871f9cfSDan McDonald * for the LOGIN mech.
374*2871f9cfSDan McDonald */
375*2871f9cfSDan McDonald if (oparams->user == NULL) {
376*2871f9cfSDan McDonald auth_result = _plug_get_authid(params->utils, &user, prompt_need);
377*2871f9cfSDan McDonald
378*2871f9cfSDan McDonald if ((auth_result != SASL_OK) && (auth_result != SASL_INTERACT))
379*2871f9cfSDan McDonald return auth_result;
380*2871f9cfSDan McDonald }
381*2871f9cfSDan McDonald
382*2871f9cfSDan McDonald /* try to get the password */
383*2871f9cfSDan McDonald if (text->password == NULL) {
384*2871f9cfSDan McDonald pass_result = _plug_get_password(params->utils, &text->password,
385*2871f9cfSDan McDonald &text->free_password, prompt_need);
386*2871f9cfSDan McDonald
387*2871f9cfSDan McDonald if ((pass_result != SASL_OK) && (pass_result != SASL_INTERACT))
388*2871f9cfSDan McDonald return pass_result;
389*2871f9cfSDan McDonald }
390*2871f9cfSDan McDonald
391*2871f9cfSDan McDonald /* free prompts we got */
392*2871f9cfSDan McDonald if (prompt_need && *prompt_need) {
393*2871f9cfSDan McDonald params->utils->free(*prompt_need);
394*2871f9cfSDan McDonald *prompt_need = NULL;
395*2871f9cfSDan McDonald }
396*2871f9cfSDan McDonald
397*2871f9cfSDan McDonald /* if there are prompts not filled in */
398*2871f9cfSDan McDonald if ((auth_result == SASL_INTERACT) || (pass_result == SASL_INTERACT)) {
399*2871f9cfSDan McDonald /* make the prompt list */
400*2871f9cfSDan McDonald result =
401*2871f9cfSDan McDonald #ifdef _INTEGRATED_SOLARIS_
402*2871f9cfSDan McDonald _plug_make_prompts(params->utils, &text->h, prompt_need,
403*2871f9cfSDan McDonald NULL, NULL,
404*2871f9cfSDan McDonald auth_result == SASL_INTERACT ?
405*2871f9cfSDan McDonald gettext("Please enter your authentication name") : NULL,
406*2871f9cfSDan McDonald NULL,
407*2871f9cfSDan McDonald pass_result == SASL_INTERACT ?
408*2871f9cfSDan McDonald gettext("Please enter your password") : NULL, NULL,
409*2871f9cfSDan McDonald NULL, NULL, NULL,
410*2871f9cfSDan McDonald NULL, NULL, NULL);
411*2871f9cfSDan McDonald #else
412*2871f9cfSDan McDonald _plug_make_prompts(params->utils, prompt_need,
413*2871f9cfSDan McDonald NULL, NULL,
414*2871f9cfSDan McDonald auth_result == SASL_INTERACT ?
415*2871f9cfSDan McDonald "Please enter your authentication name" : NULL,
416*2871f9cfSDan McDonald NULL,
417*2871f9cfSDan McDonald pass_result == SASL_INTERACT ?
418*2871f9cfSDan McDonald "Please enter your password" : NULL, NULL,
419*2871f9cfSDan McDonald NULL, NULL, NULL,
420*2871f9cfSDan McDonald NULL, NULL, NULL);
421*2871f9cfSDan McDonald #endif /* _INTEGRATED_SOLARIS_ */
422*2871f9cfSDan McDonald if (result != SASL_OK) return result;
423*2871f9cfSDan McDonald
424*2871f9cfSDan McDonald return SASL_INTERACT;
425*2871f9cfSDan McDonald }
426*2871f9cfSDan McDonald
427*2871f9cfSDan McDonald if (!text->password) {
428*2871f9cfSDan McDonald PARAMERROR(params->utils);
429*2871f9cfSDan McDonald return SASL_BADPARAM;
430*2871f9cfSDan McDonald }
431*2871f9cfSDan McDonald
432*2871f9cfSDan McDonald result = params->canon_user(params->utils->conn, user, 0,
433*2871f9cfSDan McDonald SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams);
434*2871f9cfSDan McDonald if (result != SASL_OK) return result;
435*2871f9cfSDan McDonald
436*2871f9cfSDan McDonald /* server should have sent request for username - we ignore it */
437*2871f9cfSDan McDonald if (!serverin) {
438*2871f9cfSDan McDonald #ifdef _SUN_SDK_
439*2871f9cfSDan McDonald params->utils->log(params->utils->conn, SASL_LOG_ERR,
440*2871f9cfSDan McDonald "Server didn't issue challenge for USERNAME");
441*2871f9cfSDan McDonald #else
442*2871f9cfSDan McDonald SETERROR( params->utils,
443*2871f9cfSDan McDonald "Server didn't issue challenge for USERNAME");
444*2871f9cfSDan McDonald #endif /* _SUN_SDK_ */
445*2871f9cfSDan McDonald return SASL_BADPROT;
446*2871f9cfSDan McDonald }
447*2871f9cfSDan McDonald
448*2871f9cfSDan McDonald if (!clientout) {
449*2871f9cfSDan McDonald PARAMERROR( params->utils );
450*2871f9cfSDan McDonald return SASL_BADPARAM;
451*2871f9cfSDan McDonald }
452*2871f9cfSDan McDonald
453*2871f9cfSDan McDonald if (clientoutlen) *clientoutlen = oparams->alen;
454*2871f9cfSDan McDonald *clientout = oparams->authid;
455*2871f9cfSDan McDonald
456*2871f9cfSDan McDonald text->state = 2;
457*2871f9cfSDan McDonald
458*2871f9cfSDan McDonald return SASL_CONTINUE;
459*2871f9cfSDan McDonald }
460*2871f9cfSDan McDonald
461*2871f9cfSDan McDonald case 2:
462*2871f9cfSDan McDonald /* server should have sent request for password - we ignore it */
463*2871f9cfSDan McDonald if (!serverin) {
464*2871f9cfSDan McDonald #ifdef _SUN_SDK_
465*2871f9cfSDan McDonald params->utils->log(params->utils->conn, SASL_LOG_ERR,
466*2871f9cfSDan McDonald "Server didn't issue challenge for PASSWORD");
467*2871f9cfSDan McDonald #else
468*2871f9cfSDan McDonald SETERROR( params->utils,
469*2871f9cfSDan McDonald "Server didn't issue challenge for PASSWORD");
470*2871f9cfSDan McDonald #endif /* _SUN_SDK_ */
471*2871f9cfSDan McDonald return SASL_BADPROT;
472*2871f9cfSDan McDonald }
473*2871f9cfSDan McDonald
474*2871f9cfSDan McDonald if (!clientout) {
475*2871f9cfSDan McDonald PARAMERROR(params->utils);
476*2871f9cfSDan McDonald return SASL_BADPARAM;
477*2871f9cfSDan McDonald }
478*2871f9cfSDan McDonald
479*2871f9cfSDan McDonald if (clientoutlen) *clientoutlen = text->password->len;
480*2871f9cfSDan McDonald *clientout = (char *)text->password->data;
481*2871f9cfSDan McDonald
482*2871f9cfSDan McDonald /* set oparams */
483*2871f9cfSDan McDonald oparams->doneflag = 1;
484*2871f9cfSDan McDonald oparams->mech_ssf = 0;
485*2871f9cfSDan McDonald oparams->maxoutbuf = 0;
486*2871f9cfSDan McDonald oparams->encode_context = NULL;
487*2871f9cfSDan McDonald oparams->encode = NULL;
488*2871f9cfSDan McDonald oparams->decode_context = NULL;
489*2871f9cfSDan McDonald oparams->decode = NULL;
490*2871f9cfSDan McDonald oparams->param_version = 0;
491*2871f9cfSDan McDonald
492*2871f9cfSDan McDonald return SASL_OK;
493*2871f9cfSDan McDonald
494*2871f9cfSDan McDonald default:
495*2871f9cfSDan McDonald params->utils->log(NULL, SASL_LOG_ERR,
496*2871f9cfSDan McDonald "Invalid LOGIN client step %d\n", text->state);
497*2871f9cfSDan McDonald return SASL_FAIL;
498*2871f9cfSDan McDonald }
499*2871f9cfSDan McDonald
500*2871f9cfSDan McDonald return SASL_FAIL; /* should never get here */
501*2871f9cfSDan McDonald }
502*2871f9cfSDan McDonald
login_client_mech_dispose(void * conn_context,const sasl_utils_t * utils)503*2871f9cfSDan McDonald static void login_client_mech_dispose(void *conn_context,
504*2871f9cfSDan McDonald const sasl_utils_t *utils)
505*2871f9cfSDan McDonald {
506*2871f9cfSDan McDonald client_context_t *text = (client_context_t *) conn_context;
507*2871f9cfSDan McDonald
508*2871f9cfSDan McDonald if (!text) return;
509*2871f9cfSDan McDonald
510*2871f9cfSDan McDonald /* free sensitive info */
511*2871f9cfSDan McDonald if (text->free_password) _plug_free_secret(utils, &(text->password));
512*2871f9cfSDan McDonald #ifdef _INTEGRATED_SOLARIS_
513*2871f9cfSDan McDonald convert_prompt(utils, &text->h, NULL);
514*2871f9cfSDan McDonald #endif /* _INTEGRATED_SOLARIS_ */
515*2871f9cfSDan McDonald
516*2871f9cfSDan McDonald utils->free(text);
517*2871f9cfSDan McDonald }
518*2871f9cfSDan McDonald
519*2871f9cfSDan McDonald static sasl_client_plug_t login_client_plugins[] =
520*2871f9cfSDan McDonald {
521*2871f9cfSDan McDonald {
522*2871f9cfSDan McDonald "LOGIN", /* mech_name */
523*2871f9cfSDan McDonald 0, /* max_ssf */
524*2871f9cfSDan McDonald SASL_SEC_NOANONYMOUS, /* security_flags */
525*2871f9cfSDan McDonald SASL_FEAT_SERVER_FIRST, /* features */
526*2871f9cfSDan McDonald NULL, /* required_prompts */
527*2871f9cfSDan McDonald NULL, /* glob_context */
528*2871f9cfSDan McDonald &login_client_mech_new, /* mech_new */
529*2871f9cfSDan McDonald &login_client_mech_step, /* mech_step */
530*2871f9cfSDan McDonald &login_client_mech_dispose, /* mech_dispose */
531*2871f9cfSDan McDonald NULL, /* mech_free */
532*2871f9cfSDan McDonald NULL, /* idle */
533*2871f9cfSDan McDonald NULL, /* spare */
534*2871f9cfSDan McDonald NULL /* spare */
535*2871f9cfSDan McDonald }
536*2871f9cfSDan McDonald };
537*2871f9cfSDan McDonald
login_client_plug_init(sasl_utils_t * utils,int maxversion,int * out_version,sasl_client_plug_t ** pluglist,int * plugcount)538*2871f9cfSDan McDonald int login_client_plug_init(sasl_utils_t *utils,
539*2871f9cfSDan McDonald int maxversion,
540*2871f9cfSDan McDonald int *out_version,
541*2871f9cfSDan McDonald sasl_client_plug_t **pluglist,
542*2871f9cfSDan McDonald int *plugcount)
543*2871f9cfSDan McDonald {
544*2871f9cfSDan McDonald if (maxversion < SASL_CLIENT_PLUG_VERSION) {
545*2871f9cfSDan McDonald SETERROR(utils, "Version mismatch in LOGIN");
546*2871f9cfSDan McDonald return SASL_BADVERS;
547*2871f9cfSDan McDonald }
548*2871f9cfSDan McDonald
549*2871f9cfSDan McDonald *out_version = SASL_CLIENT_PLUG_VERSION;
550*2871f9cfSDan McDonald *pluglist = login_client_plugins;
551*2871f9cfSDan McDonald *plugcount = 1;
552*2871f9cfSDan McDonald
553*2871f9cfSDan McDonald return SASL_OK;
554*2871f9cfSDan McDonald }
555