Back to index

openldap  2.4.31
sasl.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 
00016 #include "portable.h"
00017 
00018 #ifdef HAVE_CYRUS_SASL
00019 
00020 #include <stdio.h>
00021 #include <ac/stdlib.h>
00022 #include <ac/string.h>
00023 #include <ac/unistd.h>
00024 
00025 #ifdef HAVE_SASL_SASL_H
00026 #include <sasl/sasl.h>
00027 #else
00028 #include <sasl.h>
00029 #endif
00030 
00031 #include <ldap.h>
00032 #include "ldap_pvt.h"
00033 #include "lutil_ldap.h"
00034 
00035 
00036 typedef struct lutil_sasl_defaults_s {
00037        char *mech;
00038        char *realm;
00039        char *authcid;
00040        char *passwd;
00041        char *authzid;
00042        char **resps;
00043        int nresps;
00044 } lutilSASLdefaults;
00045 
00046 
00047 void
00048 lutil_sasl_freedefs(
00049        void *defaults )
00050 {
00051        lutilSASLdefaults *defs = defaults;
00052 
00053        assert( defs != NULL );
00054        
00055        if (defs->mech) ber_memfree(defs->mech);
00056        if (defs->realm) ber_memfree(defs->realm);
00057        if (defs->authcid) ber_memfree(defs->authcid);
00058        if (defs->passwd) ber_memfree(defs->passwd);
00059        if (defs->authzid) ber_memfree(defs->authzid);
00060        if (defs->resps) ldap_charray_free(defs->resps);
00061 
00062        ber_memfree(defs);
00063 }
00064 
00065 void *
00066 lutil_sasl_defaults(
00067        LDAP *ld,
00068        char *mech,
00069        char *realm,
00070        char *authcid,
00071        char *passwd,
00072        char *authzid )
00073 {
00074        lutilSASLdefaults *defaults;
00075        
00076        defaults = ber_memalloc( sizeof( lutilSASLdefaults ) );
00077 
00078        if( defaults == NULL ) return NULL;
00079 
00080        defaults->mech = mech ? ber_strdup(mech) : NULL;
00081        defaults->realm = realm ? ber_strdup(realm) : NULL;
00082        defaults->authcid = authcid ? ber_strdup(authcid) : NULL;
00083        defaults->passwd = passwd ? ber_strdup(passwd) : NULL;
00084        defaults->authzid = authzid ? ber_strdup(authzid) : NULL;
00085 
00086        if( defaults->mech == NULL ) {
00087               ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech );
00088        }
00089        if( defaults->realm == NULL ) {
00090               ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm );
00091        }
00092        if( defaults->authcid == NULL ) {
00093               ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid );
00094        }
00095        if( defaults->authzid == NULL ) {
00096               ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid );
00097        }
00098        defaults->resps = NULL;
00099        defaults->nresps = 0;
00100 
00101        return defaults;
00102 }
00103 
00104 static int interaction(
00105        unsigned flags,
00106        sasl_interact_t *interact,
00107        lutilSASLdefaults *defaults )
00108 {
00109        const char *dflt = interact->defresult;
00110        char input[1024];
00111 
00112        int noecho=0;
00113        int challenge=0;
00114 
00115        switch( interact->id ) {
00116        case SASL_CB_GETREALM:
00117               if( defaults ) dflt = defaults->realm;
00118               break;
00119        case SASL_CB_AUTHNAME:
00120               if( defaults ) dflt = defaults->authcid;
00121               break;
00122        case SASL_CB_PASS:
00123               if( defaults ) dflt = defaults->passwd;
00124               noecho = 1;
00125               break;
00126        case SASL_CB_USER:
00127               if( defaults ) dflt = defaults->authzid;
00128               break;
00129        case SASL_CB_NOECHOPROMPT:
00130               noecho = 1;
00131               challenge = 1;
00132               break;
00133        case SASL_CB_ECHOPROMPT:
00134               challenge = 1;
00135               break;
00136        }
00137 
00138        if( dflt && !*dflt ) dflt = NULL;
00139 
00140        if( flags != LDAP_SASL_INTERACTIVE &&
00141               ( dflt || interact->id == SASL_CB_USER ) )
00142        {
00143               goto use_default;
00144        }
00145 
00146        if( flags == LDAP_SASL_QUIET ) {
00147               /* don't prompt */
00148               return LDAP_OTHER;
00149        }
00150 
00151        if( challenge ) {
00152               if( interact->challenge ) {
00153                      fprintf( stderr, _("Challenge: %s\n"), interact->challenge );
00154               }
00155        }
00156 
00157        if( dflt ) {
00158               fprintf( stderr, _("Default: %s\n"), dflt );
00159        }
00160 
00161        snprintf( input, sizeof input, "%s: ",
00162               interact->prompt ? interact->prompt : _("Interact") );
00163 
00164        if( noecho ) {
00165               interact->result = (char *) getpassphrase( input );
00166               interact->len = interact->result
00167                      ? strlen( interact->result ) : 0;
00168 
00169        } else {
00170               /* prompt user */
00171               fputs( input, stderr );
00172 
00173               /* get input */
00174               interact->result = fgets( input, sizeof(input), stdin );
00175 
00176               if( interact->result == NULL ) {
00177                      interact->len = 0;
00178                      return LDAP_UNAVAILABLE;
00179               }
00180 
00181               /* len of input */
00182               interact->len = strlen(input); 
00183 
00184               if( interact->len > 0 && input[interact->len - 1] == '\n' ) {
00185                      /* input includes '\n', trim it */
00186                      interact->len--;
00187                      input[interact->len] = '\0';
00188               }
00189        }
00190 
00191 
00192        if( interact->len > 0 ) {
00193               /* duplicate */
00194               char *p = (char *)interact->result;
00195               ldap_charray_add(&defaults->resps, interact->result);
00196               interact->result = defaults->resps[defaults->nresps++];
00197 
00198               /* zap */
00199               memset( p, '\0', interact->len );
00200 
00201        } else {
00202 use_default:
00203               /* input must be empty */
00204               interact->result = (dflt && *dflt) ? dflt : "";
00205               interact->len = strlen( interact->result );
00206        }
00207 
00208        return LDAP_SUCCESS;
00209 }
00210 
00211 int lutil_sasl_interact(
00212        LDAP *ld,
00213        unsigned flags,
00214        void *defaults,
00215        void *in )
00216 {
00217        sasl_interact_t *interact = in;
00218 
00219        if( ld == NULL ) return LDAP_PARAM_ERROR;
00220 
00221        if( flags == LDAP_SASL_INTERACTIVE ) {
00222               fputs( _("SASL Interaction\n"), stderr );
00223        }
00224 
00225        while( interact->id != SASL_CB_LIST_END ) {
00226               int rc = interaction( flags, interact, defaults );
00227 
00228               if( rc )  return rc;
00229               interact++;
00230        }
00231        
00232        return LDAP_SUCCESS;
00233 }
00234 #endif