/****************************************************************************
 %name: lstst.c %
 %version: 10.1.1 %
 %date_modified: Tue May 17 16:47:21 2005 %

 Copyright (c) 1997-2005 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.
**************************************************************************/


/***************************************************************
 *** This code is available at "www.developer.novell.com/ndk/ **
 ***************************************************************/

/* Sample LDAP client code for SecretStore Service APIs */


#ifndef UCHAR
#define UCHAR	unsigned char
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef WIN32
#include <conio.h>
#endif

#ifdef N_PLAT_NLM
#include	<signal.h>
#include	<nwthread.h>
#endif

#include <time.h>

#ifdef N_PLAT_UNIX
#define getch getchar
#endif



#ifdef N_PLAT_NLM
#ifdef FAST_ALLOC
/* for the fast allocation stuff */
LONG						sleptFlag;
static	void 			*ssLSSCLAllocRTag;

static	struct 
{
	LONG 	signature; 
	char 	*name; 
	void 	**tag;
} ssclAllocTag = {0x54524C41L, "SSLDAPCL Alloc Memory", &ssLSSCLAllocRTag};

void 			*ss_GetAllocTag(void);
static int 	ss_InitSSAllocTag(void);

#include	"ssmem.h"
#endif /* FAST_ALLOC */
#endif


#include "nssscl.h"
#include "nssbldno.h"



/*
 * Global data
 */
static int   		optIdx = 1;	   		//* index into parent argv vector
static int	   	optionString = 1;	//* character checked for validity
static char 		*optArg = NULL;		//* argument associated with option

#define BADCHAR 	(int)'?'
#define ERRMSG  	""

/* interactive flag */
static int	aFlag = 1;




/*  */
/*
 * NAME - sss_GetOpt
 *
 * DESCRIPTION
 *	An implementation of the Unix getopt() function.
 *
 */

int	sss_GetOpt
		(
			int 		nArgc, 
			char 		**nArgv, 
			char 		*optStr
		)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	static		char		*place = ERRMSG;
			 	char		*nxtOpt;

/* ############################## CODE STARTS HERE ############################ */

	if(!*place)  
	{
		if((optIdx >= nArgc) ||
			((*(place = nArgv[optIdx]) != '-')
				&& (*(place = nArgv[optIdx]) != '/')) ||
					(!*++place))
		{
			return(-1);
		}

		if((*place == '-') || (*place == '/'))
		{
			++optIdx;
			return(-1);
		}
	}

	if((optionString = (int)*place++) == (int)'=' || 
			!(nxtOpt = strchr(optStr, optionString))) 
	{
		if(!*place) 
		{
			++optIdx;
		}

		return(BADCHAR);
	}

	if(*++nxtOpt != '=') 
	{
		optArg = NULL;
		if(!*place) 
		{
			++optIdx;
		}
	}
	else 
	{
		if(*place)
		{
			optArg = place + 1;
		}
		else if(nArgc <= ++optIdx) 
		{
			place = ERRMSG;
			return(BADCHAR);
		}
	 	else 
		{
	 		optArg = nArgv[optIdx];
		}

		place = ERRMSG;
		++optIdx;
	}

	return(optionString);

/* ########################## CODE ENDS HERE ######################### */
} /* end of GetOPt */




void Pause()
{ /* beginning of the call */
/* ############################## CODE STARTS HERE ############################ */

	if(aFlag)
	{
		printf("\nPress a key ==>\n");
		getch();
	}
/* ########################## CODE ENDS HERE ######################### */
} /* end of Pause */



/*  */
/*
 * NAME - PrintFlags
 *
 * DESCRIPTION
 *	This function will print the 
 *	status flags read form a secret.		   
 *		   
 */
void PrintFlags(char *msg, unsigned long	statFlags)
{ /* beginning of the call */
/* ############################## CODE STARTS HERE ############################ */

	if(aFlag)
	{
		printf("\n%s", msg);

		if(statFlags & NSSS_ENHANCED_PROTECT_INFO_F)
			printf("\tENHANCED PROTECTION...\n");

		if(statFlags & NSSS_STORE_NOT_SYNCED_F)
			printf("\tSTORE NOT SYNCED...\n");

		if(statFlags & NSSS_SECRET_NOT_INITIALIZED_F)
			printf("\tSECRET NOT INITIALIZED...\n");

		if(statFlags & NSSS_SECRET_LOCKED_F)
			printf("\tSECRET LOCKED...\n");

		/* doesn't apply to the server */
		if(strcmp(msg, "SecretStore Flags:\n"))
		{
			if(statFlags & NSSS_ADMIN_LAST_MOD_F)
				printf("\tADMIN MODIFIED LAST...\n");
			else
				printf("\tOWNER MODIFIED LAST...\n");
		}

		if(statFlags & NSSS_EP_PWORD_PRESENT_F)
			printf("\tEP PWORD PRESENT...\n");

		if(statFlags & NSSS_EP_MASTER_PWORD_PRESENT_F)
			printf("\tMASTER PWORD PRESENT...\n");
		
		if(statFlags & NSSS_MP_NOT_ALLOWED_F)
			printf("\tMASTER PWORD NOT ALLOWED...\n");

		if(statFlags & NSSS_HIDDEN_SECRET_F)
			printf("\tHIDDEN SECRET IN SECRETSTORE...\n");

		if(statFlags & NSSS_ADMIN_UNLOCKED_F)
			printf("\tADMIN LAST UNLOCKED THE SECRETSTORE...\n");
	}

/* ########################## CODE ENDS HERE ######################### */
} /* end of PrintFlags */






#ifdef N_PLAT_NLM

/* ########################################################################### */
/* ############################ NetWare  SPECIFICS ########################### */
/* ########################################################################### */

/* 
 **	These prototypes added here because no NWSDK
 ** 	header file contains them anymore.
 */
//N_EXTERN_LIBRARY(NWCCODE)
extern int
NWCallsInit
(
   nptr reserved1,
   nptr reserved2
);

//N_EXTERN_LIBRARY(NWCCODE)
extern int
NWCallsTerm
(
   nptr reserved
);


