]> git.sur5r.net Git - openldap/blob - libraries/libldap/sasl.c
Set ciphers from slapd.conf.
[openldap] / libraries / libldap / sasl.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5
6 /*
7  *      BindRequest ::= SEQUENCE {
8  *              version         INTEGER,
9  *              name            DistinguishedName,       -- who
10  *              authentication  CHOICE {
11  *                      simple          [0] OCTET STRING -- passwd
12 #ifdef HAVE_KERBEROS
13  *                      krbv42ldap      [1] OCTET STRING
14  *                      krbv42dsa       [2] OCTET STRING
15 #endif
16  *                      sasl            [3] SaslCredentials     -- LDAPv3
17  *              }
18  *      }
19  *
20  *      BindResponse ::= SEQUENCE {
21  *              COMPONENTS OF LDAPResult,
22  *              serverSaslCreds         OCTET STRING OPTIONAL -- LDAPv3
23  *      }
24  *
25  */
26
27 #include "portable.h"
28
29 #include <stdio.h>
30
31 #include <ac/socket.h>
32 #include <ac/string.h>
33 #include <ac/time.h>
34
35 #include "ldap-int.h"
36
37
38 /*
39  * ldap_sasl_bind - bind to the ldap server (and X.500).  The dn, mechanism, and
40  * credentials of the entry to which to bind are supplied.  The message id
41  * of the request initiated is provided upon successful (LDAP_SUCCESS) return.
42  *
43  * Example:
44  *      ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us",
45  *          "mechanism", "secret", NULL, NULL, &msgid )
46  */
47
48 int
49 ldap_sasl_bind(
50         LDAP                    *ld,
51         LDAP_CONST char *dn,
52         LDAP_CONST char *mechanism,
53         struct berval   *cred,
54         LDAPControl             **sctrls,
55         LDAPControl             **cctrls,
56         int                             *msgidp )
57 {
58         BerElement      *ber;
59         int rc;
60
61         Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 );
62
63         assert( ld != NULL );
64         assert( LDAP_VALID( ld ) );
65         assert( msgidp != NULL );
66
67         if( msgidp == NULL ) {
68                 ld->ld_errno = LDAP_PARAM_ERROR;
69                 return ld->ld_errno;
70         }
71
72         if( mechanism != LDAP_SASL_SIMPLE
73                 && ld->ld_version < LDAP_VERSION3)
74         {
75                 ld->ld_errno = LDAP_NOT_SUPPORTED;
76                 return ld->ld_errno;
77         }
78
79         if ( dn == NULL )
80                 dn = "";
81
82         /* create a message to send */
83         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
84                 ld->ld_errno = LDAP_NO_MEMORY;
85                 return ld->ld_errno;
86         }
87
88         assert( BER_VALID( ber ) );
89
90         if( mechanism == LDAP_SASL_SIMPLE ) {
91                 /* simple bind */
92                 rc = ber_printf( ber, "{it{istO}" /*}*/,
93                         ++ld->ld_msgid, LDAP_REQ_BIND,
94                         ld->ld_version, dn, LDAP_AUTH_SIMPLE,
95                         cred );
96                 
97         } else if ( cred == NULL ) {
98                 /* SASL bind w/o creditials */
99                 rc = ber_printf( ber, "{it{ist{s}}" /*}*/,
100                         ++ld->ld_msgid, LDAP_REQ_BIND,
101                         ld->ld_version, dn, LDAP_AUTH_SASL,
102                         mechanism );
103
104         } else {
105                 /* SASL bind w/ creditials */
106                 rc = ber_printf( ber, "{it{ist{sO}}" /*}*/,
107                         ++ld->ld_msgid, LDAP_REQ_BIND,
108                         ld->ld_version, dn, LDAP_AUTH_SASL,
109                         mechanism, cred );
110         }
111
112         if( rc == -1 ) {
113                 ld->ld_errno = LDAP_ENCODING_ERROR;
114                 ber_free( ber, 1 );
115                 return( -1 );
116         }
117
118         /* Put Server Controls */
119         if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
120                 ber_free( ber, 1 );
121                 return ld->ld_errno;
122         }
123
124         if ( ber_printf( ber, /*{*/ "}" ) == -1 ) {
125                 ld->ld_errno = LDAP_ENCODING_ERROR;
126                 ber_free( ber, 1 );
127                 return ld->ld_errno;
128         }
129
130 #ifndef LDAP_NOCACHE
131         if ( ld->ld_cache != NULL ) {
132                 ldap_flush_cache( ld );
133         }
134 #endif /* !LDAP_NOCACHE */
135
136         /* send the message */
137         *msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber );
138
139         if(*msgidp < 0)
140                 return ld->ld_errno;
141
142         return LDAP_SUCCESS;
143 }
144
145 /*
146  * ldap_sasl_bind_s - bind to the ldap server (and X.500) using simple
147  * authentication.  The dn and password of the entry to which to bind are
148  * supplied.  LDAP_SUCCESS is returned upon success, the ldap error code
149  * otherwise.
150  *
151  * Example:
152  *      ldap_sasl_bind_s( ld, "cn=manager, o=university of michigan, c=us",
153  *          "mechanism", "secret", NULL, NULL, &servercred )
154  */
155
156 int
157 ldap_sasl_bind_s(
158         LDAP                    *ld,
159         LDAP_CONST char *dn,
160         LDAP_CONST char *mechanism,
161         struct berval   *cred,
162         LDAPControl             **sctrls,
163         LDAPControl             **cctrls,
164         struct berval   **servercredp )
165 {
166         int     rc, msgid;
167         LDAPMessage     *result;
168         struct berval   *scredp = NULL;
169
170         Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind_s\n", 0, 0, 0 );
171
172         /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */
173         if( servercredp != NULL ) {
174                 if (ld->ld_version < LDAP_VERSION3) {
175                         ld->ld_errno = LDAP_NOT_SUPPORTED;
176                         return ld->ld_errno;
177                 }
178                 *servercredp = NULL;
179         }
180
181         rc = ldap_sasl_bind( ld, dn, mechanism, cred, sctrls, cctrls, &msgid );
182
183         if ( rc != LDAP_SUCCESS ) {
184                 return( rc );
185         }
186
187         if ( ldap_result( ld, msgid, 1, NULL, &result ) == -1 ) {
188                 return( ld->ld_errno ); /* ldap_result sets ld_errno */
189         }
190
191         /* parse the results */
192         scredp = NULL;
193         if( servercredp != NULL ) {
194                 rc = ldap_parse_sasl_bind_result( ld, result, &scredp, 0 );
195         }
196
197         if( rc != LDAP_SUCCESS ) {
198                 ldap_msgfree( result );
199                 return( rc );
200         }
201
202         rc = ldap_result2error( ld, result, 1 );
203
204         if( rc == LDAP_SUCCESS ) {
205                 if( servercredp != NULL ) {
206                         *servercredp = scredp;
207                 }
208
209         } else if (scredp != NULL ) {
210                 ber_bvfree(scredp);
211         }
212
213         return rc;
214 }
215
216
217 /*
218  * Parse BindResponse:
219  *
220  *   BindResponse ::= [APPLICATION 1] SEQUENCE {
221  *     COMPONENTS OF LDAPResult,
222  *     serverSaslCreds  [7] OCTET STRING OPTIONAL }
223  *
224  *   LDAPResult ::= SEQUENCE {
225  *     resultCode      ENUMERATED,
226  *     matchedDN       LDAPDN,
227  *     errorMessage    LDAPString,
228  *     referral        [3] Referral OPTIONAL }
229  */
230
231 int
232 ldap_parse_sasl_bind_result(
233         LDAP                    *ld,
234         LDAPMessage             *res,
235         struct berval   **servercredp,
236         int                             freeit )
237 {
238         ber_int_t errcode;
239         struct berval* scred;
240
241         ber_tag_t tag;
242         BerElement      *ber;
243
244         Debug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 );
245
246         assert( ld != NULL );
247         assert( LDAP_VALID( ld ) );
248         assert( res != NULL );
249
250         if ( ld == NULL || res == NULL ) {
251                 return LDAP_PARAM_ERROR;
252         }
253
254         if(servercredp != NULL) {
255                 if( ld->ld_version < LDAP_VERSION2 ) {
256                         return LDAP_NOT_SUPPORTED;
257                 }
258                 *servercredp = NULL;
259         }
260
261         if( res->lm_msgtype == LDAP_RES_BIND ) {
262                 ld->ld_errno = LDAP_PARAM_ERROR;
263                 return ld->ld_errno;
264         }
265
266         errcode = LDAP_SUCCESS;
267         scred = NULL;
268
269         if ( ld->ld_error ) {
270                 LDAP_FREE( ld->ld_error );
271                 ld->ld_error = NULL;
272         }
273         if ( ld->ld_matched ) {
274                 LDAP_FREE( ld->ld_matched );
275                 ld->ld_matched = NULL;
276         }
277
278         /* parse results */
279
280         ber = ber_dup( res->lm_ber );
281
282         if ( ld->ld_version < LDAP_VERSION2 ) {
283                 tag = ber_scanf( ber, "{ia}",
284                         &errcode, &ld->ld_error );
285
286         } else {
287                 ber_len_t len;
288
289                 tag = ber_scanf( ber, "{iaa" /*}*/,
290                         &errcode, &ld->ld_matched, &ld->ld_error );
291
292                 if( tag != LBER_ERROR ) {
293                         tag = ber_peek_tag(ber, &len);
294                 }
295
296                 if( tag == LDAP_TAG_REFERRAL ) {
297                         /* skip 'em */
298                         tag = ber_scanf( ber, "x" );
299
300                         if( tag != LBER_ERROR ) {
301                                 tag = ber_peek_tag(ber, &len);
302                         }
303                 }
304
305                 /* need to clean out misc items */
306                 if( tag == LDAP_TAG_SASL_RES_CREDS ) {
307                         tag = ber_scanf( ber, "O", &scred );
308                 }
309         }
310
311         if ( tag == LBER_ERROR ) {
312                 errcode = LDAP_DECODING_ERROR;
313         }
314
315         if( ber != NULL ) {
316                 ber_free( ber, 0 );
317         }
318
319         /* return */
320         if ( errcode == LDAP_SUCCESS && servercredp != NULL ) {
321                 *servercredp = scred;
322
323         } else if ( scred != NULL ) {
324                 ber_bvfree( scred );
325         }
326
327         if ( freeit ) {
328                 ldap_msgfree( res );
329         }
330
331         ld->ld_errno = errcode;
332         return( ld->ld_errno );
333 }