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 * the regents of the university of michigan
13 * permission is granted to use, copy, create derivative works and
14 * redistribute this software and such derivative works for any purpose,
15 * so long as the name of the university of michigan is not used in
16 * any advertising or publicity pertaining to the use or distribution
17 * of this software without specific, written prior authorization. if
18 * the above copyright notice or any other identification of the
19 * university of michigan is included in any copy of any portion of
20 * this software, then the disclaimer below must also be included.
22 * this software is provided as is, without representation from the
23 * university of michigan as to its fitness for any purpose, and without
24 * warranty by the university of michigan of any kind, either express
25 * or implied, including without limitation the implied warranties of
26 * merchantability and fitness for a particular purpose. the regents
27 * of the university of michigan shall not be liable for any damages,
28 * including special, indirect, incidental, or consequential damages,
29 * with respect to any claim arising out or in connection with the use
30 * of the software, even if it has been or is hereafter advised of the
31 * possibility of such damages.
34 #include <afs/param.h>
44 #include "afsd_init.h"
48 #include <WINNT\afsreg.h>
60 //#define REGISTER_POWER_NOTIFICATIONS 1
61 #include "afsd_flushvol.h"
63 extern void afsi_log(char *pattern, ...);
65 static SERVICE_STATUS ServiceStatus;
66 static SERVICE_STATUS_HANDLE StatusHandle;
68 HANDLE hAFSDMainThread = NULL;
70 HANDLE hAFSDWorkerThread[WORKER_THREADS];
73 HANDLE WaitToTerminate, DoTerminate;
78 unsigned int MainThreadId;
82 extern int traceOnPanic;
83 extern HANDLE afsi_file;
85 int powerEventsRegistered = 0;
88 * Notifier function for use by osi_panic
90 static void afsd_notifier(char *msgp, char *filep, long line)
98 sprintf(tbuffer, "Error at file %s, line %d: %s",
101 sprintf(tbuffer, "Error at unknown location: %s", msgp);
103 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
105 ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, line, NULL, 1, 0, ptbuf, NULL);
106 DeregisterEventSource(h);
110 osi_LogEnable(afsd_logp);
112 afsd_ForceTrace(TRUE);
113 buf_ForceTrace(TRUE);
115 afsi_log("--- begin dump ---");
116 cm_DumpSCache(afsi_file, "a", 0);
118 cm_dnlcDump(afsi_file, "a");
120 cm_DumpBufHashTable(afsi_file, "a", 0);
121 smb_DumpVCP(afsi_file, "a", 0);
122 afsi_log("--- end dump ---");
129 SetEvent(WaitToTerminate);
131 SetEvent(DoTerminate);
132 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
133 for (i = 0; i < WORKER_THREADS; i++)
134 CloseHandle(hAFSDWorkerThread[i]);
138 if (GetCurrentThreadId() == MainThreadId)
139 longjmp(notifier_jmp, 1);
142 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
143 ServiceStatus.dwWin32ExitCode = NO_ERROR;
144 ServiceStatus.dwCheckPoint = 0;
145 ServiceStatus.dwWaitHint = 0;
146 ServiceStatus.dwControlsAccepted = 0;
147 SetServiceStatus(StatusHandle, &ServiceStatus);
153 * For use miscellaneously in smb.c; need to do better
155 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
161 afsd_ServiceFlushVolume(DWORD dwlpEventData)
163 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
166 ** If UI bit is not set, user interaction is not possible
167 ** BUT, since we are a NON-interactive service, and therefore
168 ** have NO user I/O, it doesn't much matter.
169 ** This benign code left here as example of how to find this out
171 BOOL bUI = (dwlpEventData & 1);
174 if ( PowerNotificationThreadNotify() )
180 /* flush was unsuccessful, or timeout - deny shutdown */
181 dwRet = ERROR_NETWORK_BUSY;
184 /* to deny hibernate, simply return
185 // any value besides NO_ERROR.
187 // dwRet = ERROR_NETWORK_BUSY;
194 /* service control handler used in nt4 only for backward compat. */
196 afsd_ServiceControlHandler(DWORD ctrlCode)
199 DWORD dummyLen, doTrace;
203 case SERVICE_CONTROL_SHUTDOWN:
204 case SERVICE_CONTROL_STOP:
205 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
206 ServiceStatus.dwWin32ExitCode = NO_ERROR;
207 ServiceStatus.dwCheckPoint = 1;
208 ServiceStatus.dwWaitHint = 30000;
209 ServiceStatus.dwControlsAccepted = 0;
210 SetServiceStatus(StatusHandle, &ServiceStatus);
212 if (ctrlCode == SERVICE_CONTROL_STOP)
213 afsi_log("SERVICE_CONTROL_STOP");
215 afsi_log("SERVICE_CONTROL_SHUTDOWN");
217 /* Write all dirty buffers back to server */
220 /* Force trace if requested */
221 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
222 AFSREG_CLT_SVC_PARAM_SUBKEY,
223 0, KEY_QUERY_VALUE, &parmKey);
224 if (code != ERROR_SUCCESS)
227 dummyLen = sizeof(doTrace);
228 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
230 (BYTE *) &doTrace, &dummyLen);
231 RegCloseKey (parmKey);
232 if (code != ERROR_SUCCESS)
235 afsd_ForceTrace(FALSE);
236 buf_ForceTrace(FALSE);
241 SetEvent(WaitToTerminate);
243 SetEvent(DoTerminate);
247 case SERVICE_CONTROL_INTERROGATE:
248 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
249 ServiceStatus.dwWin32ExitCode = NO_ERROR;
250 ServiceStatus.dwCheckPoint = 0;
251 ServiceStatus.dwWaitHint = 0;
252 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
253 SetServiceStatus(StatusHandle, &ServiceStatus);
255 /* XXX handle system shutdown */
256 /* XXX handle pause & continue */
262 ** Extended ServiceControlHandler that provides Event types
263 ** for monitoring Power events, for example.
266 afsd_ServiceControlHandlerEx(
274 DWORD dummyLen, doTrace;
276 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
280 case SERVICE_CONTROL_SHUTDOWN:
281 case SERVICE_CONTROL_STOP:
282 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
283 ServiceStatus.dwWin32ExitCode = NO_ERROR;
284 ServiceStatus.dwCheckPoint = 1;
285 ServiceStatus.dwWaitHint = 30000;
286 ServiceStatus.dwControlsAccepted = 0;
287 SetServiceStatus(StatusHandle, &ServiceStatus);
289 /* Write all dirty buffers back to server */
292 /* Force trace if requested */
293 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
294 AFSREG_CLT_SVC_PARAM_SUBKEY,
295 0, KEY_QUERY_VALUE, &parmKey);
296 if (code != ERROR_SUCCESS)
299 dummyLen = sizeof(doTrace);
300 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
302 (BYTE *) &doTrace, &dummyLen);
303 RegCloseKey (parmKey);
304 if (code != ERROR_SUCCESS)
307 afsd_ForceTrace(FALSE);
308 buf_ForceTrace(FALSE);
313 SetEvent(WaitToTerminate);
315 SetEvent(DoTerminate);
320 case SERVICE_CONTROL_INTERROGATE:
321 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
322 ServiceStatus.dwWin32ExitCode = NO_ERROR;
323 ServiceStatus.dwCheckPoint = 0;
324 ServiceStatus.dwWaitHint = 0;
325 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
326 SetServiceStatus(StatusHandle, &ServiceStatus);
327 afsi_log("SERVICE_CONTROL_INTERROGATE");
331 /* XXX handle system shutdown */
332 /* XXX handle pause & continue */
333 case SERVICE_CONTROL_POWEREVENT:
335 afsi_log("SERVICE_CONTROL_POWEREVENT");
337 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
338 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
339 ** Return any error code to deny request,
340 ** i.e. as if returning BROADCAST_QUERY_DENY
342 if (powerEventsRegistered) {
343 switch((int) dwEventType)
345 case PBT_APMQUERYSUSPEND:
346 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
347 /* Write all dirty buffers back to server */
351 case PBT_APMQUERYSTANDBY:
352 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
353 /* Write all dirty buffers back to server */
358 /* allow remaining case PBT_WhatEver */
360 afsi_log("SERVICE_CONTROL_APMSUSPEND");
364 afsi_log("SERVICE_CONTROL_APMSTANDBY");
367 case PBT_APMRESUMECRITICAL:
368 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
371 case PBT_APMRESUMESUSPEND:
372 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
375 case PBT_APMRESUMESTANDBY:
376 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
379 case PBT_APMBATTERYLOW:
380 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
383 case PBT_APMPOWERSTATUSCHANGE:
384 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
387 case PBT_APMOEMEVENT:
388 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
391 case PBT_APMRESUMEAUTOMATIC:
392 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
396 afsi_log("SERVICE_CONTROL_unknown");
402 case SERVICE_CONTROL_CUSTOM_DUMP:
404 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
405 GenerateMiniDump(NULL);
409 } /* end switch(ctrlCode) */
413 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
415 * Mount a drive into AFS if there global mapping
417 /* DEE Could check first if we are run as SYSTEM */
418 #define MAX_RETRIES 30
419 static void MountGlobalDrives(void)
421 char szAfsPath[_MAX_PATH];
422 char szDriveToMapTo[5];
426 DWORD dwIndex = 0, dwRetry = 0;
428 DWORD dwSubMountSize;
429 char szSubMount[256];
432 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
434 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
435 if (dwResult != ERROR_SUCCESS)
438 while (dwRetry < MAX_RETRIES) {
439 dwDriveSize = sizeof(szDriveToMapTo);
440 dwSubMountSize = sizeof(szSubMount);
441 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
442 if (dwResult != ERROR_MORE_DATA) {
443 if (dwResult != ERROR_SUCCESS) {
444 if (dwResult != ERROR_NO_MORE_ITEMS)
445 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
451 for ( ; dwRetry < MAX_RETRIES; dwRetry++)
454 memset (&nr, 0x00, sizeof(NETRESOURCE));
456 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
458 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
459 nr.dwType=RESOURCETYPE_DISK;
460 nr.lpLocalName=szDriveToMapTo;
461 nr.lpRemoteName=szAfsPath;
462 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
463 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
465 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
466 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
467 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
468 if (dwResult == NO_ERROR) {
471 /* wait for smb server to come up */
472 Sleep((DWORD)1000 /* miliseconds */);
474 /* Disconnect any previous mappings */
475 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
485 static void DismountGlobalDrives()
487 char szAfsPath[_MAX_PATH];
488 char szDriveToMapTo[5];
494 DWORD dwSubMountSize;
495 char szSubMount[256];
498 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
500 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
501 if (dwResult != ERROR_SUCCESS)
506 dwDriveSize = sizeof(szDriveToMapTo);
507 dwSubMountSize = sizeof(szSubMount);
508 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
509 if (dwResult != ERROR_MORE_DATA) {
510 if (dwResult != ERROR_SUCCESS) {
511 if (dwResult != ERROR_NO_MORE_ITEMS)
512 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
517 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
519 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
520 dwResult = WNetCancelConnection(szAfsPath, TRUE);
522 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
532 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
534 DWORD dwVersionHandle;
535 LPVOID pVersionInfo = 0;
537 LPDWORD pLangInfo = 0;
538 LPTSTR szVersion = 0;
540 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
541 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
544 afsi_log("GetFileVersionInfoSize failed");
545 return GetLastError();
548 pVersionInfo = malloc(size);
550 afsi_log("out of memory 1");
551 return ERROR_NOT_ENOUGH_MEMORY;
554 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
555 if (retval = GetLastError())
557 afsi_log("GetFileVersionInfo failed: %d", retval);
561 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
562 (LPVOID*)&pLangInfo, &len);
563 if (retval = GetLastError())
565 afsi_log("VerQueryValue 1 failed: %d", retval);
570 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
571 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
573 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
574 if (retval = GetLastError())
576 /* try again with language 409 since the old binaries were tagged wrong */
578 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
581 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
582 if (retval = GetLastError()) {
583 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
587 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
588 szOutput[dwOutput - 1] = 0;
597 static HINSTANCE hCrypt32;
598 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
599 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
600 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
601 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
602 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
603 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
604 HCRYPTMSG* phMsg, const void** ppvContext);
605 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
606 void* pvData, DWORD* pcbData);
607 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
608 DWORD dwFindFlags, DWORD dwFindType,
609 const void* pvFindPara,
610 PCCERT_CONTEXT pPrevCertContext);
611 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
612 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
613 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
614 PCERT_INFO pCertId2);
615 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
617 void LoadCrypt32(void)
619 hCrypt32 = LoadLibrary("crypt32");
623 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
624 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
625 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
626 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
627 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
628 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
629 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
630 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
632 if ( !pCertGetNameString ||
633 !pCryptQueryObject ||
634 !pCryptMsgGetParam ||
635 !pCertFindCertificateInStore ||
638 !pCertCompareCertificate ||
639 !pCertFreeCertificateContext)
641 FreeLibrary(hCrypt32);
646 void UnloadCrypt32(void)
648 FreeLibrary(hCrypt32);
651 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
653 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
655 wchar_t wfilename[260];
661 HCERTSTORE hStore = NULL;
662 HCRYPTMSG hMsg = NULL;
663 PCMSG_SIGNER_INFO pSignerInfo = NULL;
664 PCCERT_CONTEXT pCertContext = NULL;
667 if ( hCrypt32 == NULL )
670 ZeroMemory(&CertInfo, sizeof(CertInfo));
671 mbstowcs(wfilename, filename, 260);
673 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
675 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
676 CERT_QUERY_FORMAT_FLAG_BINARY,
686 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
692 fResult = pCryptMsgGetParam(hMsg,
693 CMSG_SIGNER_INFO_PARAM,
699 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
705 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
707 fResult = pCryptMsgGetParam(hMsg,
708 CMSG_SIGNER_INFO_PARAM,
714 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
720 CertInfo.Issuer = pSignerInfo->Issuer;
721 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
723 pCertContext = pCertFindCertificateInStore(hStore,
726 CERT_FIND_SUBJECT_CERT,
731 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
739 LocalFree(pSignerInfo);
742 CertFreeCertificateContext(pCertContext);*/
745 pCertCloseStore(hStore,0);
748 pCryptMsgClose(hMsg);
753 BOOL VerifyTrust(CHAR * filename)
755 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
756 WIN_TRUST_SUBJECT_FILE fSubjectFile;
757 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
758 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
759 wchar_t wfilename[260];
761 BOOL success = FALSE;
763 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
766 if (filename == NULL )
769 hWinTrust = LoadLibrary("wintrust");
773 if (((FARPROC) pWinVerifyTrust =
774 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
776 FreeLibrary(hWinTrust);
780 mbstowcs(wfilename, filename, 260);
782 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
784 fSubjectFile.lpPath = wfilename;
785 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
786 FALSE, GetCurrentProcessId());
787 fContextWSubject.SubjectType = &subject;
788 fContextWSubject.Subject = &fSubjectFile;
790 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
792 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
793 CloseHandle( fSubjectFile.hFile );
794 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
795 CloseHandle( fContextWSubject.hClientToken );
797 if (ret == ERROR_SUCCESS) {
800 DWORD gle = GetLastError();
802 case TRUST_E_PROVIDER_UNKNOWN:
803 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
805 case TRUST_E_NOSIGNATURE:
806 afsi_log("VerifyTrust failed: Unsigned executable");
808 case TRUST_E_EXPLICIT_DISTRUST:
809 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
811 case TRUST_E_SUBJECT_NOT_TRUSTED:
812 afsi_log("VerifyTrust failed: File is not trusted");
814 case TRUST_E_BAD_DIGEST:
815 afsi_log("VerifyTrust failed: Executable has been modified");
817 case CRYPT_E_SECURITY_SETTINGS:
818 afsi_log("VerifyTrust failed: local security options prevent verification");
821 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
825 FreeLibrary(hWinTrust);
829 void LogCertCtx(PCCERT_CONTEXT pCtx) {
831 LPTSTR szName = NULL;
833 if ( hCrypt32 == NULL )
836 // Get Issuer name size.
837 if (!(dwData = pCertGetNameString(pCtx,
838 CERT_NAME_SIMPLE_DISPLAY_TYPE,
839 CERT_NAME_ISSUER_FLAG,
843 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
847 // Allocate memory for Issuer name.
848 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
851 if (!(pCertGetNameString(pCtx,
852 CERT_NAME_SIMPLE_DISPLAY_TYPE,
853 CERT_NAME_ISSUER_FLAG,
857 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
861 // print Issuer name.
862 afsi_log("Issuer Name: %s", szName);
866 // Get Subject name size.
867 if (!(dwData = pCertGetNameString(pCtx,
868 CERT_NAME_SIMPLE_DISPLAY_TYPE,
873 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
877 // Allocate memory for subject name.
878 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
881 if (!(pCertGetNameString(pCtx,
882 CERT_NAME_SIMPLE_DISPLAY_TYPE,
887 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
891 // Print Subject Name.
892 afsi_log("Subject Name: %s", szName);
900 BOOL AFSModulesVerify(void)
903 CHAR afsdVersion[128];
904 CHAR modVersion[128];
905 CHAR checkName[1024];
906 BOOL trustVerified = FALSE;
912 PCCERT_CONTEXT pCtxService = NULL;
914 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
915 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
916 DWORD dummyLen, code;
917 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
918 DWORD verifyServiceSig = TRUE;
921 hPSAPI = LoadLibrary("psapi");
923 if ( hPSAPI == NULL )
926 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
929 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
932 afsi_log("%s version %s", filename, afsdVersion);
934 if (((FARPROC) pGetModuleFileNameExA =
935 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
936 ((FARPROC) pEnumProcessModules =
937 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
944 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
945 AFSREG_CLT_SVC_PARAM_SUBKEY,
946 0, KEY_QUERY_VALUE, &parmKey);
947 if (code == ERROR_SUCCESS) {
948 dummyLen = sizeof(cacheSize);
949 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
950 (BYTE *) &cacheSize, &dummyLen);
951 RegCloseKey (parmKey);
954 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
955 0, KEY_QUERY_VALUE, &parmKey);
956 if (code == ERROR_SUCCESS) {
957 dummyLen = sizeof(verifyServiceSig);
958 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
959 (BYTE *) &verifyServiceSig, &dummyLen);
960 RegCloseKey (parmKey);
963 if (verifyServiceSig && cacheSize < 716800) {
964 trustVerified = VerifyTrust(filename);
966 afsi_log("Signature Verification disabled");
972 // get a certificate context for the signer of afsd_service.
973 pCtxService = GetCertCtx(filename);
975 LogCertCtx(pCtxService);
978 // Get a list of all the modules in this process.
979 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
980 FALSE, GetCurrentProcessId());
982 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
984 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
986 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
988 char szModName[2048];
990 // Get the full path to the module's file.
991 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
993 lstrcpy(checkName, szModName);
996 if ( strstr(checkName, "afspthread.dll") ||
997 strstr(checkName, "afsauthent.dll") ||
998 strstr(checkName, "afsrpc.dll") ||
999 strstr(checkName, "libafsconf.dll") ||
1000 strstr(checkName, "libosi.dll") )
1002 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
1007 afsi_log("%s version %s", szModName, modVersion);
1008 if (strcmp(afsdVersion,modVersion)) {
1009 afsi_log("Version mismatch: %s", szModName);
1012 if ( trustVerified ) {
1013 if ( !VerifyTrust(szModName) ) {
1014 afsi_log("Signature Verification failed: %s", szModName);
1017 else if (pCtxService) {
1018 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
1020 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1021 pCtxService->pCertInfo,
1023 afsi_log("Certificate mismatch: %s", szModName);
1031 pCertFreeCertificateContext(pCtx);
1040 pCertFreeCertificateContext(pCtxService);
1044 FreeLibrary(hPSAPI);
1046 CloseHandle(hProcess);
1051 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
1054 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
1055 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1057 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1058 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1061 afsd_Main(DWORD argc, LPTSTR *argv)
1073 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1074 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1077 osi_InitPanic(afsd_notifier);
1078 osi_InitTraceOption();
1084 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1085 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1086 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1089 DoTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_DoTerminate"));
1090 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1091 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_DoTerminate"));
1095 hAdvApi32 = LoadLibrary("advapi32.dll");
1096 if (hAdvApi32 == NULL)
1098 afsi_log("Fatal: cannot load advapi32.dll");
1102 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1103 if (pRegisterServiceCtrlHandlerEx)
1105 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1106 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1110 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1113 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1114 ServiceStatus.dwServiceSpecificExitCode = 0;
1115 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1116 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1117 ServiceStatus.dwCheckPoint = 1;
1118 ServiceStatus.dwWaitHint = 30000;
1119 /* accept Power Events */
1120 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1121 SetServiceStatus(StatusHandle, &ServiceStatus);
1125 HANDLE h; char *ptbuf[1];
1126 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1127 ptbuf[0] = "AFS start pending";
1128 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1129 DeregisterEventSource(h);
1132 #ifdef REGISTER_POWER_NOTIFICATIONS
1139 /* see if we should handle power notifications */
1140 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1141 0, KEY_QUERY_VALUE, &hkParm);
1142 if (code == ERROR_SUCCESS) {
1143 dummyLen = sizeof(bpower);
1144 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1145 (BYTE *) &bpower, &dummyLen);
1147 if(code != ERROR_SUCCESS)
1150 RegCloseKey(hkParm);
1152 /* create thread used to flush cache */
1154 PowerNotificationThreadCreate();
1155 powerEventsRegistered = 1;
1160 /* Verify the versions of the DLLs which were loaded */
1161 if (!AFSModulesVerify()) {
1162 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1163 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1164 ServiceStatus.dwCheckPoint = 0;
1165 ServiceStatus.dwWaitHint = 0;
1166 ServiceStatus.dwControlsAccepted = 0;
1167 SetServiceStatus(StatusHandle, &ServiceStatus);
1169 /* exit if initialization failed */
1173 /* allow an exit to be called prior to any initialization */
1174 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1178 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1181 hookRc = initHook();
1183 FreeLibrary(hHookDll);
1186 if (hookRc == FALSE)
1188 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1189 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1190 ServiceStatus.dwCheckPoint = 0;
1191 ServiceStatus.dwWaitHint = 0;
1192 ServiceStatus.dwControlsAccepted = 0;
1193 SetServiceStatus(StatusHandle, &ServiceStatus);
1195 /* exit if initialization failed */
1200 /* allow another 15 seconds to start */
1201 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1202 ServiceStatus.dwServiceSpecificExitCode = 0;
1203 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1204 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1205 ServiceStatus.dwCheckPoint = 2;
1206 ServiceStatus.dwWaitHint = 20000;
1207 /* accept Power Events */
1208 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1209 SetServiceStatus(StatusHandle, &ServiceStatus);
1214 MainThreadId = GetCurrentThreadId();
1215 jmpret = setjmp(notifier_jmp);
1220 code = afsd_InitCM(&reason);
1222 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1223 osi_panic(reason, __FILE__, __LINE__);
1227 ServiceStatus.dwCheckPoint++;
1228 ServiceStatus.dwWaitHint -= 5000;
1229 SetServiceStatus(StatusHandle, &ServiceStatus);
1231 code = afsd_InitDaemons(&reason);
1233 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1234 osi_panic(reason, __FILE__, __LINE__);
1237 /* allow an exit to be called post rx initialization */
1238 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1242 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1245 hookRc = rxStartedHook();
1247 FreeLibrary(hHookDll);
1250 if (hookRc == FALSE)
1252 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1253 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1254 ServiceStatus.dwCheckPoint = 0;
1255 ServiceStatus.dwWaitHint = 0;
1256 ServiceStatus.dwControlsAccepted = 0;
1257 SetServiceStatus(StatusHandle, &ServiceStatus);
1259 /* exit if initialization failed */
1265 ServiceStatus.dwCheckPoint++;
1266 ServiceStatus.dwWaitHint -= 5000;
1267 SetServiceStatus(StatusHandle, &ServiceStatus);
1271 code = afsd_InitSMB(&reason, MessageBox);
1273 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1274 osi_panic(reason, __FILE__, __LINE__);
1277 code = ifs_Init(&reason);
1279 afsi_log("ifs_Init failed: %s (code = %d)", reason, code);
1280 osi_panic(reason, __FILE__, __LINE__);
1282 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1283 hAFSDWorkerThread[cnt] = CreateThread(NULL, 0, ifs_MainLoop, 0, 0, NULL);
1286 /* allow an exit to be called post smb initialization */
1287 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1291 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1294 hookRc = smbStartedHook();
1296 FreeLibrary(hHookDll);
1299 if (hookRc == FALSE)
1301 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1302 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1303 ServiceStatus.dwCheckPoint = 0;
1304 ServiceStatus.dwWaitHint = 0;
1305 ServiceStatus.dwControlsAccepted = 0;
1306 SetServiceStatus(StatusHandle, &ServiceStatus);
1308 /* exit if initialization failed */
1313 MountGlobalDrives();
1316 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1317 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1318 ServiceStatus.dwCheckPoint = 0;
1319 ServiceStatus.dwWaitHint = 0;
1321 /* accept Power events */
1322 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1323 SetServiceStatus(StatusHandle, &ServiceStatus);
1326 HANDLE h; char *ptbuf[1];
1327 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1328 ptbuf[0] = "AFS running";
1329 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1330 DeregisterEventSource(h);
1334 /* allow an exit to be called when started */
1335 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1339 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1342 hookRc = startedHook();
1344 FreeLibrary(hHookDll);
1347 if (hookRc == FALSE)
1349 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1350 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1351 ServiceStatus.dwCheckPoint = 0;
1352 ServiceStatus.dwWaitHint = 0;
1353 ServiceStatus.dwControlsAccepted = 0;
1354 SetServiceStatus(StatusHandle, &ServiceStatus);
1356 /* exit if initialization failed */
1362 WaitForSingleObject(WaitToTerminate, INFINITE);
1364 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
1365 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1366 CloseHandle(hAFSDWorkerThread[cnt]);
1369 afsi_log("Received Termination Signal, Stopping Service");
1372 HANDLE h; char *ptbuf[1];
1373 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1374 ptbuf[0] = "AFS quitting";
1375 ReportEvent(h, GlobalStatus ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
1376 0, 0, NULL, 1, 0, ptbuf, NULL);
1377 DeregisterEventSource(h);
1380 /* allow an exit to be called prior to stopping the service */
1381 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1385 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1388 hookRc = stoppingHook();
1390 FreeLibrary(hHookDll);
1393 if (hookRc == FALSE)
1395 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1396 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1397 ServiceStatus.dwCheckPoint = 0;
1398 ServiceStatus.dwWaitHint = 0;
1399 ServiceStatus.dwControlsAccepted = 0;
1400 SetServiceStatus(StatusHandle, &ServiceStatus);
1402 /* exit if initialization failed */
1408 #ifdef AFS_FREELANCE_CLIENT
1409 cm_FreelanceShutdown();
1410 afsi_log("Freelance Shutdown complete");
1413 DismountGlobalDrives();
1414 afsi_log("Global Drives dismounted");
1416 cm_DaemonShutdown();
1417 afsi_log("Daemon shutdown complete");
1420 afsi_log("Buffer shutdown complete");
1423 afsi_log("rx finalization complete");
1426 afsi_log("smb shutdown complete");
1430 cm_ShutdownMappedMemory();
1432 #ifdef REGISTER_POWER_NOTIFICATIONS
1433 /* terminate thread used to flush cache */
1434 if (powerEventsRegistered)
1435 PowerNotificationThreadExit();
1438 /* allow an exit to be called after stopping the service */
1439 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1443 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1446 hookRc = stoppedHook();
1448 FreeLibrary(hHookDll);
1452 /* Remove the ExceptionFilter */
1453 SetUnhandledExceptionFilter(NULL);
1455 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1456 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1457 ServiceStatus.dwCheckPoint = 0;
1458 ServiceStatus.dwWaitHint = 0;
1459 ServiceStatus.dwControlsAccepted = 0;
1460 SetServiceStatus(StatusHandle, &ServiceStatus);
1463 DWORD __stdcall afsdMain_thread(void* notUsed)
1465 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1466 afsd_Main(1, (LPTSTR*)argv);
1472 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1476 main(int argc, char * argv[])
1478 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1479 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1484 for (i = 1; i < argc; i++) {
1485 if (!stricmp(argv[i],"--validate-cache")) {
1486 if (++i != argc - 1) {
1491 return cm_ValidateMappedMemory(argv[i]);
1498 if (!StartServiceCtrlDispatcher(dispatchTable))
1500 LONG status = GetLastError();
1501 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1504 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1506 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1509 SetEvent(WaitToTerminate);
1511 SetEvent(DoTerminate);
1516 if ( hAFSDMainThread ) {
1517 WaitForSingleObject( hAFSDMainThread, INFINITE );
1518 CloseHandle( hAFSDMainThread );