*** dsap/common/attribute.c.orig	Mon Sep 21 17:11:32 1992
--- dsap/common/attribute.c	Fri Sep 25 10:08:42 1992
***************
*** 53,58 ****
--- 53,61 ----
  AttributeType at_searchacl;
  AttributeType at_listacl;
  AttributeType at_authpolicy;
+ #ifdef KERBEROS
+ AttributeType at_kerberosname;
+ #endif
  OID alias_oc;
  OID quipu_dsa_oid;
  OID extern_obj_oid;
***************
*** 90,95 ****
--- 93,101 ----
  	at_searchacl    = AttrT_new (SEARCHACL_OID);
  	at_listacl      = AttrT_new (LISTACL_OID);
  	at_authpolicy   = AttrT_new (AUTHPOLICY_OID);
+ #ifdef KERBEROS
+ 	at_kerberosname = AttrT_new (KERBEROSNAME_OID);
+ #endif
  
  	at_subord 	= AttrT_new (SUBORD_OID);
  	at_xref 	= AttrT_new (XREF_OID);
*** h/quipu/bind.h.orig	Tue Jun 23 17:13:11 1992
--- h/quipu/bind.h	Fri Sep 25 16:21:15 1992
***************
*** 25,30 ****
--- 25,33 ----
  #define QUIPUBIND
  #include "quipu/name.h"
  #include "quipu/authen.h"
+ #ifdef KERBEROS
+ #include <krb.h>
+ #endif
  
  	/* THIS SECTION GIVES BIND PARAMETERS */
  
***************
*** 52,57 ****
--- 55,61 ----
      char * dba_vtmp;	/* pepsy */
      int    dba_vlen;    /* pepsy */
      struct alg_id dba_alg;
+     struct type_UNIV_EXTERNAL *dba_external;
  };
  
  struct ds_bind_error {
***************
*** 70,74 ****
--- 74,95 ----
      char    dbe_data[DBE_SIZE];		/*   data */
      
  };
+ 
+ #ifdef KERBEROS
+ 
+ struct kerberos_parms {
+ 	DN	kp_dn;		/* DN to bind as */
+ 
+ 	int	kp_version;
+ #define AUTH_TYPE_KERBEROS_V4	1
+ #define AUTH_TYPE_KERBEROS_V5	2
+ 
+ 	u_long	kp_enonce[2];
+ #define kp_nonce	kp_enonce[0]
+ 
+ 	KTEXT_ST kp_ktxt;	/* kerberos authenticator and ticket */
+ };
+ 
+ #endif /* KERBEROS */
  
  #endif
*** h/quipu/oid.h.orig	Sat Jun 27 10:39:02 1992
--- h/quipu/oid.h	Fri Sep 25 10:08:43 1992
***************
*** 65,70 ****
--- 65,71 ----
  #define SEARCHACL_OID	"0.9.2342.19200300.100.1.57"
  #define LISTACL_OID	"0.9.2342.19200300.100.1.58"
  #define AUTHPOLICY_OID	"0.9.2342.19200300.100.1.59"
+ #define KERBEROSNAME_OID	"1.3.6.1.4.1.250.1.33"
  
  	/* Signature Algorithm */
  #ifdef  OSISEC
*** quipu/sys_tai.c.orig	Sat Aug 29 09:57:38 1992
--- quipu/sys_tai.c	Fri Sep 25 10:08:45 1992
***************
*** 61,66 ****
--- 61,70 ----
  #ifdef TURBO_INDEX
  extern int optimized_only;
  #endif
+ #ifdef KERBEROS
+ extern char *kerberos_name;
+ extern char *kerberos_keyfile;
+ #endif
  
  unsigned bind_policy = POLICY_ACCESS_ALL;
  unsigned strong_policy = POLICY_ACCESS_ALL;
***************
*** 109,114 ****
--- 113,120 ----
  #define GETEDB_SIZE	 48
  #define AUTHFILE	 50
  #define FASTSTART	 51
