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