/*********************************************************************** * * Copyright (C) 2005-2006 Novell, Inc. 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. * ***********************************************************************/ /*********************************************************************** * * Following are registry entries, which must be created in order * to run this login extension; * * [HKEY_LOCAL_MACHINE\SOFTWARE\Novell\Graphical Login\NWLGE\LCredMgr] * "LoginExtName"="lcredmgr.dll" * "LoginExtDesc"="CASA Login Extension" * "LoginExtType"=DWORD:00008002 // means MASTER + AUTHENTICATE * ***********************************************************************/ //===[ Header files specific to this module ]============================== #include "lcredmgr.h" #define N_PLAT_MSW4 #define N_ARCH_32 #include #include #include #include #include #include //===[ External data ]============================== extern PSETCREDENTIAL pCASASetCredential; //===[ External prototypes ]============================== //===[ Manifest constants ]============================== //===[ Type definitions ]============================== //===[ Function Prototypes ]============================== N_TYPEDEF_CALLBACK(NWDSCCODE,pNWDSCreateContext)(NWDSContextHandle N_FAR *); N_TYPEDEF_CALLBACK(NWDSCCODE,pNWDSSetContext)(NWDSContextHandle,nint,nptr); N_TYPEDEF_CALLBACK(NWDSCCODE,pNWDSWhoAmI)(NWDSContextHandle,pnstr8); N_TYPEDEF_CALLBACK(NWDSCCODE,pNWDSFreeContext)(NWDSContextHandle); N_TYPEDEF_CALLBACK(NWCCODE,pNWLoginExtInit)(pNWLGAccessRec*,pNWVersion,pNWVersion,nptr,nptr); N_TYPEDEF_CALLBACK(NWCCODE,pNWLGGetLoginData)(nint,nint,nptr,nint); //===[ Global Variables ]============================== NWLGAccessRec g_NextAccess = {0, 0, 0}, *g_pAccess = 0; BOOL g_passwordChanged = FALSE; //++======================================================================= int SetCredentialsInWallet( pnstr pTree, pnstr pUser, nint passwordLen, pnstr pPassword ) //=======================================================================-- { int ccode; SSCS_BASIC_CREDENTIAL basicCredential; SSCS_SECRET_ID_T traditionalClient; SSCS_SECRET_ID_T tree; BOOLEAN bLibraryLoaded; #ifdef _DEBUG DebugPrint("Tree name [%s]\n", pTree); DebugPrint("User name [%s]\n", pUser); DebugPrint("Password [%s]\n", pPassword); #endif bLibraryLoaded = InitCASALibrary(); if (bLibraryLoaded == FALSE) { SetLastError(NO_ERROR); return NO_ERROR; } strcpy((char *)&traditionalClient.id, "Traditional_Client"); traditionalClient.len = (long)strlen((char *)&traditionalClient.id) + 1; strcpy((char *)&tree.id, pTree); strupr((char *)&tree.id); tree.len = (long)strlen((char *)&tree.id) + 1; basicCredential.unFlags = USERNAME_TYPE_NDS_FDN_F; if (!pUser) { // // Logout trying to clear the credentials // basicCredential.unLen = 0; basicCredential.pwordLen = 0; ccode = (*pCASASetCredential)( 0, &traditionalClient, &tree, SSCS_CRED_TYPE_BASIC_F, &basicCredential, NULL); #ifdef _DEBUG DebugPrint("miCASASetCredential returned 0x%x\n", ccode); #endif } else { basicCredential.pwordLen = passwordLen; if (passwordLen) { strcpy((char *)&basicCredential.password, pPassword); basicCredential.pwordLen++; } strcpy((char *)&basicCredential.username, pUser); basicCredential.unLen = (unsigned long)strlen((char *)&basicCredential.username) + 1; ccode = (*pCASASetCredential)( 0, &traditionalClient, &tree, SSCS_CRED_TYPE_BASIC_F, &basicCredential, NULL); #ifdef _DEBUG DebugPrint("miCASASetCredential returned 0x%x\n", ccode); #endif } return (ccode); } //++======================================================================= int GetUserFDN( pnstr pTree, pnstr pUser ) //=======================================================================-- { int ccode; HMODULE hInst; NWDSContextHandle hContext; pNWDSCreateContext pfCreateContext; pNWDSSetContext pfSetContext; pNWDSWhoAmI pfWhoAmI; pNWDSFreeContext pfFreeContext; hInst = GetModuleHandle(L"NETWIN32.DLL"); pfCreateContext = (pNWDSCreateContext)GetProcAddress(hInst,"NWDSCreateContextHandle"); pfSetContext = (pNWDSSetContext)GetProcAddress(hInst,"NWDSSetContext"); pfWhoAmI = (pNWDSWhoAmI)GetProcAddress(hInst,"NWDSWhoAmI"); pfFreeContext = (pNWDSFreeContext)GetProcAddress(hInst,"NWDSFreeContext"); if (!pfCreateContext || !pfSetContext || !pfWhoAmI || !pfFreeContext) { return -1; } ccode = pfCreateContext(&hContext); if (ccode == SUCCESS) { pfSetContext(hContext, DCK_TREE_NAME, pTree); pfSetContext(hContext, DCK_NAME_CONTEXT, "[root]"); ccode = pfWhoAmI(hContext, pUser); #ifdef _DEBUG DebugPrint("NWDSWhoAmI returned 0x%x\n", ccode); #endif pfFreeContext(hContext); } return ccode; } //++======================================================================= N_GLOBAL_CALLBACK(NWCCODE) OurEventHandler( pNWLGAccessRec pAccess, nint event, nint eventType, nint eventSubType, nparam parm1, nparam parm2, nflag32 flags ) //=======================================================================-- { pNWLGGetLoginData pGetLoginData; pNWLGStartInfo data; HMODULE hInst; NWCCODE rc, retCode = NWLG_EVT_OK; char szUserFDN[MAX_DN_BYTES]; switch (event) { case NWLG_PRE_SCRIPTS: #ifdef _DEBUG DebugPrint("EventHandler called with NWLG_PRE_SCRIPTS.\n"); #endif case NWLG_SYNC_PWD_END: #ifdef _DEBUG DebugPrint("EventHandler called with NWLG_SYNC_PWD_END.\n"); #endif hInst = GetModuleHandle(L"LGNWNT32.DLL"); pGetLoginData = (pNWLGGetLoginData)GetProcAddress(hInst,"NWLGGetLoginData"); if (pGetLoginData) { rc = pGetLoginData(NWLG_SD_START_INFO, 0, &data, sizeof(&data)); if (rc == NWLG_OK) { if (data && data->password && data->restartMode != 2) { if (g_passwordChanged == FALSE) { rc = GetUserFDN(data->tree, szUserFDN); if (rc == SUCCESS) { #ifdef _DEBUG DebugPrint("GetUserFDN returned user [%s]\n", szUserFDN); #endif SetCredentialsInWallet( data->tree, szUserFDN, data->passwordLen, data->password); } } #ifdef _DEBUG else { DebugPrint("Credentials not set since password changed flag = TRUE.\n"); } #endif } #ifdef _DEBUG else { DebugPrint("No NWLG_SD_START_INFO returned from NWLGGetLoginData or no password data or invalid restartMode.\n"); } #endif } #ifdef _DEBUG else { DebugPrint("GetLoginData for NWLG_SD_START_INFO failed. 0x%X\n", rc); } #endif } #ifdef _DEBUG else { DebugPrint("GetProcAddress for NWLGGetLoginData failed, module handle 0x%x, error %d\n", hInst, GetLastError()); } #endif break; case NWLG_TERMINATE: #ifdef _DEBUG DebugPrint("EventHandler called with NWLG_TERMINATE.\n"); #endif // We have to unchain here ! pAccess->pEventHandler = g_NextAccess.pEventHandler; } // It is time to chain to the default handler, which will take care of // all events (because our DLL is a master extension, not a secondary, // and does not handle events as expected from master extension). // The default handler was copied when our DLL was initialized. if (g_NextAccess.pEventHandler) { retCode = (*g_NextAccess.pEventHandler) (pAccess,event,eventType,eventSubType,parm1,parm2,flags); } return (retCode); } //++======================================================================= N_GLOBAL_CALLBACK(NWCCODE) OurIOHandler( pNWLGAccessRec pAccess, nint ioEvent, nparam param1, nparam param2, nflag32 flags ) //=======================================================================-- { pNWLGGetLoginData pGetLoginData; pNWLGStartInfo data; HINSTANCE hInst; NWCCODE rc, rcode = NWLG_OK; char szUserFDN[MAX_DN_BYTES]; switch (ioEvent) { #ifdef _DEBUG DebugPrint("IOHandler called.\n"); #endif case NWLG_IO_CHANGE_PWD: #ifdef _DEBUG DebugPrint("IOHandler called with NWLG_IO_CHANGE_PWD.\n"); #endif if (g_NextAccess.pIOHandler) { rcode = g_NextAccess.pIOHandler(pAccess, ioEvent, param1, param2, flags); if (NWLG_CANCEL != pAccess->status) { hInst = GetModuleHandle(L"LGNWNT32.DLL"); pGetLoginData = (pNWLGGetLoginData)GetProcAddress(hInst,"NWLGGetLoginData"); if (pGetLoginData) { rc = pGetLoginData(NWLG_SD_START_INFO, 0, &data, sizeof(&data)); if (rc == NWLG_OK) { if (data && param1 && ((pNWLGUserID)param1)->password) { if (data->restartMode != 2) { g_passwordChanged = TRUE; rc = GetUserFDN(data->tree, szUserFDN); if (rc == SUCCESS) { #ifdef _DEBUG DebugPrint("GetUserFDN returned user [%s]\n", szUserFDN); #endif SetCredentialsInWallet( data->tree, szUserFDN, (unsigned long)strlen(((pNWLGUserID)param1)->password), ((pNWLGUserID)param1)->password); } } #ifdef _DEBUG else { DebugPrint("Invalid restartMode.\n"); } #endif } #ifdef _DEBUG else { DebugPrint("No NWLG_SD_START_INFO returned from NWLGGetLoginData or no password data.\n"); } #endif } #ifdef _DEBUG else { DebugPrint("GetLoginData for NWLG_SD_START_INFO failed. 0x%X\n", rc); } #endif } #ifdef _DEBUG else { DebugPrint("GetProcAddress for NWLGGetLoginData failed, module handle 0x%x, error %d\n", hInst, GetLastError()); } #endif } #ifdef _DEBUG else { DebugPrint("Password change cancelled by previous IOHandler!\n"); } #endif } #ifdef _DEBUG else { DebugPrint("Previous IOHandler not presend?!\n"); } #endif break; default: if (g_NextAccess.pIOHandler) { rcode = g_NextAccess.pIOHandler(pAccess, ioEvent, param1, param2, flags); } } return (rcode); } //++======================================================================= void InitLoginExtension( ) //=======================================================================-- { NWCCODE ccode; HINSTANCE hInst; NWVersion versionSupported, runtimeVersion; pNWLoginExtInit pLoginExtInit; hInst = GetModuleHandle(L"LGNWNT32.DLL"); if (hInst) { pLoginExtInit = (pNWLoginExtInit)GetProcAddress(hInst,"NWLoginExtInit"); if (pLoginExtInit) { versionSupported.major = 1; versionSupported.minor = 0; versionSupported.revision = 0; ccode = pLoginExtInit( &g_pAccess, &versionSupported, &runtimeVersion, NULL, NULL); if (ccode == NWLG_OK) { // Save off the old pointers g_NextAccess = *g_pAccess; if (g_pAccess) { g_pAccess->pIOHandler = OurIOHandler; g_pAccess->pEventHandler = (pEvtHndlr)OurEventHandler; } } } } return; } //========================================================================= //=========================================================================