/***********************************************************************
 * 
 *  Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; version 2.1
 *  of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, Novell, Inc.
 * 
 *  To contact Novell about this file by physical or electronic mail, 
 *  you may find current contact information at www.novell.com.
 * 
 ***********************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <micasa_mgmd.h>
#include <micasa.h>


#define	GSS_BLD_STR	"1.6.0"

#define 	SSCS_BINARY_TYPE_F				0x00000004L
static char	SSCS_APP_SECRET[] = {'S','S','_','A','p','p', 0};

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////


/*
 * Global data
 */
int		optErr = 1;			// if error message should be printed
int   	optIdx = 1;	   		// index into parent argv vector
int   	optionString = 1;	// character checked for validity
char 	*optArg = NULL;		// argument associated with option

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

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


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

	if(aFlag)
	{
	}
/* ########################## CODE ENDS HERE ######################### */
} /* end of Pause */



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

	SSCS_SECRETSTORE_T   	ssid = {0};
	SSCS_SECRETSTORE_INFO_T	ssInfo = {0};
	SSCS_KEYCHAIN_ID_T		keyChainID = {0};
	
	SSCS_READEXT_T			rInfo = {0};
	void					*ssContext = NULL;

	int						appTstFlag = 0, multiCredTstFlag = 0, multiEntryTstFlag = 0;
	char					*secret;
	

	static char			multiEntryCredSet[] = {'S','h','a','r','e','d','S','e','c','r','e','t',' ','M','u','l','t','i','p','l','e',' ','E','n','t','r','y',' ','C','r','e','d','S','e','t',' ','T','e','s','t',0};

	int						rcode = NSSCS_SUCCESS;
	int						exCount = 1, i, j, remLock = 0, unlock = 0,
							master = 0, rCount = 1;
	long					opCount, bufSize = NSSCS_MAX_SECRET_BUF_LEN;
	unsigned long			startTime, endTime, pFlag = 0L, count = 0;

	SSCS_SECRET_ID_T		secretID = {0};

	// SharedSecret data
	void					*secretHandle;			// handle for passing to functions
	SSCS_SH_SECRET_ID_T		shSecret; 				// SharedSecret struct
	char					*key = NULL;
	unsigned char			*value = NULL;
	int						kLen = 0;
	int						vLen = 0;

	SSCS_SH_SECRET_ID_LIST_T	shSecIDList = {0}; 


	SSCS_BASIC_CREDENTIAL	credential = {0};
	SSCS_SECRET_ID_T		appSecretId = {0};
	SSCS_SECRET_ID_T		sharedSecretId = {0};
	
	SSCS_EXT_T ext = {0};



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

	if((secret = (char *)malloc(NSSCS_MAX_SECRET_BUF_LEN)) == NULL)
	{

		printf("\nSecret Buffer Malloc Failed!!!\n");
		exit(-1);
	}

	if((value = (unsigned char *)malloc(NSSCS_MAX_SECRET_BUF_LEN)) == NULL)
	{

		printf("\nValue Buffer Malloc Failed!!!\n");
		exit(-1);
	}

	if((key = (char *)malloc(NSSCS_MAX_SECRET_ID_LEN)) == NULL)
	{

		printf("\nKey Buffer Malloc Failed!!!\n");
		exit(-1);
	}

	memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
	memset(value, 0, NSSCS_MAX_SECRET_BUF_LEN);
	memset(secret, 0, NSSCS_MAX_SECRET_BUF_LEN);

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

	// Initialize the SID to the user ID if the owner

	strcpy(ssid.ssName, "testuser");
	ssid.version = NSSCS_VERSION_NUMBER;

