#include "mysccs.h"
SCCSID("@(#)creds.c   %E%   SAP   %I%")

static char * this_File GNU_UNUSED = __FILE__;
/************************************************************************/
/* $Id: //tools/src/freeware/gsstest/creds.c#2 $
 ************************************************************************
 *
 * Copyright (c) 1998-2000  SAP AG.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by SAP AG"
 *
 * 4. The name "SAP AG" must not be used to endorse or promote products
 *    derived from this software without prior written permission.
 *    For written permission, please contact www.press@sap.com
 *
 * 5. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by SAP AG"
 *
 * THIS SOFTWARE IS PROVIDED BY SAP AG ``AS IS'' AND ANY EXPRESSED
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. SAP AG SHALL BE LIABLE FOR ANY DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE ONLY IF CAUSED BY SAP AG'S
 * INTENT OR GROSS NEGLIGENCE. IN CASE SAP AG IS LIABLE UNDER THIS
 * AGREEMENT FOR DAMAGES CAUSED BY SAP AG'S GROSS NEGLIGENCE SAP AG
 * FURTHER SHALL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT, AND SHALL NOT BE LIABLE IN EXCESS OF THE AMOUNT OF
 * DAMAGES TYPICALLY FORESEEABLE FOR SAP AG, WHICH SHALL IN NO EVENT
 * EXCEED US$ 500.000.- 
 *
 ************************************************************************/


#include "gsstest.h"


/*
 * cred_tests()
 *
 *
 */
