xref: /onnv-gate/usr/src/lib/libldap4/common/kbind.c (revision 3857:21b9b714e4ab)
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