/* ###################################################################### */
/* ############################  COMMON DECLS ########################### */
/* ###################################################################### */


void			UnloadLDAPSSCLMain(int	sigNbr);

static	int		ssLSSCLThreadGroupID = 0;
unsigned 	int		ssLSSCLModuleHandle = 0;

#endif



/*  */
/*
 * NAME - ss_GetLoginInfo
 *
 * DESCRIPTION
 *	login to SecretStore.		   
 *		   
 */
int	ss_GetLoginInfo
		(
			char 				*targetDN,
			SSS_CONTEXT_T		*ctx
		)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */
       
	char					portStr[256];
	int						rc = NSSS_SUCCESS;
	SS_LDAPBIND_INFO_T		*ldapBindInfo = NULL;


/* ############################## CODE STARTS HERE ############################ */

	ldapBindInfo = (SS_LDAPBIND_INFO_T *)ctx->bindInfo;

	printf("\n Enter the following sequence to login to an LDAP server:");
	printf("\n (For default values press ENTER at the prompt)");
	printf("\n <LDAP Host Name> <Port No.> <Login DN> <Target DN> <Password> <Root Cert File Name>");
	printf("\n Example:\n lstst nsd19.provo.novell.com 636 cn=janedoe,o=novell password\n\n");
	printf("\nc or: ");
	printf("\n Example:\n lstst 151.155.160.85 636 cn=admin,o=novell cn=johndoe,o=novell password myKey.der\n\n");

	/* LDAP host name
	   ============== */
	printf("Enter the LDAP Server DNS Name/IP Address: ");
	gets(ldapBindInfo->lHostName);
	if(strlen(ldapBindInfo->lHostName) == 0)
	{
		printf("Server Name required!!\n");
		return(NSSS_E_INVALID_PARAM);
	}

	printf("LDAP Host = [%s]\n", ldapBindInfo->lHostName);
	printf( "\n" );

	/* LDAP port number
	   ================ */
	memset(portStr, 0, 256);
	printf("Enter LDAP Port Number (636-default): ");
	gets(portStr);

	if(strlen(portStr))
	{
		ldapBindInfo->portNum = atoi(portStr);
	}
	else
	{
		ldapBindInfo->portNum = 636L;
	}

	printf("LDAP Port = [%d]\n", ldapBindInfo->portNum);
	printf( "\n" );

	/* LDAP login DN
	   ============= */
	printf("Enter Login DN in LDAP Format (\"cn=johndoe, o=novell\"): ");
	gets(ctx->callerDN.id);

	if((ctx->callerDN.len = strlen(ctx->callerDN.id)) == 0)
	{
		printf("Login DN required!!\n");
		return(NSSS_E_INVALID_PARAM);
	}
	ctx->callerDN.len++;

	printf("Login DN = [%s]\n", ctx->callerDN.id);
	printf( "\n" );

	/* LDAP target DN
	   ============= */
	memset(targetDN, 0, 256);
	printf("Enter LDAP Target DN (\"cn=janedoe, o=novell\"): ");
	gets(targetDN);

	if(strlen(targetDN) == 0)
	{
		strcpy(targetDN, ctx->callerDN.id);
	}

	printf("Target DN = [%s]\n", targetDN);
	printf( "\n" );

	/* LDAP login password
	   =================== */
	printf("Enter the LDAP Login Password: ");
	gets(ldapBindInfo->loginPword);

	printf("Enter Root Certificate File Name: (<Enter for Auto-retrieval>)");
	gets(ldapBindInfo->trustedRootCert);
	printf( "\n" );

	if(strlen(ldapBindInfo->trustedRootCert))
	{
		printf("Trusted Root Certificate = [%s]\n", ldapBindInfo->trustedRootCert);
	}

	return(NSSS_SUCCESS);

/* ########################## CODE ENDS HERE ######################### */
} /* end of ss_GetLoginInfo */






/*  */
/*
 * NAME - main
 *
 * DESCRIPTION
 *	SecretStore LDAP test program.		   
 *		   
 */
int	main
		(
			int 		argc, 
			char 		**argv
		)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	SS_LDAPBIND_INFO_T		lbInfo = {0};
	SSS_CONTEXT_T			ctx = {0};
	SSS_GSINFOEXT_T			gsInfo = {0};
	SSS_READEXT_T			rInfo = {0};
	SS_SECRET_T				secretIDList = {0};
	char					srchStr[] = "*";
	SS_OBJECT_DN_T			targetObjDN = {0};
	char					*nameStr;

	char					*passwordSS[15] = 
							{
								"LDAP test01_password", "LDAP test02_password",
								"LDAP test03_password", "LDAP test04_password",
								"LDAP test05_password", "LDAP test06_password",
								"LDAP test07_password", "LDAP test08_password",
								"LDAP test09_password", "LDAP test10_password",
								"LDAP test11_password", "LDAP test12_password",
								"LDAP test13_password", "LDAP test14_password",
								"LDAP test15_password"
							};

	char					*appNames[15] =
							{
								"//novell.com/LDAP NDK SSS Test APP01", 
								"//novell.com/LDAP NDK SSS Test APP02", 
								"//novell.com/LDAP NDK SSS Test APP03", 
								"//novell.com/LDAP NDK SSS Test APP04", 
								"//novell.com/LDAP NDK SSS Test APP05", 
								"//novell.com/LDAP NDK SSS Test APP06", 
								"//novell.com/LDAP NDK SSS Test APP07", 
								"//novell.com/LDAP NDK SSS Test APP08", 
								"//novell.com/LDAP NDK SSS Test APP09", 
								"//novell.com/LDAP NDK SSS Test APP10", 
								"//novell.com/LDAP NDK SSS Test APP11", 
								"//novell.com/LDAP NDK SSS Test APP12", 
								"//novell.com/LDAP NDK SSS Test APP13", 
								"//novell.com/LDAP NDK SSS Test APP14", 
								"//novell.com/LDAP NDK SSS Test APP15"
							};

	int						rcode = NSSS_SUCCESS, nslFlag = 0, repairFlag = 0,
							exCount = 1, i, j, remLock = 0, unlock = 0,
							master = 0, k, rCount = 1;
	SS_SECRET_T				readSecret = {0}, writeSecret = {0};
	long					opCount = 0, bufSize = strlen(passwordSS[0])+1;
	unsigned long			startTime, endTime, pFlag = 0L, count = 0, haveContext = 0;
	int						c, nslCount = 0;

	struct tm				*latStamp, *crtStamp, *lmtStamp, *unlockTStamp;
	SS_PWORD_T				mPassword = {8, "Pyramid"}, masterPword = {0}, pword = {0}, 
							ePassword = {12, "ep_password"};
	SS_HINT_T				mpHint = {0}, hint = {28, "My Key To The SecretStore!!"};
	SS_SECRET_ID_T			secretID = {0};

/* ############################## CODE STARTS HERE ############################ */

	printf("\nSecretStore NDK LDAP Test Program version %s ...\n\n", GSS_BLD_STR);

#ifdef	N_PLAT_NLM
	AtUnload(UnloadLDAPSSCLMain);
	atexit(UnloadLDAPSSCLMain);

	ssLSSCLModuleHandle = GetNLMHandle();

#ifdef FAST_ALLOC
 		if(ss_InitSSAllocTag())
		{
			goto ERROR_1;
		}
#endif /* FAST_ALLOC */

	ssLSSCLThreadGroupID = GetThreadGroupID();

	if((rcode = NWCallsInit(NULL, NULL)))
	{
		printf("CLIB Initialization Failed [%d]!!\n", rcode);
		goto ERROR_1;
	}

	signal(SIGTERM, UnloadLDAPSSCLMain);

#endif

	if(argc > 1)
	{
		while((c = sss_GetOpt(argc, argv, "dDnNaAbBmMsSc=C=r=R=?hH")) != -1)
		{
			switch(c)
			{
				//* repair
				case 'd':
				case 'D':
					repairFlag = 1;
					break;

				//* NSL mode
				case 'n':
				case 'N':
					nslFlag = 1;
					break;
				
				//* 512k Secret
				case 'a':
				case 'A':
					bufSize = 512; //* bytes
					break;

				//* 32k Secret
				case 'b':
				case 'B':
					bufSize = NSSS_MID_SECRET_BUF_LEN;
					break;

				//* 4k Secret
				case 'm':
				case 'M':
					bufSize = NSSS_MIN_SECRET_BUF_LEN; 
					break;

				case 's':
				case 'S':
					/* set active flag to FALSE */
					aFlag = 0;
					printf("Silent Running Mode Active...\n");
					break;

				case 'c':
				case 'C':
					exCount = atoi(optArg);
					break;

				case 'r':
				case 'R':
					rCount = atoi(optArg);
					break;

				default:
					//* case '?':
					//* case 'h':
					//*case 'H':
					printf("\nUsage: lstst [/n][/m]|[/d][/b][/a][/s /c=[count] /r=[rcount] | /? | /h ]\n");
					printf("\tOptions: [ /n | /N ] for 128k Secrets 5 Minutes Run Emulating NSL.\n");
					printf("\tOptions: [ /a | /A ] for Average 512k Secret Buffer Size.\n");
					printf("\tOptions: [ /m | /M ] for Medium 4k Secret Buffer Size.\n");
					printf("\tOptions: [ /b | /B ] for Big 32k Secret Buffer Size.\n");
					printf("\tOptions: [ /d | /D ] for Deleting Corrupted SecretStore.\n");
					printf("\tOptions: [ /s | /S ] for Silent Running.\n");
					printf("\t\tSilent sub-Option [ /c | /C ] for number of times to run.\n");
					printf("\t\tSilent sub-Option [ /r | /R ] for number of times to Read data.\n");
					printf("\tExample: lstst /s /c=1000 /r=100\n");
					printf("\tOption: [ /h | /H  | /? ] for Help.\n");
					printf("\tNo command line options will activate interactive running.\n\n");
					printf("\t The\"/\" and \"-\" for identifying options are interchangeable.\n\n");
					exit(0);
			}
		} 
	}
	else
	{
 		printf("Full Interactive Running Mode Active...\n");
	}

	printf("[%d]k secret size buffer chosen...\n", bufSize);
	printf("Execution Count Set to: [%d]\n", exCount);
	printf("Read Count Set to: [%d]\n", rCount);

	ctx.bindInfo = &lbInfo;
	targetObjDN.len = strlen(targetObjDN.id)+1;

	printf("Initializing...\n");

	if(nslFlag)
	{
		aFlag = 0;
		exCount = 1;
		rCount = 1000000;
		bufSize = 128;		
	}

	if(repairFlag)
	{
		aFlag = 0;
		exCount = 1;
		rCount = 1;
	}

	/* Allocate the buffer used for writing secrets. */
	if(!(writeSecret.data = (char *)malloc(bufSize)))
	{
		printf("Error:secret MALLOC FAILED!\n");
		goto ERROR_1;
	}

	memset(writeSecret.data, 0, bufSize);
	writeSecret.len = bufSize;

	/* Allocate and initialize the buffer used for reading secrets. */
	if(!(readSecret.data = (char *)malloc(NSSS_MAX_SECRET_BUF_LEN + 
				sizeof(SS_SECRET_T))))
	{
		printf("Error:readSecret MALLOC FAILED!\n");
		goto ERROR_1;
	}
	memset(readSecret.data, 0, NSSS_MAX_SECRET_BUF_LEN);
	readSecret.len = NSSS_MAX_SECRET_BUF_LEN;

	/* allocate and initialize the enumSecIDBuf for ENUM */
	if(!(secretIDList.data = (char *)malloc(NSSS_MAX_IDLIST_BUF_LEN)))
	{
		printf("Error: secretIDList MALLOC FAILED!\n");
		goto ERROR_1;
	}

	secretIDList.len = NSSS_MAX_IDLIST_BUF_LEN;

	startTime = time(NULL);
	printf("Done...\n");
	Pause();

	if(ss_GetLoginInfo(targetObjDN.id, &ctx))
	{
		printf("Error: Getting LDAP Login Info FAILED!\n");
		goto ERROR_1;
	}

	targetObjDN.len = strlen(targetObjDN.id)+1;


	do
	{
		/* need to get a new context */
		if(pFlag & NSSS_DESTROY_CONTEXT_F)
		{
			pFlag &= ~NSSS_DESTROY_CONTEXT_F;
			pFlag |= NSSS_GET_CONTEXT_F;
			ctx.flags = NSSS_LDAP_CTX_F;
		}
		else
		{
			if(haveContext)
			{
				/* reusing the existing context */
				pFlag = 0;
			}
			else
			{
				/* first time */
				pFlag |= NSSS_GET_CONTEXT_F;
			}

			/* already have context for reuse */
			ctx.flags |= (NSSS_LDAP_CTX_F | NSSS_BINDLDAP_F);
		}

		memset(&gsInfo, 0, sizeof(SSS_GSINFOEXT_T));

		if(rcode = NSSSGetServiceInformation(&ctx, &targetObjDN, pFlag, &gsInfo, NULL))
		{
			//* Call failed.
			printf("\nError [%d] NSSSGetServiceInformation\n", rcode);
			goto ERROR_1;
		}
		else
		{ 
			//* Print out service information.
			printf("\nClient Version = [%d.%d.%d]\n",
				((gsInfo.clientVersion >> 16)  & 0x000000FF) , 
					((gsInfo.clientVersion >> 8) & 0x000000FF), 
						(gsInfo.clientVersion & 0x000000FF));

			printf("\nServer Version = [%d.%d.%d]\n",
				((gsInfo.serverVersion >> 16) & 0x000000FF) , 
					((gsInfo.serverVersion >> 8) & 0x000000FF), 
						(gsInfo.serverVersion & 0x000000FF));

			if(gsInfo.serverCryptoStrength == NSSS_NICI_DOMESTIC_ENGINE)
			{
				printf("Server Crypto Strength = DOMESTIC\n");
			}
			else
			{
				printf("Server Crypto Strength = EXPORT\n");
			}
			
			printf("\nSecret Count = %d\n", gsInfo.secretCount);

			if(gsInfo.lockCount)
			{
				printf("Lock Count = %d\n", gsInfo.lockCount);
			}

			printf("\nSecretStore's NDS Tree = %s\n", ctx.ssServerInfo.treeName);

			if(gsInfo.hintLen)
			{
				printf("\nMaster Password Hint = %s\n", gsInfo.hint);
			}

			if(gsInfo.secretCount)
			{
			  PrintFlags("\nSecretStore Flags:\n", gsInfo.statusFlags);
			}

			if(gsInfo.enumBufLen)
			{
				printf("\nEnumeration Buffer Length in Chars = %d\n", gsInfo.enumBufLen);
			}

			if(gsInfo.statusFlags & NSSS_ADMIN_UNLOCKED_F)
			{
				unlockTStamp = localtime((long *)&gsInfo.unlockTStamp);
	 			if(unlockTStamp)
				{
					printf("\nLast Admin Unlock time stamp: %s", asctime(unlockTStamp));
				}

				printf("\nLast Admin Unlock DN = %s\n", gsInfo.admnDN);
			}
		}

		//* reset the flag
		haveContext = 1;
		pFlag &= ~NSSS_GET_CONTEXT_F;
		if(aFlag)
		{
			printf("\nDo you want to CONTINUE (y/n)? ");
			c = getch();
			putchar(c);
			printf("\n\n");
		}
		else
		{
			 c = 'y';
		}

		if(!((c == 'y') || (c == 'Y')))
		{
			aFlag = 0;
			goto ERROR_1;
		}

		for(j = 0, opCount = 0; j < exCount; j++)
		{
			if(aFlag)
			{
				printf("\nDo you want to CREATE/WRITE the secrets (y/n)? ");
				c = getch();
				putchar(c);
				printf("\n\n");
			}
			else
			{
				if(repairFlag)
				{
					c = 'n';
				}
				else
				{
					c = 'y';
				}
			}

			if(c == 'y' || c == 'Y')
			{
				for(i = 1; i < 16; i++)
				{
					/* initialize the app secret buffers */
					memset(writeSecret.data, 0, bufSize);
					strcpy(writeSecret.data, passwordSS[i-1]);

					/* initialize the secret ID buffers */
					strcpy(secretID.id, appNames[i-1]);
					secretID.len = strlen(secretID.id)+1;

					if(i % 2)
					{
						printf("\nCreating secret ID [%s] in SS\n", secretID.id);
						//* writing secret here
						if(rcode = NSSSWriteSecret(&ctx, &targetObjDN, pFlag | NSSS_CHK_SID_FOR_COLISION_F, 
									NULL, &secretID, &writeSecret, NULL))
						{
							printf("Error [%d] NSSSWriteSecret\n", rcode);
							printf("Secret[%d] = [%s], len [%d]\n", i, writeSecret.data, writeSecret.len);
							Pause();
						}
						else
						{
							printf("Wrote Secret[%d] = [%s], len [%d]\n", i, writeSecret.data, writeSecret.len);
						}	
					}
					else
					{
						//* Write a secret bypassing NSSSAddSecretID and
						//* use ep password to further protect the secret
						if(rcode = NSSSWriteSecret(&ctx, &targetObjDN,
							(pFlag | NSSS_ENHANCED_PROTECTION_F
							| NSSS_EP_PASSWORD_USED_F), &ePassword, &secretID, &writeSecret, NULL))
						{
							printf("\nError [%d] NSSSWriteSecret\n", rcode);
							printf("Secret[%d] = [%s], len [%d]\n",	i,
								writeSecret.data, writeSecret.len);
							Pause();
						}
						else
						{
							printf("\nWrote Secret[%d] = [%s], len [%d]\n",	i,
								writeSecret.data, writeSecret.len);
						}
					}
					opCount++;
				}

				gsInfo.statusFlags |= NSSS_ENHANCED_PROTECT_INFO_F;
			}

			if(( gsInfo.statusFlags & NSSS_ENHANCED_PROTECT_INFO_F ) && (!repairFlag))
			{
				if(!(gsInfo.statusFlags & NSSS_EP_MASTER_PWORD_PRESENT_F))
				{
					if(aFlag)
					{
						printf("\nDo you want to SET the Master Password(y/n)(n for default...)? ");
						c = getch();
						putchar(c);
						printf("\n");
					}
					else
					{
						c = 'n';
					}

					if(c == 'y' || c == 'Y')
					{
						/* not very secure but good for sample code demonstration */
						printf("Enter your Master password (64 chars max): ");
						gets(masterPword.pword);
						printf("\n");

						printf("\nEnter your Master password Hint(64 chars max): ");
						gets(mpHint.hint);
						printf("\n");

						if(rcode = NSSSSetEPMasterPassword(&ctx, &targetObjDN, pFlag, &masterPword, &mpHint, NULL))
						{
							printf("Error [%d] NSSSSetEPMasterPassword Failed!\n", rcode	);
						}		
						else
						{
							printf("\nNSSSSetEPMasterPassword Succeeded...\n", rcode);
							printf("Your Master Password was set to: %s\n", masterPword.pword);
							printf("Your Master Password Hint was set to: %s\n\n", mpHint.hint);
							masterPword.pwordLen = strlen(masterPword.pword)+1;
							mpHint.hintLen = strlen(mpHint.hint)+1;
						}
					}
					else
					{
						if(aFlag)
						{
							 printf("\nSet Master Password to default(y/n)? ");
							 c = getch();
							 putchar(c);
							 printf("\n");
						}
						else
						{
							c = 'y';
						}

						if(c == 'y' || c == 'Y')
						{
							masterPword = mPassword;
							mpHint = hint;
							if(rcode = NSSSSetEPMasterPassword(&ctx, &targetObjDN, pFlag, 
									&masterPword, &mpHint, NULL))
							{
								printf("Error [%d] NSSSSetEPMasterPassword Failed!\n", rcode);
							}		
							else
							{
								printf("\nNSSSSetEPMasterPassword Succeeded...\n", rcode);
								printf("Your Master Password was set to: %s\n", masterPword.pword);
								printf("Your Master Password Hint was set to: %s\n\n", mpHint.hint);
							}
						}
						else
						{
							printf("NO MasterPassword present!!\n");
						}
					}
				}
				else
				{
					printf("MasterPassword Already present...\n");
					if(aFlag)
					{
						 printf("\nDid you use the default Master password:(y/n)? ");
						 c = getch();
						 putchar(c);
						 printf("\n");
					}
					else
					{
						c = 'y';
					}

					if((c != 'y') && (c != 'Y'))
					{
						printf("Enter your Master password (64 chars max): ");
						gets(masterPword.pword);
						masterPword.pwordLen = strlen(masterPword.pword)+1;
						printf("\n");

					}
					else
					{
						 masterPword = mPassword;
					}
				}
				
				opCount++;
			}

			if(nslFlag)
			{
				printf("\n<<=============== STARTING NSL OPS ======================>\n");
				startTime = time(NULL);
			}

			for(k = 0; k < rCount; k++)
			{
				if(aFlag)
				{
					printf("\nDo you want to Read the secrets (y/n)? ");
					c = getch();
					putchar(c);
					printf("\n\n");
				}
				else
				{
					if(repairFlag)
					{
						c = 'n';
					}
					else
					{
						c = 'y';
					}
				}

				if(nslFlag)
				{
					//* do a GetServiceInfo
					memset(&gsInfo, 0, sizeof(SSS_GSINFOEXT_T));

					if(rcode = NSSSGetServiceInformation(&ctx, &targetObjDN, pFlag, &gsInfo, NULL))
					{
						//* Call failed.
						printf("\nError [%d] NSSSGetServiceInformation\n", rcode);
						goto ERROR_1;
					}
					else
					{
						//* Call failed.
						printf("\nSecretStore GetService Info Succeeded...\n");
					}

					nslCount++;
					opCount++;

					strcpy(pword.pword, masterPword.pword);
					pword.pwordLen = masterPword.pwordLen;	
					// unlock the secret store
					if(rcode = NSSSUnlockSecrets(&ctx, &targetObjDN, 
							(pFlag | NSSS_EP_MASTER_PWORD_USED_F), &pword, NULL))
					{
						printf("Error [%d] NSSSUnlockSecrets\n", rcode);
						Pause();
					}
					else
					{
						printf("SecretStore Unlocked...\n");
					}
					nslCount++;
					opCount++;
				}

				/* enumerate the secrets */
				count = 0;
				secretIDList.len = NSSS_MAX_IDLIST_BUF_LEN;

				if(rcode = NSSSEnumerateSecretIDs(&ctx, &targetObjDN, pFlag,
					srchStr, &count, &secretIDList, NULL))
				{
					printf("Error [%d] NSSSEnumerateSecretIDs\n", rcode);
					secretIDList.len = 0;
					Pause();
				}
				else
				{
					if(nslFlag)
					{
						printf("SecretStore Enumerate Seceret IDs Succeeded...\n\n");
					}
					else
					{
						printf("\nNumber of Secrets = [%d]\nRaw Secret ID Buffer from SS [%s]\n", 
							count, (char*)secretIDList.data);
					}
				}
				
				opCount++;
				nslCount++;

				if(c == 'y' || c == 'Y')
				{
					memset(&rInfo, 0, sizeof(SSS_READEXT_T));
					if(secretIDList.len)
					{
						nameStr = strtok((char *)&secretIDList.data[0], "*");

						for(i = 1; i <= (int)count; i++)
						{
							readSecret.len = NSSS_MAX_SECRET_BUF_LEN;
							rInfo.statFlags = 0;
					
							if(nslFlag)
							{
								strcpy(secretID.id, appNames[i-1]);
								secretID.len = strlen(secretID.id)+1;
								if(i % 2)
								{
									/* for read the length should be initialized */
									if(rcode = NSSSReadSecret(&ctx, &targetObjDN, pFlag,
											NULL, &rInfo, &secretID, &readSecret, NULL))
									{
										printf("Read SecretID[%d] [%s] Failed = [%d]!!!\n", i, secretID.id, rcode);
									}
									else
									{
										printf("Read SecretID[%d] [%s] Succeeded...\n", i, secretID.id);
									}
									nslCount++;
									opCount++;

								}
								else
								{
									/* for read the length should be initialized */
									if(rcode = NSSSReadSecret(&ctx, &targetObjDN, 
									(pFlag | NSSS_ENHANCED_PROTECTION_F | NSSS_EP_MASTER_PWORD_USED_F),
										&masterPword, &rInfo, &secretID, &readSecret, NULL))
									{
										printf("Read SecretID[%d] [%s] Failed = [%d]!!!\n", i, secretID.id, rcode);
									}
									else
									{
										printf("Read SecretID[%d] [%s] Succeeded...\n", i, secretID.id);
									}
					  				nslCount++;
					  				opCount++;
								}
							}
							else
							{
								strcpy(secretID.id, nameStr);
								secretID.len = strlen(secretID.id)+1;
								/* for read the length should be initialized */
								rcode = NSSSReadSecret(&ctx, &targetObjDN, pFlag,
										NULL, &rInfo, &secretID, &readSecret, NULL);

								nslCount++;
								opCount++;

								/* nds passord has changed */
								if(rcode == NSSS_E_NDS_PWORD_CHANGED)
								{
									unlock = 1;
									
									printf("Status Flags = [0x%x]\n", rInfo.statFlags);
									PrintFlags("Secret Flags:\n", rInfo.statFlags);
									Pause();
									goto Unlock_label;
								}
								
								//* for demonstration purposes use master password and
								//* enhanced protection password alternatively
								if(rcode == NSSS_E_EP_ACCESS_DENIED)
								{
									if(master)
									{	/* try the master password */
										readSecret.len = NSSS_MAX_SECRET_BUF_LEN;

										/* for read the length should be initialized */
										if(rcode = NSSSReadSecret(&ctx, &targetObjDN, 
										(pFlag | NSSS_ENHANCED_PROTECTION_F | NSSS_EP_MASTER_PWORD_USED_F),
											&masterPword, &rInfo, &secretID, &readSecret, NULL))
										{
											printf("\nStatus Flags = [0x%x]\n", rInfo.statFlags);
											printf("Read SecretID[%d] = [%s]\n", i, secretID.id);
											printf("Error [%d] NSSSReadSecret\n", rcode);
											PrintFlags("Secret Flags:\n", rInfo.statFlags);
											Pause();
											nslCount++;
											opCount++;
											continue;
										}
										else
										{
											master = 0;
											nslCount++;
											opCount++;
										}
									}
									else
									{
										/* try the ep password */
										readSecret.len = NSSS_MAX_SECRET_BUF_LEN;

										if(rcode = NSSSReadSecret(&ctx, &targetObjDN, 
											(pFlag | NSSS_ENHANCED_PROTECTION_F | NSSS_EP_PASSWORD_USED_F),
											&ePassword, &rInfo, &secretID, &readSecret, NULL))
										{
											printf("\nStatus Flags = [0x%x]\n", rInfo.statFlags);
											printf("Read SecretID[%d] = [%s]\n", i, secretID.id);
											printf("Error [%d] NSSSReadSecret\n", rcode);
											PrintFlags("Secret Flags:\n", rInfo.statFlags);
											Pause();
											opCount++;
											nslCount++;
											continue;
										}
										else
										{
											master = 1;
											nslCount++;
											opCount++;
										}
									}
								}
								
								if(rcode == NSSS_SUCCESS)
								{
									printf("\nStatus Flags = [0x%x]\n", rInfo.statFlags);
									PrintFlags("Secret Flags:\n", rInfo.statFlags);
									printf("Read Secret[%d] = [%s], len [%d]\n", i,
										readSecret.data, readSecret.len);

									if(aFlag)
									{								
										crtStamp = localtime((long *)&rInfo.crtStamp);
										if(crtStamp)
										{
											printf("\nCreation time stamp: %s",
												asctime(crtStamp));
										}

										latStamp = localtime((long *)&rInfo.latStamp);
										if(latStamp && rInfo.latStamp)
										{	
											printf("Last accessed time stamp: %s",
												asctime(latStamp));
										}

										lmtStamp = localtime((long *)&rInfo.lmtStamp);
										if(lmtStamp)
										{
											printf("Last modified time stamp: %s\n",
												asctime(lmtStamp));
										}
									}								
								}
								else
								{
									printf("Read Secret Failed!! = [%d]\n", rcode);
									PrintFlags("Secret Flags:\n", rInfo.statFlags);
									printf("Status Flags = [0x%x]\n", rInfo.statFlags);
									Pause();
								}
							
								nameStr = strtok(NULL, "*");
							}

						} /* end for read secret count */
					}
				} /* endif y */

				if(nslFlag)
				{
					endTime = time(NULL);
					if(endTime < startTime+300)
					{
						continue;
					}
					else
					{
						break;
					}
				}

			} /* end for */

		Unlock_label:
			
			if(unlock)
			{
				printf("\nDo you want to REMOVE LOCKED SECRETS(y/n)? ");
				c = getch();
				putchar(c);
				printf("\n\n");

				if((c == 'y') || (c == 'Y'))
				{
					remLock = 1;
					// remove lock from the SecretStore
					if(rcode = NSSSUnlockSecrets(&ctx, &targetObjDN, 
							(pFlag | NSSS_REMOVE_LOCK_FROM_STORE_F), NULL, NULL))
					{
						printf("Error [%d] NSSSUnlockSecrets\n", rcode);
						Pause();
					}
					else
					{
						printf("SecretStore Unlocked by removing the lock...\n"); 
					}
					opCount++;
				}
				else
				{		
					printf("\nDo you want to use Master Password to Unlock (y/n)? ");
					c = getch();
					putchar(c);
					printf("\n");

					if((c == 'y') || (c == 'Y'))
					{
						if(gsInfo.statusFlags & NSSS_EP_MASTER_PWORD_PRESENT_F)
						{
							strcpy(pword.pword, masterPword.pword);
							pword.pwordLen = masterPword.pwordLen;	
							// unlock the secret store
							if(rcode = NSSSUnlockSecrets(&ctx, &targetObjDN, 
								(pFlag | NSSS_EP_MASTER_PWORD_USED_F),
							 		&pword, NULL))
							{
								printf("Error [%d] NSSSUnlockSecrets\n", rcode);
								Pause();
							}
							else
							{
								printf("SecretStore Unlocked...\n");
							}
							opCount++;

						}
						else
						{
							printf("Master password not set!! ");
							Pause();									
							goto ERROR_1;
						}
					}
					else
					{
						/* try the NDS password */
						/* not very secure but good for sample code demonstration */
						printf("Enter your previous valid NDS password: ");
						gets(pword.pword);
						pword.pwordLen = strlen(pword.pword)+1;
						printf("\n");

						if(rcode = NSSSUnlockSecrets(&ctx, &targetObjDN, pFlag,	&pword, NULL))
						{
							printf("Error [%d] NSSSUnlockSecrets\n", rcode);
							Pause();
						}
						else
						{
							printf("SecretStore Unlocked...\n");
						}
						opCount++;
					}
				}


				if(secretIDList.len)
				{
					/* now read the secrets again */
					secretIDList.len = NSSS_MAX_IDLIST_BUF_LEN;
					count = 0;
					if(rcode = NSSSEnumerateSecretIDs(&ctx, &targetObjDN, pFlag,  
						srchStr, &count, &secretIDList, NULL))
					{
						printf("Error [%d] NSSSEnumerateSecretIDs\n", rcode);
						Pause();
					}

					opCount++;
					nameStr = strtok((char *)&secretIDList.data[0], "*");

					for(i = 1; i <= (int)count; i++)
					{
						readSecret.len = NSSS_MAX_SECRET_BUF_LEN;
						strcpy(secretID.id, nameStr);
						secretID.len = strlen(secretID.id)+1;

						rInfo.statFlags = 0;
						if(remLock)
						{
							/* for read the length should be initialized */
							if(rcode = NSSSReadSecret(&ctx, &targetObjDN, pFlag,  
									NULL, &rInfo, &secretID, &readSecret, NULL))
							{
								printf("Status Flags = [0x%x]\n", rInfo.statFlags);
								printf("Read SecretID[%d] = [%s]\n", i, secretID.id);
								printf("Error [%d] NSSSReadSecret\n", rcode);
								Pause();
							}
							opCount++;
						}
						else
						{
							/* do the test read */
							if(rcode = NSSSReadSecret(&ctx, &targetObjDN, pFlag,  
									NULL, &rInfo, &secretID, &readSecret, NULL))
							{
								if(rcode != NSSS_E_EP_ACCESS_DENIED)
								{
									printf("Status Flags = [0x%x]\n", rInfo.statFlags);
									printf("Read SecretID[%d] = [%s]\n", i, secretID.id);
									printf("Error [%d] NSSSReadSecret\n", rcode);
									Pause();
								}
								opCount++;
							}
							
							if(rcode == NSSS_E_EP_ACCESS_DENIED)
							{
								if(rInfo.statFlags & NSSS_EP_PWORD_PRESENT_F)
								{
									/* read again */
									readSecret.len = NSSS_MAX_SECRET_BUF_LEN;
									/* use the master password to read */
									/* for read the lenght should be initialized */
									if(rcode = NSSSReadSecret(&ctx, &targetObjDN, 
											(pFlag | NSSS_ENHANCED_PROTECTION_F | NSSS_EP_MASTER_PWORD_USED_F),
											&masterPword, &rInfo, &secretID, &readSecret, NULL))
									{
										printf("\nStatus Flags = [0x%x]\n", rInfo.statFlags);
										printf("Read SecretID[%d] = [%s]\n", i, secretID.id);
										printf("Error [%d] NSSSReadSecret\n", rcode);
										PrintFlags("Secret Flags:\n", rInfo.statFlags);
										Pause();
									}
									opCount++;
								}
							}
						}
						
						if(rcode == NSSS_SUCCESS)
						{
							printf("\nStatus Flags = [0x%x]\n", rInfo.statFlags);
							PrintFlags("Secret Flags:\n", rInfo.statFlags);
							printf("Read Secret[%d] = [%s], len [%d]\n", 
												i, readSecret.data, readSecret.len);
							if(aFlag)
							{
								crtStamp = localtime((long *)&rInfo.crtStamp);
								if(crtStamp)
								{
									printf("\nCreation time stamp: %s", asctime(crtStamp));
								}

								latStamp = localtime((long *)&rInfo.latStamp);
								if(latStamp && rInfo.latStamp)
								{
									printf("Last accessed time stamp: %s", asctime(latStamp));
								}

								lmtStamp = localtime((long *)&rInfo.lmtStamp);
								if(lmtStamp)
								{
									printf("Last modified time stamp: %s\n", asctime(lmtStamp));
								}
							}
						}
						nameStr = strtok(NULL, "*");
					} /* end for ... */
				}
			} /* if unlock */

			/* for looping you should reset */
			unlock = 0;
			if(nslFlag)
			{
				printf("\n<<=============== ENDING NSL OPS ======================>\n");
			}

			if(aFlag)
			{
				printf("\nDo you want to REMOVE the secrets(y/n)? ");
				c = getch();
				putchar(c);
				printf("\n\n");
			}
			else
			{
				c = 'y';
			}

			if(c == 'y' || c == 'Y')
			{
				if(aFlag)
				{
					printf("\nOne at a time(y/n)? ");
					c = getch();
					putchar(c);
					printf("\n");
				}
				else
				{
					if(repairFlag)
					{
						c = 'n';
					}
					else
					{
						c = 'y';
					}
				}

				if(c == 'y' || c == 'Y')
				{
					if(secretIDList.len)
					{
						/* now remove the secrets added here */
						for(i = 1; i < 16; i++)
						{
							strcpy(secretID.id, appNames[ i - 1 ]);
							secretID.len = strlen(secretID.id)+1;

							/* can remove one secret at a time */
							if((i == 15) && (aFlag))
							{
								pFlag |= NSSS_DESTROY_CONTEXT_F;
							}

							if(rcode = NSSSRemoveSecret(&ctx, &targetObjDN, pFlag, 
									&secretID, NULL))
							{
								printf("\nError [%d] NSSSRemoveSecret\n", rcode);
								printf("SecretID[%d] = [%s]\n", i, secretID.id);
								Pause();
							}
							else
							{
								printf("\nRemoved secret[%d] = [%s] from SS\n", i, secretID.id);
							}
							haveContext = 0;
							opCount++;
						}
					}
				}
				else
				{
					/* remove the SecretStore */
					if(rcode = NSSSRemoveSecretStore(&ctx, &targetObjDN, pFlag, NULL))
					{
						printf("\nError [%d] NSSSRemoveSecretStore\n", rcode);
					}
					else
					{
						printf("\nRemoved SecretStore\n");
					}

					pFlag |= NSSS_DESTROY_CONTEXT_F;
					haveContext = 0;
					opCount++;
				}
			}

			printf("\n\n\n");

			if(!nslFlag)
			{
				printf("NUMBER OF THE LOOPS = %d\n", j+1);
				printf("NUMBER OF OPERATIONS COMPLETED = %d\n", opCount);
			}

		} /* end for */

		if(aFlag)
		{
			printf("Do you want to run again? (y/n) ");
			c = getch();
			putchar(c);
			printf("\n\n");
		}
		else
		{
			c = 'n';
			pFlag |= NSSS_DESTROY_CONTEXT_F;
			if(rcode = NSSSRemoveSecretStore(&ctx, &targetObjDN, pFlag, NULL))
			{
				printf("\nSecretStore LDAP Context Freed\n");
				opCount++;
			}
		}
	}
	while(c == 'y' || c == 'Y');

	if(!nslFlag)
	{
		endTime = time(NULL);
	}
	else
	{
		printf("\nNUMBER OF THE NSL USERS = %d\n", k+1);
		printf("TOTAL NUMBER OF OPERATIONS COMPLETED = %d\n", opCount);
		printf("NUMBER OF NSL COMPLETED OPERATIONS = %d\n", nslCount);
		printf("\nNSL START TIME = [%ld]\n", startTime);
		printf("NSL FINISH TIME = [%ld]\n\n", endTime);
	}

	printf("ELAPSED TIME IN SECONDS = [%ld]\n\n", (endTime - startTime));