int
cred_tests( DLL_GSSFP_T * p_gssfp_ini, DLL_GSSFP_T * p_gssfp_acc )
{
   gss_name_t	    default_ini_name	= GSS_C_NO_NAME;
   gss_buffer_desc  pr_buffer;
   gss_cred_id_t    ini_cred1		= GSS_C_NO_CREDENTIAL;
   gss_cred_id_t    ini_cred2		= GSS_C_NO_CREDENTIAL; 
   gss_cred_id_t    ini_cred3		= GSS_C_NO_CREDENTIAL; 
   gss_cred_id_t    ini_cred4		= GSS_C_NO_CREDENTIAL; 
   gss_cred_id_t    ini_cred5		= GSS_C_NO_CREDENTIAL; 
   gss_cred_id_t    acc_cred6		= GSS_C_NO_CREDENTIAL; 
   gss_cred_id_t    acc_cred7		= GSS_C_NO_CREDENTIAL;
   gss_cred_id_t    acc_cred8	        = GSS_C_NO_CREDENTIAL;
   gss_cred_id_t    acc_cred9	        = GSS_C_NO_CREDENTIAL;
   OM_uint32	    lifetime;
   OM_uint32	    maj_stat;
   int		    rc			= 0;
   int		    rci			= 0;


   pr_buffer.value  = NULL;
   pr_buffer.length = 0;


   XVEB((V_SHOW, "====================\nTesting credentials management functions ...\n----------\n"));


   rci = check_default_initiator_cred( 1, p_gssfp_ini,
				       &default_ini_name, &pr_buffer, &(p_gssfp_ini->can_nametype)  );
   rc += rci;
   if ( p_gssfp_ini!=p_gssfp_acc ) {
      /* copy the OID pointer.  This may not be a good practice, but it should work. */
      /* we may not be able to check_default_initiator_cred() on p_gssfp_acc ...     */
      p_gssfp_acc->can_nametype = p_gssfp_ini->can_nametype;
   }

   if ( pr_buffer.value!=NULL && pr_buffer.length>0 ) {
      VERBOSE_DUPMEM( pr_buffer.value, pr_buffer.length,
		      (p_gssfp_ini->initiator), (p_gssfp_ini->initiator_len) );
      if ( p_gssfp_ini!=p_gssfp_acc ) {
	 VERBOSE_DUPMEM( pr_buffer.value, pr_buffer.length,
			 (p_gssfp_acc->initiator), (p_gssfp_acc->initiator_len) );
      }

      XVEB((V_SHOW, "  My own name/identity (from default creds) resolves to\n"
		    "    \"%.*s\"\n",
		    (int) pr_buffer.length, (char *)pr_buffer.value ));
      print_oid( 3, "Nametype oid", p_gssfp_ini->can_nametype );
      XVEB((V_SHOW, "\n"));

      XVEB((V_TEST, "Examining the exported name framing\n"));
      rci = dump_exported_name( 1, p_gssfp_ini, "Hex-dump of exported name", default_ini_name, NULL );
      XVEB((V_RESULT, rci, 0, NULL ));
      rc += rci;

      XVEB((V_SHOW, "\n"));
      if ( p_gssfp_ini->acceptor==NULL ) {
	 XVEB((V_SHOW, "  Since you didn't give me a target name, I'll try to talk to myself!\n"));
	 VERBOSE_DUPMEM( pr_buffer.value, pr_buffer.length,
			 (p_gssfp_ini->acceptor), (p_gssfp_ini->acceptor_len) );
	 if ( p_gssfp_ini!=p_gssfp_acc ) {
	    VERBOSE_DUPMEM( pr_buffer.value, pr_buffer.length,
			    (p_gssfp_acc->acceptor), (p_gssfp_acc->acceptor_len) );
	 }
      }
      XVEB((V_SHOW, "\n"));
   }

   XVEB((V_TEST, "acquiring *default* initiating credentials (simple)\n"));
   rci = sap_acquire_cred( verbose_level, p_gssfp_ini, SNC_SIMPLE_CRED, GSS_C_INITIATE,
			   GSS_C_NO_NAME, NULL, 0, GSS_C_NO_OID, &lifetime, &ini_cred1, &maj_stat );
   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;

   XVEB((V_TEST, "acquiring *default* initiating credentials (query)\n"));
   rci = sap_acquire_cred( verbose_level, p_gssfp_ini, SNC_CHECKED_CRED, GSS_C_INITIATE,
			   GSS_C_NO_NAME, NULL, 0, GSS_C_NO_OID, &lifetime, &ini_cred2, &maj_stat );
   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;

   XVEB((V_TEST, "acquiring initiating credentials (gss_name_t)\n"));
   rci = sap_acquire_cred( verbose_level, p_gssfp_ini, SNC_GSSNAMED_CRED, GSS_C_INITIATE,
			   default_ini_name, NULL, 0, GSS_C_NO_OID, &lifetime, &ini_cred3, &maj_stat );
   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;

   XVEB((V_TEST, "acquiring initiating credentials (printable name)\n"));
   rci = sap_acquire_cred( verbose_level, p_gssfp_ini, SNC_PRNAMED_CRED, GSS_C_INITIATE,
			   GSS_C_NO_NAME, (p_gssfp_ini->initiator), (p_gssfp_ini->initiator_len),
			   (p_gssfp_ini->can_nametype), &lifetime, &ini_cred4, &maj_stat );
   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;

   XVEB((V_TEST, "acquiring initiating credentials (can. printable name)\n"));
   rci = sap_acquire_cred( verbose_level, p_gssfp_ini, SNC_PRNAMED_VIA_XP_CRED, GSS_C_INITIATE,
			   GSS_C_NO_NAME, (p_gssfp_ini->initiator), (p_gssfp_ini->initiator_len),
			   (p_gssfp_ini->can_nametype), &lifetime, &ini_cred5, &maj_stat );
   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;


   if ( p_gssfp_acc->acceptor!=NULL ) {
      XVEB((V_TEST, "acquiring accepting credentials for target (printable name)\n"));
      XVEB((V_SHOW, "  for identity \"%.*s\"\n",
		    (int)p_gssfp_acc->acceptor_len, p_gssfp_acc->acceptor));
      rci = sap_acquire_cred( verbose_level, p_gssfp_acc, SNC_PRNAMED_CRED, GSS_C_ACCEPT,
			      GSS_C_NO_NAME, (p_gssfp_acc->acceptor), (p_gssfp_acc->acceptor_len),
			      (p_gssfp_acc->can_nametype), &lifetime, &acc_cred6, &maj_stat );
      if ( acc_cred6!=GSS_C_NO_CREDENTIAL ) {
	 rci += printable_name_from_cred( verbose_level, p_gssfp_acc, acc_cred6, CTX_ACCEPTOR,
					  &(p_gssfp_acc->can_acc), &(p_gssfp_acc->can_acc_len),
					  &(p_gssfp_acc->can_nametype) );
	 if ( p_gssfp_ini!=p_gssfp_acc ) {
	    rci += printable_name_from_cred( verbose_level, p_gssfp_acc, acc_cred6, CTX_ACCEPTOR,
					  &(p_gssfp_ini->can_acc), &(p_gssfp_ini->can_acc_len),
					  &(p_gssfp_acc->can_nametype) );
	 }
	 XVEB((V_SHOW, "  canonical identity \"%.*s\"\n",
		       (int)p_gssfp_acc->can_acc_len, p_gssfp_acc->can_acc));

      }
      XVEB((V_RESULT, rci, 0, NULL ));
      rc += rci;

      XVEB((V_TEST, "acquiring accepting credentials for target (can. printable name)\n"));
      rci = sap_acquire_cred( verbose_level, p_gssfp_acc, SNC_PRNAMED_VIA_XP_CRED, GSS_C_ACCEPT,
			      GSS_C_NO_NAME, (p_gssfp_acc->acceptor), (p_gssfp_acc->acceptor_len),
			      (p_gssfp_acc->can_nametype), &lifetime, &acc_cred7, &maj_stat );
      XVEB((V_RESULT, rci, 0, NULL ));
      rc += rci;
   }


   XVEB((V_TEST, "acquiring *default* accepting credentials (simple)\n"));
   rci = sap_acquire_cred( verbose_level, p_gssfp_acc, SNC_SIMPLE_CRED, GSS_C_ACCEPT,
			   GSS_C_NO_NAME, NULL, 0, GSS_C_NO_OID, &lifetime, &acc_cred8, &maj_stat );
   if ( acc_cred8!=GSS_C_NO_CREDENTIAL ) {
      rci += printable_name_from_cred( verbose_level, p_gssfp_acc, acc_cred8, CTX_ACCEPTOR,
				       &(p_gssfp_acc->def_acc), &(p_gssfp_acc->def_acc_len),
				       &(p_gssfp_acc->can_nametype) );
   }
   if ( rci>0  &&  acc_cred8==GSS_C_NO_CREDENTIAL ) {
      /* We don't necessarily have *default* accepting credentials,        */
      /* or we may not have access to the *default* accepting credentials. */
      XVEB((V_SHOW, "  *default* accepting credentials not available.\n"));
      rci = 0;
   }
   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;

   XVEB((V_TEST, "acquiring *default* accepting credentials (query)\n"));
   rci = sap_acquire_cred( verbose_level, p_gssfp_acc, SNC_CHECKED_CRED, GSS_C_ACCEPT,
			   GSS_C_NO_NAME, NULL, 0, GSS_C_NO_OID, &lifetime, &acc_cred9, &maj_stat );
   if ( rci>0  &&  acc_cred9==GSS_C_NO_CREDENTIAL ) {
      /* We don't necessarily have *default* accepting credentials,        */
      /* or we may not have access to the *default* accepting credentials. */
      XVEB((V_SHOW, "  *default* accepting credentials not available.\n"));
      rci = 0;
   }
   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;


   rc += release_buffer( p_gssfp_ini, &pr_buffer );
   rc += release_cred(	 p_gssfp_ini, &ini_cred1  );
   rc += release_cred(   p_gssfp_ini, &ini_cred2  );
   rc += release_cred(   p_gssfp_ini, &ini_cred3  );
   rc += release_cred(   p_gssfp_ini, &ini_cred4  );
   rc += release_cred(   p_gssfp_ini, &ini_cred5  );
   rc += release_cred(   p_gssfp_acc, &acc_cred6  );
   rc += release_cred(   p_gssfp_acc, &acc_cred7  );
   rc += release_cred(   p_gssfp_acc, &acc_cred8  );
   rc += release_cred(   p_gssfp_acc, &acc_cred9  );

   rc += release_name( p_gssfp_ini, &default_ini_name );

   return(rc);

} /* cred_tests() */



