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 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 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 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 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 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 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 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 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