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