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