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

static char * this_File GNU_UNUSED = __FILE__;

/************************************************************************/
/* $Id: //tools/src/freeware/gsstest/oids.c#4 $
 ************************************************************************
 *
 * 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"



/*
 * release_oid_set()
 *
 */
int
release_oid_set( DLL_GSSFP_T * p_gssfp, gss_OID_set * pp_oid_set )
{
   char      * gss_call = "gss_release_oid_set";
   OM_uint32   min_stat;
   OM_uint32   maj_stat;
   int	       rc	= 0;

   if ( *pp_oid_set==BOGUS_OID_SET ) {

      *pp_oid_set = GSS_C_NO_OID_SET;

   } else if ( *pp_oid_set!=GSS_C_NO_OID_SET ) {

      BOGUS_INI_MINOR( min_stat );

      start_timer();
      maj_stat = (p_gssfp->gss_release_oid_set)( &min_stat, pp_oid_set );
      timedelay = read_timer();
      rc += print_status(p_gssfp, GSS_RELEASE_OID_SET, maj_stat, min_stat);

      if (maj_stat!=GSS_S_COMPLETE) {

	 rc++;

      }
      if ( *pp_oid_set!=GSS_C_NO_OID_SET ) {
	 XVEB((V_ERR, "%s() didn't clear handle !\n", gss_call));
	 *pp_oid_set = GSS_C_NO_OID_SET;
	 rc++;
      }
   }

   return(rc);

} /* release_oid_set() */



struct known_oids_s {
   gss_OID_desc     oid;
   char           * label;
   oid_type_et	    type;
};

static struct known_oids_s known_oids[] = {
   /*=========================================================================*/
   /* here are some recognized Nametype OIDs			              */
   /*=========================================================================*/

