]> git.sur5r.net Git - openldap/blob - libraries/libldap/kbind.c
Update comments to reflect RFC2251 specs.
[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, credlen;
64 #ifdef STR_TRANSLATION
65         int             str_translation_on;
66 #endif /* STR_TRANSLATION */
67
68         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1\n", 0, 0, 0 );
69
70         if ( dn == NULL )
71                 dn = "";
72
73         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "ldapserver",
74             &credlen )) == NULL ) {
75                 return( -1 );   /* ld_errno should already be set */
76         }
77
78         /* create a message to send */
79         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
80                 LDAP_FREE( cred );
81                 return( -1 );
82         }
83
84 #ifdef STR_TRANSLATION
85         if (( str_translation_on = (( ber->ber_options &
86             LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
87                 ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
88         }
89 #endif /* STR_TRANSLATION */
90
91         /* fill it in */
92         rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
93             ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen );
94
95 #ifdef STR_TRANSLATION
96         if ( str_translation_on ) {     /* restore translation */
97                 ber->ber_options |= LBER_TRANSLATE_STRINGS;
98         }
99 #endif /* STR_TRANSLATION */
100
101         if ( rc == -1 ) {
102                 LDAP_FREE( cred );
103                 ber_free( ber, 1 );
104                 ld->ld_errno = LDAP_ENCODING_ERROR;
105                 return( -1 );
106         }
107
108         LDAP_FREE( cred );
109
110 #ifndef LDAP_NOCACHE
111         if ( ld->ld_cache != NULL ) {
112                 ldap_flush_cache( ld );
113         }
114 #endif /* !LDAP_NOCACHE */
115
116         /* send the message */
117         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
118 }
119
120 int
121 ldap_kerberos_bind1_s( LDAP *ld, LDAP_CONST char *dn )
122 {
123         int             msgid;
124         LDAPMessage     *res;
125
126         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1_s\n", 0, 0, 0 );
127
128         /* initiate the bind */
129         if ( (msgid = ldap_kerberos_bind1( ld, dn )) == -1 )
130                 return( ld->ld_errno );
131
132         /* wait for a result */
133         if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
134             == -1 ) {
135                 return( ld->ld_errno ); /* ldap_result sets ld_errno */
136         }
137
138         return( ldap_result2error( ld, res, 1 ) );
139 }
140
141 /*
142  * ldap_kerberos_bind2 - initiate a bind to the X.500 server using
143  * kerberos authentication.  The dn is supplied.  It is assumed the user
144  * already has a valid ticket granting ticket.  The msgid of the
145  * request is returned on success (suitable for passing to ldap_result()),
146  * -1 is returned if there's trouble.
147  *
148  * Example:
149  *      ldap_kerberos_bind2( ld, "cn=manager, o=university of michigan, c=us" )
150  */
151 int
152 ldap_kerberos_bind2( LDAP *ld, LDAP_CONST char *dn )
153 {
154         BerElement      *ber;
155         char            *cred;
156         int             rc, credlen;
157 #ifdef STR_TRANSLATION
158         int             str_translation_on;
159 #endif /* STR_TRANSLATION */
160
161         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2\n", 0, 0, 0 );
162
163         if ( dn == NULL )
164                 dn = "";
165
166         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "x500dsa", &credlen ))
167             == NULL ) {
168                 return( -1 );   /* ld_errno should already be set */
169         }
170
171         /* create a message to send */
172         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
173                 LDAP_FREE( cred );
174                 return( -1 );
175         }
176
177 #ifdef STR_TRANSLATION
178         if (( str_translation_on = (( ber->ber_options &
179             LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
180                 ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
181         }
182 #endif /* STR_TRANSLATION */
183
184         /* fill it in */
185         rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
186             ld->ld_version, dn, LDAP_AUTH_KRBV42, cred, credlen );
187
188
189 #ifdef STR_TRANSLATION
190         if ( str_translation_on ) {     /* restore translation */
191                 ber->ber_options |= LBER_TRANSLATE_STRINGS;
192         }
193 #endif /* STR_TRANSLATION */
194
195         LDAP_FREE( cred );
196
197         if ( rc == -1 ) {
198                 ber_free( ber, 1 );
199                 ld->ld_errno = LDAP_ENCODING_ERROR;
200                 return( -1 );
201         }
202
203         /* send the message */
204         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
205 }
206
207 /* synchronous bind to DSA using kerberos */
208 int
209 ldap_kerberos_bind2_s( LDAP *ld, LDAP_CONST char *dn )
210 {
211         int             msgid;
212         LDAPMessage     *res;
213
214         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2_s\n", 0, 0, 0 );
215
216         /* initiate the bind */
217         if ( (msgid = ldap_kerberos_bind2( ld, dn )) == -1 )
218                 return( ld->ld_errno );
219
220         /* wait for a result */
221         if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
222             == -1 ) {
223                 return( ld->ld_errno ); /* ldap_result sets ld_errno */
224         }
225
226         return( ldap_result2error( ld, res, 1 ) );
227 }
228
229 /* synchronous bind to ldap and DSA using kerberos */
230 int
231 ldap_kerberos_bind_s( LDAP *ld, LDAP_CONST char *dn )
232 {
233         int     err;
234
235         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind_s\n", 0, 0, 0 );
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         int *len )
257 {
258         KTEXT_ST        ktxt;
259         int             err;
260         char            realm[REALM_SZ], *cred, *krbinstance;
261
262         Debug( LDAP_DEBUG_TRACE, "ldap_get_kerberosv4_credentials\n", 0, 0, 0 );
263
264         if ( (err = krb_get_tf_realm( tkt_string(), realm )) != KSUCCESS ) {
265 #ifdef LDAP_LIBUI
266                 fprintf( stderr, "krb_get_tf_realm failed (%s)\n",
267                     krb_err_txt[err] );
268 #endif /* LDAP_LIBUI */
269                 ld->ld_errno = LDAP_INVALID_CREDENTIALS;
270                 return( NULL );
271         }
272
273         krbinstance = ld->ld_defconn->lconn_krbinstance;
274
275         if ( (err = krb_mk_req( &ktxt, service, krbinstance, realm, 0 ))
276             != KSUCCESS ) {
277 #ifdef LDAP_LIBUI
278                 fprintf( stderr, "krb_mk_req failed (%s)\n", krb_err_txt[err] );
279 #endif /* LDAP_LIBUI */
280                 ld->ld_errno = LDAP_INVALID_CREDENTIALS;
281                 return( NULL );
282         }
283
284         if ( ( cred = LDAP_MALLOC( ktxt.length )) == NULL ) {
285                 ld->ld_errno = LDAP_NO_MEMORY;
286                 return( NULL );
287         }
288
289         *len = ktxt.length;
290         memcpy( cred, ktxt.dat, ktxt.length );
291
292         return( cred );
293 }
294
295 #endif /* !AUTHMAN */
296 #endif /* HAVE_KERBEROS */