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