//	printf("Execution Count Set to: [%d]\n", exCount);
//	printf("Initializing...\n");

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


	if((ssContext =	miCASAOpenSecretStoreCache(&ssid, 0, NULL)) == NULL)
	{
		rcode = NSSCS_E_CANT_OPEN_CLIENT_CACHE;
		printf("\nCache Failed to Open!!!\n");
		goto ERROR_1;
	}
	else
	{
		printf("\nCache Opened...\n");
	}

	keyChainID.len = SSCS_S_KC_ID_CHARS;
	strcpy(keyChainID.keychainID, SSCS_SESSION_KEY_CHAIN_ID);

	for(j = 0, opCount = 0; j < exCount; j++)
	{


			// ***************************************************
			// *********		Enumerting Secrets	     *********
			// ***************************************************

			
			printf("\nEnumerating the Secrets ....\r\n ");

			shSecIDList.enumHandle = 1;
			shSecIDList.returnedIDs = 20;
			shSecIDList.secIDList = (SSCS_SH_SECRET_ID_T *)malloc(20 * sizeof(SSCS_SH_SECRET_ID_T));
			if(shSecIDList.secIDList)
			{
				memset(shSecIDList.secIDList, 0 , 20 * sizeof(SSCS_SH_SECRET_ID_T));	
				do
				{
					if((rcode = miCASAEnumerateSecretIDs(ssContext, &keyChainID, 0, NULL, &shSecIDList, NULL)) == NSSCS_SUCCESS)
					{
						if (shSecIDList.returnedIDs > 0)
						{
						for(i = 0; i < (int)shSecIDList.returnedIDs; i++)
						{
							if(shSecIDList.secIDList[i].type & SSCS_APPLICATION_TYPE_F)
							{
								printf("\nSS_App:\r\n");
							}
							else if(shSecIDList.secIDList[i].type & SSCS_CREDENTIAL_TYPE_F)
							{
								printf("\nSS_CredSet:\r\n");
							}
							else if(shSecIDList.secIDList[i].type & SSCS_BINARY_TYPE_F)
							{
								printf("\nSS_Binary:\r\n");
							}
							else
							{
								printf("\n Unsupported SecretID type .... ");
							}

							//printf("\nLength of the SecretID [%ld]\n", shSecIDList.secIDList[i].len);	
							printf("SecretID [%s]\n", shSecIDList.secIDList[i].name);

							if(shSecIDList.secIDList[i].type & SSCS_CREDENTIAL_TYPE_F)
							// dump the values
							{
								shSecret.type = SSCS_CREDENTIAL_TYPE_F;							
								//strcpy(shSecret.name, shSecIDList.secIDList[i].name);
								strncpy(shSecret.name, (&(shSecIDList.secIDList[i]).name[11]), shSecIDList.secIDList[i].len -11);

								shSecret.len = strlen(shSecret.name)+1;

								secretHandle = miCASA_CreateSHSHandle();  // create a new secretHandle
								if(!secretHandle)
								{
									goto ERROR_1;
								}
								
								
						
								rcode = miCASAReadSecret(ssContext, &keyChainID, 0, secretHandle, &shSecret, NULL, &rInfo, NULL);
								
								if(rcode != NSSCS_SUCCESS)
								{
									printf("\nmiCASAReadSecret returned [%d] when reading [%s]\n\n", rcode, multiEntryCredSet);
									Pause();
									goto ERROR_1;
								}

								
							
								if(!(rcode = miCASA_GetNextSHSEntry(1, secretHandle, &kLen, key, &vLen, value)))
								{
									while(rcode == NSSCS_SUCCESS)
									{
										if(0 == strlen(key))
										{
											break;
										}

										strcpy(secret, key);
										strcat(secret, "=");
										strcat(secret, (char *)value);
										printf("\t [%s]=[%s]\n", key, value);
										
										// clear the buffers
										memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
										memset(value, 0, NSSCS_MAX_SECRET_BUF_LEN);
										memset(secret, 0, NSSCS_MAX_SECRET_BUF_LEN);

										rcode = miCASA_GetNextSHSEntry(0, secretHandle, &kLen, key, &vLen, value);
									}
								}

								miCASA_DestroySHSHandle(secretHandle);  // destroy the secretHandle
							}
						}
						}
						else
						{
							printf("No secrets found in cache\r\n");
							return;
						}
						
					}
					else
					{
						printf("Enumerate secrets returned %d\r\n", rcode);
						// resize the array based on the count returned because the cache engine below
						// does not support iterations 
						if(rcode == NSSCS_E_ENUM_BUFF_TOO_SHORT)
						{
							shSecIDList.enumHandle = 1;
							free(shSecIDList.secIDList);
							shSecIDList.secIDList = (SSCS_SH_SECRET_ID_T *)malloc(shSecIDList.returnedIDs * sizeof(SSCS_SH_SECRET_ID_T));
						}

						if((rcode = miCASAEnumerateSecretIDs(ssContext, &keyChainID, 0, NULL, &shSecIDList, NULL)) == NSSCS_SUCCESS)
						{
							for(i = 0; i < (int)shSecIDList.returnedIDs; i++)
							{
								if(shSecIDList.secIDList[i].type & SSCS_APPLICATION_TYPE_F)
								{
									printf("\nSS_App:\r\n");
								}
								else if(shSecIDList.secIDList[i].type & SSCS_CREDENTIAL_TYPE_F)
								{
									printf("\nSS_CredSet:\r\n");
								}
								else if(shSecIDList.secIDList[i].type & SSCS_BINARY_TYPE_F)
								{
									printf("\nSS_Binary:\r\n ");
								}
								else
								{
									printf("\n Unsupported SecretID type .... ");
								}

								//printf("Length of the SecretID [%ld]\n", shSecIDList.secIDList[i].len);	
								printf("SecretID [%s]\n", shSecIDList.secIDList[i].name);
							}
						}
						else
						{
							printf("Enumerate secrets returned %d\r\n", rcode);
						}
					}

				}
				while(shSecIDList.enumHandle);
			}
			else
			{
				printf("\nEnum Malloc fialed .... ");
			}



	} /* end for */

	endTime = time(NULL);	

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

ERROR_1:

	if(secret)
	{
		memset(secret, 0, NSSCS_MAX_SECRET_BUF_LEN);
		free(secret);
	}

	if(value)
	{
		memset(value, 0, NSSCS_MAX_SECRET_BUF_LEN);
		free(value);
	}

	if(key)
	{
		memset(key, 0, NSSCS_MAX_SECRET_ID_LEN);
		free(key);
	}


	if(ssContext)
	{
		rcode = miCASACloseSecretStoreCache(ssContext, 0, NULL); 
	}

	if(shSecIDList.secIDList)
    {
	   free(shSecIDList.secIDList);
	}

	Pause();

	exit(rcode);


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