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