// ----------------------------------------------------------
// File:	ni_kerb95.c
//
// Contents:	main module for ni_kerb95.dll.
//				ni_kerb5.dll is the DLL to provide  
//				authentication module which authenticates on kerberos-4,
//				for ni_pam 
// Warning:		The worst thing about ni_kerb95.dll is that it hardcodes 
//				the kerberos realm to "UMICH.EDU" in ni_kerb95.h
//				This should be fixed but I am waiting kerb95 to be fixed.				
// 
// History:		10-10-97	Naomaru Itoi	created

#include "ni_kerb95.h"

// global valuables. 
HINSTANCE	hDllInstance;	// my instance
KStruct		kStruct;		// Kerbnet95 global struct.
//HANDLE		hUser;			// user handle for local machine.

// functions

BOOL
WINAPI
DllMain(
		HINSTANCE hInstance,
		DWORD dwReason,
		LPVOID lpReserved)
{
    switch (dwReason)
    {
        case DLL_PROCESS_ATTACH:
            DisableThreadLibraryCalls ( hInstance );
            hDllInstance = hInstance;

        case DLL_PROCESS_DETACH:
        default:
            return(TRUE);
    }
}

BOOL
WINAPI
ni_sm_authenticate(NISTRUCT *niStruct)
{	
	INT rv;
	WCHAR wcBuf[StrLen];

	D(L"ni_kerb95 : ni_sm_authenticate() called. \n");

	kStruct.hTicketCache = (HANDLE)0;

	rv = KrbDoesTktCacheExist();
	if (!rv) {
		printf("Creating ticket cache ...\n");
		KrbCreateCache(CacheSize, &(kStruct.hTicketCache));
		// permit the ticket cache to everybody.
		PermitTicketCache();
	}
	else {
		printf("Ticket cache already exists.\n");
	}
	
	// make username@domain -> identity

	wprintf(L"doing %s,%s", niStruct->username, niStruct->domain);
	wsprintf (kStruct.identity, L"%s@%s", niStruct->username, niStruct->domain);

	
	KrbParseIdentity (kStruct.identity,
		kStruct.principal, kStruct.instance, kStruct.realm);
	wprintf(L"parse %s -> %s, %s, %s\n", 
		kStruct.identity, kStruct.principal, kStruct.instance, kStruct.realm);

	// print parsing
	/*
	wsprintf (wcBuf,L"Parsing %s_ -> %s_,%s_,%s_\n", 
		kStruct.identity, kStruct.principal, kStruct.instance, kStruct.realm);
	NIError(wcBuf, L"NI_KERB95");
	*/
	//wprintf(L"password=%s\n", niStruct->password);
	/*
	wsprintf (wcBuf,L"Trying to get TGT for %s_,%s_,%s_,%s_\n", 
		kStruct.principal, kStruct.instance,
		kStruct.realm, niStruct->password);
	NIError(wcBuf, L"NI_KERB95");
	*/
	if (!KrbRequestTGT (kStruct.principal, kStruct.instance,
		kStruct.realm, niStruct->password,
		KerberosVersion)){
		NIError (L"could not get tgt", L"NI_KERB95");
		return NI_FAILURE;
	}
	else {
		wsprintf (wcBuf,L"%s: succeeded to get kerb95 TGT\n", niStruct->username);
		NIError(wcBuf, L"NI_KERB95");
		//wprintf(L"Got TGT!\n");
		return NI_SUCCESS;
	}
}

// ni_sm_logout()
// logout kerberos 4 = destroy k4 ticket.
// 1997/10/10, Naomaru Itoi, created

BOOL WINAPI ni_sm_logout()
{
	LPKTKT tkt;

	wprintf(L"ni_kerb95 : ni_sm_logout() called. \n");
	while ((tkt = KrbWalkCache(TRUE)) != NULL) {
		KrbDeleteTicketA(tkt->principal,tkt->principal_instance,tkt->service,
			tkt->service_instance,tkt->realm,(WORD)(tkt->kversion));
	}

	/*
	if (pgData->pSecurityData != NULL) {
		GlobalFree(pgData->pSecurityData);
		pgData->pSecurityData = NULL;
	}
	*/

	KrbSetCurrIdentity(L"",L"",L"");
	KrbReleaseCache(&(kStruct.hTicketCache));

	/*
	KrbDeleteTicket(kStruct.principal,kStruct.instance,L"krbtgt",
		kStruct.realm, kStruct.realm,4);
      */

	return NI_SUCCESS;
}