   /****************************/
   /* well known Nametype OIDs */
   /****************************/
   {
      {  6, (void *)"\x2b\x06\x01\x05\x06\x02"			}, /* IANA: hostbased service {1 3 6 1 5 6 2} (new but DEPRECATED !) */
      "(GSS_C_NT_HOSTBASED_SERVICE_X)",
      OID_NAMETYPE
   },
   {
      {  6, (void *)"\x2b\x06\x01\x05\x06\x03"			}, /* IANA: anonymous name    {1 3 6 1 5 6 3} */
      "GSS_C_NT_ANONYMOUS",
      OID_NAMETYPE
   },
   {
      {  6, (void *)"\x2b\x06\x01\x05\x06\x04"			}, /* IANA: exported name     {1 3 6 1 5 6 4} */
      "GSS_C_NT_EXPORTED_NAME",
      OID_NAMETYPE
   },
   {
      { 10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"	}, /* MIT: user name          {1 2 840 113554 1 2 1 1} */
      "GSS_C_NT_USER_NAME",
      OID_NAMETYPE
   },
   {
      { 10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"	}, /* MIT: Machine UID name   {1 2 840 113554 1 2 1 2} */
      "GSS_C_NT_MACHINE_UID_NAME",
      OID_NAMETYPE
   },
   {
      { 10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"	}, /* MIT: String UID name    {1 2 840 113554 1 2 1 3}*/
      "GSS_C_NT_STRING_UID_NAME",
      OID_NAMETYPE
   },
   {
      { 10, (void *)"\052\206\110\206\367\022\001\002\001\004"	}, /* MIT: Hostbased Service  {1 2 840 113554 1 2 1 4} */
      "GSS_C_NT_HOSTBASED_SERVICE",
      OID_NAMETYPE
   },
   {
      { 10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"  }, /* MIT: Kerberos 5 principal name (rfc1964)       {1 2 840 113554 1 2 2 1}*/
      "GSS_KRB5_NT_PRINCIPAL_NAME",
      OID_NAMETYPE
   },

   /******************************/
   /* lesser known Nametype OIDs */
   /******************************/
   {
      { 10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x02"  }, /* MIT: Kerberos 5 principal name (internal form) {1 2 840 113554 1 2 2 2} */
      "Huh? This is not in rfc1964!",
      OID_NAMETYPE
   },
   {
      { 11, "\053\006\001\004\001\205\066\002\001\002\001"	}, /* SAP: SAPntlm "NT-domain\user" {1 3 6 1 4 1 694 2 1 2 1} */
      "GSS_SAP_NT_DOMAIN_USER",
      OID_NAMETYPE
   },
   {
      {  6, "\053\044\003\001\046\001"			        }, /* SECUDE: Secude X.500 Distinguished Name {1 3 36 3 1 38 1} */
      "GSS_SECUDE_NT_X500_NAME",
      OID_NAMETYPE
   },
   {
      {  9, "\053\006\001\004\001\201\172\002\001"	        }, /* Entrust SPKM X.500 Distinguished Name {1 3 6 1 4 1 250 2 1} */
      "GSS_ENTRUST_NT_X500_NAME",
      OID_NAMETYPE
   },

   {
      { 10, "\052\206\072\000\001\331\310\145\005\001"	        }, /* Baltimore ECS SPKM X.500 Distinguished Name {1 2 826 0 1 1467493 5 1} */
      "Baltimore ECS Desktop X.500 DN",
      OID_NAMETYPE
   },

   {
      {  9, "\052\206\110\206\367\015\005\004\002"	        }, /* SecurityDynamics Keon Agent Name {1 2 840 113549 5 4 2} */
      "SecurityDynamics Keon Agent Name",
      OID_NAMETYPE
   },

   {
      { 10, "\052\203\010\214\232\103\002\002\002\001"	        }, /* NEC SecureWare X.500 Distinguished Name {1 2 392 200003 2 2 2 1} */
      "NEC SecureWare X.500 DN",
      OID_NAMETYPE
   },

   {
      { 10, "\053\006\001\004\001\226\171\245\112\002"	        }, /* secunet T-Secure X.500 DN  {1 3 6 1 4 1 2937 4810 2} */
      "secunet T-Secure X.500 DN",
      OID_MECHANISM
   },

   {
      { 10, "\053\006\001\004\001\244\146\002\002\003"	        }, /* Safelayer KeyOne ToolKit X.500 DN  {1 3 6 1 4 1 4710 2 2 3} */
      "Safelayer KeyOne X.500 DN",
      OID_NAMETYPE
   },

   {
       {  9, "\053\006\001\004\001\273\143\002\002"             }, /* Unisecurity SecuTrust X.500 DN  {1 3 6 1 4 1 7651 2 2} */
       "Unisecurity SecuTrust X.500 DN",
       OID_NAMETYPE
   },

   {
       {  9, "\052\131\026\140\154\073\002\004\001"             }, /* SECUI.COM TrustNet X.500 DN  {1 2 89 22 96 108 59 2 4 1} */
       "SECUI.COM TrustNet X.500 DN",
       OID_NAMETYPE
   },

   {
       { 10, "\052\203\032\214\232\116\007\002\001\002"         }, /* Penta Security Systems X.500 DN {1 2 410 200014 7 2 1 2} */
       "Penta Security Systems X.500 DN",
	OID_NAMETYPE
   },

   {
       {  9, "\053\006\001\004\001\365\137\002\001"             }, /* Frontier Solutions Inc. X.500 DN  {1 3 6 1 4 1 15071 2 1} */
       "Frontier Solutions Inc. X.500 DN",
       OID_NAMETYPE
   },

   {
       { 10, "\053\006\001\004\001\327\012\003\001\002"         }, /* Siemens Information Systems Ltd. SISLER X.500 DN  {1 3 6 1 4 1 11146 3 1 2} */
       "Siemens SISLER X.500 DN",
       OID_NAMETYPE
   },

   {
       { 11, "\053\006\001\004\001\213\072\163\171\001\014"     }, /* DN OID from RFC-2252 Section 6.9 LDAPv3 Attribute Syntax Def */
       "DN from rfc-2252-6.9 LDAPv3",
	OID_NAMETYPE
   },

   {
       { 10, "\x2B\x06\x01\x04\x01\xAF\x2B\x03\x01\x02"         }, /* AdNovum GSSv2 Distinguished Name */
       "AdNovum GSSv2 DN",
       OID_NAMETYPE
   },

   {
       {  9,  "\x2b\x06\x01\x04\x01\x81\x9e\x5d\x02"            }, /* LISSI X.500 Distinguished Name  {1 3 6 1 4 1 20317 2} */
       "GSS_LISSI_NT_X500_NAME",
       OID_NAMETYPE
   },

   /*=========================================================================*/
   /* here are some recognized Mechanism OIDs				      */
   /*=========================================================================*/

   /*****************************/
   /* well known Mechanism OIDs */
   /*****************************/
   {
      {  5, "\053\005\001\005\002"			        }, /* DOD: Kerberos 5 (old)  {1 3 5 1 5 2}   */
      "Kerberos 5 (PRE-rfc1964)",
      OID_MECHANISM
   },
   {
      {  9, "\052\206\110\206\367\022\001\002\002"	        }, /* MIT: Kerberos 5 (RFC1964) {1 2 840 113554 1 2 2} */
      "Kerberos 5 (v2 - rfc1964)",
      OID_MECHANISM
   },
   {
      {  7, "\053\006\001\005\005\001\001"			}, /* Entrust: SPKM-1   {1 3 6 1 5 5 1 1} */
      "SPKM-1 (rfc2025)",
      OID_MECHANISM
   },
   {
      {  7, "\053\006\001\005\005\001\002"		        }, /* Entrust: SPKM-2   {1 3 6 1 5 5 1 2} */
      "SPKM-2 (rfc2025)",
      OID_MECHANISM
   },
   {
      {  7, "\053\006\001\005\005\001\003"		        }, /* Mike Eisler: LIPKEY / SPKM-3    {1 3 6 1 5 5 1 3} */
      "LIPKEY / SPKM-3 (rfc2847)",
      OID_MECHANISM
   },
   {
      {  7, "\052\014\002\207\163\007\005"		        }, /* DASS MechType is  {1 3 12 2 1011 7 5} */
      "DEC DASS (rfc1507)",
      OID_MECHANISM
   },
   {
      {  6, "\053\014\001\056\001\003"			        }, /* SESAME v3  1.3.12.1.46.1.3 */
      "SESAME v3",
      OID_MECHANISM
   },
   {
      {  6, "\053\014\001\056\001\004"			        }, /* SESAME v4  1.3.12.1.46.1.4 */
      "SESAME v4",
      OID_MECHANISM
   },
   {
      {  6, "\053\014\001\056\001\005"			        }, /* SESAME v5  {1 3 12 1 46 1 5} */
      "SESAME v5",
      OID_MECHANISM
   },
   {
      {  6, "\053\006\001\005\005\002"			        }, /* SPNEGO  {1 3 6 1 5 5 2}  iso.org.dod.internet.security.mechanism.snego (see RFC2478) */
      "SPNEGO (rfc2478)",
      OID_MECHANISM
   },

   /*******************************/
   /* lesser known Mechanism OIDs */
   /*******************************/
   {
      {  6, "\053\044\003\001\045\001"			        }, /* SECUDE: SECUDE 5.0  {1 3 36 3 1 37 1} */
      "Secude 5",
      OID_MECHANISM
   },
   {
      { 10, "\053\006\001\004\001\205\066\002\001\002"	        }, /* SAP: SAPntlm {1 3 6 1 4 1 694 2 1 2} */
      "SAPntlm SSO (NT4/Win95)",
      OID_MECHANISM
   },

   {
      {  7, "\053\014\001\056\001\062\001"                      }, /* AccessMaster GSS-Light  { 1 3 12 1 46 1 50 1} */
      "AccessMaster GSS-Light",
      OID_MECHANISM
   },

   {
      {  7, "\053\014\001\056\001\062\002"                      }, /* AccessMaster DCE  {1 3 12 1 46 1 50 2} */
      "AccessMaster DCE",
      OID_MECHANISM
   },

   {
      { 10, "\052\206\072\000\001\331\310\145\003\002"	        }, /* Baltimore ECS IDUP-GSSAPI mechanism {1 2 826 0 1 1467493 3 2} */
      "Baltimore ECS Desktop IDUP-Mechanism",
      OID_MECHANISM
   },

   {
      {  9, "\052\206\110\206\367\015\005\004\001"	        }, /* SecurityDynamics Keon Agent {1 2 840 113549 5 4 1} */
      "SecurityDynamics Keon Agent",
      OID_MECHANISM
   },

   {
      {  9, "\052\206\110\206\367\015\005\004\003"	        }, /* RSA Keon Agent {1 2 840 113549 5 4 3} */
      "RSA Keon Agent",
      OID_MECHANISM
   },

   {
      {  9, "\052\203\010\214\232\103\002\002\002"	        }, /* NEC SecureWare {1 2 392 200003 2 2 2} */
      "NEC SecureWare",
      OID_MECHANISM
   },

   {
      { 10, "\053\006\001\004\001\226\171\245\112\001"	        }, /* secunet T-Secure gssapi mechanism  {1 3 6 1 4 1 2937 4810 1} */
      "secunet T-Secure",
      OID_MECHANISM
   },

   {
      { 10, "\053\006\001\004\001\244\146\002\001\001"	        }, /* Safelayer KeyOne ToolKit SSL mechanism  {1 3 6 1 4 1 4710 2 1 1} */
      "Safelayer KeyOne Toolkit",
      OID_MECHANISM
   },

   {
      {  9, "\052\131\026\140\154\073\002\003\001"              }, /* SECUI TrustNet  {1 2 89 22 96 108 59 2 3 1} */
      "SECUI.COM TrustNet",
      OID_MECHANISM
   },

   {
      { 10, "\052\203\032\214\232\116\007\002\001\001"          }, /* Penta Security Systems ISIGN  {1 2 410 200014 7 2 1 1} */
      "Penta Security Systems ISIGN",
      OID_MECHANISM
   },

   {
      { 10, "\053\006\001\004\001\327\012\003\001\001"          }, /* Siemens Information Systems SISLER {1 3 6 1 4 1 11146 3 1 1} */
      "Siemens Information Systems SISLER",
      OID_MECHANISM
   },

   {
       { 10, "\x2B\x06\x01\x04\x01\xAF\x2B\x03\x01\x01"         }, /* AdNovum GSSv2 Mechanism */
       "AdNovum GSSv2",
       OID_NAMETYPE
   },

   {
       {  9,  "\x2b\x06\x01\x04\x01\x81\x9e\x5d\x01"            }, /* LISSI-SNC 1.0  {1 3 6 1 4 1 20317 1} */
       "LISSI-SNC",
       OID_MECHANISM
   },

   /*=========================================================================*/
   /* Other OIDs around GSS-API (haven't figured out what these are used for) */
   /*=========================================================================*/

   /* DCE OIDs (I don't know what they really are) */
   {
      {  4, "\053\030\011\011"				       }, /* DCE 1.1   1.3.24.9.9  */
      "GSSDCE_C_OID_DCENAME",
      OID_MECHANISM
   },

   {
      {  4, "\053\030\011\010"				       }, /* DCE 1.1   1.3.24.9.8  */
      "GSSDCE_C_OID_DCE_KRBV5_DES",
      OID_MECHANISM
   },

   {
      {  9, "\052\203\110\206\367\022\001\002\002"	       }, /* DCE 1.1  1.2.456.113554.1.2.2 */
      "GSSDCE_C_OID_KRBV5_DES_RFC",
      OID_MECHANISM
   },

   /* Marker for the end of the list */
   {
      {  0, NULL },
      (char *)0
   }

};

gss_OID	 nt_hb_service_alt    = &(known_oids[0].oid);
gss_OID  nt_anonymous	      = &(known_oids[1].oid);
gss_OID  nt_export_name	      = &(known_oids[2].oid);
gss_OID  nt_user_name	      = &(known_oids[3].oid);
gss_OID	 nt_machine_uid	      = &(known_oids[4].oid);
gss_OID	 nt_string_uid	      = &(known_oids[5].oid);
gss_OID	 nt_hb_service	      = &(known_oids[6].oid);




/*
 * oid_to_str()
 *
 * The length of the static buffer oidbuf[] limits the length of
 * the OID that may be successfully converted into printable
 * with this function.  However, it should be sufficient for all
 * OIDs with reasonable length.
 *
 */
char *
oid_to_str( gss_OID	p_oid )
{
   static char oidbuf[256];
   char        numbuf[32];
   Ulong       num; 
   int         more;
   Uint        i, curlen, len, maxch;
   Uchar     * bytes;
   Uchar       uch;

   maxch = (sizeof(oidbuf)/sizeof(oidbuf[0])) - 8; /* reserve space at the end */
   memset(oidbuf, 0, sizeof(oidbuf));

   if ( p_oid==NULL ) {

      /* this is not really an OID, but GSS_C_NO_OID is a valid */
      /* input in many places and we don't want to special-case */
      /* the visualization in the upper layers.                 */
      strcpy( oidbuf, "(NULL)" );

   } else { /* p_oid!=NULL */

      bytes = (unsigned char *)(p_oid->elements);
      uch   = bytes[0];
      sprintf(oidbuf, "{%u %u", (unsigned int)(uch/40), (unsigned int)(uch%40));

      curlen = (unsigned int)strlen(oidbuf);
      more   = FALSE;

      for( i=1 ; i<p_oid->length ; i++ ) {
	 uch  = bytes[i];
	 num  = (uch & 0x7f) + ( (more) ? (num<<7) : 0 );
	 more = ( (uch>127) ? TRUE : FALSE );
	 if (more==FALSE) {
	    sprintf(numbuf," %lu", (Ulong)num);
	    len = (unsigned int)strlen(numbuf);
	    if ( len + 1 + 1 + curlen > maxch ) {
	       memcpy( &(oidbuf[curlen]), " ...", (size_t)5 );
	       curlen += 4;
	       more    = FALSE;
	       break;
	    }
	    memcpy( &(oidbuf[curlen]), numbuf, (size_t)(len+1) );
	    curlen += len;
	 }
      }

      if (more!=FALSE) {
         memcpy( &(oidbuf[curlen]), " TR!", (size_t) 5 );
	 curlen += 4;
      }

      oidbuf[curlen++] = '}';
      oidbuf[curlen]   = '\0';

   } /* p_oid!=NULL */

   return(oidbuf);

} /* oid_to_str() */




/***************************************************************
 * compare_oid()
 *
 * Compares two gss_OID objects.
 *   returns   0   when p_oid1 == p_oid2
 *   returns !=0   other times
 *
 ***************************************************************/
int
compare_oid( gss_OID  p_oid1, gss_OID  p_oid2 )
{
   unsigned char *p1, *p2;
   int            l1, l2;

   if ( p_oid1 == p_oid2 ) { return( 0); }
   if ( p_oid1 == NULL   ) { return(-1); }
   if ( p_oid2 == NULL   ) { return( 1); }

   /* casting size_t down to ints                      */
   /* OIDs longer than ANSI-C INT_MAX are bogus anyway */
   l1 = (int)p_oid1->length;
   l2 = (int)p_oid2->length;

   p1 = (unsigned char *) p_oid1->elements;
   p2 = (unsigned char *) p_oid2->elements;

   /* I'm too lazy to further break these special cases down right now */
   if ( p1==NULL || p2==NULL || l1==0 || l2==0 ) { return(-1); }

   if ( l1 != l2 ) { return( l1 - l2 ); }

   return( memcmp( p1, p2, l1 ) );

} /* compare_oid() */




/***************************************************************
 * compare_oid_set()
 *
 * Compares two gss_OID_set objects.
 *   returns   0   when p_oid_set1 == p_oid_set2
 *   returns !=0   other times
 *
 ***************************************************************/
int
compare_oid_set( gss_OID_set  p_oid_set1, gss_OID_set  p_oid_set2 )
{
   gss_OID        p1, p2;
   int            c1, c2;
   int            rc = -1;
   int            i;
   int            j;

   if ( p_oid_set1 == p_oid_set2 ) { return( 0); }
   if ( p_oid_set1 == NULL       ) { return(-1); }
   if ( p_oid_set2 == NULL       ) { return( 1); }


   /* casting size_t down to ints                            */
   /* OID_sets larger than ANSI-C INT_MAX are awkward anyway */
   c1 = (int)p_oid_set1->count;
   c2 = (int)p_oid_set2->count;

   p1 = p_oid_set1->elements;
   p2 = p_oid_set2->elements;

   /* I'm too lazy to further break these special cases down right now */
   if ( p1==NULL || p2==NULL || c1==0 || c2==0 ) { return(-1); }

   if ( c1 != c2 ) { return( c1 - c2 ); }

   for ( i=0 ; i<c1 ; i++ ) {
      rc = compare_oid( &(p1[i]), &(p2[i]) );
      if ( rc!=0 ) {
	 /* maybe the oids are in a different order ? (rarely) */
	 for ( j=0 ; j<c2 ; j++ ) {
	    rc = compare_oid( &(p1[i]), &(p2[j]) );
	    if (rc==0)
	       break;
	 }
	 if (rc!=0)
	    return(rc);
      }
   }

   return( 0 );

} /* compare_oid_set() */




/*
 * check_oid_in_oidset()
 *
 * returns:
 *   rc == 0:   p_oid is     contained in p_oid_set
 *   rc  > 0:   p_oid is NOT contained in p_oid_set
 */
int
check_oid_in_oidset( int      p_trclevel,
		     char   * p_name,       gss_OID       p_oid,
		     char   * p_name_set,   gss_OID_set   p_oid_set )
{
   int    rc = 0;
   int    vlevel;
   int    found;
   Uint   i;
   
   vlevel = ( p_trclevel>=2 ) ? 2 : 0;

   if ( p_oid==GSS_C_NO_OID ) {
      rc++;
      XVEB((V_OK, vlevel, "check_oid_in_oidset(): NULL gss_OID \"%s\"!\n", p_name));
   } else if ( p_oid->length==0  ||  p_oid->elements==NULL ) {
      rc++;
      XVEB((V_OK, vlevel, "check_oid_in_oidset(): Invalid gss_OID \"%s\"!\n", p_name));
   }

   if ( p_oid_set==GSS_C_NO_OID_SET ) {
      rc++;
      XVEB((V_OK, vlevel, "check_oid_in_oidset(): NULL gss_OID_set \"%s\"!\n", p_name_set));
   } else if ( p_oid_set->count==0  ||  p_oid_set->elements==NULL ) {
      rc++;
      XVEB((V_OK, vlevel, "check_oid_subset(): %s gss_OID_set \"%s\"!\n",
		  p_oid_set->count==0 ? "EMPTY" : "Invalid",   p_name_set));
   }

   if ( rc>0 ) 
      return(rc);

   for ( i=0 , found=0 ; i<p_oid_set->count ; i++ ) {
      if ( compare_oid( p_oid, &(p_oid_set->elements[i]) )==0 ) {
	 found=1;
	 break;
      }
   }

   if ( found==0 ) {
      rc++;
      XVEB((V_OK, vlevel, "check_oid_in_oidset(): OID \"%s\" missing from OID_set \"%s\"!\n",
		  p_name, p_name_set ));
   
   }

   return(rc);

} /* check_oid_in_oidset() */




/*
 * validate_oid()
 *
 *
 */
int
validate_oid( DLL_GSSFP_T * p_gssfp,
	      oid_type_et   p_oid_type,   char     * p_prefix,
	      char        * p_name_oid,   gss_OID    p_oid )
{
   int	    rc = 0;

   if ( p_oid==GSS_C_NO_OID ) {

      XVEB((V_ERR, "%s: %s==GSS_C_NO_OID -- INVALID!\n",
	           p_prefix, p_name_oid ));
      rc++;

   } else if ( p_oid->length==0 || p_oid->elements==NULL ) {

      XVEB((V_ERR, "%s: %s=={length=%u, elements=ptr:%p} -- INVALID!\n",
		   p_prefix, p_name_oid,
		   (Uint)p_oid->length, p_oid->elements));
      rc++;

   } else {

      switch( p_oid_type ) {

	 case OID_NAMETYPE:
	    if ( p_gssfp->nt_list!=GSS_C_NO_OID_SET ) {
	       rc = check_oid_in_oidset( 0, p_name_oid, p_oid,
				         "supported nametypes", p_gssfp->nt_list );
	       if ( rc!=0 ) {
		  XVEB((V_ERR, "%s: %s not in supported nametypes!!\n",
			p_prefix, p_name_oid ));
	       }
	    }
	    break;

	 case OID_MECHANISM:
	    if ( p_gssfp->mech_set!=GSS_C_NO_OID_SET ) {
	       rc = check_oid_in_oidset( 0, p_name_oid, p_oid,
					  "supported mech_set", p_gssfp->mech_set );
	       if ( rc!=0 ) {
		  XVEB((V_ERR, "%s: %s not in supported mechanisms!!\n",
			p_prefix, p_name_oid ));
	       }
	    }
	    break;

	 case OID_ANY:
	 default:	break;

      } /* end switch() */

   }

   return(rc);

} /* validate_oid() */



/*
 * validate_oidset()
 *
 * verify an gss_OID_set if it at least looks like it could be valid
 *
 */
int
validate_oidset( DLL_GSSFP_T  * p_gssfp,
		 oid_type_et    p_oid_type,      char         * p_prefix,
		 char         * p_name_set,      gss_OID_set    p_oid_set )
{
   gss_OID  oid;
   int	    rc     = 0;
   int	    result = 0;
   Uint	    i;

   if ( p_oid_set==GSS_C_NO_OID_SET ) {

      XVEB((V_ERR, "%s: %s==GSS_C_NO_OID_SET -- INVALID!\n",
      p_prefix, p_name_set));
      rc++;

   } else if ( p_oid_set->count==0 && p_oid_set->elements==NULL ) {

      XVEB((V_ERR, "%s: %s=={0, ptr:NULL} -- INVALID!\n",
      p_prefix, p_name_set));
      rc++;

   } else if ( p_oid_set->count==0 || p_oid_set->elements==NULL ) {

      XVEB((V_ERR, "%s: %s=={%u,ptr:%p} -- INVALID!\n",
		   p_prefix, p_name_set,
		   (Uint) p_oid_set->count, p_oid_set->elements ));
      rc++;

   } else if ( p_oid_set->count>200 ) {

      XVEB((V_ERR, "%s: %s=={%u,ptr:%p} -- OID flood (%u)??\n",
		   p_prefix, p_name_set,
		   (Uint) p_oid_set->count, p_oid_set->elements ));
      rc++;

   } else {
      
      for ( i=0 ; i<p_oid_set->count ; i++ ) {
	 oid = &(p_oid_set->elements[i]);

	 if ( oid->length>32 ) {
	    XVEB((V_ERR, "%s: gss_OID_set %s {count=%u, elements=ptr:%p}\n"
			 "          contains a giant member OID [%u] {length=%u, elements=ptr:%p}!\n",
			 p_prefix, p_name_set,
			 (Uint)p_oid_set->count, p_oid_set->elements,
			 (Uint)i, (Uint)oid->length, oid->elements ));
	    rc++;
	    break;
	 }

	 if ( oid->length==0 || oid->elements==NULL ) {
	    XVEB((V_ERR, "%s: gss_OID_set %s {count=%u, elements=ptr:%p}\n"
		         "          contains an INVALID member OID [%u] {length=%u, elements=ptr:%p}!\n",
			 p_prefix, p_name_set,
			 (Uint)p_oid_set->count, p_oid_set->elements,
			 (Uint)i, (Uint)oid->length, oid->elements ));
	    rc++;
	    break;
	 }

	 switch( p_oid_type ) {


	    case OID_NAMETYPE:
		  if ( p_gssfp->nt_list!=GSS_C_NO_OID_SET ) {
		     char  tname[32];
		     result = check_oid_in_oidset( 0, NULL, oid, NULL, p_gssfp->nt_list );
		     if (result!=0) {
			rc++;
			XVEB((V_ERR, "%s: member OID #%u of \"%s\" (%u oids)\n"
			             "       was not indicated by gss_inquire_nametypes_for_mech():\n",
				     p_prefix, (Uint)i, p_name_set, (Uint)p_oid_set->count ));
			sprintf(tname, "oid[%u]", (Uint)i);
			print_oid(2, tname, oid );
		     }
		  }
		  break;


	    case OID_MECHANISM:
		  if ( p_gssfp->mech_set!=GSS_C_NO_OID_SET ) {
		     char  tname[32];
		     result = check_oid_in_oidset( 0, NULL, oid, NULL, p_gssfp->mech_set );
		     if ( result!=0 ) {
			rc++;
			XVEB((V_ERR, "%s: member OID #%u of \"%s\" (%u oids)\n"
				     "       was not indicated by gss_indicate_mechs():\n",
				     p_prefix, (Uint)i, p_name_set, (Uint)p_oid_set->count ));
			sprintf(tname, "oid[%u]", (Uint)i);
			print_oid(2, tname, oid );
		     }
		  }
		  break;


	    case OID_ANY:
	    default:
		  break;

	 }

      }
   }

   return(rc);

} /* validate_oidset() */




/*
 * check_oid_subset()
 *
 * returns:
 *   rc == 0:   p_oid_set1 is     a subset of p_oid_set2
 *   rc  > 0:   p_oid_set1 is NOT a subset of p_oid_set2 
 */
int
check_oid_subset( int      p_trclevel,
		  char   * p_name_set1,    gss_OID_set   p_oid_set1,
		  char   * p_name_set2,    gss_OID_set   p_oid_set2 )
{
   gss_OID   oid1;
   gss_OID   oid2;
   int       vlevel;
   int       rc = 0;
   int       found;
   Uint   i, j;

   vlevel = (p_trclevel>=2 ) ? 2 : 0;

   if ( p_oid_set1==GSS_C_NO_OID_SET ) {
      rc++;
      XVEB((V_OK, vlevel, "check_oid_subset(): NULL gss_OID_set \"%s\"!\n", p_name_set1));
   } else if ( p_oid_set1->count==0  ||  p_oid_set1->elements==NULL ) {
      rc++;
      XVEB((V_OK, vlevel, "check_oid_subset(): %s gss_OID_set \"%s\"!\n",
		  p_oid_set1->count==0 ? "EMPTY" : "Invalid",   p_name_set1));
   }

   if ( p_oid_set2==GSS_C_NO_OID_SET ) {
      rc++;
      XVEB((V_OK, vlevel, "check_oid_subset(): NULL gss_OID_set \"%s\"!\n", p_name_set2));
   } else if ( p_oid_set2->count==0  ||  p_oid_set2->elements==NULL ) {
      rc++;
      XVEB((V_OK, vlevel, "check_oid_subset(): %s gss_OID_set \"%s\"!\n",
		  p_oid_set2->count==0 ? "EMPTY" : "Invalid",   p_name_set2));
   }

   if ( rc>0 )
      return(rc);


   for ( i=0 ; i<p_oid_set1->count ; i++ ) {
      oid1 = &(p_oid_set1->elements[i]);
      if ( oid1->length==0 || oid1->elements==NULL ) {
	 XVEB((V_ERR, "check_oid_subset(): invalid gss_OID_set %s!\n", p_name_set1));
	 rc++;
	 break;
      }
      for ( j=0, found=0 ; j<p_oid_set2->count ; j++ ) {
	 oid2 = &(p_oid_set2->elements[j]);
	 if ( oid2->length==0 || oid2->elements==NULL ) {
	    XVEB((V_ERR, "check_oid_subset(): invalid gss_OID_set %s!\n", p_name_set2));
	    rc++;
	    break;
	 }
	 if ( compare_oid( oid1, oid2 )==0 ) {
	    found=1;
	    break;
	 }
      }
      if (found==0) {
	 rc++;
	 XVEB((V_OK, vlevel, "check_oid_subset(): OID #%u from OID_set \"%s\" invalid or missing in \"%s\"!\n",
	       (Uint)i, p_name_set1, p_name_set2 ));
      }
   }

   return(rc);

} /* check_oid_subset() */




/*
 * verify_oid_subset()
 *
 *
 */
int
verify_oid_subset( int      p_trclevel,
		   char   * p_prefix,
		   char   * p_name_set1,   gss_OID_set   p_oid_set1,
		   char   * p_name_set2,   gss_OID_set   p_oid_set2 )
{
   int     rc = 0;

   if ( p_trclevel>=3 ) {
      XVEB((V_SHOW, "%s: called verify_oid_subset( %s, %s ) with\n",
		     p_prefix, p_name_set1, p_name_set2 ));
      print_oid_set( 2, p_name_set1, p_oid_set1 );
      print_oid_set( 2, p_name_set2, p_oid_set2 );
   }

   rc += validate_oidset( NULL, OID_ANY, p_prefix, p_name_set1, p_oid_set1 );
   rc += validate_oidset( NULL, OID_ANY, p_prefix, p_name_set2, p_oid_set2 );

   if ( rc==0 ) {
      if ( check_oid_subset( 0, p_name_set1, p_oid_set1, p_name_set2, p_oid_set2 )!=0 ) {
	 XVEB((V_ERR, "%s: %s is NOT a subset of %s !\n",
	              p_prefix, p_name_set1, p_name_set2));
	 rc++;
      }
   }

   return(rc);

} /* verify_oid_subset() */





/*
 * print_oid()
 *
 *
 */
int
print_oid( int p_trclevel, char * p_name, gss_OID p_oid )
{
   char   * oid_string = NULL;
   char   * oid_label  = "";
   char   * oid_type   = "";
   int      i; 

   /* first: always check for invalid gss_OID structures */
   if ( p_oid!=GSS_C_NO_OID ) {
      if (    (p_oid->length==0 && p_oid->elements!=NULL)
	   || (p_oid->length>0  && p_oid->elements==NULL) ) {
	 XVEB((V_ERR, "    %s is an INVALID gss_OID (length=%u, elements=ptr:%p)\n",
		     p_name,  (Uint)p_oid->length, p_oid->elements ));
	 return(1);
      }
   }

   /* generate no ouput for p_trclevel==0 */
   if ( p_trclevel<=0 )
      return(0);

   oid_string = oid_to_str( p_oid );

   if ( p_oid==GSS_C_NO_OID ) {

      oid_label = "GSS_C_NO_OID";

   } else { /* p_oid!=GSS_C_NO_OID */

      for ( i=0 ; known_oids[i].label!=NULL ; i++ ) {
	 if ( compare_oid( p_oid, &(known_oids[i].oid) )==0 ) {
	    oid_label = known_oids[i].label;
	    if (known_oids[i].type==OID_MECHANISM) {
	       oid_type = "MECH= ";
	    } else if (known_oids[i].type==OID_NAMETYPE) {
	       oid_type = "  NT= ";
	    }
	    break;
	 }
      }

   } /* p_oid!=GSS_C_NO_OID */

   if ( p_name==NULL || p_name[0]=='\0' ) {

      XVEB((V_SHOW, "      %-35s %s%s\n",
	    oid_string, oid_type, oid_label));

   } else {

      XVEB((V_SHOW, "  %s = %-30s %s%s\n",
	    p_name, oid_string, oid_type, oid_label));

   }

   return(0);

} /* print_oid() */




/*
 * dump_oid_cstruct()
 *
 *
 */
void
dump_oid_cstruct( int p_trclevel, char * p_prefix, gss_OID p_oid )
{
   char     dump[256];
   size_t   len;
   size_t   j;

   if ( p_trclevel>=0 && p_oid!=GSS_C_NO_OID && p_oid->length<(sizeof(dump)/8) ) {

      sprintf( dump, "{ %u, \"", (Uint)p_oid->length );
      for ( j=0 ; j<p_oid->length ; j++ ) {
	 len = strlen(dump);
	 sprintf( &(dump[len]), "\\%03o", (int) ((Uchar *)(p_oid->elements))[j] );
      }
      len = strlen(dump);
      sprintf( &(dump[len]), "\" }" );

      XVEB((V_SHOW, "  %s = %s\n", p_prefix, dump ));

   }

   return;

} /* dump_oid_cstruct() */




/*
 * print_oid_set()
 *
 *
 */
int
print_oid_set( int p_trclevel, char * p_name, gss_OID_set p_oid_set )
{
   char     index[32];
   Uint     i;
   int      rc       = 0;

   /* first: always check for defective gss_OID_sets */ 
   if ( p_oid_set!=GSS_C_NO_OID_SET ) {
      if ( (p_oid_set->count==0      && p_oid_set->elements!=NULL)
	    ||  (p_oid_set->count>0  && p_oid_set->elements==NULL) ) {
 
	 XVEB((V_ERR, "    %s is an INVALID gss_OID_set (count=%u, elements=ptr:%p)\n",
		      p_name, (Uint) p_oid_set->count, p_oid_set->elements ));
	 return(1);
      }

      for ( i=0 ; i<p_oid_set->count ; i++ ) {
	 if ( p_oid_set->elements[i].elements==NULL || p_oid_set->elements[i].length==0 ) {
	    XVEB((V_ERR, "    %s is a DEFECTIVE gss_OID_set\n"
	              "     -- it contains invalid member_oid [%u] (length=%u, elements=ptr:%p)\n",
		      (Uint)i,
		      (Uint) p_oid_set->elements[i].length,
		      p_oid_set->elements[i].elements ));
	    return(1);
	 }
      }
   }

   /* no more output and checks if trclevel==0 */
   if ( p_trclevel<=0 )
      return(0);

   if ( p_oid_set==NULL ) {

      XVEB((V_SHOW, "  %s is GSS_C_NO_OID_SET\n", p_name ));

   } else if ( p_oid_set->count==0 && p_oid_set->elements==NULL ) {

      XVEB((V_SHOW, "  %s is an \"empty gss_OID_set\"\n", p_name));

   } else {

      XVEB((V_SHOW, "  %s contains %u gss_OID element%s:\n  {\n",
	    p_name, (Uint)p_oid_set->count, ((p_oid_set->count==1) ? "" : "s") ));
      for ( i=0 ; i<p_oid_set->count ; i++ ) {
	 sprintf(index, "  [%2u]", (Uint)i);
	 rc += print_oid( p_trclevel, index, &(p_oid_set->elements[i]) );
      }
      XVEB((V_SHOW, "  }\n"));

   }

   return(rc);

} /* print_oid_set() */



/*
 * oid_in_oid_set()
 *
 * Test whether p_oid is contained in p_oid_set
 */
int
oid_in_oid_set( gss_OID_set p_oid_set, gss_OID p_oid )
{
   Uint    i;
   size_t  len;

   if ( p_oid == GSS_C_NO_OID  ||  p_oid->elements==NULL  ||  p_oid->length==0 )
      /* this is an invalid OID */
      return(-1);

   if ( p_oid_set != GSS_C_NO_OID_SET ) {
      len = p_oid->length;

      for ( i=0 ; i<(p_oid_set->count) ; i++ ) {
	 if ( (p_oid_set->elements[i]).elements!=NULL ) {
	    if ( (p_oid_set->elements[i]).length == len
	         &&  !memcmp( (p_oid_set->elements)[i].elements, p_oid->elements, len) ) {
	       return(i);
	    }
	 }
      }
   }

   return(-1);

} /* oid_in_oid_set() */

