]> git.sur5r.net Git - openldap/blob - libraries/libldap/kbind.c
according to sasl documentation, prompts is filled only if SASL_INTERACT is returned
[openldap] / libraries / libldap / kbind.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*  Portions
7  *  Copyright (c) 1993 Regents of the University of Michigan.
8  *  All rights reserved.
9  *
10  *  kbind.c
11  */
12
13 /*
14  *      BindRequest ::= SEQUENCE {
15  *              version         INTEGER,
16  *              name            DistinguishedName,       -- who
17  *              authentication  CHOICE {
18  *                      simple          [0] OCTET STRING -- passwd
19 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
20  *                      krbv42ldap      [1] OCTET STRING
21  *                      krbv42dsa       [2] OCTET STRING
22 #endif
23  *                      sasl            [3] SaslCredentials     -- LDAPv3
24  *              }
25  *      }
26  *
27  *      BindResponse ::= SEQUENCE {
28  *              COMPONENTS OF LDAPResult,
29  *              serverSaslCreds         OCTET STRING OPTIONAL -- LDAPv3
30  *      }
31  *
32  */
33
34 #include "portable.h"
35
36 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
37
38 #include <stdio.h>
39 #include <ac/stdlib.h>
40
41 #include <ac/krb.h>
42 #include <ac/socket.h>
43 #include <ac/string.h>
44 #include <ac/time.h>
45
46 #include "ldap-int.h"
47
48 /*
49  * ldap_kerberos_bind1 - initiate a bind to the ldap server using
50  * kerberos authentication.  The dn is supplied.  It is assumed the user
51  * already has a valid ticket granting ticket.  The msgid of the
52  * request is returned on success (suitable for passing to ldap_result()),
53  * -1 is returned if there's trouble.
54  *
55  * Example:
56  *      ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" )
57  */
58 int
59 ldap_kerberos_bind1( LDAP *ld, LDAP_CONST char *dn )
60 {
61         BerElement      *ber;
62         char            *cred;
63         int             rc;
64         ber_len_t credlen;
65
66 #ifdef NEW_LOGGING
67         LDAP_LOG ( OPERATION, ENTRY, "ldap_kerberos_bind1\n", 0, 0, 0 );
68 #else
69         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1\n", 0, 0, 0 );
70 #endif
71
72         if( ld->ld_version > LDAP_VERSION2 ) {
73                 ld->ld_errno = LDAP_NOT_SUPPORTED;
74                 return -1;
75         }
76
77         if ( dn == NULL )
78                 dn = "";
79
80         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "ldapserver",
81             &credlen )) == NULL ) {
82                 return( -1 );   /* ld_errno should already be set */
83         }
84
85         /* create a message to send */
86         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
87                 LDAP_FREE( cred );
88                 return( -1 );
89         }
90
91         /* fill it in */
92         rc = ber_printf( ber, "{it{istoN}N}", ++ld->ld_msgid, LDAP_REQ_BIND,
93             ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen );
94
95         if ( rc == -1 ) {
96                 LDAP_FREE( cred );
97                 ber_free( ber, 1 );
98                 ld->ld_errno = LDAP_ENCODING_ERROR;
99                 return( -1 );
100         }
101
102         LDAP_FREE( cred );
103
104 #ifndef LDAP_NOCACHE
105         if ( ld->ld_cache != NULL ) {
106                 ldap_flush_cache( ld );
107         }
108 #endif /* !LDAP_NOCACHE */
109
110         /* send the message */
111         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
112 }
113
114 int
115 ldap_kerberos_bind1_s( LDAP *ld, LDAP_CONST char *dn )
116 {
117         int             msgid;
118         LDAPMessage     *res;
119
120 #ifdef NEW_LOGGING
121         LDAP_LOG ( OPERATION, ENTRY, "ldap_kerberos_bind1_s\n", 0, 0, 0 );
122 #else
123         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1_s\n", 0, 0, 0 );
124 #endif
125
126         /* initiate the bind */
127         if ( (msgid = ldap_kerberos_bind1( ld, dn )) == -1 )
128                 return( ld->ld_errno );
129
130         /* wait for a result */
131         if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
132             == -1 ) {
133                 return( ld->ld_errno ); /* ldap_result sets ld_errno */
134         }
135
136         return( ldap_result2error( ld, res, 1 ) );
137 }
138
139 /*
140  * ldap_kerberos_bind2 - initiate a bind to the X.500 server using
141  * kerberos authentication.  The dn is supplied.  It is assumed the user
142  * already has a valid ticket granting ticket.  The msgid of the
143  * request is returned on success (suitable for passing to ldap_result()),
144  * -1 is returned if there's trouble.
145  *
146  * Example:
147  *      ldap_kerberos_bind2( ld, "cn=manager, o=university of michigan, c=us" )
148  */
149 int
150 ldap_kerberos_bind2( LDAP *ld, LDAP_CONST char *dn )
151 {
152         BerElement      *ber;
153         char            *cred;
154         int             rc;
155         ber_len_t credlen;
156
157 #ifdef NEW_LOGGING
158         LDAP_LOG ( OPERATION, ENTRY, "ldap_kerberos_bind2\n", 0, 0, 0 );
159 #else
160         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2\n", 0, 0, 0 );
161 #endif
162
163         if( ld->ld_version > LDAP_VERSION2 ) {
164                 ld->ld_errno = LDAP_NOT_SUPPORTED;
165                 return -1;
166         }
167
168         if ( dn == NULL )
169                 dn = "";
170
171         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "x500dsa", &credlen ))
172             == NULL ) {
173                 return( -1 );   /* ld_errno should already be set */
174         }
175
176         /* create a message to send */
177         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
178                 LDAP_FREE( cred );
179                 return( -1 );
180         }
181
182         /* fill it in */
183         rc = ber_printf( ber, "{it{istoN}N}", ++ld->ld_msgid, LDAP_REQ_BIND,
184             ld->ld_version, dn, LDAP_AUTH_KRBV42, cred, credlen );
185
186
187         LDAP_FREE( cred );
188
189         if ( rc == -1 ) {
190                 ber_free( ber, 1 );
191                 ld->ld_errno = LDAP_ENCODING_ERROR;
192                 return( -1 );
193         }
194
195         /* send the message */
196         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
197 }
198
199 /* synchronous bind to DSA using kerberos */
200 int
201 ldap_kerberos_bind2_s( LDAP *ld, LDAP_CONST char *dn )
202 {
203         int             msgid;
204         LDAPMessage     *res;
205
206 #ifdef NEW_LOGGING
207         LDAP_LOG ( OPERATION, ENTRY, "ldap_kerberos_bind2_s\n" , 0, 0, 0);
208 #else
209         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2_s\n", 0, 0, 0 );
210 #endif
211
212         /* initiate the bind */
213         if ( (msgid = ldap_kerberos_bind2( ld, dn )) == -1 )
214                 return( ld->ld_errno );
215
216         /* wait for a result */
217         if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
218             == -1 ) {
219                 return( ld->ld_errno ); /* ldap_result sets ld_errno */
220         }
221
222         return( ldap_result2error( ld, res, 1 ) );
223 }
224
225 /* synchronous bind to ldap and DSA using kerberos */
226 int
227 ldap_kerberos_bind_s( LDAP *ld, LDAP_CONST char *dn )
228 {
229         int     err;
230
231 #ifdef NEW_LOGGING
232         LDAP_LOG ( OPERATION, ENTRY, "ldap_kerberos_bind_s\n", 0, 0, 0 );
233 #else
234         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind_s\n", 0, 0, 0 );
235 #endif
236
237         if ( (err = ldap_kerberos_bind1_s( ld, dn )) != LDAP_SUCCESS )
238                 return( err );
239
240         return( ldap_kerberos_bind2_s( ld, dn ) );
241 }
242
243
244 #ifndef AUTHMAN
245 /*
246  * ldap_get_kerberosv4_credentials - obtain kerberos v4 credentials for ldap.
247  * The dn of the entry to which to bind is supplied.  It's assumed the
248  * user already has a tgt.
249  */
250
251 char *
252 ldap_get_kerberosv4_credentials(
253         LDAP *ld,
254         LDAP_CONST char *who,
255         LDAP_CONST char *service,
256         ber_len_t *len )
257 {
258         KTEXT_ST        ktxt;
259         int             err;
260         char            realm[REALM_SZ], *cred, *krbinstance;
261
262 #ifdef NEW_LOGGING
263         LDAP_LOG ( OPERATION, ENTRY, "ldap_get_kerberosv4_credentials\n", 0, 0, 0 );
264 #else
265         Debug( LDAP_DEBUG_TRACE, "ldap_get_kerberosv4_credentials\n", 0, 0, 0 );
266 #endif
267
268         if ( (err = krb_get_tf_realm( tkt_string(), realm )) != KSUCCESS ) {
269 #ifdef NEW_LOGGING
270                 LDAP_LOG ( OPERATION, ERR, 
271                         "ldap_get_kerberosv4_credentials: krb_get_tf_realm failed: %s\n",
272                         krb_err_txt[err], 0, 0 );
273 #else
274                 Debug( LDAP_DEBUG_ANY, "ldap_get_kerberosv4_credentials: "
275                         "krb_get_tf_realm failed: %s\n", krb_err_txt[err], 0, 0 );
276 #endif
277                 ld->ld_errno = LDAP_AUTH_UNKNOWN;
278                 return( NULL );
279         }
280
281         if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
282                 /* not connected yet */
283                 int rc = ldap_open_defconn( ld );
284
285                 if( rc < 0 ) return NULL;
286         }
287
288         krbinstance = ld->ld_defconn->lconn_krbinstance;
289
290         if ( (err = krb_mk_req( &ktxt, service, krbinstance, realm, 0 ))
291             != KSUCCESS )
292         {
293 #ifdef NEW_LOGGING
294                 LDAP_LOG ( OPERATION, ERR, 
295                         "ldap_get_kerberosv4_credentials: krb_mk_req failed: %s\n",
296                         krb_err_txt[err], 0, 0 );
297 #else
298                 Debug( LDAP_DEBUG_ANY, "ldap_get_kerberosv4_credentials: "
299                         "krb_mk_req failed (%s)\n", krb_err_txt[err], 0, 0 );
300 #endif
301                 ld->ld_errno = LDAP_AUTH_UNKNOWN;
302                 return( NULL );
303         }
304
305         if ( ( cred = LDAP_MALLOC( ktxt.length )) == NULL ) {
306                 ld->ld_errno = LDAP_NO_MEMORY;
307                 return( NULL );
308         }
309
310         *len = ktxt.length;
311         AC_MEMCPY( cred, ktxt.dat, ktxt.length );
312
313         return( cred );
314 }
315
316 #endif /* !AUTHMAN */
317 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */