/* ***************************************************************************

  $Archive: $
  $Revision: $
  $Modtime: $
 
 Copyright (c) 1998 Novell, Inc. All Rights Reserved.

 THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
 USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
 ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
 PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
 ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
 PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
 DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
 PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
 CUSTOMERS WITH RESPECT TO THIS CODE.

 ****************************************************************************/

/**************************************************************************
   READEFF.C
***************************************************************************

  This program accepts two object names and displays the effective 
  rights of the second object on the first.  If either object is not
  specified, the currently authenticated user object is used.

  USAGE :  READEFF <object1> <object2>

  exmpls:  READEFF Romeo Juliette
           READEFF cn=Romeo.ou=Montagues cn=Juliette.ou=Capulets

**************************************************************************/

#define SCREENSIZE 22

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ntypes.h>
#include <nwnet.h>
#include <nwcalls.h>
#include <nwlocale.h>

/* Globals */
NWDSContextHandle   context;
int                 iScrCount;
nbool8              bbDoLogout;

/* Prototypes */

void ShowUsage(void);
void ReadAttributes(pnstr8 strObjectName, pnstr8 strSubjectName);
void DisplayRights(pnstr8 strAttr, pnstr8 strObject, pnstr8 strSubject);
void InitDS(void);
void UninitDS(void);
void DecodeRights(pnstr8 attrName, pnstr8 rightsstring, nuint32 privs);
void PrintScreenHeader(int iIsMore, pnstr8 strObjectName, 
                       pnstr8 strSubjectName);

/***************************************************************************
**   Main Program
*/
int main(int argc, char *argv[])
{
   nstr8   strSubject[MAX_DN_CHARS];
   nstr8   strObject[MAX_DN_CHARS];

   switch(argc)
   {
      case 1:
      {
         strset(strObject, '\x0');
         strset(strSubject, '\x0');
         break;
      }
      case 2:
      {
         if(!strcmp(argv[1],"/?"))
            ShowUsage();
         strcpy(strObject, argv[1]);
         strset(strSubject, '\x0');
         break;
      }
      case 3:
      {
         strcpy(strObject, argv[1]);
         strcpy(strSubject, argv[2]);
         break;
      }
      default:
      {
         ShowUsage();
         break;
      }
   }
   InitDS();
   ReadAttributes(strupr(strObject), strupr(strSubject));
   UninitDS();
   return(0);
}

/***************************************************************************
**   Print Usage statement
*/
void ShowUsage(void)
{
   printf("\nUsage: readeff [<object> [<subject>]]\n");
   printf("\n<object> is the name of the object to which the privileges are assigned.\n");
   printf("<subject> is the name of the object to which access may be granted. It is\n");
   printf("the \"trustee\" of the <object>.\n");
   printf("Not specifying the <subject> and <object> defaults to the currently\n");
   printf("authenticated user.\n");
   exit(1);
}

