xref: /onnv-gate/usr/src/lib/libldap4/common/kbind.c (revision 3857:21b9b714e4ab)
10Sstevel@tonic-gate /*
2*3857Sstevel  * Portions Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
3*3857Sstevel  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
70Sstevel@tonic-gate 
80Sstevel@tonic-gate /*
90Sstevel@tonic-gate  *  Copyright (c) 1993 Regents of the University of Michigan.
100Sstevel@tonic-gate  *  All rights reserved.
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  *  kbind.c
130Sstevel@tonic-gate  */
140Sstevel@tonic-gate 
150Sstevel@tonic-gate #ifndef lint
160Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
170Sstevel@tonic-gate #endif
180Sstevel@tonic-gate 
190Sstevel@tonic-gate #ifdef KERBEROS
200Sstevel@tonic-gate 
210Sstevel@tonic-gate #include <stdio.h>
220Sstevel@tonic-gate #include <string.h>
230Sstevel@tonic-gate 
240Sstevel@tonic-gate #ifdef MACOS
250Sstevel@tonic-gate #include <stdlib.h>
260Sstevel@tonic-gate #include "macos.h"
270Sstevel@tonic-gate #else /* MACOS */
280Sstevel@tonic-gate #ifdef DOS
290Sstevel@tonic-gate #include "msdos.h"
300Sstevel@tonic-gate #endif /* DOS */
310Sstevel@tonic-gate #include <krb.h>
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #if !defined(DOS) && !defined( _WIN32 )
340Sstevel@tonic-gate #include <sys/types.h>
350Sstevel@tonic-gate #endif /* !DOS && !_WIN32 */
360Sstevel@tonic-gate #include <sys/time.h>
370Sstevel@tonic-gate #include <sys/socket.h>
380Sstevel@tonic-gate #endif /* MACOS */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include "lber.h"
410Sstevel@tonic-gate #include "ldap.h"
420Sstevel@tonic-gate #include "ldap-private.h"
430Sstevel@tonic-gate #include "ldap-int.h"
440Sstevel@tonic-gate 
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate  * ldap_kerberos_bind1 - initiate a bind to the ldap server using
490Sstevel@tonic-gate  * kerberos authentication.  The dn is supplied.  It is assumed the user
500Sstevel@tonic-gate  * already has a valid ticket granting ticket.  The msgid of the
510Sstevel@tonic-gate  * request is returned on success (suitable for passing to ldap_result()),
520Sstevel@tonic-gate  * -1 is returned if there's trouble.
530Sstevel@tonic-gate  *
540Sstevel@tonic-gate  * Example:
550Sstevel@tonic-gate  *	ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" )
560Sstevel@tonic-gate  */
570Sstevel@tonic-gate int
ldap_kerberos_bind1(LDAP * ld,char * dn)580Sstevel@tonic-gate ldap_kerberos_bind1( LDAP *ld, char *dn )
590Sstevel@tonic-gate {
600Sstevel@tonic-gate 	BerElement	*ber;
610Sstevel@tonic-gate 	char		*cred;
620Sstevel@tonic-gate 	int		rc, credlen;
630Sstevel@tonic-gate 	char		*get_kerberosv4_credentials();
640Sstevel@tonic-gate #ifdef STR_TRANSLATION
650Sstevel@tonic-gate 	int		str_translation_on;
660Sstevel@tonic-gate #endif /* STR_TRANSLATION */
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 	/*
690Sstevel@tonic-gate 	 * The bind request looks like this:
700Sstevel@tonic-gate 	 *	BindRequest ::= SEQUENCE {
710Sstevel@tonic-gate 	 *		version		INTEGER,
720Sstevel@tonic-gate 	 *		name		DistinguishedName,
730Sstevel@tonic-gate 	 *		authentication	CHOICE {
740Sstevel@tonic-gate 	 *			krbv42ldap	[1] OCTET STRING
750Sstevel@tonic-gate 	 *			krbv42dsa	[2] OCTET STRING
760Sstevel@tonic-gate 	 *		}
770Sstevel@tonic-gate 	 *	}
780Sstevel@tonic-gate 	 * all wrapped up in an LDAPMessage sequence.
790Sstevel@tonic-gate 	 */
800Sstevel@tonic-gate 
810Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
820Sstevel@tonic-gate 	int rv;
830Sstevel@tonic-gate 
840Sstevel@tonic-gate         LOCK_LDAP(ld);
850Sstevel@tonic-gate #endif
860Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 186, "ldap_kerberos_bind1\n"), 0, 0, 0 );
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 	if ( dn == NULL )
890Sstevel@tonic-gate 		dn = "";
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	if ( (cred = get_kerberosv4_credentials( ld, dn, "ldapserver",
920Sstevel@tonic-gate 	    &credlen )) == NULL ) {
930Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
940Sstevel@tonic-gate 		UNLOCK_LDAP(ld);
950Sstevel@tonic-gate #endif
960Sstevel@tonic-gate 		return( -1 );	/* ld_errno should already be set */
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	/* create a message to send */
1000Sstevel@tonic-gate 	if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
1010Sstevel@tonic-gate 		free( cred );
1020Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
1030Sstevel@tonic-gate 		UNLOCK_LDAP(ld);
1040Sstevel@tonic-gate #endif
1050Sstevel@tonic-gate 		return( -1 );
1060Sstevel@tonic-gate 	}
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate #ifdef STR_TRANSLATION
1090Sstevel@tonic-gate 	if (( str_translation_on = (( ber->ber_options &
1100Sstevel@tonic-gate 	    LBER_TRANSLATE_STRINGS ) != 0 ))) {	/* turn translation off */
1110Sstevel@tonic-gate 		ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
1120Sstevel@tonic-gate 	}
1130Sstevel@tonic-gate #endif /* STR_TRANSLATION */
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	/* fill it in */
1160Sstevel@tonic-gate 	rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
1170Sstevel@tonic-gate 	    ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen );
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate #ifdef STR_TRANSLATION
1200Sstevel@tonic-gate 	if ( str_translation_on ) {	/* restore translation */
1210Sstevel@tonic-gate 		ber->ber_options |= LBER_TRANSLATE_STRINGS;
1220Sstevel@tonic-gate 	}
1230Sstevel@tonic-gate #endif /* STR_TRANSLATION */
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	if ( rc == -1 ) {
1260Sstevel@tonic-gate 		free( cred );
1270Sstevel@tonic-gate 		ber_free( ber, 1 );
1280Sstevel@tonic-gate 		ld->ld_errno = LDAP_ENCODING_ERROR;
1290Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
1300Sstevel@tonic-gate 		UNLOCK_LDAP(ld);
1310Sstevel@tonic-gate #endif
1320Sstevel@tonic-gate 		return( -1 );
1330Sstevel@tonic-gate 	}
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	free( cred );
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate #ifndef NO_CACHE
1380Sstevel@tonic-gate 	if ( ld->ld_cache != NULL ) {
1390Sstevel@tonic-gate 		ldap_flush_cache( ld );
1400Sstevel@tonic-gate 	}
1410Sstevel@tonic-gate #endif /* !NO_CACHE */
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	/* send the message */
1440Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
1450Sstevel@tonic-gate 	rv = send_initial_request( ld, LDAP_REQ_BIND, dn, ber );
1460Sstevel@tonic-gate         UNLOCK_LDAP(ld);
1470Sstevel@tonic-gate 	return ( rv );
1480Sstevel@tonic-gate #else
1490Sstevel@tonic-gate 	return ( send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
1500Sstevel@tonic-gate #endif
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate int
ldap_kerberos_bind1_s(LDAP * ld,char * dn)1540Sstevel@tonic-gate ldap_kerberos_bind1_s( LDAP *ld, char *dn )
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate 	int		msgid;
1570Sstevel@tonic-gate 	LDAPMessage	*res;
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 187, "ldap_kerberos_bind1_s\n"), 0, 0, 0 );
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	/* initiate the bind */
1620Sstevel@tonic-gate 	if ( (msgid = ldap_kerberos_bind1( ld, dn )) == -1 )
1630Sstevel@tonic-gate 		return( ld->ld_errno );
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	/* wait for a result */
1660Sstevel@tonic-gate 	if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
1670Sstevel@tonic-gate 	    == -1 ) {
1680Sstevel@tonic-gate 		return( ld->ld_errno );	/* ldap_result sets ld_errno */
1690Sstevel@tonic-gate 	}
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	return( ldap_result2error( ld, res, 1 ) );
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate /*
1750Sstevel@tonic-gate  * ldap_kerberos_bind2 - initiate a bind to the X.500 server using
1760Sstevel@tonic-gate  * kerberos authentication.  The dn is supplied.  It is assumed the user
1770Sstevel@tonic-gate  * already has a valid ticket granting ticket.  The msgid of the
1780Sstevel@tonic-gate  * request is returned on success (suitable for passing to ldap_result()),
1790Sstevel@tonic-gate  * -1 is returned if there's trouble.
1800Sstevel@tonic-gate  *
1810Sstevel@tonic-gate  * Example:
1820Sstevel@tonic-gate  *	ldap_kerberos_bind2( ld, "cn=manager, o=university of michigan, c=us" )
1830Sstevel@tonic-gate  */
1840Sstevel@tonic-gate int
ldap_kerberos_bind2(LDAP * ld,char * dn)1850Sstevel@tonic-gate ldap_kerberos_bind2( LDAP *ld, char *dn )
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	BerElement	*ber;
1880Sstevel@tonic-gate 	char		*cred;
1890Sstevel@tonic-gate 	int		rc, credlen;
1900Sstevel@tonic-gate 	char		*get_kerberosv4_credentials();
1910Sstevel@tonic-gate #ifdef STR_TRANSLATION
1920Sstevel@tonic-gate 	int		str_translation_on;
1930Sstevel@tonic-gate #endif /* STR_TRANSLATION */
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
1960Sstevel@tonic-gate 	int rv;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate         LOCK_LDAP(ld);
1990Sstevel@tonic-gate #endif
2000Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 188, "ldap_kerberos_bind2\n"), 0, 0, 0 );
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	if ( dn == NULL )
2030Sstevel@tonic-gate 		dn = "";
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if ( (cred = get_kerberosv4_credentials( ld, dn, "x500dsa", &credlen ))
2060Sstevel@tonic-gate 	    == NULL ) {
2070Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
2080Sstevel@tonic-gate 		UNLOCK_LDAP(ld);
2090Sstevel@tonic-gate #endif
2100Sstevel@tonic-gate 		return( -1 );	/* ld_errno should already be set */
2110Sstevel@tonic-gate 	}
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	/* create a message to send */
2140Sstevel@tonic-gate 	if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
2150Sstevel@tonic-gate 		free( cred );
2160Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
2170Sstevel@tonic-gate 		UNLOCK_LDAP(ld);
2180Sstevel@tonic-gate #endif
2190Sstevel@tonic-gate 		return( -1 );
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate #ifdef STR_TRANSLATION
2230Sstevel@tonic-gate 	if (( str_translation_on = (( ber->ber_options &
2240Sstevel@tonic-gate 	    LBER_TRANSLATE_STRINGS ) != 0 ))) {	/* turn translation off */
2250Sstevel@tonic-gate 		ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate #endif /* STR_TRANSLATION */
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	/* fill it in */
2300Sstevel@tonic-gate 	rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
2310Sstevel@tonic-gate 	    ld->ld_version, dn, LDAP_AUTH_KRBV42, cred, credlen );
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate #ifdef STR_TRANSLATION
2350Sstevel@tonic-gate 	if ( str_translation_on ) {	/* restore translation */
2360Sstevel@tonic-gate 		ber->ber_options |= LBER_TRANSLATE_STRINGS;
2370Sstevel@tonic-gate 	}
2380Sstevel@tonic-gate #endif /* STR_TRANSLATION */
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	free( cred );
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	if ( rc == -1 ) {
2430Sstevel@tonic-gate 		ber_free( ber, 1 );
2440Sstevel@tonic-gate 		ld->ld_errno = LDAP_ENCODING_ERROR;
2450Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
2460Sstevel@tonic-gate 		UNLOCK_LDAP(ld);
2470Sstevel@tonic-gate #endif
2480Sstevel@tonic-gate 		return( -1 );
2490Sstevel@tonic-gate 	}
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	/* send the message */
2520Sstevel@tonic-gate #if defined( SUN ) && defined( _REENTRANT )
2530Sstevel@tonic-gate 	rv = send_initial_request( ld, LDAP_REQ_BIND, dn, ber );
2540Sstevel@tonic-gate         UNLOCK_LDAP(ld);
2550Sstevel@tonic-gate 	return ( rv );
2560Sstevel@tonic-gate #endif
2570Sstevel@tonic-gate 	return ( send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate /* synchronous bind to DSA using kerberos */
2610Sstevel@tonic-gate int
ldap_kerberos_bind2_s(LDAP * ld,char * dn)2620Sstevel@tonic-gate ldap_kerberos_bind2_s( LDAP *ld, char *dn )
2630Sstevel@tonic-gate {
2640Sstevel@tonic-gate 	int		msgid;
2650Sstevel@tonic-gate 	LDAPMessage	*res;
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 189, "ldap_kerberos_bind2_s\n"), 0, 0, 0 );
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	/* initiate the bind */
2700Sstevel@tonic-gate 	if ( (msgid = ldap_kerberos_bind2( ld, dn )) == -1 )
2710Sstevel@tonic-gate 		return( ld->ld_errno );
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	/* wait for a result */
2740Sstevel@tonic-gate 	if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
2750Sstevel@tonic-gate 	    == -1 ) {
2760Sstevel@tonic-gate 		return( ld->ld_errno );	/* ldap_result sets ld_errno */
2770Sstevel@tonic-gate 	}
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	return( ldap_result2error( ld, res, 1 ) );
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate /* synchronous bind to ldap and DSA using kerberos */
2830Sstevel@tonic-gate int
ldap_kerberos_bind_s(LDAP * ld,char * dn)2840Sstevel@tonic-gate ldap_kerberos_bind_s( LDAP *ld, char *dn )
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate 	int	err;
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 190, "ldap_kerberos_bind_s\n"), 0, 0, 0 );
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	if ( (err = ldap_kerberos_bind1_s( ld, dn )) != LDAP_SUCCESS )
2910Sstevel@tonic-gate 		return( err );
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	return( ldap_kerberos_bind2_s( ld, dn ) );
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate #ifndef AUTHMAN
2980Sstevel@tonic-gate /*
2990Sstevel@tonic-gate  * get_kerberosv4_credentials - obtain kerberos v4 credentials for ldap.
3000Sstevel@tonic-gate  * The dn of the entry to which to bind is supplied.  It's assumed the
3010Sstevel@tonic-gate  * user already has a tgt.
3020Sstevel@tonic-gate  */
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate char *
get_kerberosv4_credentials(LDAP * ld,char * who,char * service,int * len)3050Sstevel@tonic-gate get_kerberosv4_credentials( LDAP *ld, char *who, char *service, int *len )
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate 	KTEXT_ST	ktxt;
3080Sstevel@tonic-gate 	int		err;
3090Sstevel@tonic-gate 	char		realm[REALM_SZ], *cred, *krbinstance;
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 191, "get_kerberosv4_credentials\n"), 0, 0, 0 );
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	if ( (err = krb_get_tf_realm( tkt_string(), realm )) != KSUCCESS ) {
3140Sstevel@tonic-gate #ifndef NO_USERINTERFACE
3150Sstevel@tonic-gate 		fprintf( stderr, "krb_get_tf_realm failed (%s)\n",
3160Sstevel@tonic-gate 		    krb_err_txt[err] );
3170Sstevel@tonic-gate #endif /* NO_USERINTERFACE */
3180Sstevel@tonic-gate 		ld->ld_errno = LDAP_INVALID_CREDENTIALS;
3190Sstevel@tonic-gate 		return( NULL );
3200Sstevel@tonic-gate 	}
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate #ifdef LDAP_REFERRALS
3230Sstevel@tonic-gate 	krbinstance = ld->ld_defconn->lconn_krbinstance;
3240Sstevel@tonic-gate #else /* LDAP_REFERRALS */
3250Sstevel@tonic-gate 	krbinstance = ld->ld_host;
3260Sstevel@tonic-gate #endif /* LDAP_REFERRALS */
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	if ( (err = krb_mk_req( &ktxt, service, krbinstance, realm, 0 ))
3290Sstevel@tonic-gate 	    != KSUCCESS ) {
3300Sstevel@tonic-gate #ifndef NO_USERINTERFACE
3310Sstevel@tonic-gate 		fprintf( stderr, "krb_mk_req failed (%s)\n", krb_err_txt[err] );
3320Sstevel@tonic-gate #endif /* NO_USERINTERFACE */
3330Sstevel@tonic-gate 		ld->ld_errno = LDAP_INVALID_CREDENTIALS;
3340Sstevel@tonic-gate 		return( NULL );
3350Sstevel@tonic-gate 	}
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	if ( ( cred = malloc( ktxt.length )) == NULL ) {
3380Sstevel@tonic-gate 		ld->ld_errno = LDAP_NO_MEMORY;
3390Sstevel@tonic-gate 		return( NULL );
3400Sstevel@tonic-gate 	}
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	*len = ktxt.length;
3430Sstevel@tonic-gate 	memcpy( cred, ktxt.dat, ktxt.length );
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	return( cred );
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate #endif /* !AUTHMAN */
3490Sstevel@tonic-gate #endif /* KERBEROS */
350