/* ########################## CODE EXITS HERE ##################### */

ERROR_1:

	NSSSGetServiceInformation(&ctx, NULL, (pFlag | NSSS_DESTROY_CONTEXT_F), &gsInfo, NULL);

#ifdef N_PLAT_NLM
	NWCallsTerm(NULL);
#endif

	if(secretIDList.data)
	{
		free(secretIDList.data);
	}

	if(readSecret.data)
	{
		free(readSecret.data);
	}

	if(writeSecret.data)
	{
		free(writeSecret.data);
	}

	Pause();

	return(0);

/* ########################## CODE ENDS HERE ##################### */
}  




#ifdef N_PLAT_NLM
#ifdef FAST_ALLOC

/*  */
/*
 * NAME - ss_InitSSAllocTag
 *
 * DESCRIPTION
 *		   
 */
static int ss_InitSSAllocTag(void)
{ /* beginning of the call */
/* ############################## CODE STARTS HERE ############################ */

	if (!(*ssclAllocTag.tag = (void *)AllocateResourceTag((void *)ssLSSCLModuleHandle,
				ssclAllocTag.name, ssclAllocTag.signature)))
	{
		return(NSSS_E_SYSTEM_FAILURE);
	}
	else
	{
		return(NSSS_SUCCESS);
	}

/* ########################## CODE ENDS HERE ##################### */
} /* end of ss_InitSSAllocTag */




