]> git.sur5r.net Git - openldap/blob - libraries/libldap/kbind.c
Howard convinced me that this version is slightly better.
[openldap] / libraries / libldap / kbind.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 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 HAVE_KERBEROS
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 HAVE_KERBEROS
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 /*
50  * ldap_kerberos_bind1 - initiate a bind to the ldap server using
51  * kerberos authentication.  The dn is supplied.  It is assumed the user
52  * already has a valid ticket granting ticket.  The msgid of the
53  * request is returned on success (suitable for passing to ldap_result()),
54  * -1 is returned if there's trouble.
55  *
56  * Example:
57  *      ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" )
58  */
59 int
60 ldap_kerberos_bind1( LDAP *ld, LDAP_CONST char *dn )
61 {
62         BerElement      *ber;
63         char            *cred;
64         int             rc;
65         ber_len_t credlen;
66 #ifdef STR_TRANSLATION
67         int             str_translation_on;
68 #endif /* STR_TRANSLATION */
69
70         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1\n", 0, 0, 0 );
71
72         if ( dn == NULL )
73                 dn = "";
74
75         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "ldapserver",
76             &credlen )) == NULL ) {
77                 return( -1 );   /* ld_errno should already be set */
78         }
79
80         /* create a message to send */
81         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
82                 LDAP_FREE( cred );
83                 return( -1 );
84         }
85
86 #ifdef STR_TRANSLATION
87         if (( str_translation_on = (( ber->ber_options &
88             LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
89                 ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
90         }
91 #endif /* STR_TRANSLATION */
92
93         /* fill it in */
94         rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
95             ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen );
96
97 #ifdef STR_TRANSLATION
98         if ( str_translation_on ) {     /* restore translation */
99                 ber->ber_options |= LBER_TRANSLATE_STRINGS;
100         }
101 #endif /* STR_TRANSLATION */
102
103         if ( rc == -1 ) {
104                 LDAP_FREE( cred );
105                 ber_free( ber, 1 );
106                 ld->ld_errno = LDAP_ENCODING_ERROR;
107                 return( -1 );
108         }
109
110         LDAP_FREE( cred );
111
112 #ifndef LDAP_NOCACHE
113         if ( ld->ld_cache != NULL ) {
114                 ldap_flush_cache( ld );
115         }
116 #endif /* !LDAP_NOCACHE */
117
118         /* send the message */
119         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
120 }
121
122 int
123 ldap_kerberos_bind1_s( LDAP *ld, LDAP_CONST char *dn )
124 {
125         int             msgid;
126         LDAPMessage     *res;
127
128         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1_s\n", 0, 0, 0 );
129
130         /* initiate the bind */
131         if ( (msgid = ldap_kerberos_bind1( ld, dn )) == -1 )
132                 return( ld->ld_errno );
133
134         /* wait for a result */
135         if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
136             == -1 ) {
137                 return( ld->ld_errno ); /* ldap_result sets ld_errno */
138         }
139
140         return( ldap_result2error( ld, res, 1 ) );
141 }
142
143 /*
144  * ldap_kerberos_bind2 - initiate a bind to the X.500 server using
145  * kerberos authentication.  The dn is supplied.  It is assumed the user
146  * already has a valid ticket granting ticket.  The msgid of the
147  * request is returned on success (suitable for passing to ldap_result()),
148  * -1 is returned if there's trouble.
149  *
150  * Example:
151  *      ldap_kerberos_bind2( ld, "cn=manager, o=university of michigan, c=us" )
152  */
153 int
154 ldap_kerberos_bind2( LDAP *ld, LDAP_CONST char *dn )
155 {
156         BerElement      *ber;
157         char            *cred;
158         int             rc;
159         ber_len_t credlen;
160 #ifdef STR_TRANSLATION
161         int             str_translation_on;
162 #endif /* STR_TRANSLATION */
163
164         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2\n", 0, 0, 0 );
165
166         if ( dn == NULL )
167                 dn = "";
168
169         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "x500dsa", &credlen ))
170             == NULL ) {
171                 return( -1 );   /* ld_errno should already be set */
172         }
173
174         /* create a message to send */
175         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
176                 LDAP_FREE( cred );
177                 return( -1 );
178         }
179
180 #ifdef STR_TRANSLATION
181         if (( str_translation_on = (( ber->ber_options &
182             LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
183                 ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
184         }
185 #endif /* STR_TRANSLATION */
186
187         /* fill it in */
188         rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
189             ld->ld_version, dn, LDAP_AUTH_KRBV42, cred, credlen );
190
191
192 #ifdef STR_TRANSLATION
193         if ( str_translation_on ) {     /* restore translation */
194                 ber->ber_options |= LBER_TRANSLATE_STRINGS;
195         }
196 #endif /* STR_TRANSLATION */
197
198         LDAP_FREE( cred );
199
200         if ( rc == -1 ) {
201                 ber_free( ber, 1 );
202                 ld->ld_errno = LDAP_ENCODING_ERROR;
203                 return( -1 );
204         }
205
206         /* send the message */
207         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
208 }
209
210 /* synchronous bind to DSA using kerberos */
211 int
212 ldap_kerberos_bind2_s( LDAP *ld, LDAP_CONST char *dn )
213 {
214         int             msgid;
215         LDAPMessage     *res;
216
217         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2_s\n", 0, 0, 0 );
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, ld->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         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind_s\n", 0, 0, 0 );
239
240         if ( (err = ldap_kerberos_bind1_s( ld, dn )) != LDAP_SUCCESS )
241                 return( err );
242
243         return( ldap_kerberos_bind2_s( ld, dn ) );
244 }
245
246
247 #ifndef AUTHMAN
248 /*
249  * ldap_get_kerberosv4_credentials - obtain kerberos v4 credentials for ldap.
250  * The dn of the entry to which to bind is supplied.  It's assumed the
251  * user already has a tgt.
252  */
253
254 char *
255 ldap_get_kerberosv4_credentials(
256         LDAP *ld,
257         LDAP_CONST char *who,
258         LDAP_CONST char *service,
259         ber_len_t *len )
260 {
261         KTEXT_ST        ktxt;
262         int             err;
263         char            realm[REALM_SZ], *cred, *krbinstance;
264
265         Debug( LDAP_DEBUG_TRACE, "ldap_get_kerberosv4_credentials\n", 0, 0, 0 );
266
267         if ( (err = krb_get_tf_realm( tkt_string(), realm )) != KSUCCESS ) {
268 #ifdef LDAP_LIBUI
269                 fprintf( stderr, "krb_get_tf_realm failed (%s)\n",
270                     krb_err_txt[err] );
271 #endif /* LDAP_LIBUI */
272                 ld->ld_errno = LDAP_INVALID_CREDENTIALS;
273                 return( NULL );
274         }
275
276         if( ! ber_pvt_sb_in_use( &ld->ld_sb ) ) {
277                 /* not connected yet */
278                 int rc = ldap_open_defconn( ld );
279
280                 if( rc < 0 ) return NULL;
281         }
282
283         krbinstance = ld->ld_defconn->lconn_krbinstance;
284
285         if ( (err = krb_mk_req( &ktxt, service, krbinstance, realm, 0 ))
286             != KSUCCESS ) {
287 #ifdef LDAP_LIBUI
288                 fprintf( stderr, "krb_mk_req failed (%s)\n", krb_err_txt[err] );
289 #endif /* LDAP_LIBUI */
290                 ld->ld_errno = LDAP_INVALID_CREDENTIALS;
291                 return( NULL );
292         }
293
294         if ( ( cred = LDAP_MALLOC( ktxt.length )) == NULL ) {
295                 ld->ld_errno = LDAP_NO_MEMORY;
296                 return( NULL );
297         }
298
299         *len = ktxt.length;
300         memcpy( cred, ktxt.dat, ktxt.length );
301
302         return( cred );
303 }
304
305 #endif /* !AUTHMAN */
306 #endif /* HAVE_KERBEROS */