3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
13 #include "proto-slap.h"
18 char **supportedSASLMechanisms = NULL;
19 char *sasl_host = NULL;
21 #ifdef HAVE_CYRUS_SASL
27 static void *slap_sasl_mutex_new(void)
29 ldap_pvt_thread_mutex_t *mutex;
31 mutex = (ldap_pvt_thread_mutex_t *) ch_malloc( sizeof(ldap_pvt_thread_mutex_t) );
32 if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) {
38 static int slap_sasl_mutex_lock(void *mutex)
40 return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex );
43 static int slap_sasl_mutex_unlock(void *mutex)
45 return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex );
48 static void slap_sasl_mutex_dispose(void *mutex)
50 (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex );
55 slap_sasl_err2ldap( int saslerr )
61 rc = LDAP_SASL_BIND_IN_PROGRESS;
73 rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
76 rc = LDAP_INVALID_CREDENTIALS;
79 rc = LDAP_INSUFFICIENT_ACCESS;
83 rc = LDAP_INAPPROPRIATE_AUTH;
98 sasl_conn_t *server = NULL;
100 sasl_set_alloc( ch_malloc, ch_calloc, ch_realloc, ch_free );
104 slap_sasl_mutex_lock,
105 slap_sasl_mutex_unlock,
106 slap_sasl_mutex_dispose );
108 /* server name should be configurable */
109 rc = sasl_server_init( NULL, "slapd" );
111 if( rc != SASL_OK ) {
112 Debug( LDAP_DEBUG_ANY, "sasl_server_init failed\n",
117 if( sasl_host == NULL ) {
118 static char hostname[MAXHOSTNAMELEN+1];
120 if( gethostname( hostname, MAXHOSTNAMELEN ) == 0 ) {
121 hostname[MAXHOSTNAMELEN] = '\0';
122 sasl_host = hostname;
126 rc = sasl_server_new( "ldap", sasl_host, NULL, NULL,
130 if( rc != SASL_OK ) {
131 Debug( LDAP_DEBUG_ANY, "sasl_server_new failed\n",
136 #ifndef SLAPD_IGNORE_RFC2829
138 /* security flags should be configurable */
139 sasl_security_properties_t secprops;
140 memset(&secprops, '\0', sizeof(secprops));
141 secprops.security_flags = SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS;
142 secprops.property_names = NULL;
143 secprops.property_values = NULL;
145 rc = sasl_setprop( server, SASL_SEC_PROPS, &secprops );
147 if( rc != SASL_OK ) {
148 Debug( LDAP_DEBUG_ANY, "sasl_setprop failed\n",
155 rc = sasl_listmech( server, NULL, NULL, ",", NULL,
158 if( rc != SASL_OK ) {
159 Debug( LDAP_DEBUG_ANY, "sasl_listmech failed: %d\n",
164 Debug( LDAP_DEBUG_TRACE, "SASL mechanisms: %s\n",
167 supportedSASLMechanisms = str2charray( mechs, "," );
170 lutil_passwd_sasl_conn = server;
172 sasl_dispose( &server );
178 int sasl_destroy( void )
181 sasl_dispose( &lutil_passwd_sasl_conn );
183 charray_free( supportedSASLMechanisms );
187 #ifdef HAVE_CYRUS_SASL
197 struct berval response;
202 Debug(LDAP_DEBUG_ARGS,
203 "==> sasl_bind: dn=\"%s\" mech=%s cred->bv_len=%d\n",
204 dn, mech, cred ? cred->bv_len : 0 );
206 if ( conn->c_sasl_bind_context == NULL ) {
207 sasl_callback_t callbacks[4];
211 if (be->be_sasl_authorize) {
212 callbacks[cbnum].id = SASL_CB_PROXY_POLICY;
213 callbacks[cbnum].proc = be->be_sasl_authorize;
214 callbacks[cbnum].context = be;
218 if (be->be_sasl_getsecret) {
219 callbacks[cbnum].id = SASL_CB_SERVER_GETSECRET;
220 callbacks[cbnum].proc = be->be_sasl_getsecret;
221 callbacks[cbnum].context = be;
225 if (be->be_sasl_putsecret) {
226 callbacks[cbnum].id = SASL_CB_SERVER_PUTSECRET;
227 callbacks[cbnum].proc = be->be_sasl_putsecret;
228 callbacks[cbnum].context = be;
233 callbacks[cbnum].id = SASL_CB_LIST_END;
234 callbacks[cbnum].proc = NULL;
235 callbacks[cbnum].context = NULL;
237 /* create new SASL context */
238 sc = sasl_server_new( "ldap", sasl_host, global_realm,
239 callbacks, SASL_SECURITY_LAYER, &conn->c_sasl_bind_context );
241 if( sc != SASL_OK ) {
242 send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ),
243 NULL, "could not create new SASL context", NULL, NULL );
247 conn->c_authmech = ch_strdup( mech );
249 sc = sasl_server_start( conn->c_sasl_bind_context,
251 cred->bv_val, cred->bv_len,
252 (char **)&response.bv_val, &reslen, &errstr );
254 response.bv_len = reslen;
256 if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) {
257 send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ),
258 NULL, errstr, NULL, NULL );
264 sc = sasl_server_step( conn->c_sasl_bind_context,
265 cred->bv_val, cred->bv_len,
266 (char **)&response.bv_val, &reslen, &errstr );
268 response.bv_len = reslen;
270 if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) {
271 send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ),
272 NULL, errstr, NULL, NULL );
276 if ( sc == SASL_OK ) {
279 sc = sasl_getprop( conn->c_sasl_bind_context, SASL_USERNAME,
282 if ( sc != SASL_OK ) {
283 send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ),
284 NULL, "no SASL username", NULL, NULL );
287 Debug(LDAP_DEBUG_TRACE, "sasl_bind: username=%s\n",
290 if( !strncasecmp( authzid, "anonymous", sizeof("anonyous")-1 ) &&
291 ( ( authzid[sizeof("anonymous")] == '\0' ) ||
292 ( authzid[sizeof("anonymous")] == '@' ) ) )
294 Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: anonymous\n",
298 *edn = ch_malloc( sizeof( "authzid=" ) + strlen( authzid ) );
299 strcpy( *edn, "authzid=" );
300 strcat( *edn, authzid );
302 Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: authzdn: \"%s\"\n",
306 send_ldap_sasl( conn, op, rc = LDAP_SUCCESS,
307 NULL, NULL, NULL, NULL, &response );
310 } else if ( sc == SASL_CONTINUE ) {
311 send_ldap_sasl( conn, op, rc = LDAP_SASL_BIND_IN_PROGRESS,
312 NULL, NULL, NULL, NULL, &response );
315 if ( sc != SASL_CONTINUE && conn->c_sasl_bind_context != NULL ) {
316 sasl_dispose( &conn->c_sasl_bind_context );
317 conn->c_sasl_bind_context = NULL;
320 Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: rc=%d\n", rc, 0, 0);
324 #endif /* HAVE_CYRUS_SASL */
327 /* no SASL support */
339 send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
340 NULL, "SASL unavailable", NULL, NULL );
345 int sasl_init( void ) { return 0; }
346 int sasl_destroy( void ) { return 0; }