/*
 * cred_usage()
 *
 *
 */
char *
cred_usage( gss_cred_usage_t  p_usage )
{
   static char unknown[64];

   switch( (int)p_usage ) {
      case GSS_C_BOTH:	      return("\"BOTH\"");
      case GSS_C_INITIATE:    return("\"INITIATE\"");
      case GSS_C_ACCEPT:      return("\"ACCEPT\"");
   }

   sprintf(unknown, "\"unknown (%d)\"", (int)p_usage);

   return(unknown);

} /* cred_usage() */




/*
 * release_cred()
 *
 *
 */
int
release_cred( DLL_GSSFP_T * p_gssfp, gss_cred_id_t * cred )
{
   OM_uint32 min_stat;
   OM_uint32 maj_stat;
   int       rc = 0;

   if ( *cred==BOGUS_CRED ) {

      *cred = GSS_C_NO_CREDENTIAL;

   } else if ( *cred!=GSS_C_NO_CREDENTIAL ) {

      BOGUS_INI_MINOR( min_stat );
      start_timer();
      maj_stat = (p_gssfp->gss_release_cred)( &min_stat, cred );
      timedelay = read_timer();
      rc += print_status(p_gssfp, GSS_RELEASE_CRED, maj_stat, min_stat);

      if ( maj_stat!=GSS_S_COMPLETE ) {
	 rc++;
      }
   }

   if ( *cred!=GSS_C_NO_CREDENTIAL ) {
     fprintf(vfp, "(gss_cred_id_t)cred   was not zeroed!\n");
     rc++;
     *cred = GSS_C_NO_CREDENTIAL;
   }

   return(rc);

} /* release_cred() */




/*
 * acquire_cred()
 *
 *
 */
int
acquire_cred( int		   p_trclevel,	      DLL_GSSFP_T    * p_gssfp,
	      gss_cred_usage_t     p_usage,	      gss_name_t       p_name,
	      gss_OID_set	   p_desired_mechs,
	      gss_cred_id_t	 * pp_cred,	      gss_OID_set    * pp_actual_mechs,
	      OM_uint32		 * pp_lifetime,	      OM_uint32	     * pp_maj_stat )
{
   char        * gss_call    = "gss_acquire_cred";
   OM_uint32     min_stat;
   OM_uint32     maj_stat    = GSS_S_FAILURE;
   int	         rc          = 0;
   gss_call_et   callno;
   
   callno = (p_usage==GSS_C_ACCEPT) ? GSS_ACQUIRE_CRED_A : GSS_ACQUIRE_CRED_I;

   BOGUS_INI_OID_SET( pp_actual_mechs );
   BOGUS_INI_CRED(    pp_cred         );
   BOGUS_INI_VALUE(   pp_lifetime     );
   BOGUS_INI_MINOR(   min_stat        );

   start_timer();
   maj_stat = (p_gssfp->gss_acquire_cred)( &min_stat, p_name, GSS_C_INDEFINITE,
					   p_desired_mechs, p_usage,
					   pp_cred, pp_actual_mechs, pp_lifetime );
   timedelay = read_timer();
   rc += print_status( p_gssfp, callno, maj_stat, min_stat );

   BOGUS_CHECK_CRED(    pp_cred,         "cred_handle"	      );
   BOGUS_CHECK_OID_SET( pp_actual_mechs, "actual_mechs"       );
   BOGUS_CHECK_VALUE(   pp_lifetime,     "lifetime"           );

   if ( maj_stat!=GSS_S_COMPLETE ) {

      /* failure */
      rc++;
      if ( pp_actual_mechs!=NULL && *pp_actual_mechs!=GSS_C_NO_OID_SET ) {
	 rc++;
	 XVEB((V_ERR, "%s() failed but returned acutal_mechs!\n", gss_call));
	 rc += release_oid_set( p_gssfp, pp_actual_mechs );
      }

      if ( *pp_cred!=NULL ) {
	 rc++;
	 XVEB((V_ERR, "%s() failed but returned cred_handle!\n", gss_call));
	 rc += release_cred( p_gssfp, pp_cred );
      }

   } else {

      /* success */
      if ( pp_actual_mechs!=NULL ) {
	 if ( *pp_actual_mechs==GSS_C_NO_OID_SET ) {
	    rc++;
	    XVEB((V_ERR, "%s() succeeded but failed to return actual_mechs!\n", gss_call));
	 } else {
	    rc += validate_oidset( p_gssfp, OID_MECHANISM,
				   gss_call, "actual_mechs", *pp_actual_mechs );
	 }
      }

      if ( *pp_cred==GSS_C_NO_CREDENTIAL ) {
	 rc++;
	 XVEB((V_ERR, "%s() succeeded but failed to return cred handle!\n", gss_call));
      }

   }

   if ( pp_maj_stat!=NULL ) { *pp_maj_stat = maj_stat; }

   return(rc);

} /* acquire_cred() */




