1/* $NetBSD: sasl.c,v 1.1.1.3 2010/12/12 15:22:11 adam Exp $ */ 2 3/* OpenLDAP: pkg/ldap/libraries/liblutil/sasl.c,v 1.22.2.5 2010/04/13 20:23:06 kurt Exp */ 4/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2010 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 18#include "portable.h" 19 20#ifdef HAVE_CYRUS_SASL 21 22#include <stdio.h> 23#include <ac/stdlib.h> 24#include <ac/string.h> 25#include <ac/unistd.h> 26 27#ifdef HAVE_SASL_SASL_H 28#include <sasl/sasl.h> 29#else 30#include <sasl.h> 31#endif 32 33#include <ldap.h> 34#include "ldap_pvt.h" 35#include "lutil_ldap.h" 36 37 38typedef struct lutil_sasl_defaults_s { 39 char *mech; 40 char *realm; 41 char *authcid; 42 char *passwd; 43 char *authzid; 44 char **resps; 45 int nresps; 46} lutilSASLdefaults; 47 48 49void 50lutil_sasl_freedefs( 51 void *defaults ) 52{ 53 lutilSASLdefaults *defs = defaults; 54 55 assert( defs != NULL ); 56 57 if (defs->mech) ber_memfree(defs->mech); 58 if (defs->realm) ber_memfree(defs->realm); 59 if (defs->authcid) ber_memfree(defs->authcid); 60 if (defs->passwd) ber_memfree(defs->passwd); 61 if (defs->authzid) ber_memfree(defs->authzid); 62 if (defs->resps) ldap_charray_free(defs->resps); 63 64 ber_memfree(defs); 65} 66 67void * 68lutil_sasl_defaults( 69 LDAP *ld, 70 char *mech, 71 char *realm, 72 char *authcid, 73 char *passwd, 74 char *authzid ) 75{ 76 lutilSASLdefaults *defaults; 77 78 defaults = ber_memalloc( sizeof( lutilSASLdefaults ) ); 79 80 if( defaults == NULL ) return NULL; 81 82 defaults->mech = mech ? ber_strdup(mech) : NULL; 83 defaults->realm = realm ? ber_strdup(realm) : NULL; 84 defaults->authcid = authcid ? ber_strdup(authcid) : NULL; 85 defaults->passwd = passwd ? ber_strdup(passwd) : NULL; 86 defaults->authzid = authzid ? ber_strdup(authzid) : NULL; 87 88 if( defaults->mech == NULL ) { 89 ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech ); 90 } 91 if( defaults->realm == NULL ) { 92 ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm ); 93 } 94 if( defaults->authcid == NULL ) { 95 ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid ); 96 } 97 if( defaults->authzid == NULL ) { 98 ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid ); 99 } 100 defaults->resps = NULL; 101 defaults->nresps = 0; 102 103 return defaults; 104} 105 106static int interaction( 107 unsigned flags, 108 sasl_interact_t *interact, 109 lutilSASLdefaults *defaults ) 110{ 111 const char *dflt = interact->defresult; 112 char input[1024]; 113 114 int noecho=0; 115 int challenge=0; 116 117 switch( interact->id ) { 118 case SASL_CB_GETREALM: 119 if( defaults ) dflt = defaults->realm; 120 break; 121 case SASL_CB_AUTHNAME: 122 if( defaults ) dflt = defaults->authcid; 123 break; 124 case SASL_CB_PASS: 125 if( defaults ) dflt = defaults->passwd; 126 noecho = 1; 127 break; 128 case SASL_CB_USER: 129 if( defaults ) dflt = defaults->authzid; 130 break; 131 case SASL_CB_NOECHOPROMPT: 132 noecho = 1; 133 challenge = 1; 134 break; 135 case SASL_CB_ECHOPROMPT: 136 challenge = 1; 137 break; 138 } 139 140 if( dflt && !*dflt ) dflt = NULL; 141 142 if( flags != LDAP_SASL_INTERACTIVE && 143 ( dflt || interact->id == SASL_CB_USER ) ) 144 { 145 goto use_default; 146 } 147 148 if( flags == LDAP_SASL_QUIET ) { 149 /* don't prompt */ 150 return LDAP_OTHER; 151 } 152 153 if( challenge ) { 154 if( interact->challenge ) { 155 fprintf( stderr, _("Challenge: %s\n"), interact->challenge ); 156 } 157 } 158 159 if( dflt ) { 160 fprintf( stderr, _("Default: %s\n"), dflt ); 161 } 162 163 snprintf( input, sizeof input, "%s: ", 164 interact->prompt ? interact->prompt : _("Interact") ); 165 166 if( noecho ) { 167 interact->result = (char *) getpassphrase( input ); 168 interact->len = interact->result 169 ? strlen( interact->result ) : 0; 170 171 } else { 172 /* prompt user */ 173 fputs( input, stderr ); 174 175 /* get input */ 176 interact->result = fgets( input, sizeof(input), stdin ); 177 178 if( interact->result == NULL ) { 179 interact->len = 0; 180 return LDAP_UNAVAILABLE; 181 } 182 183 /* len of input */ 184 interact->len = strlen(input); 185 186 if( interact->len > 0 && input[interact->len - 1] == '\n' ) { 187 /* input includes '\n', trim it */ 188 interact->len--; 189 input[interact->len] = '\0'; 190 } 191 } 192 193 194 if( interact->len > 0 ) { 195 /* duplicate */ 196 char *p = (char *)interact->result; 197 ldap_charray_add(&defaults->resps, interact->result); 198 interact->result = defaults->resps[defaults->nresps++]; 199 200 /* zap */ 201 memset( p, '\0', interact->len ); 202 203 } else { 204use_default: 205 /* input must be empty */ 206 interact->result = (dflt && *dflt) ? dflt : ""; 207 interact->len = strlen( interact->result ); 208 } 209 210 return LDAP_SUCCESS; 211} 212 213int lutil_sasl_interact( 214 LDAP *ld, 215 unsigned flags, 216 void *defaults, 217 void *in ) 218{ 219 sasl_interact_t *interact = in; 220 221 if( ld == NULL ) return LDAP_PARAM_ERROR; 222 223 if( flags == LDAP_SASL_INTERACTIVE ) { 224 fputs( _("SASL Interaction\n"), stderr ); 225 } 226 227 while( interact->id != SASL_CB_LIST_END ) { 228 int rc = interaction( flags, interact, defaults ); 229 230 if( rc ) return rc; 231 interact++; 232 } 233 234 return LDAP_SUCCESS; 235} 236#endif 237