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