/*
 * NAME - ss_GetAllocTag
 *
 * DESCRIPTION
 *		   
 */
void 	*ss_GetAllocTag(void)
{
	return (ssLSSCLAllocRTag);
}


#endif /* FAST_ALLOC */



/*  */
/*
 * NAME - SSPINCanIUnload
 *
 * DESCRIPTION
 *		   
 *		   
 */
int 	SSLDAPCLCanIUnload(void)
{
	return (NSSS_SUCCESS);	/*	For now	*/
}



/*	Object modules compiled with bt=NETWARE in the WatCom IDE	*/
/*	reference this symbol.  Make it a dummy routine so that it	*/
/*	is resolved in the link.												*/

void __WATCOM_Prelude(void){}





/*  */
/*
 * NAME - ss_GetLDAPPINThreadGroupID
 *
 * DESCRIPTION
 *		   
 */
int	ss_GetLDAPCLThreadGroupID(void)
{
	return (ssLSSCLThreadGroupID);
}


/*  */
/*
 * NAME - ss_GetLDAPCLModuleHandle
 *
 * DESCRIPTION
 *		   
 */
unsigned int	ss_GetLDAPCLModuleHandle(void)
{
	return (ssLSSCLModuleHandle);
}



/*  */
/*
 * NAME - UnloadLDAPSSCLMain
 *
 * DESCRIPTION
 *		   
 *		   
 */
void	UnloadLDAPSSCLMain(int	sigNbr)
{ /* beginning of the call */
/* ########################## DECLARATIONS START HERE ######################### */

	int		tgid;

/* ############################## CODE STARTS HERE ############################ */

	sigNbr = sigNbr;
	tgid = SetThreadGroupID(ssLSSCLThreadGroupID);

	NWCallsTerm(NULL);

	SetThreadGroupID(tgid);

/* ############################### CODE ENDS HERE ############################# */
} /* end of UnloadLDAPSSPINMain */



#endif
