1*cf1d77f7Schristos /* $NetBSD: sasl.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */
24e6df137Slukem
333197c6aStron /* $OpenLDAP$ */
42de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
52de962bdSlukem *
6*cf1d77f7Schristos * Copyright 1998-2021 The OpenLDAP Foundation.
72de962bdSlukem * All rights reserved.
82de962bdSlukem *
92de962bdSlukem * Redistribution and use in source and binary forms, with or without
102de962bdSlukem * modification, are permitted only as authorized by the OpenLDAP
112de962bdSlukem * Public License.
122de962bdSlukem *
132de962bdSlukem * A copy of this license is available in the file LICENSE in the
142de962bdSlukem * top-level directory of the distribution or, alternatively, at
152de962bdSlukem * <http://www.OpenLDAP.org/license.html>.
162de962bdSlukem */
172de962bdSlukem
188bd9f7cdSchristos #include <sys/cdefs.h>
19*cf1d77f7Schristos __RCSID("$NetBSD: sasl.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
208bd9f7cdSchristos
212de962bdSlukem #include "portable.h"
222de962bdSlukem
232de962bdSlukem #ifdef HAVE_CYRUS_SASL
242de962bdSlukem
252de962bdSlukem #include <stdio.h>
262de962bdSlukem #include <ac/stdlib.h>
272de962bdSlukem #include <ac/string.h>
282de962bdSlukem #include <ac/unistd.h>
292de962bdSlukem
302de962bdSlukem #ifdef HAVE_SASL_SASL_H
312de962bdSlukem #include <sasl/sasl.h>
322de962bdSlukem #else
332de962bdSlukem #include <sasl.h>
342de962bdSlukem #endif
352de962bdSlukem
362de962bdSlukem #include <ldap.h>
372de962bdSlukem #include "ldap_pvt.h"
382de962bdSlukem #include "lutil_ldap.h"
392de962bdSlukem
402de962bdSlukem
412de962bdSlukem typedef struct lutil_sasl_defaults_s {
422de962bdSlukem char *mech;
432de962bdSlukem char *realm;
442de962bdSlukem char *authcid;
452de962bdSlukem char *passwd;
462de962bdSlukem char *authzid;
472de962bdSlukem char **resps;
482de962bdSlukem int nresps;
492de962bdSlukem } lutilSASLdefaults;
502de962bdSlukem
512de962bdSlukem
522de962bdSlukem void
lutil_sasl_freedefs(void * defaults)532de962bdSlukem lutil_sasl_freedefs(
542de962bdSlukem void *defaults )
552de962bdSlukem {
562de962bdSlukem lutilSASLdefaults *defs = defaults;
572de962bdSlukem
582de962bdSlukem assert( defs != NULL );
592de962bdSlukem
602de962bdSlukem if (defs->mech) ber_memfree(defs->mech);
612de962bdSlukem if (defs->realm) ber_memfree(defs->realm);
622de962bdSlukem if (defs->authcid) ber_memfree(defs->authcid);
632de962bdSlukem if (defs->passwd) ber_memfree(defs->passwd);
642de962bdSlukem if (defs->authzid) ber_memfree(defs->authzid);
652de962bdSlukem if (defs->resps) ldap_charray_free(defs->resps);
662de962bdSlukem
672de962bdSlukem ber_memfree(defs);
682de962bdSlukem }
692de962bdSlukem
702de962bdSlukem void *
lutil_sasl_defaults(LDAP * ld,char * mech,char * realm,char * authcid,char * passwd,char * authzid)712de962bdSlukem lutil_sasl_defaults(
722de962bdSlukem LDAP *ld,
732de962bdSlukem char *mech,
742de962bdSlukem char *realm,
752de962bdSlukem char *authcid,
762de962bdSlukem char *passwd,
772de962bdSlukem char *authzid )
782de962bdSlukem {
792de962bdSlukem lutilSASLdefaults *defaults;
802de962bdSlukem
812de962bdSlukem defaults = ber_memalloc( sizeof( lutilSASLdefaults ) );
822de962bdSlukem
832de962bdSlukem if( defaults == NULL ) return NULL;
842de962bdSlukem
852de962bdSlukem defaults->mech = mech ? ber_strdup(mech) : NULL;
862de962bdSlukem defaults->realm = realm ? ber_strdup(realm) : NULL;
872de962bdSlukem defaults->authcid = authcid ? ber_strdup(authcid) : NULL;
882de962bdSlukem defaults->passwd = passwd ? ber_strdup(passwd) : NULL;
892de962bdSlukem defaults->authzid = authzid ? ber_strdup(authzid) : NULL;
902de962bdSlukem
912de962bdSlukem if( defaults->mech == NULL ) {
922de962bdSlukem ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech );
932de962bdSlukem }
942de962bdSlukem if( defaults->realm == NULL ) {
952de962bdSlukem ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm );
962de962bdSlukem }
972de962bdSlukem if( defaults->authcid == NULL ) {
982de962bdSlukem ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid );
992de962bdSlukem }
1002de962bdSlukem if( defaults->authzid == NULL ) {
1012de962bdSlukem ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid );
1022de962bdSlukem }
1032de962bdSlukem defaults->resps = NULL;
1042de962bdSlukem defaults->nresps = 0;
1052de962bdSlukem
1062de962bdSlukem return defaults;
1072de962bdSlukem }
1082de962bdSlukem
interaction(unsigned flags,sasl_interact_t * interact,lutilSASLdefaults * defaults)1092de962bdSlukem static int interaction(
1102de962bdSlukem unsigned flags,
1112de962bdSlukem sasl_interact_t *interact,
1122de962bdSlukem lutilSASLdefaults *defaults )
1132de962bdSlukem {
1142de962bdSlukem const char *dflt = interact->defresult;
1152de962bdSlukem char input[1024];
1162de962bdSlukem
1172de962bdSlukem int noecho=0;
1182de962bdSlukem int challenge=0;
1192de962bdSlukem
1202de962bdSlukem switch( interact->id ) {
1212de962bdSlukem case SASL_CB_GETREALM:
1222de962bdSlukem if( defaults ) dflt = defaults->realm;
1232de962bdSlukem break;
1242de962bdSlukem case SASL_CB_AUTHNAME:
1252de962bdSlukem if( defaults ) dflt = defaults->authcid;
1262de962bdSlukem break;
1272de962bdSlukem case SASL_CB_PASS:
1282de962bdSlukem if( defaults ) dflt = defaults->passwd;
1292de962bdSlukem noecho = 1;
1302de962bdSlukem break;
1312de962bdSlukem case SASL_CB_USER:
1322de962bdSlukem if( defaults ) dflt = defaults->authzid;
1332de962bdSlukem break;
1342de962bdSlukem case SASL_CB_NOECHOPROMPT:
1352de962bdSlukem noecho = 1;
1362de962bdSlukem challenge = 1;
1372de962bdSlukem break;
1382de962bdSlukem case SASL_CB_ECHOPROMPT:
1392de962bdSlukem challenge = 1;
1402de962bdSlukem break;
1412de962bdSlukem }
1422de962bdSlukem
1432de962bdSlukem if( dflt && !*dflt ) dflt = NULL;
1442de962bdSlukem
1452de962bdSlukem if( flags != LDAP_SASL_INTERACTIVE &&
1462de962bdSlukem ( dflt || interact->id == SASL_CB_USER ) )
1472de962bdSlukem {
1482de962bdSlukem goto use_default;
1492de962bdSlukem }
1502de962bdSlukem
1512de962bdSlukem if( flags == LDAP_SASL_QUIET ) {
1522de962bdSlukem /* don't prompt */
1532de962bdSlukem return LDAP_OTHER;
1542de962bdSlukem }
1552de962bdSlukem
1562de962bdSlukem if( challenge ) {
1572de962bdSlukem if( interact->challenge ) {
1582de962bdSlukem fprintf( stderr, _("Challenge: %s\n"), interact->challenge );
1592de962bdSlukem }
1602de962bdSlukem }
1612de962bdSlukem
1622de962bdSlukem if( dflt ) {
1632de962bdSlukem fprintf( stderr, _("Default: %s\n"), dflt );
1642de962bdSlukem }
1652de962bdSlukem
1662de962bdSlukem snprintf( input, sizeof input, "%s: ",
1672de962bdSlukem interact->prompt ? interact->prompt : _("Interact") );
1682de962bdSlukem
1692de962bdSlukem if( noecho ) {
1702de962bdSlukem interact->result = (char *) getpassphrase( input );
1712de962bdSlukem interact->len = interact->result
1722de962bdSlukem ? strlen( interact->result ) : 0;
1732de962bdSlukem
1742de962bdSlukem } else {
1752de962bdSlukem /* prompt user */
1762de962bdSlukem fputs( input, stderr );
1772de962bdSlukem
1782de962bdSlukem /* get input */
1792de962bdSlukem interact->result = fgets( input, sizeof(input), stdin );
1802de962bdSlukem
1812de962bdSlukem if( interact->result == NULL ) {
1822de962bdSlukem interact->len = 0;
1832de962bdSlukem return LDAP_UNAVAILABLE;
1842de962bdSlukem }
1852de962bdSlukem
1862de962bdSlukem /* len of input */
1872de962bdSlukem interact->len = strlen(input);
1882de962bdSlukem
1892de962bdSlukem if( interact->len > 0 && input[interact->len - 1] == '\n' ) {
1902de962bdSlukem /* input includes '\n', trim it */
1912de962bdSlukem interact->len--;
1922de962bdSlukem input[interact->len] = '\0';
1932de962bdSlukem }
1942de962bdSlukem }
1952de962bdSlukem
1962de962bdSlukem
1972de962bdSlukem if( interact->len > 0 ) {
1982de962bdSlukem /* duplicate */
1992de962bdSlukem char *p = (char *)interact->result;
2002de962bdSlukem ldap_charray_add(&defaults->resps, interact->result);
2012de962bdSlukem interact->result = defaults->resps[defaults->nresps++];
2022de962bdSlukem
2032de962bdSlukem /* zap */
2042de962bdSlukem memset( p, '\0', interact->len );
2052de962bdSlukem
2062de962bdSlukem } else {
2072de962bdSlukem use_default:
2082de962bdSlukem /* input must be empty */
2092de962bdSlukem interact->result = (dflt && *dflt) ? dflt : "";
2102de962bdSlukem interact->len = strlen( interact->result );
2112de962bdSlukem }
2122de962bdSlukem
2132de962bdSlukem return LDAP_SUCCESS;
2142de962bdSlukem }
2152de962bdSlukem
lutil_sasl_interact(LDAP * ld,unsigned flags,void * defaults,void * in)2162de962bdSlukem int lutil_sasl_interact(
2172de962bdSlukem LDAP *ld,
2182de962bdSlukem unsigned flags,
2192de962bdSlukem void *defaults,
2202de962bdSlukem void *in )
2212de962bdSlukem {
2222de962bdSlukem sasl_interact_t *interact = in;
2232de962bdSlukem
2242de962bdSlukem if( flags == LDAP_SASL_INTERACTIVE ) {
2252de962bdSlukem fputs( _("SASL Interaction\n"), stderr );
2262de962bdSlukem }
2272de962bdSlukem
2282de962bdSlukem while( interact->id != SASL_CB_LIST_END ) {
2292de962bdSlukem int rc = interaction( flags, interact, defaults );
2302de962bdSlukem
2312de962bdSlukem if( rc ) return rc;
2322de962bdSlukem interact++;
2332de962bdSlukem }
2342de962bdSlukem
2352de962bdSlukem return LDAP_SUCCESS;
2362de962bdSlukem }
2372de962bdSlukem #endif
238