/***************************************************************************
** Read the attributes for strObjectName then read the effective rights
** that strSubjectName has for each of the attributes in strObjectName.
*/
void ReadAttributes(pnstr8 strObjectName, pnstr strSubjectName)
{
   NWDSCCODE   ccode;
   nint32      lIterationHandle = NO_MORE_ITERATIONS;
   nuint32     luSyntax;
   nuint32     luAttrCount, i;
   nuint32     luValCount;
   pBuf_T      outBuf;
   nstr8       strAttrName[MAX_DN_CHARS + 1];

   if(!strcmp(strObjectName,"")) /* use current user if none specified */
   {
      ccode = NWDSWhoAmI(context, strObjectName);
      if(ccode)
      {
         printf("\nNWDSWhoAmI returned %04X", ccode);
         exit(1);
      }
   }

   if(!strcmp(strSubjectName,"")) /* use current user if none specified */
   {
      ccode = NWDSWhoAmI(context, strSubjectName);
      if(ccode)
      {
         printf("\nNWDSWhoAmI returned %04X", ccode);
         exit(1);
      }
   }

   PrintScreenHeader(0, strSubjectName, strObjectName);

   /* These are special attributes that will not be read
      with NWDSRead  */ 
                                                       
   strcpy(strAttrName,"[All Attributes Rights]");         
   DisplayRights(strAttrName, strObjectName, strSubjectName);   
   strcpy(strAttrName,"[SMS Rights]");                    
   DisplayRights(strAttrName, strObjectName, strSubjectName);
   strcpy(strAttrName,"[Entry Rights]");
   DisplayRights(strAttrName, strObjectName, strSubjectName);

   ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
   if(ccode)
   {
      printf("\nNWDSAllocBuf returned %04X", ccode);
      exit(1);
   }

   do
   {
      ccode = NWDSRead(
               /* Context Handle (IN)    */  context,        
               /* name of object (IN)    */  strObjectName,        
               /* only want names (IN)   */  DS_ATTRIBUTE_NAMES,
               /* Want all names (IN)    */  TRUE,              
               /* attribute names (IN)   */  NULL,              
               /* iteration Handle (OUT) */  &lIterationHandle,  
               /* output buffer (OUT)    */  outBuf);           
      if(ccode)
      {
         printf("\nNWDSRead(%s) returned %04X", strObjectName, ccode);
         NWDSFreeBuf(outBuf);
         exit(1);
      }

      ccode = NWDSGetAttrCount(
               /* context handle (IN)       */  context,
               /* buffer full of names (IN) */  outBuf,           
               /* num of attributes (OUT)   */  &luAttrCount);      
      if(ccode)
      {
         printf("\nNWDSGetAttrCount returned %04X", ccode);
         NWDSFreeBuf(outBuf);
         exit(1);
      }

      for(i = 0; i < luAttrCount; i++)
      {
         ccode = NWDSGetAttrName(
                  /* context handle (IN)       */  context,
                  /* buffer full of names (IN) */  outBuf,               
                  /* to hold name (OUT)        */  strAttrName,             
                  /* num of values (OUT)       */  &luValCount,            
                  /* syntax for attr (OUT)     */  &luSyntax);             
         if(ccode)
         {
            printf("\nNWDSGetAttrName returned %04X", ccode);
            NWDSFreeBuf(outBuf);
            exit(1);
         }
         DisplayRights(strAttrName, strObjectName, strSubjectName);
      }
   }
   while(lIterationHandle != -1L);

   NWDSFreeBuf(outBuf);
}

/***************************************************************************
**   Print header on screen
*/
void PrintScreenHeader(int iIsMore, pnstr strSubjectName, 
                       pnstr strObjectName)
{
   iScrCount = 0;

   if(iIsMore)
      printf("(Continued) Effective Rights of %s on object %s:\n\n", 
             strSubjectName, strObjectName);
   else
      printf("Effective Rights of %s on object %s:\n\n", 
             strSubjectName, strObjectName);
   printf("  ATTRIBUTE NAMES                   RIGHTS \n");
   printf("---------------------               -------\n");
   iScrCount += 4;
}

/**************************************************************************
**   Read and display rights for given attributes, objects, and subjects
*/
void DisplayRights(pnstr8 strAttr, pnstr8 strObject, pnstr8 strSubject)
{
   NWDSCCODE   ccode;
   nuint32     luPrivs;
   char        strRightsStr[9] = "";  /* string format of "[CRWAS]" */

   ccode = NWDSGetEffectiveRights(
             /* context handle (IN)) */ context,
             /* subject (IN)         */ strSubject,     
             /* object (IN)          */ strObject,      
             /* current attr (IN)    */ strAttr,        
             /* privs on attr (OUT)  */ &luPrivs);     
   if(ccode)
      strcpy(strRightsStr, "ERROR");
   else
      DecodeRights(strAttr, strRightsStr, luPrivs);

   printf("%-35s %-9s \n", strAttr, strRightsStr);
   iScrCount++;

   if(iScrCount == SCREENSIZE)
   {
      printf("\nHit any key to continue ...");
      getch();
      PrintScreenHeader(1, strSubject, strObject);
   }
}

/***************************************************************************
**   Establish context, standard initializations for DS calls
*/
void InitDS(void)
{
   NWDSCCODE   ccode;
   LCONV       lconvInfo;
   nstr8       strUserName[NW_MAX_USER_NAME_LEN];
   nstr8       strUserPassword[50];

   /* Initialize libraries */
   ccode=NWCallsInit(NULL,NULL);
   if(ccode)       
   {
      printf("\nNWCallsInit returned %04X", ccode);
      exit(1);
   }

   NWLlocaleconv(&lconvInfo);

   ccode = NWInitUnicodeTables(lconvInfo.country_id, lconvInfo.code_page);
   if(ccode)
   {
      printf("\nNWInitUnicodeTables returned %04X", ccode);
      exit(1);
   }

   ccode = NWDSCreateContextHandle(&context);
   if(ccode)
   {
      printf("\nNWDSCreateContextHandle returned %04X", ccode);
      exit(1);
   }

   /*  Must authenticate if not already authenticated to NDS
       (which will always be the case if this example is 
       compiled and run as an NLM).  */
   if(!NWIsDSAuthenticated())
   {
      printf("\nMust authenticate to NDS");
      printf("\nEnter User Name: ");
      gets(strUserName);
      printf("Enter User Password: ");
      gets(strUserPassword);

      ccode = NWDSLogin(context, 0, strUserName, strUserPassword, 0);
      if(ccode)
      {
         printf("\nNWDSLogin returned %X", ccode);
         exit(1);
      }
      else
      {  /* If example logs in, it will also log out */
         bbDoLogout = N_TRUE;
      }
   }
}