/*
 * inquire_cred()
 *
 *
 */
int
inquire_cred( int		  p_trclevel, DLL_GSSFP_T    * p_gssfp,
	      gss_cred_id_t	  p_cred,     ctx_type_et      p_usagetype,
	      gss_name_t        * pp_name,    OM_uint32	     * pp_lifetime,
	      gss_cred_usage_t  * pp_usage,   gss_OID_set    * pp_mechanisms,
	      OM_uint32		* pp_maj_stat )
{
   char	      * gss_call  = "gss_inquire_cred";
   OM_uint32	min_stat;
   OM_uint32	maj_stat  = GSS_S_FAILURE;
   int		rc        = 0;
   gss_call_et  callno;

   callno = (p_usagetype==CTX_ACCEPTOR) ? GSS_INQUIRE_CRED_A : GSS_INQUIRE_CRED_I;

   BOGUS_INI_NAME(    pp_name	    );
   BOGUS_INI_VALUE(   pp_lifetime   );
   BOGUS_INI_VALUE(   pp_usage      );
   BOGUS_INI_OID_SET( pp_mechanisms );
   BOGUS_INI_MINOR(   min_stat      );

   start_timer();
   maj_stat = (p_gssfp->gss_inquire_cred)( &min_stat, p_cred, pp_name,
				           pp_lifetime, pp_usage, pp_mechanisms );
   timedelay = read_timer();
   rc += print_status(p_gssfp, callno, maj_stat, min_stat);

   BOGUS_CHECK_NAME(	pp_name,       "name"	    );
   BOGUS_CHECK_VALUE(	pp_lifetime,   "lifetime"   );
   BOGUS_CHECK_VALUE(	pp_usage,      "usage"	    );
   BOGUS_CHECK_OID_SET( pp_mechanisms, "mechanisms" );

   if ( maj_stat!=GSS_S_COMPLETE ) {

      /* failure */
      rc++;

      if ( pp_name!=NULL && *pp_name!=GSS_C_NO_NAME ) {
	 rc++;
	 XVEB((V_ERR, "%s() failed but returned name!\n", gss_call));
	 rc += release_name( p_gssfp, pp_name );
      }

      if ( pp_mechanisms!=NULL && *pp_mechanisms!=GSS_C_NO_OID_SET ) {
	 rc++;
	 XVEB((V_ERR, "%s() failed but returned mechanisms!\n", gss_call));
	 rc += release_oid_set( p_gssfp, pp_mechanisms );
      }

   } else {

      /* success */
      if ( pp_name!=NULL && *pp_name==GSS_C_NO_NAME ) {
	 rc++;
	 XVEB((V_ERR, "%s() succeeded but failed to return name!\n", gss_call));
      }

      if ( pp_mechanisms!=NULL ) {
	 if ( *pp_mechanisms==GSS_C_NO_OID_SET ) {
	    rc++;
	    XVEB((V_ERR, "%s() succeeded but failed to return mechanisms!\n", gss_call));
	 } else {
	    rc += validate_oidset( p_gssfp, OID_MECHANISM,
				   gss_call, "mechanisms", *pp_mechanisms );
	 }
      }

      if ( pp_usage!=NULL ) {
	 switch( (int) (*pp_usage) ) {
	    case GSS_C_BOTH:
	    case GSS_C_INITIATE:
	    case GSS_C_ACCEPT:
		  break;

	    default:
		  rc++;
		  XVEB((V_ERR, "%s() returned invalid usage value %d!\n", gss_call,
		               (int) *pp_usage ));
	 }
      }

   }

   if ( pp_maj_stat!=NULL ) { *pp_maj_stat = maj_stat; }

   return(rc);

} /* inquire_cred() */





