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