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