/*
 * sap_acquire_cred()
 *
 *
 */
int
sap_acquire_cred( int		  p_trclevel,    DLL_GSSFP_T	  * p_gssfp,
		  sc_variants_et  p_variante,	 gss_cred_usage_t   p_usage,
		  gss_name_t      p_in_name,
		  char		* p_in_prname,	 size_t		    p_in_prname_len,
		  gss_OID	  p_nametype,
		  OM_uint32	* pp_lifetime,   gss_cred_id_t    * pp_cred,
		  OM_uint32	* pp_maj_stat )
{
   char		   * this_Call	     = "sap_acquire_cred";
   gss_name_t	     name1	     = GSS_C_NO_NAME;
   gss_name_t	     name2	     = GSS_C_NO_NAME;
   gss_OID_set_desc  our_mechs;
   OM_uint32	     maj_stat;
   int		     rc		     = 0;

   /* create an OID_set with the single OID of our selected mechanism */
   our_mechs.count    = 1;
   our_mechs.elements = p_gssfp->mech;

   switch( p_variante ) {

      case SNC_SIMPLE_CRED:
	       rc += acquire_cred( verbose_level, p_gssfp, p_usage, GSS_C_NO_NAME,
				   &our_mechs, pp_cred, NULL, pp_lifetime, &maj_stat );
	       break;


      case SNC_CHECKED_CRED:
	       rc += acquire_cred( verbose_level, p_gssfp, p_usage, GSS_C_NO_NAME,
				   &our_mechs, pp_cred, NULL, pp_lifetime, &maj_stat );
	       if ( *pp_cred!=GSS_C_NO_CREDENTIAL ) {
		  rc += inquire_cred( verbose_level, p_gssfp, *pp_cred,
				      (p_usage==GSS_C_ACCEPT) ? CTX_ACCEPTOR : CTX_INITIATOR,
				      &name1, pp_lifetime, NULL, NULL, &maj_stat);
		  if ( name1!=GSS_C_NO_NAME ) {
		     rc += name_transform_xp( p_trclevel, p_gssfp,
					      name1, &name2, &maj_stat );
		     rc += release_cred( p_gssfp, pp_cred );
		     rc += release_name( p_gssfp, &name1 );
		     if ( name2!=GSS_C_NO_NAME ) {
			rc += acquire_cred( verbose_level, p_gssfp, p_usage, name2,
					    &our_mechs, pp_cred, NULL, pp_lifetime, &maj_stat );
		     }
		  }
	       }
	       break;


      case SNC_GSSNAMED_CRED:
	       rc += acquire_cred( verbose_level, p_gssfp, p_usage, p_in_name,
				   &our_mechs, pp_cred, NULL, pp_lifetime, &maj_stat );
	       break;


      case SNC_PRNAMED_CRED:
	       rc += import_name( verbose_level, p_gssfp,
				  p_in_prname, p_in_prname_len, p_nametype,
				  &name1, &maj_stat );
	       if ( name1!=GSS_C_NO_NAME ) {
		  rc += acquire_cred( verbose_level, p_gssfp, p_usage, name1,
				      &our_mechs, pp_cred, NULL, pp_lifetime, &maj_stat );
	       }
	       break;


      case SNC_PRNAMED_VIA_XP_CRED:
	       rc += import_name( verbose_level, p_gssfp,
				  p_in_prname, p_in_prname_len,
				  p_nametype, &name1, &maj_stat );
	       if ( name1!=GSS_C_NO_NAME ) {
		  rc += name_transform_xp( p_trclevel, p_gssfp,
					   name1, &name2, &maj_stat );
		  rc += release_name( p_gssfp, &name1 );
		  if ( name2!=GSS_C_NO_NAME ) {
		     rc += acquire_cred( verbose_level, p_gssfp, p_usage, name2,
					 &our_mechs, pp_cred, NULL, pp_lifetime, &maj_stat );
		  }
	       }
	       break;


      case SNC_MISNAMED_CRED:
	       if ( bad_target_name!=NULL ) {
		  /* bad_target_name is assigned/selected in errors.c:error_with_names() */
		  rc += import_name( verbose_level, p_gssfp,
				     bad_target_name, strlen(bad_target_name),
				     p_nametype, &name1, &maj_stat );
	       } else {

		  rc += import_name( verbose_level, p_gssfp, "CN=A,C=ES", 9,
				     p_nametype, &name1, &maj_stat );
	       }

	       if ( name1!=GSS_C_NO_NAME ) {
		  rc += acquire_cred( verbose_level, p_gssfp, p_usage, name1,
				      &our_mechs, pp_cred, NULL, pp_lifetime, &maj_stat );
	       }
	       break;



      default:
	       XVEB((V_BUG, "%s(): unknown enumeration number (%u)!\n",
			    this_Call, (Uint)p_variante ));
	       break;

   }

   release_name(   p_gssfp, &name1     );
   release_name(   p_gssfp, &name2     );

   if ( pp_maj_stat!=NULL ) {  *pp_maj_stat = maj_stat; }

   return(rc);

} /* sap_acquire_cred() */




/*
 * check_default_initiator_cred()
 *
 *
 */
