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