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"
24 #include <WINNT\afsreg.h>
35 //#define REGISTER_POWER_NOTIFICATIONS 1
36 #include "afsd_flushvol.h"
38 extern void afsi_log(char *pattern, ...);
40 static SERVICE_STATUS ServiceStatus;
41 static SERVICE_STATUS_HANDLE StatusHandle;
43 HANDLE hAFSDMainThread = NULL;
45 HANDLE WaitToTerminate;
50 unsigned int MainThreadId;
54 extern int traceOnPanic;
55 extern HANDLE afsi_file;
57 int powerEventsRegistered = 0;
60 * Notifier function for use by osi_panic
62 static void afsd_notifier(char *msgp, char *filep, long line)
69 sprintf(tbuffer, "Error at file %s, line %d: %s",
72 sprintf(tbuffer, "Error at unknown location: %s", msgp);
74 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
76 ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, line, NULL, 1, 0, ptbuf, NULL);
77 DeregisterEventSource(h);
81 osi_LogEnable(afsd_logp);
83 afsd_ForceTrace(TRUE);
86 afsi_log("--- begin dump ---");
87 cm_DumpSCache(afsi_file, "a", 0);
89 cm_dnlcDump(afsi_file, "a");
91 cm_DumpBufHashTable(afsi_file, "a", 0);
92 smb_DumpVCP(afsi_file, "a", 0);
93 afsi_log("--- end dump ---");
99 SetEvent(WaitToTerminate);
102 if (GetCurrentThreadId() == MainThreadId)
103 longjmp(notifier_jmp, 1);
106 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
107 ServiceStatus.dwWin32ExitCode = NO_ERROR;
108 ServiceStatus.dwCheckPoint = 0;
109 ServiceStatus.dwWaitHint = 0;
110 ServiceStatus.dwControlsAccepted = 0;
111 SetServiceStatus(StatusHandle, &ServiceStatus);
117 * For use miscellaneously in smb.c; need to do better
119 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
125 afsd_ServiceFlushVolume(DWORD dwlpEventData)
127 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
130 ** If UI bit is not set, user interaction is not possible
131 ** BUT, since we are a NON-interactive service, and therefore
132 ** have NO user I/O, it doesn't much matter.
133 ** This benign code left here as example of how to find this out
135 BOOL bUI = (dwlpEventData & 1);
138 if ( PowerNotificationThreadNotify() )
144 /* flush was unsuccessful, or timeout - deny shutdown */
145 dwRet = ERROR_NETWORK_BUSY;
148 /* to deny hibernate, simply return
149 // any value besides NO_ERROR.
151 // dwRet = ERROR_NETWORK_BUSY;
158 /* service control handler used in nt4 only for backward compat. */
160 afsd_ServiceControlHandler(DWORD ctrlCode)
163 DWORD dummyLen, doTrace;
167 case SERVICE_CONTROL_SHUTDOWN:
168 case SERVICE_CONTROL_STOP:
169 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
170 ServiceStatus.dwWin32ExitCode = NO_ERROR;
171 ServiceStatus.dwCheckPoint = 1;
172 ServiceStatus.dwWaitHint = 30000;
173 ServiceStatus.dwControlsAccepted = 0;
174 SetServiceStatus(StatusHandle, &ServiceStatus);
176 if (ctrlCode == SERVICE_CONTROL_STOP)
177 afsi_log("SERVICE_CONTROL_STOP");
179 afsi_log("SERVICE_CONTROL_SHUTDOWN");
181 /* Write all dirty buffers back to server */
184 /* Force trace if requested */
185 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
186 AFSREG_CLT_SVC_PARAM_SUBKEY,
187 0, KEY_QUERY_VALUE, &parmKey);
188 if (code != ERROR_SUCCESS)
191 dummyLen = sizeof(doTrace);
192 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
194 (BYTE *) &doTrace, &dummyLen);
195 RegCloseKey (parmKey);
196 if (code != ERROR_SUCCESS)
199 afsd_ForceTrace(FALSE);
200 buf_ForceTrace(FALSE);
204 SetEvent(WaitToTerminate);
207 case SERVICE_CONTROL_INTERROGATE:
208 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
209 ServiceStatus.dwWin32ExitCode = NO_ERROR;
210 ServiceStatus.dwCheckPoint = 0;
211 ServiceStatus.dwWaitHint = 0;
212 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
213 SetServiceStatus(StatusHandle, &ServiceStatus);
215 /* XXX handle system shutdown */
216 /* XXX handle pause & continue */
222 ** Extended ServiceControlHandler that provides Event types
223 ** for monitoring Power events, for example.
226 afsd_ServiceControlHandlerEx(
234 DWORD dummyLen, doTrace;
236 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
240 case SERVICE_CONTROL_SHUTDOWN:
241 case SERVICE_CONTROL_STOP:
242 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
243 ServiceStatus.dwWin32ExitCode = NO_ERROR;
244 ServiceStatus.dwCheckPoint = 1;
245 ServiceStatus.dwWaitHint = 30000;
246 ServiceStatus.dwControlsAccepted = 0;
247 SetServiceStatus(StatusHandle, &ServiceStatus);
249 /* Write all dirty buffers back to server */
252 /* Force trace if requested */
253 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
254 AFSREG_CLT_SVC_PARAM_SUBKEY,
255 0, KEY_QUERY_VALUE, &parmKey);
256 if (code != ERROR_SUCCESS)
259 dummyLen = sizeof(doTrace);
260 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
262 (BYTE *) &doTrace, &dummyLen);
263 RegCloseKey (parmKey);
264 if (code != ERROR_SUCCESS)
267 afsd_ForceTrace(FALSE);
268 buf_ForceTrace(FALSE);
272 SetEvent(WaitToTerminate);
276 case SERVICE_CONTROL_INTERROGATE:
277 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
278 ServiceStatus.dwWin32ExitCode = NO_ERROR;
279 ServiceStatus.dwCheckPoint = 0;
280 ServiceStatus.dwWaitHint = 0;
281 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
282 SetServiceStatus(StatusHandle, &ServiceStatus);
283 afsi_log("SERVICE_CONTROL_INTERROGATE");
287 /* XXX handle system shutdown */
288 /* XXX handle pause & continue */
289 case SERVICE_CONTROL_POWEREVENT:
291 afsi_log("SERVICE_CONTROL_POWEREVENT");
293 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
294 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
295 ** Return any error code to deny request,
296 ** i.e. as if returning BROADCAST_QUERY_DENY
298 if (powerEventsRegistered) {
299 switch((int) dwEventType)
301 case PBT_APMQUERYSUSPEND:
302 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
303 /* Write all dirty buffers back to server */
307 case PBT_APMQUERYSTANDBY:
308 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
309 /* Write all dirty buffers back to server */
314 /* allow remaining case PBT_WhatEver */
316 afsi_log("SERVICE_CONTROL_APMSUSPEND");
320 afsi_log("SERVICE_CONTROL_APMSTANDBY");
323 case PBT_APMRESUMECRITICAL:
324 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
327 case PBT_APMRESUMESUSPEND:
328 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
331 case PBT_APMRESUMESTANDBY:
332 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
335 case PBT_APMBATTERYLOW:
336 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
339 case PBT_APMPOWERSTATUSCHANGE:
340 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
343 case PBT_APMOEMEVENT:
344 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
347 case PBT_APMRESUMEAUTOMATIC:
348 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
352 afsi_log("SERVICE_CONTROL_unknown");
357 } /* end switch(ctrlCode) */
361 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
363 * Mount a drive into AFS if there global mapping
365 /* DEE Could check first if we are run as SYSTEM */
366 #define MAX_RETRIES 30
367 static void MountGlobalDrives(void)
369 char szAfsPath[_MAX_PATH];
370 char szDriveToMapTo[5];
374 DWORD dwIndex = 0, dwRetry = 0;
376 DWORD dwSubMountSize;
377 char szSubMount[256];
380 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
382 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
383 if (dwResult != ERROR_SUCCESS)
386 while (dwRetry < MAX_RETRIES) {
387 dwDriveSize = sizeof(szDriveToMapTo);
388 dwSubMountSize = sizeof(szSubMount);
389 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
390 if (dwResult != ERROR_MORE_DATA) {
391 if (dwResult != ERROR_SUCCESS) {
392 if (dwResult != ERROR_NO_MORE_ITEMS)
393 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
398 for ( ; dwRetry < MAX_RETRIES; dwRetry++)
401 memset (&nr, 0x00, sizeof(NETRESOURCE));
403 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
405 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
406 nr.dwType=RESOURCETYPE_DISK;
407 nr.lpLocalName=szDriveToMapTo;
408 nr.lpRemoteName=szAfsPath;
409 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
410 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
412 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
413 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
414 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
415 if (dwResult == NO_ERROR) {
418 /* wait for smb server to come up */
419 Sleep((DWORD)1000 /* miliseconds */);
421 /* Disconnect any previous mappings */
422 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
429 static void DismountGlobalDrives()
431 char szAfsPath[_MAX_PATH];
432 char szDriveToMapTo[5];
438 DWORD dwSubMountSize;
439 char szSubMount[256];
442 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
444 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
445 if (dwResult != ERROR_SUCCESS)
449 dwDriveSize = sizeof(szDriveToMapTo);
450 dwSubMountSize = sizeof(szSubMount);
451 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
452 if (dwResult != ERROR_MORE_DATA) {
453 if (dwResult != ERROR_SUCCESS) {
454 if (dwResult != ERROR_NO_MORE_ITEMS)
455 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
460 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
462 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
463 dwResult = WNetCancelConnection(szAfsPath, TRUE);
465 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
472 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
474 DWORD dwVersionHandle;
475 LPVOID pVersionInfo = 0;
477 LPDWORD pLangInfo = 0;
478 LPTSTR szVersion = 0;
480 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
481 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
484 afsi_log("GetFileVersionInfoSize failed");
485 return GetLastError();
488 pVersionInfo = malloc(size);
490 afsi_log("out of memory 1");
491 return ERROR_NOT_ENOUGH_MEMORY;
494 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
495 if (retval = GetLastError())
497 afsi_log("GetFileVersionInfo failed: %d", retval);
501 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
502 (LPVOID*)&pLangInfo, &len);
503 if (retval = GetLastError())
505 afsi_log("VerQueryValue 1 failed: %d", retval);
510 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
511 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
513 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
514 if (retval = GetLastError())
516 /* try again with language 409 since the old binaries were tagged wrong */
518 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
521 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
522 if (retval = GetLastError()) {
523 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
527 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
528 szOutput[dwOutput - 1] = 0;
537 static HINSTANCE hCrypt32;
538 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
539 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
540 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
541 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
542 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
543 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
544 HCRYPTMSG* phMsg, const void** ppvContext);
545 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
546 void* pvData, DWORD* pcbData);
547 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
548 DWORD dwFindFlags, DWORD dwFindType,
549 const void* pvFindPara,
550 PCCERT_CONTEXT pPrevCertContext);
551 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
552 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
553 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
554 PCERT_INFO pCertId2);
555 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
557 void LoadCrypt32(void)
559 hCrypt32 = LoadLibrary("crypt32");
563 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
564 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
565 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
566 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
567 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
568 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
569 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
570 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
572 if ( !pCertGetNameString ||
573 !pCryptQueryObject ||
574 !pCryptMsgGetParam ||
575 !pCertFindCertificateInStore ||
578 !pCertCompareCertificate ||
579 !pCertFreeCertificateContext)
581 FreeLibrary(hCrypt32);
586 void UnloadCrypt32(void)
588 FreeLibrary(hCrypt32);
591 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
593 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
595 wchar_t wfilename[260];
601 HCERTSTORE hStore = NULL;
602 HCRYPTMSG hMsg = NULL;
603 PCMSG_SIGNER_INFO pSignerInfo = NULL;
604 PCCERT_CONTEXT pCertContext = NULL;
607 if ( hCrypt32 == NULL )
610 ZeroMemory(&CertInfo, sizeof(CertInfo));
611 mbstowcs(wfilename, filename, 260);
613 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
615 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
616 CERT_QUERY_FORMAT_FLAG_BINARY,
626 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
632 fResult = pCryptMsgGetParam(hMsg,
633 CMSG_SIGNER_INFO_PARAM,
639 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
645 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
647 fResult = pCryptMsgGetParam(hMsg,
648 CMSG_SIGNER_INFO_PARAM,
654 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
660 CertInfo.Issuer = pSignerInfo->Issuer;
661 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
663 pCertContext = pCertFindCertificateInStore(hStore,
666 CERT_FIND_SUBJECT_CERT,
671 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
679 LocalFree(pSignerInfo);
682 CertFreeCertificateContext(pCertContext);*/
685 pCertCloseStore(hStore,0);
688 pCryptMsgClose(hMsg);
693 BOOL VerifyTrust(CHAR * filename)
695 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
696 WIN_TRUST_SUBJECT_FILE fSubjectFile;
697 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
698 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
699 wchar_t wfilename[260];
701 BOOL success = FALSE;
703 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
706 if (filename == NULL )
709 hWinTrust = LoadLibrary("wintrust");
713 if (((FARPROC) pWinVerifyTrust =
714 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
716 FreeLibrary(hWinTrust);
720 mbstowcs(wfilename, filename, 260);
722 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
724 fSubjectFile.lpPath = wfilename;
725 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
726 FALSE, GetCurrentProcessId());
727 fContextWSubject.SubjectType = &subject;
728 fContextWSubject.Subject = &fSubjectFile;
730 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
732 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
733 CloseHandle( fSubjectFile.hFile );
734 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
735 CloseHandle( fContextWSubject.hClientToken );
737 if (ret == ERROR_SUCCESS) {
740 DWORD gle = GetLastError();
742 case TRUST_E_PROVIDER_UNKNOWN:
743 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
745 case TRUST_E_NOSIGNATURE:
746 afsi_log("VerifyTrust failed: Unsigned executable");
748 case TRUST_E_EXPLICIT_DISTRUST:
749 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
751 case TRUST_E_SUBJECT_NOT_TRUSTED:
752 afsi_log("VerifyTrust failed: File is not trusted");
754 case TRUST_E_BAD_DIGEST:
755 afsi_log("VerifyTrust failed: Executable has been modified");
757 case CRYPT_E_SECURITY_SETTINGS:
758 afsi_log("VerifyTrust failed: local security options prevent verification");
761 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
765 FreeLibrary(hWinTrust);
769 void LogCertCtx(PCCERT_CONTEXT pCtx) {
771 LPTSTR szName = NULL;
773 if ( hCrypt32 == NULL )
776 // Get Issuer name size.
777 if (!(dwData = pCertGetNameString(pCtx,
778 CERT_NAME_SIMPLE_DISPLAY_TYPE,
779 CERT_NAME_ISSUER_FLAG,
783 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
787 // Allocate memory for Issuer name.
788 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
791 if (!(pCertGetNameString(pCtx,
792 CERT_NAME_SIMPLE_DISPLAY_TYPE,
793 CERT_NAME_ISSUER_FLAG,
797 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
801 // print Issuer name.
802 afsi_log("Issuer Name: %s", szName);
806 // Get Subject name size.
807 if (!(dwData = pCertGetNameString(pCtx,
808 CERT_NAME_SIMPLE_DISPLAY_TYPE,
813 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
817 // Allocate memory for subject name.
818 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
821 if (!(pCertGetNameString(pCtx,
822 CERT_NAME_SIMPLE_DISPLAY_TYPE,
827 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
831 // Print Subject Name.
832 afsi_log("Subject Name: %s", szName);
840 BOOL AFSModulesVerify(void)
843 CHAR afsdVersion[128];
844 CHAR modVersion[128];
845 CHAR checkName[1024];
846 BOOL trustVerified = FALSE;
852 PCCERT_CONTEXT pCtxService = NULL;
854 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
855 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
856 DWORD dummyLen, code;
857 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
858 DWORD verifyServiceSig = TRUE;
861 hPSAPI = LoadLibrary("psapi");
863 if ( hPSAPI == NULL )
866 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
869 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
872 afsi_log("%s version %s", filename, afsdVersion);
874 if (((FARPROC) pGetModuleFileNameExA =
875 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
876 ((FARPROC) pEnumProcessModules =
877 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
884 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
885 AFSREG_CLT_SVC_PARAM_SUBKEY,
886 0, KEY_QUERY_VALUE, &parmKey);
887 if (code == ERROR_SUCCESS) {
888 dummyLen = sizeof(cacheSize);
889 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
890 (BYTE *) &cacheSize, &dummyLen);
891 RegCloseKey (parmKey);
894 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
895 0, KEY_QUERY_VALUE, &parmKey);
896 if (code == ERROR_SUCCESS) {
897 dummyLen = sizeof(verifyServiceSig);
898 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
899 (BYTE *) &verifyServiceSig, &dummyLen);
900 RegCloseKey (parmKey);
903 if (verifyServiceSig && cacheSize < 716800) {
904 trustVerified = VerifyTrust(filename);
906 afsi_log("Signature Verification disabled");
912 // get a certificate context for the signer of afsd_service.
913 pCtxService = GetCertCtx(filename);
915 LogCertCtx(pCtxService);
918 // Get a list of all the modules in this process.
919 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
920 FALSE, GetCurrentProcessId());
922 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
924 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
926 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
928 char szModName[2048];
930 // Get the full path to the module's file.
931 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
933 lstrcpy(checkName, szModName);
936 if ( strstr(checkName, "afspthread.dll") ||
937 strstr(checkName, "afsauthent.dll") ||
938 strstr(checkName, "afsrpc.dll") ||
939 strstr(checkName, "libafsconf.dll") ||
940 strstr(checkName, "libosi.dll") )
942 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
947 afsi_log("%s version %s", szModName, modVersion);
948 if (strcmp(afsdVersion,modVersion)) {
949 afsi_log("Version mismatch: %s", szModName);
952 if ( trustVerified ) {
953 if ( !VerifyTrust(szModName) ) {
954 afsi_log("Signature Verification failed: %s", szModName);
957 else if (pCtxService) {
958 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
960 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
961 pCtxService->pCertInfo,
963 afsi_log("Certificate mismatch: %s", szModName);
971 pCertFreeCertificateContext(pCtx);
980 pCertFreeCertificateContext(pCtxService);
986 CloseHandle(hProcess);
990 typedef BOOL ( APIENTRY * AfsdInitHook )(void);
991 #define AFSD_INIT_HOOK "AfsdInitHook"
992 #define AFSD_HOOK_DLL "afsdhook.dll"
995 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
998 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
999 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1001 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1002 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1005 afsd_Main(DWORD argc, LPTSTR *argv)
1012 HANDLE hInitHookDll;
1014 AfsdInitHook initHook;
1017 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1018 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1021 osi_InitPanic(afsd_notifier);
1022 osi_InitTraceOption();
1028 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1029 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1030 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1033 hAdvApi32 = LoadLibrary("advapi32.dll");
1034 if (hAdvApi32 == NULL)
1036 afsi_log("Fatal: cannot load advapi32.dll");
1040 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1041 if (pRegisterServiceCtrlHandlerEx)
1043 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1044 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1048 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1051 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1052 ServiceStatus.dwServiceSpecificExitCode = 0;
1053 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1054 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1055 ServiceStatus.dwCheckPoint = 1;
1056 ServiceStatus.dwWaitHint = 30000;
1057 /* accept Power Events */
1058 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
1059 SetServiceStatus(StatusHandle, &ServiceStatus);
1063 HANDLE h; char *ptbuf[1];
1064 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1065 ptbuf[0] = "AFS start pending";
1066 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1067 DeregisterEventSource(h);
1070 #ifdef REGISTER_POWER_NOTIFICATIONS
1077 /* see if we should handle power notifications */
1078 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1079 0, KEY_QUERY_VALUE, &hkParm);
1080 if (code == ERROR_SUCCESS) {
1081 dummyLen = sizeof(bpower);
1082 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1083 (BYTE *) &bpower, &dummyLen);
1085 if(code != ERROR_SUCCESS)
1088 RegCloseKey(hkParm);
1090 /* create thread used to flush cache */
1092 PowerNotificationThreadCreate();
1093 powerEventsRegistered = 1;
1098 /* Verify the versions of the DLLs which were loaded */
1099 if (!AFSModulesVerify()) {
1100 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1101 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1102 ServiceStatus.dwCheckPoint = 0;
1103 ServiceStatus.dwWaitHint = 0;
1104 ServiceStatus.dwControlsAccepted = 0;
1105 SetServiceStatus(StatusHandle, &ServiceStatus);
1107 /* exit if initialization failed */
1111 /* allow an exit to be called prior to any initialization */
1112 hInitHookDll = LoadLibrary(AFSD_HOOK_DLL);
1115 BOOL hookRc = FALSE;
1116 initHook = ( AfsdInitHook ) GetProcAddress(hInitHookDll, AFSD_INIT_HOOK);
1119 hookRc = initHook();
1121 FreeLibrary(hInitHookDll);
1122 hInitHookDll = NULL;
1124 if (hookRc == FALSE)
1126 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1127 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1128 ServiceStatus.dwCheckPoint = 0;
1129 ServiceStatus.dwWaitHint = 0;
1130 ServiceStatus.dwControlsAccepted = 0;
1131 SetServiceStatus(StatusHandle, &ServiceStatus);
1133 /* exit if initialization failed */
1138 /* allow another 15 seconds to start */
1139 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1140 ServiceStatus.dwServiceSpecificExitCode = 0;
1141 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1142 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1143 ServiceStatus.dwCheckPoint = 2;
1144 ServiceStatus.dwWaitHint = 20000;
1145 /* accept Power Events */
1146 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
1147 SetServiceStatus(StatusHandle, &ServiceStatus);
1152 MainThreadId = GetCurrentThreadId();
1153 jmpret = setjmp(notifier_jmp);
1158 code = afsd_InitCM(&reason);
1160 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1161 osi_panic(reason, __FILE__, __LINE__);
1165 ServiceStatus.dwCheckPoint++;
1166 ServiceStatus.dwWaitHint -= 5000;
1167 SetServiceStatus(StatusHandle, &ServiceStatus);
1169 code = afsd_InitDaemons(&reason);
1171 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1172 osi_panic(reason, __FILE__, __LINE__);
1176 ServiceStatus.dwCheckPoint++;
1177 ServiceStatus.dwWaitHint -= 5000;
1178 SetServiceStatus(StatusHandle, &ServiceStatus);
1180 code = afsd_InitSMB(&reason, MessageBox);
1182 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1183 osi_panic(reason, __FILE__, __LINE__);
1186 MountGlobalDrives();
1189 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1190 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1191 ServiceStatus.dwCheckPoint = 0;
1192 ServiceStatus.dwWaitHint = 0;
1194 /* accept Power events */
1195 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
1196 SetServiceStatus(StatusHandle, &ServiceStatus);
1199 HANDLE h; char *ptbuf[1];
1200 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1201 ptbuf[0] = "AFS running";
1202 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1203 DeregisterEventSource(h);
1207 WaitForSingleObject(WaitToTerminate, INFINITE);
1209 afsi_log("Received Termination Signal, Stopping Service");
1212 HANDLE h; char *ptbuf[1];
1213 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1214 ptbuf[0] = "AFS quitting";
1215 ReportEvent(h, GlobalStatus ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
1216 0, 0, NULL, 1, 0, ptbuf, NULL);
1217 DeregisterEventSource(h);
1220 #ifdef AFS_FREELANCE_CLIENT
1221 cm_FreelanceShutdown();
1222 afsi_log("Freelance Shutdown complete");
1225 DismountGlobalDrives();
1226 afsi_log("Global Drives dismounted");
1228 cm_DaemonShutdown();
1229 afsi_log("Daemon shutdown complete");
1232 afsi_log("Buffer shutdown complete");
1235 afsi_log("rx finalization complete");
1238 afsi_log("smb shutdown complete");
1242 cm_ShutdownMappedMemory();
1244 #ifdef REGISTER_POWER_NOTIFICATIONS
1245 /* terminate thread used to flush cache */
1246 if (powerEventsRegistered)
1247 PowerNotificationThreadExit();
1250 /* Remove the ExceptionFilter */
1251 SetUnhandledExceptionFilter(NULL);
1253 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1254 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1255 ServiceStatus.dwCheckPoint = 0;
1256 ServiceStatus.dwWaitHint = 0;
1257 ServiceStatus.dwControlsAccepted = 0;
1258 SetServiceStatus(StatusHandle, &ServiceStatus);
1261 DWORD __stdcall afsdMain_thread(void* notUsed)
1263 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1264 afsd_Main(1, (LPTSTR*)argv);
1270 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1274 main(int argc, char * argv[])
1276 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1277 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1282 for (i = 1; i < argc; i++) {
1283 if (!stricmp(argv[i],"--validate-cache")) {
1284 if (++i != argc - 1) {
1289 return cm_ValidateMappedMemory(argv[i]);
1296 if (!StartServiceCtrlDispatcher(dispatchTable))
1298 LONG status = GetLastError();
1299 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1302 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1304 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1306 SetEvent(WaitToTerminate);
1310 if ( hAFSDMainThread ) {
1311 WaitForSingleObject( hAFSDMainThread, INFINITE );
1312 CloseHandle( hAFSDMainThread );