int
check_default_initiator_cred( int	     p_trclevel,    DLL_GSSFP_T       * p_gssfp,
			      gss_name_t   * pp_name_ret,   gss_buffer_t        p_prname_ret,
			      gss_OID	   * pp_oid  )
{
   gss_cred_usage_t  usage1i;
   gss_cred_usage_t  usage2i;
   gss_cred_usage_t  usage3i;
   gss_cred_usage_t  usage4i;
   gss_cred_id_t     cred1	 = GSS_C_NO_CREDENTIAL;
   gss_cred_id_t     cred2	 = GSS_C_NO_CREDENTIAL;
   gss_cred_id_t     cred4	 = GSS_C_NO_CREDENTIAL;
   gss_cred_id_t     cred5	 = GSS_C_NO_CREDENTIAL;
   gss_name_t	     name1i	 = GSS_C_NO_NAME;
   gss_name_t	     name2i	 = GSS_C_NO_NAME;
   gss_name_t	     name3i	 = GSS_C_NO_NAME;
   gss_name_t	     name4i	 = GSS_C_NO_NAME;
   gss_name_t	   * name	 = NULL;
   gss_OID_set       mechs1      = GSS_C_NO_OID_SET;
   gss_OID_set       mechs1i	 = GSS_C_NO_OID_SET;
   gss_OID_set	     mechs2	 = GSS_C_NO_OID_SET;
   gss_OID_set       mechs2i     = GSS_C_NO_OID_SET;
   gss_OID_set	     mechs3i	 = GSS_C_NO_OID_SET;
   gss_OID_set       mechs4	 = GSS_C_NO_OID_SET;
   gss_OID_set	     mechs4i	 = GSS_C_NO_OID_SET;
   gss_OID_set_desc  our_mechs;
   OM_uint32	     lifetime1;
   OM_uint32	     lifetime1i;
   OM_uint32	     lifetime2;
   OM_uint32	     lifetime2i;
   OM_uint32	     lifetime3i;
   OM_uint32	     lifetime4;
   OM_uint32	     lifetime4i;
   OM_uint32	     maj_stat;
   int		     rc          = 0;
   int		     rci	 = 0;
   time_t	     enter       = time(NULL);

   /* create an OID_set with the single OID of our selected mechanism */
   our_mechs.count    = 1;
   our_mechs.elements = p_gssfp->mech;

   /* clear return parameter for nametype of default initiator name */
   if ( pp_oid!=NULL ) { *pp_oid = GSS_C_NO_OID; }

   /* Test Case # 1 :
    *  try to acquire default INITIATING credential (GSS_C_NO_NAME) with no mech_list
    */
   XVEB((V_TEST, "*default* initiating credentials (acquire_cred default mechs)\n"));

   rci = acquire_cred( verbose_level, p_gssfp, GSS_C_INITIATE, GSS_C_NO_NAME, GSS_C_NO_OID_SET,
		       &cred1, &mechs1, &lifetime1, &maj_stat );

   if ( cred1!=GSS_C_NO_CREDENTIAL ) {

      rci += verify_oid_subset( 0, "gss_acquire_cred(NO_OID_SET)",
				  "selected mechanism", &our_mechs, "actual_mechs", mechs1 );
      /*
       * consistency check on credentials attributes
       */
      rci += inquire_cred( verbose_level, p_gssfp, cred1, CTX_INITIATOR, /* see above! */
			   &name1i, &lifetime1i, &usage1i, &mechs1i, &maj_stat );

      if ( maj_stat==GSS_S_COMPLETE || name1i!=GSS_C_NO_NAME ) {
	 rci += check_lifetime_change( p_trclevel, enter, lifetime1, lifetime1i );
      }

      if ( maj_stat==GSS_S_COMPLETE || mechs1i!=GSS_C_NO_OID_SET ) {
	 if ( compare_oid_set( mechs1, mechs1i )!=0 ) {
	    XVEB((V_ERR, "actual_mechs from acquire_cred() and inquire_cred() DIFFER!\n"));
	    rci++;
	 }
      }

   } /* cred1!=GSS_C_NO_CREDENTIAL */

   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;



   if ( name1i!=GSS_C_NO_NAME || mechs1!=GSS_C_NO_OID_SET ) {

      if ( mechs1!=GSS_C_NO_OID_SET ) {
	 rc += print_oid_set( 2, "actual_mechs from gss_acquire_cred()", mechs1 );
      }

      if ( name1i!=GSS_C_NO_NAME ) {
	 gss_buffer_desc   prname;

	 rc += display_name( 2, p_gssfp, name1i, &prname, pp_oid, NULL );
	 if ( p_prname_ret==NULL ) {
	    rc += release_buffer( p_gssfp, &prname );
	 } else {
	    p_prname_ret->value  = prname.value;
	    p_prname_ret->length = prname.length;
	 }
      }
      XVEB((V_SHOW, "----------\n"));
   }

   /*
    * Test Case # 2 :
    *  try to acquire default INITIATING credential (GSS_C_NO_NAME) with selected mechanism
    */
   XVEB((V_TEST, "*default* initiating credentials (acquire_cred specific mechs)\n"));

   rci = acquire_cred( verbose_level, p_gssfp, GSS_C_INITIATE, GSS_C_NO_NAME,
		       &our_mechs, &cred2, &mechs2, &lifetime2, &maj_stat );

   if ( cred2!=GSS_C_NO_CREDENTIAL ) {

      rci += check_lifetime_change( p_trclevel, enter, lifetime1, lifetime2 );
      rci += verify_oid_subset( 0, "gss_acquire_cred(mech!)",
				   "selected mechanism", &our_mechs, "actual_mechs", mechs2 );

      rci += inquire_cred( verbose_level, p_gssfp, cred2, CTX_INITIATOR, /* see above! */
			  &name2i, &lifetime2i, &usage2i, &mechs2i, &maj_stat );

      if ( maj_stat==GSS_S_COMPLETE  ||  name2i!=GSS_C_NO_NAME ) {
	 rci += check_lifetime_change( p_trclevel, enter, lifetime1, lifetime2i );
	 rci += verify_same_name( p_trclevel, p_gssfp, "acquiring default credentials",
				  "name1", name1i, "name2", name2i );
      }

      if ( maj_stat==GSS_S_COMPLETE || mechs2i!=GSS_C_NO_OID_SET ) {
	 if ( compare_oid_set( mechs2, mechs2i )!=0 ) {
	    XVEB((V_ERR, "actual_mechs from acquire_cred() and inquire_cred() DIFFER!\n"));
	    rci++;
	 }
      }

   } /* cred2!=GSS_C_NO_CREDENTIAL */

   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;

   /*
    * Test Case # 3 :
    *  try to inquire the default INITIATING credentials
    */
   XVEB((V_TEST, "*default* initiating credentials (inquire_cred only)\n"));

   rci = inquire_cred( verbose_level, p_gssfp, GSS_C_NO_CREDENTIAL, CTX_INITIATOR, /* default = Ini */
		       &name3i, &lifetime3i, &usage3i, &mechs3i, &maj_stat );

   if ( maj_stat==GSS_S_COMPLETE || name3i!=GSS_C_NO_NAME ) {
      rci += check_lifetime_change( p_trclevel, enter, lifetime1, lifetime3i );
      rci += verify_same_name( p_trclevel, p_gssfp, "inquiring default credentials",
			       "name1", name1i, "name3", name3i );
   }

   if ( maj_stat==GSS_S_COMPLETE || mechs3i!=GSS_C_NO_OID_SET ) {
      rci += verify_oid_subset( 0, "gss_inquire_cred()",
				  "available mechanisms", &our_mechs, "actual_mechs", mechs3i );
   }

   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;

   /* This call should return the name of the default credentials, */
   /* so try hard to find a working call combination ...	   */

   if ( name1i!=GSS_C_NO_NAME ) {
      name = &name1i;
   } else if ( name2i!=GSS_C_NO_NAME ) {
      name = &name2i;
   } else if ( name3i!=GSS_C_NO_NAME ) {
      name = &name3i;
   }
   
   if ( name==NULL ) {
      XVEB((V_ERR, "unable to retrieve name from default initiating credentials!\n"));
      rc++;
   } else {

      /*
       * Test Case # 4 :
       *  try to acquire INITIATING credential (reuse name) with selected mechanism
       */
      XVEB((V_TEST, "named default initiating credentials (acquire_cred with name)\n"));

      rci = acquire_cred( verbose_level, p_gssfp, GSS_C_INITIATE, *name,
			  &our_mechs, &cred4, &mechs4, &lifetime4, &maj_stat );

      if ( cred4!=GSS_C_NO_CREDENTIAL ) {

	 rci += check_lifetime_change( p_trclevel, enter, lifetime1, lifetime4 );
	 rci += verify_oid_subset( 0, "gss_acquire_cred(name!)",
				  "selected mechanism", &our_mechs, "actual_mechs", mechs4 );

	 rci += inquire_cred( verbose_level, p_gssfp, cred4, CTX_INITIATOR, /* see above! */
			      &name4i, &lifetime4i, &usage4i, &mechs4i, &maj_stat );

	 if ( maj_stat==GSS_S_COMPLETE || name4i!=GSS_C_NO_NAME ) {
	    rci += check_lifetime_change( p_trclevel, enter, lifetime1, lifetime4i );
	    rci += verify_same_name( p_trclevel, p_gssfp, "acquiring default credentials by name",
				     "name1", *name, "name4", name4i );
	 }

	 if ( maj_stat==GSS_S_COMPLETE || mechs4i!=GSS_C_NO_OID_SET ) {
	    if ( compare_oid_set( mechs4, mechs4i )!=0 ) {
	       XVEB((V_ERR, "actual_mechs from acquire_cred() and inquire_cred() DIFFER!\n"));
	       rci++;
	    }
	 }

      } /* cred4!=GSS_C_NO_CREDENTIAL */

      XVEB((V_RESULT, rci, 0, NULL ));
      rc += rci;

   }

   /*
    * Test Case # 5 :
    *  try to acquire default INITIATING credential (GSS_C_NO_NAME) with selected mechanism,
    *  leaving out all optional parameters
    */
   XVEB((V_TEST, "acquire_cred and inquire_cred with NO optional parameters\n"));

   rci = acquire_cred( verbose_level, p_gssfp, GSS_C_INITIATE, GSS_C_NO_NAME,
		       &our_mechs, &cred5, NULL, NULL, &maj_stat );

   if ( cred5!=GSS_C_NO_CREDENTIAL ) {

      rci += inquire_cred( verbose_level, p_gssfp, cred5, CTX_INITIATOR, /* see above! */
			  NULL, NULL, NULL, NULL, &maj_stat );

   } /* cred5!=GSS_C_NO_CREDENTIAL */

   XVEB((V_RESULT, rci, 0, NULL ));
   rc += rci;

   /*
    * End Test Cases
    *
    */

   if ( pp_name_ret!=NULL  &&  name!=NULL ) {
      /* This call is supposed to return a gss_name_t */
      *pp_name_ret = *name;
      *name        = GSS_C_NO_NAME;
   }

   rc += release_cred(    p_gssfp, &cred1   );
   rc += release_cred(    p_gssfp, &cred2   );
   rc += release_cred(    p_gssfp, &cred4   );
   rc += release_cred(    p_gssfp, &cred5   );

   rc += release_name( p_gssfp, &name1i  );
   rc += release_name( p_gssfp, &name2i  );
   rc += release_name( p_gssfp, &name3i  );
   rc += release_name( p_gssfp, &name4i  );

   rc += release_oid_set( p_gssfp, &mechs1  );
   rc += release_oid_set( p_gssfp, &mechs1i );
   rc += release_oid_set( p_gssfp, &mechs2  );
   rc += release_oid_set( p_gssfp, &mechs2i );
   rc += release_oid_set( p_gssfp, &mechs3i );
   rc += release_oid_set( p_gssfp, &mechs4  );
   rc += release_oid_set( p_gssfp, &mechs4i );

   return(rc);

} /* check_default_initiator_cred() */




