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