sasl.c 4.81 KB
Newer Older
1
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
2
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
4
 * Copyright 1998-2020 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
6
7
8
9
10
11
12
13
 * 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>.
14
15
16
17
18
19
20
21
22
23
24
 */

#include "portable.h"

#ifdef HAVE_CYRUS_SASL

#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/string.h>
#include <ac/unistd.h>

Howard Chu's avatar
Howard Chu committed
25
26
27
#ifdef HAVE_SASL_SASL_H
#include <sasl/sasl.h>
#else
28
#include <sasl.h>
Howard Chu's avatar
Howard Chu committed
29
#endif
30
31

#include <ldap.h>
32
#include "ldap_pvt.h"
33
34
#include "lutil_ldap.h"

35
36
37
38
39
40
41

typedef struct lutil_sasl_defaults_s {
	char *mech;
	char *realm;
	char *authcid;
	char *passwd;
	char *authzid;
42
43
	char **resps;
	int nresps;
44
45
46
} lutilSASLdefaults;


47
48
49
50
51
void
lutil_sasl_freedefs(
	void *defaults )
{
	lutilSASLdefaults *defs = defaults;
52
53

	assert( defs != NULL );
54
55
56
57
58
59
60
61
62
63
64
	
	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);
}

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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;

80
81
82
83
84
	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;
85
86
87
88
89
90
91
92
93
94
95
96
97

	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 );
	}
98
99
	defaults->resps = NULL;
	defaults->nresps = 0;
100
101
102
103

	return defaults;
}

104
static int interaction(
105
106
107
	unsigned flags,
	sasl_interact_t *interact,
	lutilSASLdefaults *defaults )
108
{
109
	const char *dflt = interact->defresult;
110
111
112
113
114
115
	char input[1024];

	int noecho=0;
	int challenge=0;

	switch( interact->id ) {
116
117
118
119
120
121
122
123
124
125
126
127
128
	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;
129
130
131
132
133
134
135
	case SASL_CB_NOECHOPROMPT:
		noecho = 1;
		challenge = 1;
		break;
	case SASL_CB_ECHOPROMPT:
		challenge = 1;
		break;
136
137
138
139
	}

	if( dflt && !*dflt ) dflt = NULL;

140
141
142
	if( flags != LDAP_SASL_INTERACTIVE &&
		( dflt || interact->id == SASL_CB_USER ) )
	{
143
144
145
		goto use_default;
	}

146
	if( flags == LDAP_SASL_QUIET ) {
147
148
		/* don't prompt */
		return LDAP_OTHER;
149
150
151
152
	}

	if( challenge ) {
		if( interact->challenge ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
153
			fprintf( stderr, _("Challenge: %s\n"), interact->challenge );
154
		}
155
156
157
	}

	if( dflt ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
158
		fprintf( stderr, _("Default: %s\n"), dflt );
159
160
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
161
	snprintf( input, sizeof input, "%s: ",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
162
		interact->prompt ? interact->prompt : _("Interact") );
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

	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 */
194
		char *p = (char *)interact->result;
195
196
		ldap_charray_add(&defaults->resps, interact->result);
		interact->result = defaults->resps[defaults->nresps++];
197
198
199
200
201

		/* zap */
		memset( p, '\0', interact->len );

	} else {
202
use_default:
Kurt Zeilenga's avatar
Kurt Zeilenga committed
203
		/* input must be empty */
204
205
		interact->result = (dflt && *dflt) ? dflt : "";
		interact->len = strlen( interact->result );
206
207
208
209
210
211
212
	}

	return LDAP_SUCCESS;
}

int lutil_sasl_interact(
	LDAP *ld,
213
	unsigned flags,
214
	void *defaults,
215
216
217
218
	void *in )
{
	sasl_interact_t *interact = in;

219
	if( flags == LDAP_SASL_INTERACTIVE ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
220
		fputs( _("SASL Interaction\n"), stderr );
221
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
222

223
	while( interact->id != SASL_CB_LIST_END ) {
224
		int rc = interaction( flags, interact, defaults );
225
226
227
228
229
230
231
232

		if( rc )  return rc;
		interact++;
	}
	
	return LDAP_SUCCESS;
}
#endif