/*
 * printable_name_from_cred()
 *
 *
 */
int
printable_name_from_cred( int	            p_trclevel,    DLL_GSSFP_T   * p_gssfp,
			  gss_cred_id_t     p_cred,	   ctx_type_et	   p_usagetype,
			  char           ** pp_prname,     size_t        * pp_prname_len,
			  gss_OID         * pp_oid )
{
   char             * this_Call  = "printable_name_from_cred";
   gss_name_t         owner	 = GSS_C_NO_NAME;
   gss_name_t	      can_owner	 = GSS_C_NO_NAME;
   gss_buffer_desc    prname;
   gss_OID	      oid	 = GSS_C_NO_OID;
   char		    * tmp_ptr	 = NULL;
   size_t	      tmp_len	 = 0;
   OM_uint32	      maj_stat;
   int		      rc	 = 0;

   (*pp_prname)     = NULL;
   (*pp_prname_len) = 0;

   prname.value     = NULL;
   prname.length    = 0;

   rc += inquire_cred( verbose_level, p_gssfp, p_cred, p_usagetype,
		       &owner, NULL, NULL, NULL, &maj_stat );
   
   if ( owner!=GSS_C_NO_NAME ) {

      if ( p_gssfp->gss_canonicalize_name==0 ) {

	 /* gss_canonicalize_name() not defined -- just take original instead */
	 can_owner = owner;
	 owner     = GSS_C_NO_NAME;

      } else {

	 rc += canonicalize_name( verbose_level, p_gssfp, owner,
				  p_gssfp->mech, &can_owner, &maj_stat );

      }

      if ( can_owner==GSS_C_NO_NAME ) {

	 XVEB((V_ERR, "%(): unable to canonicalize name!\n", this_Call ));
	 rc++;

      } else {

	 rc += display_name( verbose_level, p_gssfp, owner, &prname, &oid, &maj_stat );
	 if ( prname.length==0  ||  prname.value==NULL ) {
	    rc++; /* Huh?  No name returned ?? */
	 } else {
	    VERBOSE_DUPMEM( prname.value, prname.length, tmp_ptr, tmp_len );
	    (*pp_prname)     = tmp_ptr;
	    (*pp_prname_len) = tmp_len;
	 }

	 if ( oid==GSS_C_NO_OID ) {

	    XVEB((V_ERR, "%s(): missing nametype oid from display_name()!\n", this_Call ));
	    rc++;
	 
	 } else { /* oid!=GSS_C_NO_OID */

	    if ( pp_oid!=NULL ) {

	       if (*pp_oid==GSS_C_NO_OID) {

		  (*pp_oid) = oid;

	       } else { /* (*pp_oid)!=GSS_C_NO_OID */

		  if ( compare_oid(oid, (*pp_oid))!=0 ) {
		     XVEB((V_ERR, "%s(): Unexpected nametype_oid returned from display_name()\n",
				  this_Call));
		     print_oid( 2, "expected",     *pp_oid );
		     print_oid( 2, "got nametype",  oid    );
		     rc++;
		  }

	       } /* (*pp_oid)!=GSS_C_NO_OID */

	    } /* oid!=GSS_C_NO_OID */

	 } /* oid!=GSS_C_NO_OID */

      } /* can_owner!=GSS_C_NO_NAME */

   } /* owner!=GSS_C_NO_NAME */

   rc += release_buffer( p_gssfp, &prname    );
   rc += release_name(   p_gssfp, &owner     );
   rc += release_name(   p_gssfp, &can_owner );

   return(rc);

} /* printable_name_from_cred() */
