]> git.sur5r.net Git - openldap/blob - servers/slapd/sasl.c
Per ITS#419, don't require SLAPD_RLOOKUPS when HAVE_TCPD
[openldap] / servers / slapd / sasl.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <ac/stdlib.h>
10 #include <stdio.h>
11
12 #include "slap.h"
13 #include "proto-slap.h"
14
15 #include <lber.h>
16 #include <ldap_log.h>
17
18 char **supportedSASLMechanisms = NULL;
19
20 #ifdef HAVE_CYRUS_SASL
21 static void *sasl_pvt_mutex_new(void)
22 {
23         ldap_pvt_thread_mutex_t *mutex;
24
25         mutex = (ldap_pvt_thread_mutex_t *)ch_malloc( sizeof(ldap_pvt_thread_mutex_t) );
26         if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) {
27                 return mutex;
28         }
29         return NULL;
30 }
31
32 static int sasl_pvt_mutex_lock(void *mutex)
33 {
34         return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex );
35 }
36
37 static int sasl_pvt_mutex_unlock(void *mutex)
38 {
39         return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex );
40 }
41
42 static void sasl_pvt_mutex_dispose(void *mutex)
43 {
44         (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex );
45         free( mutex );
46 }
47
48 int sasl_init( void )
49 {
50         int rc;
51         char *mechs;
52         sasl_conn_t *server = NULL;
53
54         sasl_set_alloc( ch_malloc, ch_calloc, ch_realloc, ch_free ); 
55
56         sasl_set_mutex( sasl_pvt_mutex_new, sasl_pvt_mutex_lock,
57                 sasl_pvt_mutex_unlock, sasl_pvt_mutex_dispose );
58
59         rc = sasl_server_init( NULL, "slapd" );
60
61         if( rc != SASL_OK ) {
62                 Debug( LDAP_DEBUG_ANY, "sasl_server_init failed\n",
63                         0, 0, 0 );
64                 return -1;
65         }
66
67         rc = sasl_server_new( "ldap", NULL, NULL, NULL,
68                 SASL_SECURITY_LAYER, 
69                 &server );
70
71         if( rc != SASL_OK ) {
72                 Debug( LDAP_DEBUG_ANY, "sasl_server_new failed\n",
73                         0, 0, 0 );
74                 return -1;
75         }
76
77 #ifdef RESTRICT_SASL
78         {
79                 sasl_security_properties_t secprops;
80                 memset(&secprops, 0, sizeof(secprops));
81                 secprops.security_flags = SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS;
82                 secprops.property_names = NULL;
83                 secprops.property_values = NULL;
84         
85                 rc = sasl_setprop( server, SASL_SEC_PROPS, &secprops );
86
87                 if( rc != SASL_OK ) {
88                         Debug( LDAP_DEBUG_ANY, "sasl_setprop failed\n",
89                                 0, 0, 0 );
90                         return -1;
91                 }
92         }
93 #endif
94
95         rc = sasl_listmech( server, NULL, NULL, ",", NULL,
96                 &mechs, NULL, NULL);
97
98         if( rc != SASL_OK ) {
99                 Debug( LDAP_DEBUG_ANY, "sasl_listmech failed: %d\n",
100                         rc, 0, 0 );
101                 return -1;
102         }
103
104         Debug( LDAP_DEBUG_TRACE, "SASL mechanisms: %s\n",
105                 mechs, 0, 0 );
106
107         supportedSASLMechanisms = str2charray( mechs, "," );
108         sasl_dispose( &server );
109
110         return 0;
111 }
112
113 int sasl_destroy( void )
114 {
115         charray_free( supportedSASLMechanisms );
116         return 0;
117 }
118
119 #ifdef HAVE_CYRUS_SASL
120 int sasl_bind(
121     Backend             *be,
122     Connection          *conn,
123     Operation           *op,  
124     char                *dn,  
125     char                *ndn,
126     char                *mech,
127     struct berval       *cred,
128     char                **edn)
129 {
130         struct berval response;
131         const char *errstr;
132         int sc;
133         int rc = 1;
134
135         Debug(LDAP_DEBUG_ARGS, "==> sasl_bind: dn=%s, mech=%s, cred->bv_len=%d\n",
136                 dn, mech, cred ? cred->bv_len : 0 );
137
138         if ( conn->c_sasl_context == NULL ) {
139                 sasl_callback_t callbacks[4];
140                 int cbnum = 0;
141
142                 if (be->be_sasl_authorize) {
143                         callbacks[cbnum].id = SASL_CB_PROXY_POLICY;
144                         callbacks[cbnum].proc = be->be_sasl_authorize;
145                         callbacks[cbnum].context = be;
146                         ++cbnum;
147                 }
148
149                 if (be->be_sasl_getsecret) {
150                         callbacks[cbnum].id = SASL_CB_SERVER_GETSECRET;
151                         callbacks[cbnum].proc = be->be_sasl_getsecret;
152                         callbacks[cbnum].context = be;
153                         ++cbnum;
154                 }
155
156                 if (be->be_sasl_putsecret) {
157                         callbacks[cbnum].id = SASL_CB_SERVER_PUTSECRET;
158                         callbacks[cbnum].proc = be->be_sasl_putsecret;
159                         callbacks[cbnum].context = be;
160                         ++cbnum;
161                 }
162                 callbacks[cbnum].id = SASL_CB_LIST_END;
163                 callbacks[cbnum].proc = NULL;
164                 callbacks[cbnum].context = NULL;
165         
166                 if ( sasl_server_new( "ldap", NULL, be->be_realm,
167                         callbacks, SASL_SECURITY_LAYER, &conn->c_sasl_context ) != SASL_OK ) {
168                         send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
169                                 NULL, NULL, NULL, NULL );
170                 } else {
171                         conn->c_authmech = ch_strdup( mech );
172                         sc = sasl_server_start( conn->c_sasl_context, conn->c_authmech,
173                                 cred->bv_val, cred->bv_len, (char **)&response.bv_val,
174                                 (unsigned *)&response.bv_len, &errstr );
175                         if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) {
176                                 send_ldap_result( conn, op, ldap_pvt_sasl_err2ldap( sc ),
177                                         NULL, errstr, NULL, NULL );
178                         }
179                 }
180         } else {
181                 sc = sasl_server_step( conn->c_sasl_context, cred->bv_val, cred->bv_len,
182                         (char **)&response.bv_val, (unsigned *)&response.bv_len, &errstr );
183                 if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) {
184                         send_ldap_result( conn, op, ldap_pvt_sasl_err2ldap( sc ),
185                                 NULL, errstr, NULL, NULL );
186                 }
187         }
188         if ( sc == SASL_OK ) {
189                 char *authzid;
190
191                 if ( ( sc = sasl_getprop( conn->c_sasl_context, SASL_USERNAME,
192                         (void **)&authzid ) ) != SASL_OK ) {
193                         send_ldap_result( conn, op, ldap_pvt_sasl_err2ldap( sc ),
194                                 NULL, NULL, NULL, NULL );
195                 } else {
196                         if ( *edn != NULL ) {
197                                 free( *edn );
198                         }
199                         if ( strcasecmp( authzid, "anonymous" ) == 0 ) {
200                                 *edn = ch_strdup( "" );
201                         } else {
202                                 *edn = ch_malloc( strlen( authzid ) + sizeof( "authzid=" ) );
203                                 strcpy( *edn, "authzid=" );
204                                 strcat( *edn, authzid );
205                         }
206                         /* let FE send result */
207                         rc = 0;
208                 }
209         } else if ( sc == SASL_CONTINUE ) {
210                 /*
211                  * We set c_bind_in_progress because it doesn't appear
212                  * that connection.c sets this (unless do_bind() itself
213                  * returns LDAP_SASL_BIND_IN_PROGRESS).
214                  */
215                 conn->c_bind_in_progress = 1;
216                 send_ldap_sasl( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
217                         /* matched */ NULL, /* text */ NULL, /* refs */ NULL, /* controls */ NULL,  &response );
218         } 
219
220         Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: rc=%d\n", rc, 0, 0);
221
222         return rc;
223 }
224 #endif /* HAVE_CYRUS_SASL */
225
226 #else
227 /* no SASL support */
228 int sasl_init( void ) { return 0; }
229 int sasl_destroy( void ) { return 0; }
230 #endif