]> git.sur5r.net Git - openldap/blob - libraries/libldap/kbind.c
Add descriptive comment at top.
[openldap] / libraries / libldap / kbind.c
1 /*
2  *  Copyright (c) 1993 Regents of the University of Michigan.
3  *  All rights reserved.
4  *
5  *  kbind.c
6  */
7
8 #include "portable.h"
9
10 #ifndef lint 
11 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
12 #endif
13
14 #ifdef HAVE_KERBEROS
15
16 #include <stdio.h>
17 #include <stdlib.h>
18
19 #include <ac/krb.h>
20 #include <ac/socket.h>
21 #include <ac/string.h>
22 #include <ac/time.h>
23
24 #include "ldap-int.h"
25
26
27 /*
28  * ldap_kerberos_bind1 - initiate a bind to the ldap server using
29  * kerberos authentication.  The dn is supplied.  It is assumed the user
30  * already has a valid ticket granting ticket.  The msgid of the
31  * request is returned on success (suitable for passing to ldap_result()),
32  * -1 is returned if there's trouble.
33  *
34  * Example:
35  *      ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" )
36  */
37 int
38 ldap_kerberos_bind1( LDAP *ld, char *dn )
39 {
40         BerElement      *ber;
41         char            *cred;
42         int             rc, credlen;
43         char            *ldap_get_kerberosv4_credentials();
44 #ifdef STR_TRANSLATION
45         int             str_translation_on;
46 #endif /* STR_TRANSLATION */
47
48         /*
49          * The bind request looks like this:
50          *      BindRequest ::= SEQUENCE {
51          *              version         INTEGER,
52          *              name            DistinguishedName,
53          *              authentication  CHOICE {
54          *                      krbv42ldap      [1] OCTET STRING
55          *                      krbv42dsa       [2] OCTET STRING
56          *              }
57          *      }
58          * all wrapped up in an LDAPMessage sequence.
59          */
60
61         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1\n", 0, 0, 0 );
62
63         if ( dn == NULL )
64                 dn = "";
65
66         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "ldapserver",
67             &credlen )) == NULL ) {
68                 return( -1 );   /* ld_errno should already be set */
69         }
70
71         /* create a message to send */
72         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
73                 free( cred );
74                 return( -1 );
75         }
76
77 #ifdef STR_TRANSLATION
78         if (( str_translation_on = (( ber->ber_options &
79             LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
80                 ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
81         }
82 #endif /* STR_TRANSLATION */
83
84         /* fill it in */
85         rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
86             ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen );
87
88 #ifdef STR_TRANSLATION
89         if ( str_translation_on ) {     /* restore translation */
90                 ber->ber_options |= LBER_TRANSLATE_STRINGS;
91         }
92 #endif /* STR_TRANSLATION */
93
94         if ( rc == -1 ) {
95                 free( cred );
96                 ber_free( ber, 1 );
97                 ld->ld_errno = LDAP_ENCODING_ERROR;
98                 return( -1 );
99         }
100
101         free( cred );
102
103 #ifndef LDAP_NOCACHE
104         if ( ld->ld_cache != NULL ) {
105                 ldap_flush_cache( ld );
106         }
107 #endif /* !LDAP_NOCACHE */
108
109         /* send the message */
110         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
111 }
112
113 int
114 ldap_kerberos_bind1_s( LDAP *ld, 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, ld->ld_msgid, 1, (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, char *dn )
146 {
147         BerElement      *ber;
148         char            *cred;
149         int             rc, credlen;
150         char            *ldap_get_kerberosv4_credentials();
151 #ifdef STR_TRANSLATION
152         int             str_translation_on;
153 #endif /* STR_TRANSLATION */
154
155         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2\n", 0, 0, 0 );
156
157         if ( dn == NULL )
158                 dn = "";
159
160         if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "x500dsa", &credlen ))
161             == NULL ) {
162                 return( -1 );   /* ld_errno should already be set */
163         }
164
165         /* create a message to send */
166         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
167                 free( cred );
168                 return( -1 );
169         }
170
171 #ifdef STR_TRANSLATION
172         if (( str_translation_on = (( ber->ber_options &
173             LBER_TRANSLATE_STRINGS ) != 0 ))) { /* turn translation off */
174                 ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
175         }
176 #endif /* STR_TRANSLATION */
177
178         /* fill it in */
179         rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
180             ld->ld_version, dn, LDAP_AUTH_KRBV42, cred, credlen );
181
182
183 #ifdef STR_TRANSLATION
184         if ( str_translation_on ) {     /* restore translation */
185                 ber->ber_options |= LBER_TRANSLATE_STRINGS;
186         }
187 #endif /* STR_TRANSLATION */
188
189         free( cred );
190
191         if ( rc == -1 ) {
192                 ber_free( ber, 1 );
193                 ld->ld_errno = LDAP_ENCODING_ERROR;
194                 return( -1 );
195         }
196
197         /* send the message */
198         return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
199 }
200
201 /* synchronous bind to DSA using kerberos */
202 int
203 ldap_kerberos_bind2_s( LDAP *ld, char *dn )
204 {
205         int             msgid;
206         LDAPMessage     *res;
207
208         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2_s\n", 0, 0, 0 );
209
210         /* initiate the bind */
211         if ( (msgid = ldap_kerberos_bind2( ld, dn )) == -1 )
212                 return( ld->ld_errno );
213
214         /* wait for a result */
215         if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
216             == -1 ) {
217                 return( ld->ld_errno ); /* ldap_result sets ld_errno */
218         }
219
220         return( ldap_result2error( ld, res, 1 ) );
221 }
222
223 /* synchronous bind to ldap and DSA using kerberos */
224 int
225 ldap_kerberos_bind_s( LDAP *ld, char *dn )
226 {
227         int     err;
228
229         Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind_s\n", 0, 0, 0 );
230
231         if ( (err = ldap_kerberos_bind1_s( ld, dn )) != LDAP_SUCCESS )
232                 return( err );
233
234         return( ldap_kerberos_bind2_s( ld, dn ) );
235 }
236
237
238 #ifndef AUTHMAN
239 /*
240  * ldap_get_kerberosv4_credentials - obtain kerberos v4 credentials for ldap.
241  * The dn of the entry to which to bind is supplied.  It's assumed the
242  * user already has a tgt.
243  */
244
245 char *
246 ldap_get_kerberosv4_credentials( LDAP *ld, char *who, char *service, int *len )
247 {
248         KTEXT_ST        ktxt;
249         int             err;
250         char            realm[REALM_SZ], *cred, *krbinstance;
251
252         Debug( LDAP_DEBUG_TRACE, "ldap_get_kerberosv4_credentials\n", 0, 0, 0 );
253
254         if ( (err = krb_get_tf_realm( tkt_string(), realm )) != KSUCCESS ) {
255 #ifdef LDAP_LIBUI
256                 fprintf( stderr, "krb_get_tf_realm failed (%s)\n",
257                     krb_err_txt[err] );
258 #endif /* LDAP_LIBUI */
259                 ld->ld_errno = LDAP_INVALID_CREDENTIALS;
260                 return( NULL );
261         }
262
263 #ifdef LDAP_REFERRALS
264         krbinstance = ld->ld_defconn->lconn_krbinstance;
265 #else /* LDAP_REFERRALS */
266         krbinstance = ld->ld_host;
267 #endif /* LDAP_REFERRALS */
268
269         if ( (err = krb_mk_req( &ktxt, service, krbinstance, realm, 0 ))
270             != KSUCCESS ) {
271 #ifdef LDAP_LIBUI
272                 fprintf( stderr, "krb_mk_req failed (%s)\n", krb_err_txt[err] );
273 #endif /* LDAP_LIBUI */
274                 ld->ld_errno = LDAP_INVALID_CREDENTIALS;
275                 return( NULL );
276         }
277
278         if ( ( cred = malloc( ktxt.length )) == NULL ) {
279                 ld->ld_errno = LDAP_NO_MEMORY;
280                 return( NULL );
281         }
282
283         *len = ktxt.length;
284         memcpy( cred, ktxt.dat, ktxt.length );
285
286         return( cred );
287 }
288
289 #endif /* !AUTHMAN */
290 #endif /* HAVE_KERBEROS */