+ #define KERBEROS_NAME	 52
+ #define KERBEROS_KEY	 53
  
  static  CMD_TABLE  cmdtab[] =
  {
***************
*** 156,161 ****
--- 162,171 ----
  	"INDEX_SUBTREE",	INDEX_SUBTREE,
  	"INDEX_SIBLINGS",	INDEX_SIBLINGS,
  #endif
+ #ifdef KERBEROS
+ 	"KERBEROS_NAME",	KERBEROS_NAME,
+ 	"KERBEROS_KEY",		KERBEROS_KEY,
+ #endif
  #ifndef NO_STATS
  	"STATS",	STATS,
  #endif
***************
*** 395,400 ****
--- 405,420 ----
  		index_siblings(arg);
                  DLOG(log_dsap, LLOG_TRACE, ("Tailor index siblings %s", arg));
                  break;
+ #endif
+ #ifdef KERBEROS
+ 	case KERBEROS_NAME:
+ 		kerberos_name = strdup( arg );
+                 DLOG(log_dsap, LLOG_TRACE, ("Tailor kerberos name %s", arg));
+ 		break;
+ 	case KERBEROS_KEY:
+ 		kerberos_keyfile = strdup( arg );
+                 DLOG(log_dsap, LLOG_TRACE, ("Tailor kerberos keyfile %s", arg));
+ 		break;
  #endif
  	    default:
  		return NOTOK;
*** quipu/conn_init.c.bak	Fri Sep 25 17:18:32 1992
--- quipu/conn_init.c	Fri Sep 25 17:19:08 1992
***************
*** 177,182 ****
--- 177,185 ----
      switch(ds_bind_return)
      {
      case DS_OK:
+ #ifdef KERBEROS
+ 	cn->cn_dn = dn_cpy(ds->ds_bind_arg.dba_dn);
+ #endif
  	conn_init_res(cn);
  	break;
      case DS_ERROR_CONNECT:
*** quipu/ds_add.c.bak	Fri Sep 25 16:30:12 1992
--- quipu/ds_add.c	Fri Sep 25 16:30:57 1992
***************
*** 67,72 ****
--- 67,73 ----
  int authp;
  extern int read_only;
  extern int	entry_cmp();
+ extern DN trust_dn();
  
  	DLOG (log_dsap,LLOG_TRACE,("ds_add"));
  
***************
*** 187,193 ****
  	else
  		authp = AP_SIMPLE;
  
! 	if (check_acl ((authtype % 3) >= authp ? binddn : NULLDN, ACL_ADD,
  	    entryptr->e_acl->ac_child,dntop) == NOTOK) {
  		error->dse_type = DSE_SECURITYERROR;
  		error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
--- 188,194 ----
  	else
  		authp = AP_SIMPLE;
  
! 	if (check_acl ( trust_dn( binddn, authtype, authp ), ACL_ADD,
  	    entryptr->e_acl->ac_child,dntop) == NOTOK) {
  		error->dse_type = DSE_SECURITYERROR;
  		error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
*** quipu/ds_compare.c.bak	Fri Sep 25 16:38:20 1992
--- quipu/ds_compare.c	Fri Sep 25 16:39:01 1992
***************
*** 56,61 ****
--- 56,62 ----
  int retval;
  DN realtarget;
  int authp;
+ extern DN trust_dn();
  
  	DLOG (log_dsap,LLOG_TRACE,("ds_compare"));
  
***************
*** 110,116 ****
  	authp = entryptr->e_authp ? entryptr->e_authp->ap_readandcompare :
  	    AP_SIMPLE;
  
! 	if (check_acl ((authtype % 3) >= authp ? binddn : NULLDN, ACL_COMPARE,
  	    entryptr->e_acl->ac_entry, realtarget) == NOTOK) {
  		if (dsp && (check_acl (binddn,ACL_COMPARE,entryptr->e_acl->ac_entry, realtarget) == OK)) {
  			error->dse_type = DSE_SECURITYERROR;
--- 111,117 ----
  	authp = entryptr->e_authp ? entryptr->e_authp->ap_readandcompare :
  	    AP_SIMPLE;
  
! 	if (check_acl ( trust_dn( binddn, authtype, authp ), ACL_COMPARE,
  	    entryptr->e_acl->ac_entry, realtarget) == NOTOK) {
  		if (dsp && (check_acl (binddn,ACL_COMPARE,entryptr->e_acl->ac_entry, realtarget) == OK)) {
  			error->dse_type = DSE_SECURITYERROR;
*** quipu/ds_list.c.bak	Fri Sep 25 16:33:11 1992
--- quipu/ds_list.c	Fri Sep 25 16:37:18 1992
***************
*** 35,40 ****
--- 35,41 ----
  extern LLog * log_dsap;
  extern Entry database_root;
  static int build_result();
+ extern DN trust_dn();
  
  do_ds_list (arg, error, result, binddn, target, di_p, dsp, authtype)
      register struct ds_list_arg          *arg;
***************
*** 118,124 ****
  	/* check parent will allow listing */
  	sizelimit = SVC_NOSIZELIMIT;
  	if ( entryptr->e_lacl != NULLAV ) {
! 		if ( check_lacl( (authtype % 3) >= authp ? binddn : NULLDN,
  		    realtarget, entryptr->e_lacl, SACL_SINGLELEVEL,
  		    &sizelimit ) == NOTOK ) {
  			/* security error */
--- 119,125 ----
  	/* check parent will allow listing */
  	sizelimit = SVC_NOSIZELIMIT;
  	if ( entryptr->e_lacl != NULLAV ) {
! 		if ( check_lacl( trust_dn( binddn, authtype, authp ),
  		    realtarget, entryptr->e_lacl, SACL_SINGLELEVEL,
  		    &sizelimit ) == NOTOK ) {
  			/* security error */
***************
*** 129,135 ****
  			return( DS_ERROR_REMOTE );
  		}
  	} 
! 	if (check_acl ((authtype % 3) >= authp ? binddn : NULLDN,
  	    ACL_READ, entryptr->e_acl->ac_child, realtarget) != OK) {
  		if (dsp && (check_acl (binddn,ACL_READ, entryptr->e_acl->ac_child, realtarget) == OK)) {
  			error->dse_type = DSE_SECURITYERROR;
--- 130,136 ----
  			return( DS_ERROR_REMOTE );
  		}
  	} 
! 	if (check_acl (trust_dn( binddn, authtype, authp ),
  	    ACL_READ, entryptr->e_acl->ac_child, realtarget) != OK) {
  		if (dsp && (check_acl (binddn,ACL_READ, entryptr->e_acl->ac_child, realtarget) == OK)) {
  			error->dse_type = DSE_SECURITYERROR;
***************
*** 156,163 ****
  
  	dn_free (realtarget);
  
! 	build_result (arg, entryptr, result, error,
! 	    (authtype % 3) >= authp ? binddn : NULLDN , dsp, sizelimit);
  	return (DS_OK);
  }
  
--- 157,164 ----
  
  	dn_free (realtarget);
  
! 	build_result (arg, entryptr, result, error, trust_dn( binddn,
! 	    authtype, authp ), dsp, sizelimit);
  	return (DS_OK);
  }
  
*** quipu/ds_modifyrdn.c.bak	Fri Sep 25 16:28:21 1992
--- quipu/ds_modifyrdn.c	Fri Sep 25 16:30:04 1992
***************
*** 57,62 ****
--- 57,63 ----
  int retval;
  int authp, pauthp;
  extern int read_only;
+ DN trust_dn();
  
  	DLOG (log_dsap,LLOG_TRACE,("ds_modifyrdn"));
  
***************
*** 134,143 ****
  		pauthp = authp = AP_SIMPLE;
  	}
  
! 	if ((check_acl ((authtype % 3) >= authp ? binddn : NULLDN, ACL_WRITE,
  	    entryptr->e_acl->ac_entry, target) == NOTOK)
  	    || ((entryptr->e_parent->e_data != E_TYPE_CONSTRUCTOR)
! 	    && (check_acl ((authtype % 3) >= pauthp ? binddn : NULLDN,
  	    ACL_WRITE,entryptr->e_parent->e_acl->ac_child, target)
  	    == NOTOK)) ) {
  		error->dse_type = DSE_SECURITYERROR;
--- 135,144 ----
  		pauthp = authp = AP_SIMPLE;
  	}
  
! 	if ((check_acl ( trust_dn( binddn, authtype, authp ), ACL_WRITE,
  	    entryptr->e_acl->ac_entry, target) == NOTOK)
  	    || ((entryptr->e_parent->e_data != E_TYPE_CONSTRUCTOR)
! 	    && (check_acl ( trust_dn( binddn, authtype, pauthp ),
  	    ACL_WRITE,entryptr->e_parent->e_acl->ac_child, target)
  	    == NOTOK)) ) {
  		error->dse_type = DSE_SECURITYERROR;
*** quipu/ds_read.c.bak	Fri Sep 25 16:32:35 1992
--- quipu/ds_read.c	Fri Sep 25 16:35:47 1992
***************
*** 64,69 ****
--- 64,70 ----
  #endif
  DN realtarget;
  char authp;
+ extern DN trust_dn();
  
  	DLOG (log_dsap,LLOG_TRACE,("ds_read"));
  
***************
*** 141,147 ****
  
  	/* entry has got a full list of attributes,  eventually
  	   select one required */
! 	if (check_acl ((authtype % 3) >= authp ? binddn : NULLDN, ACL_READ,
  	    entryptr->e_acl->ac_entry, realtarget) == NOTOK) {
  		if (dsp && (check_acl (binddn,ACL_READ,entryptr->e_acl->ac_entry, realtarget) == OK)) {
  			error->dse_type = DSE_SECURITYERROR;
--- 142,148 ----
  
  	/* entry has got a full list of attributes,  eventually
  	   select one required */
! 	if (check_acl ( trust_dn( binddn, authtype, authp ), ACL_READ,
  	    entryptr->e_acl->ac_entry, realtarget) == NOTOK) {
  		if (dsp && (check_acl (binddn,ACL_READ,entryptr->e_acl->ac_entry, realtarget) == OK)) {
  			error->dse_type = DSE_SECURITYERROR;
*** quipu/ds_remove.c.bak	Fri Sep 25 16:31:03 1992
--- quipu/ds_remove.c	Fri Sep 25 16:32:05 1992
***************
*** 50,55 ****
--- 50,56 ----
  int retval;
  int authp, pauthp;
  extern int read_only;
+ extern DN trust_dn();
  
  	DLOG (log_dsap,LLOG_TRACE,("ds remove entry"));
  
***************
*** 128,136 ****
  	}
  
  	if ( ((entryptr->e_parent->e_data == E_TYPE_CONSTRUCTOR)
! 	    && (check_acl ((authtype % 3) >= authp ? binddn : NULLDN, ACL_WRITE,
  	    entryptr->e_acl->ac_entry, target) == NOTOK))
! 	    || (check_acl ((authtype % 3) >= pauthp ? binddn : NULLDN,
  	    ACL_WRITE, entryptr->e_parent->e_acl->ac_child, target) == NOTOK)) {
  		error->dse_type = DSE_SECURITYERROR;
  		error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
--- 129,137 ----
  	}
  
  	if ( ((entryptr->e_parent->e_data == E_TYPE_CONSTRUCTOR)
! 	    && (check_acl ( trust_dn( binddn, authtype, authp ), ACL_WRITE,
  	    entryptr->e_acl->ac_entry, target) == NOTOK))
! 	    || (check_acl ( trust_dn( binddn, authtype, pauthp ),
  	    ACL_WRITE, entryptr->e_parent->e_acl->ac_child, target) == NOTOK)) {
  		error->dse_type = DSE_SECURITYERROR;
  		error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
*** quipu/dish/bind.c.orig	Wed Jun 24 11:07:02 1992
--- quipu/dish/bind.c	Thu Oct  1 13:50:33 1992
***************
*** 43,48 ****
--- 43,56 ----
  
  #include "osisec-stub.h"
  
+ #ifdef KERBEROS
+ #define DEFAULT_KERBEROS_SERVICE	"x500dsa"
+ 
+ static char	*kerberos_service;
+ static char	*kerberos_instance;
+ static u_long	kerberos_nonce;
+ #endif
+ 
  extern DN       fixed_pos;
  DN	        user_name;
  
***************
*** 229,234 ****
--- 237,253 ----
  			auth_type = DBA_AUTH_SIMPLE;
  		else if (test_arg (argv[x], "-strong", 3))
  			auth_type = DBA_AUTH_STRONG;
+ #ifdef KERBEROS
+ 		else if (test_arg (argv[x], "-kerberos", 3))
+ 			auth_type = DBA_AUTH_EXTERNAL;
+ 		else if (test_arg (argv[x], "-instance", 3)) {
+ 			if ( ++x == argc || *argv[x] == '-' ) {
+ 				Usage( argv[0] );
+ 				return( NOTOK );
+ 			}
+ 			kerberos_instance = strdup( argv[x] );
+ 		}
+ #endif
  		/* -password sets the `key', whatever the mode  */
  		else if (test_arg (argv[x], "-password",2)) {
  			got_pass = TRUE;
***************
*** 301,307 ****
--- 320,331 ----
  	else
  	    newdn = NULLDN;
  
+ #ifdef KERBEROS
+ 	if (auth_type != DBA_AUTH_EXTERNAL
+ 	    && ((got_name && ! got_pass) || (*password == 0))) {
+ #else
  	if ((got_name && ! got_pass) || (*password == 0)) {
+ #endif
  		bindarg.dba_passwd_len = 0;
  		bindarg.dba_passwd[0]  = 0;
  		if ((*username != 0) && (auth_type != DBA_AUTH_NONE)) {
***************
*** 314,320 ****
--- 338,349 ----
  		(void) strcpy (bindarg.dba_passwd, password);
  	}
  
+ #ifdef KERBEROS
+ 	if ((bindarg.dba_passwd_len == 0) && (auth_type != DBA_AUTH_STRONG)
+ 	    && auth_type != DBA_AUTH_EXTERNAL)
+ #else
  	if ((bindarg.dba_passwd_len == 0) && (auth_type != DBA_AUTH_STRONG))
+ #endif
  		auth_type = DBA_AUTH_NONE;
  
  	if (*username == 0) {
***************
*** 348,353 ****
--- 377,387 ----
  		if (sign_bindarg() != OK)
  			bindarg.dba_auth_type = DBA_AUTH_NONE;
  		break;
+ #ifdef KERBEROS
+ 	case DBA_AUTH_EXTERNAL:
+ 		kerberos_bindarg();
+ 		break;
+ #endif
  	}
  
  	if (isnumeric (bdsa) && (dsadn = sequence_dn (atoi (bdsa)))) {
***************
*** 469,475 ****
  			dsa_address = myname;
  	}
  
! 	if (bound) 
  		(void) ds_unbind ();
  		
  	bound = FALSE;
--- 503,509 ----
  			dsa_address = myname;
  	}
  
! 	if (bound)
  		(void) ds_unbind ();
  		
  	bound = FALSE;
***************
*** 494,499 ****
--- 528,545 ----
  		return (NOTOK);
  	} 
  	(void) signal (SIGALRM, SIG_IGN);
+ 
+ #ifdef KERBEROS
+ 	if ( bindarg.dba_auth_type == DBA_AUTH_EXTERNAL ) {
+ 		if ( kerberos_check_mutual( &bindresult ) == NOTOK ) {
+ 			ps_print( OPT,
+ 			    "*** DSA failed mutual authentication ***\n" );
+ 			(void) ds_unbind();
+ 			return( NOTOK );
+ 		}
+ 	}
+ #endif
+ 
  	main_dsa_id = dsap_ad;
  
  #ifndef NO_STATS
***************
*** 955,957 ****
--- 1001,1086 ----
  
  	return (OK);
  }
+ 
+ #ifdef KERBEROS
+ 
+ static kerberos_bindarg()
+ {
+ 	struct type_UNIV_EXTERNAL	*e;
+ 	struct kerberos_parms		kp;
+ 	PE				pe;
+ 	int				err;
+ 	struct timeval			tv;
+ 	char				realm[REALM_SZ];
+ 	extern char			*psap2hostname();
+ 
+ 	e = (struct type_UNIV_EXTERNAL *) calloc( 1,
+ 	    sizeof(struct type_UNIV_EXTERNAL) );
+ 	e->encoding = (struct choice_UNIV_0 *) calloc( 1,
+ 	    sizeof(struct choice_UNIV_0) );
+ 	bindarg.dba_external = e;
+ 	bindarg.dba_auth_type = DBA_AUTH_EXTERNAL;
+ 
+ 	e->indirect__reference = AUTH_TYPE_KERBEROS_V4;
+ 	e->direct__reference = NULLOID;
+ 	e->data__value__descriptor = str2qb( "KRBv4 client credentials",
+ 	    24, 1 );
+ 
+ 	kp.kp_dn = bindarg.dba_dn;
+ 	kp.kp_version = AUTH_TYPE_KERBEROS_V4;
+ 
+ 	if ( kerberos_service == NULL )
+ 		kerberos_service = DEFAULT_KERBEROS_SERVICE;
+ 	if ( kerberos_instance == NULL ) {
+ 		struct PSAPaddr	*pa;
+ 		char		*p;
+ 
+ 		pa = str2paddr( dsa_address, NULLNA );
+ 		if ( (p = psap2hostname( pa )) != NULL )
+ 			kerberos_instance = strdup( p );
+ 		else
+ 			kerberos_instance = "";
+ 	}
+ 
+ 	if ( (err = krb_get_tf_realm( tkt_string(), realm )) != KSUCCESS ) {
+ 		ps_printf( OPT, "krb_get_tf_realm failed! (%s)\n",
+ 		    krb_err_txt[err]);
+ 		return;
+ 	}
+ 	gettimeofday( &tv, NULL );
+ 	kerberos_nonce = tv.tv_usec;
+ 	if ( (err = krb_mk_req( &(kp.kp_ktxt), kerberos_service,
+ 	    kerberos_instance, realm, kerberos_nonce )) != KSUCCESS ) {
+ 		ps_printf( OPT, "krb_mk_req failed! (%s)\n", krb_err_txt[err]);
+ 		return;
+ 	}
+ 
+ 	if ( encode_kerberos_parms( &pe, &kp ) == NOTOK ) {
+ 		ps_printf( OPT, "encode_kerberos_parms failed!\n" );
+ 		return;
+ 	}
+ 	e->encoding->offset = choice_UNIV_0_single__ASN1__type;
+ 	e->encoding->un.single__ASN1__type = pe;
+ }
+ 
+ kerberos_check_mutual( res )
+ struct ds_bind_arg	*res;
+ {
+ 	struct type_UNIV_EXTERNAL	*e = res->dba_external;
+ 	PE				pe;
+ 	struct kerberos_parms		*kp;
+ 
+ 	if ( e == (struct type_UNIV_EXTERNAL *) 0 )
+ 		return( NOTOK );
+ 
+ 	pe = e->encoding->un.single__ASN1__type;
+ 
+ 	/* decode the kerberos authentication parameters */
+ 	if ( decode_kerberos_parms( pe, &kp ) == NOTOK )
+ 		return( NOTOK );
+ 	pe_free( pe );
+ 
+ 	return( kp->kp_nonce == (kerberos_nonce + 1) ? OK : NOTOK );
+ }
+ 
+ #endif
*** quipu/ds_modify.c.bak	Thu Oct  1 13:53:32 1992
--- quipu/ds_modify.c	Wed Sep 30 21:46:35 1992
***************
*** 58,63 ****
--- 58,91 ----
  
  int updateerror;
  
+ DN trust_dn( dn, authtype, authpolicy )
+     DN	dn;
+     int	authtype;
+     int	authpolicy;
+ {
+ 	switch ( authpolicy ) {
+ 	case AP_TRUST:
+ 		return( dn );
+ 		break;
+ 
+ 	case AP_SIMPLE:
+ 		return( authtype >= DBA_AUTH_SIMPLE ? dn : NULLDN );
+ 		break;
+ 
+ 	case AP_STRONG:
+ 		return( authtype == DBA_AUTH_STRONG ||
+ 		    authtype == DBA_AUTH_EXTERNAL ? dn : NULLDN );
+ 		break;
+ 
+ 	default:
+ 		LLOG( log_dsap, LLOG_EXCEPTIONS, ("unknown authpolicy %d",
+ 		    authpolicy) );
+ 		break;
+ 	}
+ 
+ 	return( NULLDN );
+ }
+ 
  do_ds_modifyentry (arg, error, binddn, target, di_p, dsp, authtype)
      struct ds_modifyentry_arg   *arg;
      struct DSError              *error;
***************
*** 178,184 ****
  	authp = real_entry->e_authp ? real_entry->e_authp->ap_modification :
  	    AP_SIMPLE;
  	if (!manager(binddn))
! 		effdn = (authtype % 3) >= authp ? binddn : NULLDN;
  	else
  		effdn = binddn;
  
--- 206,212 ----
  	authp = real_entry->e_authp ? real_entry->e_authp->ap_modification :
  	    AP_SIMPLE;
  	if (!manager(binddn))
! 		effdn = trust_dn( binddn, authtype, authp );
  	else
  		effdn = binddn;
  
*** quipu/ds_bind.c.orig	Thu Aug 27 22:34:16 1992
--- quipu/ds_bind.c	Thu Oct  1 14:27:29 1992
***************
*** 38,43 ****
--- 38,48 ----
  
  #include "osisec-stub.h"
  
+ #ifdef KERBEROS
+ char	*kerberos_name;
+ char	*kerberos_keyfile;
+ #endif
+ 
  extern LLog * log_dsap;
  extern DN	mydsadn;
  struct oper_act	* oper_alloc();
***************
*** 91,97 ****
--- 96,134 ----
  /* We don't support any bilaterally-defined authentication procedures.
   * Hence, if we get EXTERNAL credentials in the bind, reject them.
   */
+ /* NOT!  We do now, if KERBEROS is defined */
+ #ifdef KERBEROS
+ 	if ( arg->dba_auth_type == DBA_AUTH_EXTERNAL ) {
+ 		int i;
  
+ 		if ( arg->dba_external->encoding->offset
+ 		    != choice_UNIV_0_single__ASN1__type ) {
+ 			DLOG(log_dsap, LLOG_EXCEPTIONS,
+ 			    ("Unknown EXTERNAL credentials"));
+ 			error->dbe_version = DBA_VERSION_V1988;
+ 			error->dbe_type = DBE_TYPE_SERVICE;
+ 			error->dbe_value = DSE_SV_UNAVAILABLE;
+ 			return (DS_ERROR_CONNECT);
+ 		}
+ 		if ( (i = kerberos_bind( arg, result, error )) == DS_OK ) {
+ #ifndef NO_STATS
+ 			(void) sprintf (buff,"Bind (%d) (kerberos)",cn->cn_ad);
+ 			pslog (log_stat,LLOG_NOTICE,buff,(IFP)dn_print,
+ 			    (caddr_t)arg->dba_dn);
+ #endif
+ 			cn->cn_authen = DBA_AUTH_EXTERNAL;
+ 		} else {
+ #ifndef NO_STATS
+ 			(void) sprintf (buff,"Bind (%d) (kerberos) (rejected)",
+ 			    cn->cn_ad);
+ 			pslog (log_stat,LLOG_NOTICE,buff,(IFP)dn_print,
+ 			    (caddr_t)arg->dba_dn);
+ #endif
+ 		}
+ 		return( i );
+ 	}
+ #endif KERBEROS
+ 
      if (arg->dba_auth_type == DBA_AUTH_EXTERNAL)
      {
  	DLOG(log_dsap, LLOG_EXCEPTIONS, ("EXTERNAL found in credentials"));
***************
*** 734,737 ****
--- 771,910 ----
  	return TRUE;
  }
  
+ #ifdef KERBEROS
  
+ static kerberos_bind( arg, result, error )
+ struct ds_bind_arg		*arg;
+ struct ds_bind_arg		*result;
+ struct ds_bind_error		*error;
+ {
+ 	Entry				ent;
+ 	Attr_Sequence			as;
+ 	AV_Sequence			av;
+ 	AttributeValue			nameav;
+ 	struct type_UNIV_EXTERNAL	*e = arg->dba_external;
+ 	PE				pe;
+ 	int				err, anyhost = 0;
+ 	struct kerberos_parms		*kp;
+ 	char				instance[INST_SZ], name[MAX_K_NAME_SZ];
+ 	AUTH_DAT			ad;
+ 	extern AttributeType		at_kerberosname;
+ 
+ 	pe = e->encoding->un.single__ASN1__type;
+ 
+ 	/* decode the kerberos authentication parameters */
+ 	if ( decode_kerberos_parms( pe, &kp ) == NOTOK ) {
+ 		DLOG( log_dsap, LLOG_EXCEPTIONS,
+ 		    ("decode_kerberos_parms failed") );
+ 		error->dbe_version = DBA_VERSION_V1988;
+ 		error->dbe_type = DBE_TYPE_SERVICE;
+ 		error->dbe_value = DSE_SV_UNAVAILABLE;
+ 		return( DS_ERROR_CONNECT );
+ 	}
+ 	pe_free( pe );
+ 
+ 	/* check it with kerberos */
+ 	if ( kerberos_keyfile == NULL )
+ 		kerberos_keyfile = "";
+ 	strcpy( instance, "*" );
+ 	if ( kerberos_name == NULL )
+ 		kerberos_name = "x500dsa";
+ 	if ( (err = krb_rd_req( &kp->kp_ktxt, kerberos_name, instance, anyhost,
+ 	    &ad, kerberos_keyfile )) != KSUCCESS ) {
+ 		DLOG( log_dsap, LLOG_NOTICE, ("krb_rd_req failed (%s)",
+ 			krb_err_txt[err]) );
+ 		error->dbe_version = DBA_VERSION_V1988;
+ 		error->dbe_type  = DBE_TYPE_SECURITY;
+ 		error->dbe_value = DSE_SC_INVALIDCREDENTIALS;
+ 		return( DS_ERROR_CONNECT );
+ 	}
+ 	sprintf( name, "%s%s%s@%s", ad.pname, *ad.pinst ? "." : "", ad.pinst,
+ 	    ad.prealm );
+ 
+ 	/* 
+ 	 * make sure the DN and kerberos principal correspond
+ 	 */
+ 
+ 	/* find the entry */
+ 	if ( (ent = local_find_entry( kp->kp_dn, TRUE )) == NULLENTRY ) {
+ 		DLOG( log_dsap, LLOG_NOTICE, ("cannot find entry") );
+ 		error->dbe_version = DBA_VERSION_V1988;
+ 		error->dbe_type = DBE_TYPE_SERVICE;
+ 		error->dbe_value = DSE_SV_UNAVAILABLE;
+ 		return( DS_ERROR_CONNECT );
+ 	}
+ 
+ 	/* see if it has a kerberosName attribute */
+ 	if ( (as = as_find_type( ent->e_attributes, at_kerberosname))
+ 	    == NULLATTR ) {
+ 		DLOG( log_dsap, LLOG_NOTICE, ("no krbnames") );
+ 		error->dbe_version = DBA_VERSION_V1988;
+ 		error->dbe_type = DBE_TYPE_SECURITY;
+ 		error->dbe_value = DSE_SC_AUTHENTICATION;
+ 		return( DS_ERROR_CONNECT );
+ 	}
+ 
+ 	if ( (nameav = str2AttrV( name, at_kerberosname->oa_syntax ))
+ 	    == NULLAttrV ) {
+ 		DLOG( log_dsap, LLOG_NOTICE, ("bad krbname format") );
+ 		error->dbe_version = DBA_VERSION_V1988;
+ 		error->dbe_type  = DBE_TYPE_SECURITY;
+ 		error->dbe_value = DSE_SC_INVALIDCREDENTIALS;
+ 		return( DS_ERROR_CONNECT );
+ 	}
+ 
+ 	/* see if it has the right value */
+ 	for ( av = as->attr_value; av != NULLAV; av = av->avseq_next ) {
+ 		if ( AttrV_cmp( av, nameav ) == 0 )
+ 			break;
+ 	}
+ 	(void) AttrV_free( nameav );
+ 	if ( av == NULLAV ) {
+ 		DLOG( log_dsap, LLOG_NOTICE, ("krbname not found (%s)", name) );
+ 		error->dbe_version = DBA_VERSION_V1988;
+ 		error->dbe_type  = DBE_TYPE_SECURITY;
+ 		error->dbe_value = DSE_SC_INVALIDCREDENTIALS;
+ 		return( DS_ERROR_CONNECT );
+ 	}
+ 
+ 	arg->dba_dn = kp->kp_dn;
+ 
+ 	/* 
+ 	 * send back mutual authentication - checksum + 1  (should be
+ 	 * encrypted in the session key XXX)
+ 	 */
+ 
+ 	kp->kp_dn = mydsadn;
+ 	ad.checksum++;
+ 	memcpy( (char *) &(kp->kp_nonce), (char *) &(ad.checksum),
+ 	    sizeof(ad.checksum) );
+ 	kp->kp_ktxt.length = 0;
+ 
+ 	if ( encode_kerberos_parms( &pe, kp ) == NOTOK ) {
+ 		DLOG( log_dsap, LLOG_EXCEPTIONS,
+ 		    ("encode_kerberos_parms failed") );
+ 		error->dbe_version = DBA_VERSION_V1988;
+ 		error->dbe_type = DBE_TYPE_SERVICE;
+ 		error->dbe_value = DSE_SV_UNAVAILABLE;
+ 		return( DS_ERROR_CONNECT );
+ 	}
+ 	free( kp );
+ 
+ 	result->dba_version = DBA_VERSION_V1988;
+ 	result->dba_auth_type = DBA_AUTH_EXTERNAL;
+ 	result->dba_external = (struct type_UNIV_EXTERNAL *) smalloc(
+ 	    sizeof(struct type_UNIV_EXTERNAL) );
+ 	result->dba_external->encoding = (struct choice_UNIV_0 *) smalloc(
+ 	    sizeof(struct choice_UNIV_0) );
+ 	result->dba_external->indirect__reference = AUTH_TYPE_KERBEROS_V4;
+ 	result->dba_external->direct__reference = NULLOID;
+ 	result->dba_external->data__value__descriptor =
+ 	    str2qb( "KRBv4 server credentials", 24, 1 );
+ 	result->dba_external->encoding->offset =
+ 	    choice_UNIV_0_single__ASN1__type;
+ 	result->dba_external->encoding->un.single__ASN1__type = pe;
+ 
+ 	return( DS_OK );
+ }
+ 
+ #endif
*** dsap/x500as/das.py.orig	Wed Jun 24 10:28:40 1992
--- dsap/x500as/das.py	Fri Sep 25 10:08:42 1992
***************
*** 188,194 ****
  
  Credentials [[P struct ds_bind_arg *]]
  	::=
! 	CHOICE <E< parm->dba_auth_type == DBA_AUTH_STRONG ? 2 : 1 >>
  	       <D< (*parm)->dba_auth_type >>
  	{
  	simple
--- 188,195 ----
  
  Credentials [[P struct ds_bind_arg *]]
  	::=
! 	CHOICE <E< parm->dba_auth_type == DBA_AUTH_STRONG ? 2
! 	    : parm->dba_auth_type == DBA_AUTH_EXTERNAL ? 3 : 1 >>
  	       <D< (*parm)->dba_auth_type >>
  	{
  	simple
***************
*** 200,206 ****
  	strong
  		[1] StrongCredentials [[p *]],
  	externalProcedure 
! 		[2] EXTERNAL [[p dba_vtmp]]
  	}
  
  -- Pulled up
--- 201,208 ----
  	strong
  		[1] StrongCredentials [[p *]],
  	externalProcedure 
! 		[2] EXTERNAL [[p parm->dba_external]]
! --			[[E encode_external_type]] [[D decode_external_type]]
  	}
  
  -- Pulled up
*** quipu/checkacl.c.bak	Fri Sep 25 16:33:02 1992
--- quipu/checkacl.c	Thu Oct  1 16:53:41 1992
***************
*** 35,40 ****
--- 35,41 ----
  
  extern int 	selector_rank[];
  extern LLog	*log_dsap;
+ extern DN	trust_dn();
  
  static common_prefix_len( a, b )
  char	*a;
***************
*** 228,235 ****
  
  	/* check auth policy allow us to believe binddn */
  	if ( e->e_authp != NULLAUTHP ) {
! 		binddn = (authtype % 3) >= e->e_authp->ap_listandsearch ?
! 		    binddn : NULLDN;
  	}
  
  	/* for each type in the filter */
--- 229,236 ----
  
  	/* check auth policy allow us to believe binddn */
  	if ( e->e_authp != NULLAUTHP ) {
! 		binddn = trust_dn( binddn, authtype,
! 		    e->e_authp->ap_listandsearch );
  	}
  
  	/* for each type in the filter */
***************
*** 471,478 ****
  
  	/* check auth policy allow us to believe binddn */
  	if ( ancestor->e_authp != NULLAUTHP ) {
! 		binddn = authtype >= ancestor->e_authp->ap_listandsearch ?
! 		    binddn : NULLDN;
  	}
  
  	if ( (rc = (struct result_count *) avl_find( (Avlnode *)local->st_sacls,
--- 472,479 ----
  
  	/* check auth policy allow us to believe binddn */
  	if ( ancestor->e_authp != NULLAUTHP ) {
! 		binddn = trust_dn( binddn, authtype,
! 		    ancestor->e_authp->ap_listandsearch );
  	}
  
  	if ( (rc = (struct result_count *) avl_find( (Avlnode *)local->st_sacls,
