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