summaryrefslogtreecommitdiffstats
path: root/libraries/liblutil/sasl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/liblutil/sasl.c')
-rw-r--r--libraries/liblutil/sasl.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/libraries/liblutil/sasl.c b/libraries/liblutil/sasl.c
new file mode 100644
index 0000000..b6a3f00
--- /dev/null
+++ b/libraries/liblutil/sasl.c
@@ -0,0 +1,232 @@
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2022 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+#include "portable.h"
+
+#ifdef HAVE_CYRUS_SASL
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_SASL_SASL_H
+#include <sasl/sasl.h>
+#else
+#include <sasl.h>
+#endif
+
+#include <ldap.h>
+#include "ldap_pvt.h"
+#include "lutil_ldap.h"
+
+
+typedef struct lutil_sasl_defaults_s {
+ char *mech;
+ char *realm;
+ char *authcid;
+ char *passwd;
+ char *authzid;
+ char **resps;
+ int nresps;
+} lutilSASLdefaults;
+
+
+void
+lutil_sasl_freedefs(
+ void *defaults )
+{
+ lutilSASLdefaults *defs = defaults;
+
+ assert( defs != NULL );
+
+ if (defs->mech) ber_memfree(defs->mech);
+ if (defs->realm) ber_memfree(defs->realm);
+ if (defs->authcid) ber_memfree(defs->authcid);
+ if (defs->passwd) ber_memfree(defs->passwd);
+ if (defs->authzid) ber_memfree(defs->authzid);
+ if (defs->resps) ldap_charray_free(defs->resps);
+
+ ber_memfree(defs);
+}
+
+void *
+lutil_sasl_defaults(
+ LDAP *ld,
+ char *mech,
+ char *realm,
+ char *authcid,
+ char *passwd,
+ char *authzid )
+{
+ lutilSASLdefaults *defaults;
+
+ defaults = ber_memalloc( sizeof( lutilSASLdefaults ) );
+
+ if( defaults == NULL ) return NULL;
+
+ defaults->mech = mech ? ber_strdup(mech) : NULL;
+ defaults->realm = realm ? ber_strdup(realm) : NULL;
+ defaults->authcid = authcid ? ber_strdup(authcid) : NULL;
+ defaults->passwd = passwd ? ber_strdup(passwd) : NULL;
+ defaults->authzid = authzid ? ber_strdup(authzid) : NULL;
+
+ if( defaults->mech == NULL ) {
+ ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech );
+ }
+ if( defaults->realm == NULL ) {
+ ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm );
+ }
+ if( defaults->authcid == NULL ) {
+ ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid );
+ }
+ if( defaults->authzid == NULL ) {
+ ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid );
+ }
+ defaults->resps = NULL;
+ defaults->nresps = 0;
+
+ return defaults;
+}
+
+static int interaction(
+ unsigned flags,
+ sasl_interact_t *interact,
+ lutilSASLdefaults *defaults )
+{
+ const char *dflt = interact->defresult;
+ char input[1024];
+
+ int noecho=0;
+ int challenge=0;
+
+ switch( interact->id ) {
+ case SASL_CB_GETREALM:
+ if( defaults ) dflt = defaults->realm;
+ break;
+ case SASL_CB_AUTHNAME:
+ if( defaults ) dflt = defaults->authcid;
+ break;
+ case SASL_CB_PASS:
+ if( defaults ) dflt = defaults->passwd;
+ noecho = 1;
+ break;
+ case SASL_CB_USER:
+ if( defaults ) dflt = defaults->authzid;
+ break;
+ case SASL_CB_NOECHOPROMPT:
+ noecho = 1;
+ challenge = 1;
+ break;
+ case SASL_CB_ECHOPROMPT:
+ challenge = 1;
+ break;
+ }
+
+ if( dflt && !*dflt ) dflt = NULL;
+
+ if( flags != LDAP_SASL_INTERACTIVE &&
+ ( dflt || interact->id == SASL_CB_USER ) )
+ {
+ goto use_default;
+ }
+
+ if( flags == LDAP_SASL_QUIET ) {
+ /* don't prompt */
+ return LDAP_OTHER;
+ }
+
+ if( challenge ) {
+ if( interact->challenge ) {
+ fprintf( stderr, _("Challenge: %s\n"), interact->challenge );
+ }
+ }
+
+ if( dflt ) {
+ fprintf( stderr, _("Default: %s\n"), dflt );
+ }
+
+ snprintf( input, sizeof input, "%s: ",
+ interact->prompt ? interact->prompt : _("Interact") );
+
+ if( noecho ) {
+ interact->result = (char *) getpassphrase( input );
+ interact->len = interact->result
+ ? strlen( interact->result ) : 0;
+
+ } else {
+ /* prompt user */
+ fputs( input, stderr );
+
+ /* get input */
+ interact->result = fgets( input, sizeof(input), stdin );
+
+ if( interact->result == NULL ) {
+ interact->len = 0;
+ return LDAP_UNAVAILABLE;
+ }
+
+ /* len of input */
+ interact->len = strlen(input);
+
+ if( interact->len > 0 && input[interact->len - 1] == '\n' ) {
+ /* input includes '\n', trim it */
+ interact->len--;
+ input[interact->len] = '\0';
+ }
+ }
+
+
+ if( interact->len > 0 ) {
+ /* duplicate */
+ char *p = (char *)interact->result;
+ ldap_charray_add(&defaults->resps, interact->result);
+ interact->result = defaults->resps[defaults->nresps++];
+
+ /* zap */
+ memset( p, '\0', interact->len );
+
+ } else {
+use_default:
+ /* input must be empty */
+ interact->result = (dflt && *dflt) ? dflt : "";
+ interact->len = strlen( interact->result );
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int lutil_sasl_interact(
+ LDAP *ld,
+ unsigned flags,
+ void *defaults,
+ void *in )
+{
+ sasl_interact_t *interact = in;
+
+ if( flags == LDAP_SASL_INTERACTIVE ) {
+ fputs( _("SASL Interaction\n"), stderr );
+ }
+
+ while( interact->id != SASL_CB_LIST_END ) {
+ int rc = interaction( flags, interact, defaults );
+
+ if( rc ) return rc;
+ interact++;
+ }
+
+ return LDAP_SUCCESS;
+}
+#endif