// ni_sm_chpass_check()
// preliminary check for change password protocol.
// 10-10-1997, Naomaru Itoi, created

INT WINAPI ni_sm_chpass_check(NISTRUCT *niStruct)
{
	return NI_SUCCESS;
}

// ni_sm_chpass()
// change password function.
// 10-10-1997, Naomaru Itoi, created

INT WINAPI ni_sm_chpass(NISTRUCT *niStruct)
{
	return NI_SUCCESS;
}


BOOL WINAPI PermitTicketCache (VOID) {
	DWORD                    dwACLsz;
	HKEY                     hkeyUser;
	SID_IDENTIFIER_AUTHORITY siaAdmin = SECURITY_NT_AUTHORITY;
	SID_IDENTIFIER_AUTHORITY siaAny = SECURITY_WORLD_SID_AUTHORITY;
	SID_IDENTIFIER_AUTHORITY siaSys = SECURITY_NT_AUTHORITY;
	PSID                     psidAdmin, psidAny, psidSys;
	PACL                     paclNew;
	SECURITY_DESCRIPTOR      sdNew;
	BOOL                     bReturn = FALSE;

	psidAdmin = NULL;
	if (!AllocateAndInitializeSid(&siaAdmin,2,SECURITY_BUILTIN_DOMAIN_RID,
			DOMAIN_ALIAS_RID_ADMINS,0,0,0,0,0,0,&psidAdmin)) {
		/* Should scream and yell at this point. */
		goto bail;
	}

	psidAny = NULL;
	if (!AllocateAndInitializeSid(&siaAny,1,SECURITY_WORLD_RID,
			0,0,0,0,0,0,0,&psidAny)) {
		goto bail;
	}

	psidSys = NULL;
	if (!AllocateAndInitializeSid(&siaSys,1,SECURITY_LOCAL_SYSTEM_RID,
			0,0,0,0,0,0,0,&psidSys)) {
		/* Should scream and yell at this point. */
		goto bail;
	}

	dwACLsz = sizeof(ACL) + (3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)))
				+ GetLengthSid(psidAdmin) + GetLengthSid(psidAny)
				+ GetLengthSid(psidSys);

	if ((paclNew = (PACL)GlobalAlloc(GPTR,dwACLsz)) == NULL) {
		/* Should scream and yell at this point. */
		goto bail;
	}

	if (!InitializeAcl(paclNew,dwACLsz,ACL_REVISION)) {
		/* Should scream and yell at this point. */
		goto bail;
	}

	if (!AddAccessAllowedAce(paclNew,ACL_REVISION,KEY_ALL_ACCESS,psidAdmin)) {
		/* Should scream and yell at this point. */
		goto bail;
	}

	if (!AddAccessAllowedAce(paclNew,ACL_REVISION,KEY_ALL_ACCESS,psidAny)) {
		/* Should scream and yell at this point. */
		goto bail;
	}

	if (!AddAccessAllowedAce(paclNew,ACL_REVISION,KEY_ALL_ACCESS,psidSys)) {
		/* Should scream and yell at this point. */
		goto bail;
	}

	if (!InitializeSecurityDescriptor(&sdNew,SECURITY_DESCRIPTOR_REVISION)) {
		/* Should scream and yell at this point. */
		goto bail;
	}

	if (!SetSecurityDescriptorDacl(&sdNew,TRUE,paclNew,FALSE)) {
		/* Should scream and yell at this point. */
		goto bail;
	}

	if (!SetKernelObjectSecurity(kStruct.hTicketCache,DACL_SECURITY_INFORMATION,&sdNew)) {
		/* Should scream and yell at this point. */
		goto bail;
	}
	bReturn = TRUE;

	bail:
	RegCloseKey(hkeyUser);
	RegFlushKey(HKEY_USERS);

	if (paclNew   != NULL) GlobalFree(paclNew);
	if (psidAdmin != NULL) FreeSid(psidAdmin);
	if (psidAny   != NULL) FreeSid(psidAny);
	if (psidSys   != NULL) FreeSid(psidSys);

	return(bReturn);
}