2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afs/param.h>
20 #include "afsd_init.h"
35 // The following is defined if you want to receive Power notifications,
36 // including Hibernation, and also subsequent flushing of AFS volumes
38 #define REGISTER_POWER_NOTIFICATIONS 1
39 #define FLUSH_VOLUME 1
43 #include "afsd_flushvol.h"
45 extern void afsi_log(char *pattern, ...);
47 static SERVICE_STATUS ServiceStatus;
48 static SERVICE_STATUS_HANDLE StatusHandle;
50 HANDLE hAFSDMainThread = NULL;
52 HANDLE WaitToTerminate;
57 unsigned int MainThreadId;
61 extern int traceOnPanic;
62 extern HANDLE afsi_file;
64 int powerEventsRegistered = 0;
67 * Notifier function for use by osi_panic
69 static void afsd_notifier(char *msgp, char *filep, long line)
76 sprintf(tbuffer, "Error at file %s, line %d: %s",
79 sprintf(tbuffer, "Error at unknown location: %s", msgp);
81 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
83 ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, line, NULL, 1, 0, ptbuf, NULL);
84 DeregisterEventSource(h);
88 osi_LogEnable(afsd_logp);
90 afsd_ForceTrace(TRUE);
93 afsi_log("--- begin dump ---");
94 cm_DumpSCache(afsi_file, "a");
96 cm_dnlcDump(afsi_file, "a");
98 cm_DumpBufHashTable(afsi_file, "a");
99 smb_DumpVCP(afsi_file, "a");
100 afsi_log("--- end dump ---");
106 SetEvent(WaitToTerminate);
109 if (GetCurrentThreadId() == MainThreadId)
110 longjmp(notifier_jmp, 1);
113 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
114 ServiceStatus.dwWin32ExitCode = NO_ERROR;
115 ServiceStatus.dwCheckPoint = 0;
116 ServiceStatus.dwWaitHint = 0;
117 ServiceStatus.dwControlsAccepted = 0;
118 SetServiceStatus(StatusHandle, &ServiceStatus);
124 * For use miscellaneously in smb.c; need to do better
126 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
132 afsd_ServiceFlushVolume(DWORD dwlpEventData)
134 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
137 ** If UI bit is not set, user interaction is not possible
138 ** BUT, since we are a NON-interactive service, and therefore
139 ** have NO user I/O, it doesn't much matter.
140 ** This benign code left here as example of how to find this out
142 BOOL bUI = (dwlpEventData & 1);
145 if ( PowerNotificationThreadNotify() )
151 /* flush was unsuccessful, or timeout - deny shutdown */
152 dwRet = ERROR_NETWORK_BUSY;
155 /* to deny hibernate, simply return
156 // any value besides NO_ERROR.
158 // dwRet = ERROR_NETWORK_BUSY;
165 /* service control handler used in nt4 only for backward compat. */
167 afsd_ServiceControlHandler(DWORD ctrlCode)
170 DWORD dummyLen, doTrace;
174 case SERVICE_CONTROL_SHUTDOWN:
175 case SERVICE_CONTROL_STOP:
176 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
177 ServiceStatus.dwWin32ExitCode = NO_ERROR;
178 ServiceStatus.dwCheckPoint = 1;
179 ServiceStatus.dwWaitHint = 30000;
180 ServiceStatus.dwControlsAccepted = 0;
181 SetServiceStatus(StatusHandle, &ServiceStatus);
184 afsd_ServiceFlushVolume((DWORD) lpEventData);
186 /* Force trace if requested */
187 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
189 0, KEY_QUERY_VALUE, &parmKey);
190 if (code != ERROR_SUCCESS)
193 dummyLen = sizeof(doTrace);
194 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
196 (BYTE *) &doTrace, &dummyLen);
197 RegCloseKey (parmKey);
198 if (code != ERROR_SUCCESS)
201 afsd_ForceTrace(FALSE);
202 buf_ForceTrace(FALSE);
206 SetEvent(WaitToTerminate);
209 case SERVICE_CONTROL_INTERROGATE:
210 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
211 ServiceStatus.dwWin32ExitCode = NO_ERROR;
212 ServiceStatus.dwCheckPoint = 0;
213 ServiceStatus.dwWaitHint = 0;
214 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
215 SetServiceStatus(StatusHandle, &ServiceStatus);
217 /* XXX handle system shutdown */
218 /* XXX handle pause & continue */
224 ** Extended ServiceControlHandler that provides Event types
225 ** for monitoring Power events, for example.
228 afsd_ServiceControlHandlerEx(
236 DWORD dummyLen, doTrace;
238 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
242 case SERVICE_CONTROL_SHUTDOWN:
243 case SERVICE_CONTROL_STOP:
244 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
245 ServiceStatus.dwWin32ExitCode = NO_ERROR;
246 ServiceStatus.dwCheckPoint = 1;
247 ServiceStatus.dwWaitHint = 30000;
248 ServiceStatus.dwControlsAccepted = 0;
249 SetServiceStatus(StatusHandle, &ServiceStatus);
252 afsd_ServiceFlushVolume((DWORD) lpEventData);
255 /* Force trace if requested */
256 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
258 0, KEY_QUERY_VALUE, &parmKey);
259 if (code != ERROR_SUCCESS)
262 dummyLen = sizeof(doTrace);
263 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
265 (BYTE *) &doTrace, &dummyLen);
266 RegCloseKey (parmKey);
267 if (code != ERROR_SUCCESS)
270 afsd_ForceTrace(FALSE);
271 buf_ForceTrace(FALSE);
275 SetEvent(WaitToTerminate);
279 case SERVICE_CONTROL_INTERROGATE:
280 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
281 ServiceStatus.dwWin32ExitCode = NO_ERROR;
282 ServiceStatus.dwCheckPoint = 0;
283 ServiceStatus.dwWaitHint = 0;
284 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
285 SetServiceStatus(StatusHandle, &ServiceStatus);
289 /* XXX handle system shutdown */
290 /* XXX handle pause & continue */
291 case SERVICE_CONTROL_POWEREVENT:
294 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
295 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
296 ** Return any error code to deny request,
297 ** i.e. as if returning BROADCAST_QUERY_DENY
299 if (powerEventsRegistered) {
300 switch((int) dwEventType)
302 case PBT_APMQUERYSUSPEND:
303 case PBT_APMQUERYSTANDBY:
307 dwRet = afsd_ServiceFlushVolume((DWORD) lpEventData);
313 /* allow remaining case PBT_WhatEver */
316 case PBT_APMRESUMECRITICAL:
317 case PBT_APMRESUMESUSPEND:
318 case PBT_APMRESUMESTANDBY:
319 case PBT_APMBATTERYLOW:
320 case PBT_APMPOWERSTATUSCHANGE:
321 case PBT_APMOEMEVENT:
322 case PBT_APMRESUMEAUTOMATIC:
328 } /* end switch(ctrlCode) */
332 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
334 * Mount a drive into AFS if there global mapping
336 /* DEE Could check first if we are run as SYSTEM */
337 #define MAX_RETRIES 30
338 static void MountGlobalDrives(void)
340 char szAfsPath[_MAX_PATH];
341 char szDriveToMapTo[5];
345 DWORD dwIndex = 0, dwRetry = 0;
347 DWORD dwSubMountSize;
348 char szSubMount[256];
351 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
353 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
354 if (dwResult != ERROR_SUCCESS)
357 while (dwRetry < MAX_RETRIES) {
358 dwDriveSize = sizeof(szDriveToMapTo);
359 dwSubMountSize = sizeof(szSubMount);
360 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
361 if (dwResult != ERROR_MORE_DATA) {
362 if (dwResult != ERROR_SUCCESS) {
363 if (dwResult != ERROR_NO_MORE_ITEMS)
364 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
369 for ( ; dwRetry < MAX_RETRIES; dwRetry++)
372 memset (&nr, 0x00, sizeof(NETRESOURCE));
374 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
376 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
377 nr.dwType=RESOURCETYPE_DISK;
378 nr.lpLocalName=szDriveToMapTo;
379 nr.lpRemoteName=szAfsPath;
380 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
381 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
383 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
384 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
385 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
386 if (dwResult == NO_ERROR) {
389 /* wait for smb server to come up */
390 Sleep((DWORD)1000 /* miliseconds */);
392 /* Disconnect any previous mappings */
393 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
400 static void DismountGlobalDrives()
402 char szAfsPath[_MAX_PATH];
403 char szDriveToMapTo[5];
409 DWORD dwSubMountSize;
410 char szSubMount[256];
413 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSConfigKeyName);
415 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
416 if (dwResult != ERROR_SUCCESS)
420 dwDriveSize = sizeof(szDriveToMapTo);
421 dwSubMountSize = sizeof(szSubMount);
422 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
423 if (dwResult != ERROR_MORE_DATA) {
424 if (dwResult != ERROR_SUCCESS) {
425 if (dwResult != ERROR_NO_MORE_ITEMS)
426 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
431 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
433 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
434 dwResult = WNetCancelConnection(szAfsPath, TRUE);
436 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
443 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
445 DWORD dwVersionHandle;
446 LPVOID pVersionInfo = 0;
448 LPDWORD pLangInfo = 0;
449 LPTSTR szVersion = 0;
451 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
452 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
455 afsi_log("GetFileVersionInfoSize failed");
456 return GetLastError();
459 pVersionInfo = malloc(size);
461 afsi_log("out of memory 1");
462 return ERROR_NOT_ENOUGH_MEMORY;
465 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
466 if (retval = GetLastError())
468 afsi_log("GetFileVersionInfo failed: %d", retval);
472 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
473 (LPVOID*)&pLangInfo, &len);
474 if (retval = GetLastError())
476 afsi_log("VerQueryValue 1 failed: %d", retval);
481 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
482 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
484 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
485 if (retval = GetLastError())
487 /* try again with language 409 since the old binaries were tagged wrong */
489 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
492 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
493 if (retval = GetLastError()) {
494 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
498 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
499 szOutput[dwOutput - 1] = 0;
508 static HINSTANCE hCrypt32;
509 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
510 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
511 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
512 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
513 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
514 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
515 HCRYPTMSG* phMsg, const void** ppvContext);
516 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
517 void* pvData, DWORD* pcbData);
518 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
519 DWORD dwFindFlags, DWORD dwFindType,
520 const void* pvFindPara,
521 PCCERT_CONTEXT pPrevCertContext);
522 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
523 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
524 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
525 PCERT_INFO pCertId2);
526 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
528 void LoadCrypt32(void)
530 hCrypt32 = LoadLibrary("crypt32");
534 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
535 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
536 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
537 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
538 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
539 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
540 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
541 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
543 if ( !pCertGetNameString ||
544 !pCryptQueryObject ||
545 !pCryptMsgGetParam ||
546 !pCertFindCertificateInStore ||
549 !pCertCompareCertificate ||
550 !pCertFreeCertificateContext)
552 FreeLibrary(hCrypt32);
557 void UnloadCrypt32(void)
559 FreeLibrary(hCrypt32);
562 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
564 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
566 wchar_t wfilename[260];
572 HCERTSTORE hStore = NULL;
573 HCRYPTMSG hMsg = NULL;
574 PCMSG_SIGNER_INFO pSignerInfo = NULL;
575 PCCERT_CONTEXT pCertContext = NULL;
578 if ( hCrypt32 == NULL )
581 ZeroMemory(&CertInfo, sizeof(CertInfo));
582 mbstowcs(wfilename, filename, 260);
584 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
586 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
587 CERT_QUERY_FORMAT_FLAG_BINARY,
597 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
603 fResult = pCryptMsgGetParam(hMsg,
604 CMSG_SIGNER_INFO_PARAM,
610 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
616 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
618 fResult = pCryptMsgGetParam(hMsg,
619 CMSG_SIGNER_INFO_PARAM,
625 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
631 CertInfo.Issuer = pSignerInfo->Issuer;
632 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
634 pCertContext = pCertFindCertificateInStore(hStore,
637 CERT_FIND_SUBJECT_CERT,
642 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
650 LocalFree(pSignerInfo);
653 CertFreeCertificateContext(pCertContext);*/
656 pCertCloseStore(hStore,0);
659 pCryptMsgClose(hMsg);
664 BOOL VerifyTrust(CHAR * filename)
666 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
667 WIN_TRUST_SUBJECT_FILE fSubjectFile;
668 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
669 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
670 wchar_t wfilename[260];
672 BOOL success = FALSE;
674 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
677 if (filename == NULL )
680 hWinTrust = LoadLibrary("wintrust");
684 if (((FARPROC) pWinVerifyTrust =
685 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
687 FreeLibrary(hWinTrust);
691 mbstowcs(wfilename, filename, 260);
693 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
695 fSubjectFile.lpPath = wfilename;
696 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
697 FALSE, GetCurrentProcessId());
698 fContextWSubject.SubjectType = &subject;
699 fContextWSubject.Subject = &fSubjectFile;
701 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
703 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
704 CloseHandle( fSubjectFile.hFile );
705 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
706 CloseHandle( fContextWSubject.hClientToken );
708 if (ret == ERROR_SUCCESS) {
711 DWORD gle = GetLastError();
713 case TRUST_E_PROVIDER_UNKNOWN:
714 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
716 case TRUST_E_NOSIGNATURE:
717 afsi_log("VerifyTrust failed: Unsigned executable");
719 case TRUST_E_EXPLICIT_DISTRUST:
720 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
722 case TRUST_E_SUBJECT_NOT_TRUSTED:
723 afsi_log("VerifyTrust failed: File is not trusted");
725 case TRUST_E_BAD_DIGEST:
726 afsi_log("VerifyTrust failed: Executable has been modified");
728 case CRYPT_E_SECURITY_SETTINGS:
729 afsi_log("VerifyTrust failed: local security options prevent verification");
732 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
736 FreeLibrary(hWinTrust);
740 void LogCertCtx(PCCERT_CONTEXT pCtx) {
742 LPTSTR szName = NULL;
744 if ( hCrypt32 == NULL )
747 // Get Issuer name size.
748 if (!(dwData = pCertGetNameString(pCtx,
749 CERT_NAME_SIMPLE_DISPLAY_TYPE,
750 CERT_NAME_ISSUER_FLAG,
754 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
758 // Allocate memory for Issuer name.
759 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
762 if (!(pCertGetNameString(pCtx,
763 CERT_NAME_SIMPLE_DISPLAY_TYPE,
764 CERT_NAME_ISSUER_FLAG,
768 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
772 // print Issuer name.
773 afsi_log("Issuer Name: %s", szName);
777 // Get Subject name size.
778 if (!(dwData = pCertGetNameString(pCtx,
779 CERT_NAME_SIMPLE_DISPLAY_TYPE,
784 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
788 // Allocate memory for subject name.
789 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
792 if (!(pCertGetNameString(pCtx,
793 CERT_NAME_SIMPLE_DISPLAY_TYPE,
798 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
802 // Print Subject Name.
803 afsi_log("Subject Name: %s", szName);
811 BOOL AFSModulesVerify(void)
814 CHAR afsdVersion[128];
815 CHAR modVersion[128];
816 CHAR checkName[1024];
817 BOOL trustVerified = FALSE;
823 PCCERT_CONTEXT pCtxService = NULL;
825 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
826 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
827 DWORD dummyLen, code;
828 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
829 DWORD verifyServiceSig = TRUE;
832 hPSAPI = LoadLibrary("psapi");
834 if ( hPSAPI == NULL )
837 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
840 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
843 afsi_log("%s version %s", filename, afsdVersion);
845 if (((FARPROC) pGetModuleFileNameExA =
846 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
847 ((FARPROC) pEnumProcessModules =
848 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
855 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
856 "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters",
857 0, KEY_QUERY_VALUE, &parmKey);
858 if (code == ERROR_SUCCESS) {
859 dummyLen = sizeof(cacheSize);
860 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
861 (BYTE *) &cacheSize, &dummyLen);
862 RegCloseKey (parmKey);
865 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client",
866 0, KEY_QUERY_VALUE, &parmKey);
867 if (code == ERROR_SUCCESS) {
868 dummyLen = sizeof(verifyServiceSig);
869 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
870 (BYTE *) &verifyServiceSig, &dummyLen);
871 RegCloseKey (parmKey);
874 if (verifyServiceSig && cacheSize < 716800) {
875 trustVerified = VerifyTrust(filename);
877 afsi_log("Signature Verification disabled");
883 // get a certificate context for the signer of afsd_service.
884 pCtxService = GetCertCtx(filename);
886 LogCertCtx(pCtxService);
889 // Get a list of all the modules in this process.
890 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
891 FALSE, GetCurrentProcessId());
893 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
895 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
897 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
899 char szModName[2048];
901 // Get the full path to the module's file.
902 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
904 lstrcpy(checkName, szModName);
907 if ( strstr(checkName, "afspthread.dll") ||
908 strstr(checkName, "afsauthent.dll") ||
909 strstr(checkName, "afsrpc.dll") ||
910 strstr(checkName, "libafsconf.dll") ||
911 strstr(checkName, "libosi.dll") )
913 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
918 afsi_log("%s version %s", szModName, modVersion);
919 if (strcmp(afsdVersion,modVersion)) {
920 afsi_log("Version mismatch: %s", szModName);
923 if ( trustVerified ) {
924 if ( !VerifyTrust(szModName) ) {
925 afsi_log("Signature Verification failed: %s", szModName);
928 else if (pCtxService) {
929 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
931 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
932 pCtxService->pCertInfo,
934 afsi_log("Certificate mismatch: %s", szModName);
942 pCertFreeCertificateContext(pCtx);
951 pCertFreeCertificateContext(pCtxService);
957 CloseHandle(hProcess);
961 typedef BOOL ( APIENTRY * AfsdInitHook )(void);
962 #define AFSD_INIT_HOOK "AfsdInitHook"
963 #define AFSD_HOOK_DLL "afsdhook.dll"
966 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
969 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
970 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
972 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
973 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
975 void afsd_Main(DWORD argc, LPTSTR *argv)
984 AfsdInitHook initHook;
987 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
988 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
991 osi_InitPanic(afsd_notifier);
992 osi_InitTraceOption();
998 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
999 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1000 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1003 hAdvApi32 = LoadLibrary("advapi32.dll");
1004 if (hAdvApi32 == NULL)
1006 afsi_log("Fatal: cannot load advapi32.dll");
1010 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1011 if (pRegisterServiceCtrlHandlerEx)
1013 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1014 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1018 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1021 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1022 ServiceStatus.dwServiceSpecificExitCode = 0;
1023 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1024 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1025 ServiceStatus.dwCheckPoint = 1;
1026 ServiceStatus.dwWaitHint = 30000;
1027 /* accept Power Events */
1028 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
1029 SetServiceStatus(StatusHandle, &ServiceStatus);
1033 HANDLE h; char *ptbuf[1];
1034 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1035 ptbuf[0] = "AFS start pending";
1036 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1037 DeregisterEventSource(h);
1040 #ifdef REGISTER_POWER_NOTIFICATIONS
1047 /* see if we should handle power notifications */
1048 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE, &hkParm);
1049 if (code == ERROR_SUCCESS) {
1050 dummyLen = sizeof(bpower);
1051 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1052 (BYTE *) &bpower, &dummyLen);
1054 if(code != ERROR_SUCCESS)
1057 RegCloseKey(hkParm);
1059 /* create thread used to flush cache */
1061 PowerNotificationThreadCreate();
1062 powerEventsRegistered = 1;
1067 /* Verify the versions of the DLLs which were loaded */
1068 if (!AFSModulesVerify()) {
1069 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1070 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1071 ServiceStatus.dwCheckPoint = 0;
1072 ServiceStatus.dwWaitHint = 0;
1073 ServiceStatus.dwControlsAccepted = 0;
1074 SetServiceStatus(StatusHandle, &ServiceStatus);
1076 /* exit if initialization failed */
1080 /* allow an exit to be called prior to any initialization */
1081 hInitHookDll = LoadLibrary(AFSD_HOOK_DLL);
1084 BOOL hookRc = FALSE;
1085 initHook = ( AfsdInitHook ) GetProcAddress(hInitHookDll, AFSD_INIT_HOOK);
1088 hookRc = initHook();
1090 FreeLibrary(hInitHookDll);
1091 hInitHookDll = NULL;
1093 if (hookRc == FALSE)
1095 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1096 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1097 ServiceStatus.dwCheckPoint = 0;
1098 ServiceStatus.dwWaitHint = 0;
1099 ServiceStatus.dwControlsAccepted = 0;
1100 SetServiceStatus(StatusHandle, &ServiceStatus);
1102 /* exit if initialization failed */
1107 /* allow another 15 seconds to start */
1108 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1109 ServiceStatus.dwServiceSpecificExitCode = 0;
1110 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1111 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1112 ServiceStatus.dwCheckPoint = 2;
1113 ServiceStatus.dwWaitHint = 20000;
1114 /* accept Power Events */
1115 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT;
1116 SetServiceStatus(StatusHandle, &ServiceStatus);
1121 MainThreadId = GetCurrentThreadId();
1122 jmpret = setjmp(notifier_jmp);
1127 code = afsd_InitCM(&reason);
1129 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1130 osi_panic(reason, __FILE__, __LINE__);
1134 ServiceStatus.dwCheckPoint++;
1135 ServiceStatus.dwWaitHint -= 5000;
1136 SetServiceStatus(StatusHandle, &ServiceStatus);
1138 code = afsd_InitDaemons(&reason);
1140 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1141 osi_panic(reason, __FILE__, __LINE__);
1145 ServiceStatus.dwCheckPoint++;
1146 ServiceStatus.dwWaitHint -= 5000;
1147 SetServiceStatus(StatusHandle, &ServiceStatus);
1149 code = afsd_InitSMB(&reason, MessageBox);
1151 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1152 osi_panic(reason, __FILE__, __LINE__);
1155 MountGlobalDrives();
1158 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1159 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1160 ServiceStatus.dwCheckPoint = 0;
1161 ServiceStatus.dwWaitHint = 0;
1163 /* accept Power events */
1164 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
1165 SetServiceStatus(StatusHandle, &ServiceStatus);
1168 HANDLE h; char *ptbuf[1];
1169 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1170 ptbuf[0] = "AFS running";
1171 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1172 DeregisterEventSource(h);
1176 WaitForSingleObject(WaitToTerminate, INFINITE);
1179 HANDLE h; char *ptbuf[1];
1180 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1181 ptbuf[0] = "AFS quitting";
1182 ReportEvent(h, GlobalStatus ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
1183 0, 0, NULL, 1, 0, ptbuf, NULL);
1184 DeregisterEventSource(h);
1187 DismountGlobalDrives();
1193 #ifdef REGISTER_POWER_NOTIFICATIONS
1194 /* terminate thread used to flush cache */
1195 if (powerEventsRegistered)
1196 PowerNotificationThreadExit();
1199 /* Remove the ExceptionFilter */
1200 SetUnhandledExceptionFilter(NULL);
1202 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1203 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1204 ServiceStatus.dwCheckPoint = 0;
1205 ServiceStatus.dwWaitHint = 0;
1206 ServiceStatus.dwControlsAccepted = 0;
1207 SetServiceStatus(StatusHandle, &ServiceStatus);
1210 DWORD __stdcall afsdMain_thread(void* notUsed)
1212 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1213 afsd_Main(1, (LPTSTR*)argv);
1220 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1221 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1225 if (!StartServiceCtrlDispatcher(dispatchTable))
1227 LONG status = GetLastError();
1228 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1231 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1233 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1235 SetEvent(WaitToTerminate);
1239 if ( hAFSDMainThread ) {
1240 WaitForSingleObject( hAFSDMainThread, INFINITE );
1241 CloseHandle( hAFSDMainThread );