/***************************************************************************
**   Release context and clean up.
*/
void UninitDS()
{
   NWDSCCODE   ccode;

   if(bbDoLogout)
   {
      ccode = NWDSLogout(context);
      if(ccode)
      {
         printf("\nNWDSLogout returned %04X", ccode);
         exit(1);
      }
   }

   ccode=NWDSFreeContext(context);
   if(ccode)
   {
      printf("\nNWDSFreeContext returned %04X", ccode);
      exit(1);
   }

   ccode=NWFreeUnicodeTables();
   if(ccode)
   {
      printf("\nNWFreeUnicodeTables returned %04X", ccode);
      exit(1);
   }
}

/***************************************************************************
**   Build rights string of the format [CRWAS] from luPrivs
*/
void DecodeRights(pnstr8 strAttrName, 
                  pnstr8 strRightsString, 
                  nuint32 luPrivs)
{
   strset(strRightsString, '\x0');
   strcat(strRightsString, "[");

   if(!strcmp(strAttrName, "[Entry Rights]"))
   {
      if(luPrivs & 0x01)                  /* DS_ENTRY_BROWSE     */
         strcat(strRightsString, "B");
      else
         strcat(strRightsString, " ");
      if(luPrivs & 0x02)                  /* DS_ENTRY_ADD        */
         strcat(strRightsString, "A");
      else
         strcat(strRightsString, " ");
      if(luPrivs & 0x04)                  /* DS_ENTRY_DELETE     */
         strcat(strRightsString, "D");
      else
         strcat(strRightsString, " ");
      if(luPrivs & 0x08)                  /* DS_ENTRY_RENAME     */
         strcat(strRightsString, "R");
      else
         strcat(strRightsString, " ");
      if(luPrivs & 0x10)                  /* DS_ENTRY_SUPERVISOR */
         strcat(strRightsString, "S");
      else
         strcat(strRightsString, " ");
   }
   else
   {
      if(!strcmp(strAttrName, "[SMS Rights]"))
      {
         if(luPrivs & 0x01)                   /* DS_SMS_SCAN    */
            strcat(strRightsString, "S");
         else
            strcat(strRightsString, " ");
         if(luPrivs & 0x02)                   /* DS_SMS_BACKUP  */
            strcat(strRightsString, "B");
         else
            strcat(strRightsString, " ");
         if(luPrivs & 0x04)                   /* DS_SMS_RESTORE */
            strcat(strRightsString, "R");
         else
            strcat(strRightsString, " ");
         if(luPrivs & 0x08)                   /* DS_SMS_RENAME  */
            strcat(strRightsString, "C");
         else
            strcat(strRightsString, " ");
         if(luPrivs & 0x10)                   /* DS_SMS_DELETE  */
            strcat(strRightsString, "D");
         else
            strcat(strRightsString, " ");
         if(luPrivs & 0x20)                   /* DS_SMS_ADMIN   */
            strcat(strRightsString, "A");
         else
            strcat(strRightsString, " ");
      }
      else    /* Attribute Rights which applies to all others       */
      {
         if(luPrivs & 0x01)                   /* DS_ATTR_COMPARE    */
            strcat(strRightsString, "C");
         else
            strcat(strRightsString, " ");
         if(luPrivs & 0x02)                   /* DS_ATTR_READ       */
            strcat(strRightsString, "R");
         else
            strcat(strRightsString, " ");
         if(luPrivs & 0x04)                   /* DS_ATTR_WRITE      */
            strcat(strRightsString, "W");
         else
            strcat(strRightsString, " ");
         if(luPrivs & 0x08)                   /* DS_ATTR_SELF       */
            strcat(strRightsString, "A");
         else
            strcat(strRightsString, " ");
         if(luPrivs & 0x20)                   /* DS_ATTR_SUPERVISOR */
            strcat(strRightsString, "S");
         else
            strcat(strRightsString, " ");
      }
   }
   strcat(strRightsString,"]\x0");
} 
