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
9 /* AFSIFS portions copyright (c) 2005
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 /* for the IFS version, set the event DoTerminate, on which all
74 worker threads wait. they will exit, and then everything else
76 HANDLE WaitToTerminate, DoTerminate;
81 unsigned int MainThreadId;
85 extern int traceOnPanic;
86 extern HANDLE afsi_file;
88 int powerEventsRegistered = 0;
91 * Notifier function for use by osi_panic
93 static void afsd_notifier(char *msgp, char *filep, long line)
101 sprintf(tbuffer, "Error at file %s, line %d: %s",
104 sprintf(tbuffer, "Error at unknown location: %s", msgp);
106 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
108 ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, line, NULL, 1, 0, ptbuf, NULL);
109 DeregisterEventSource(h);
113 osi_LogEnable(afsd_logp);
115 afsd_ForceTrace(TRUE);
116 buf_ForceTrace(TRUE);
118 afsi_log("--- begin dump ---");
119 cm_DumpSCache(afsi_file, "a", 0);
121 cm_dnlcDump(afsi_file, "a");
123 cm_DumpBufHashTable(afsi_file, "a", 0);
124 smb_DumpVCP(afsi_file, "a", 0);
125 afsi_log("--- end dump ---");
132 SetEvent(WaitToTerminate);
134 SetEvent(DoTerminate);
135 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
136 for (i = 0; i < WORKER_THREADS; i++)
137 CloseHandle(hAFSDWorkerThread[i]);
141 if (GetCurrentThreadId() == MainThreadId)
142 longjmp(notifier_jmp, 1);
145 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
146 ServiceStatus.dwWin32ExitCode = NO_ERROR;
147 ServiceStatus.dwCheckPoint = 0;
148 ServiceStatus.dwWaitHint = 0;
149 ServiceStatus.dwControlsAccepted = 0;
150 SetServiceStatus(StatusHandle, &ServiceStatus);
156 * For use miscellaneously in smb.c; need to do better
158 static int _stdcall DummyMessageBox(HWND h, LPCTSTR l1, LPCTSTR l2, UINT ui)
164 afsd_ServiceFlushVolume(DWORD dwlpEventData)
166 DWORD dwRet = ERROR_NETWORK_BUSY; /* or NO_ERROR */
169 ** If UI bit is not set, user interaction is not possible
170 ** BUT, since we are a NON-interactive service, and therefore
171 ** have NO user I/O, it doesn't much matter.
172 ** This benign code left here as example of how to find this out
174 BOOL bUI = (dwlpEventData & 1);
177 if ( PowerNotificationThreadNotify() )
183 /* flush was unsuccessful, or timeout - deny shutdown */
184 dwRet = ERROR_NETWORK_BUSY;
187 /* to deny hibernate, simply return
188 // any value besides NO_ERROR.
190 // dwRet = ERROR_NETWORK_BUSY;
197 /* service control handler used in nt4 only for backward compat. */
199 afsd_ServiceControlHandler(DWORD ctrlCode)
202 DWORD dummyLen, doTrace;
206 case SERVICE_CONTROL_SHUTDOWN:
207 case SERVICE_CONTROL_STOP:
208 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
209 ServiceStatus.dwWin32ExitCode = NO_ERROR;
210 ServiceStatus.dwCheckPoint = 1;
211 ServiceStatus.dwWaitHint = 30000;
212 ServiceStatus.dwControlsAccepted = 0;
213 SetServiceStatus(StatusHandle, &ServiceStatus);
215 if (ctrlCode == SERVICE_CONTROL_STOP)
216 afsi_log("SERVICE_CONTROL_STOP");
218 afsi_log("SERVICE_CONTROL_SHUTDOWN");
220 /* Write all dirty buffers back to server */
223 /* Force trace if requested */
224 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
225 AFSREG_CLT_SVC_PARAM_SUBKEY,
226 0, KEY_QUERY_VALUE, &parmKey);
227 if (code != ERROR_SUCCESS)
230 dummyLen = sizeof(doTrace);
231 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
233 (BYTE *) &doTrace, &dummyLen);
234 RegCloseKey (parmKey);
235 if (code != ERROR_SUCCESS)
238 afsd_ForceTrace(FALSE);
239 buf_ForceTrace(FALSE);
244 SetEvent(WaitToTerminate);
246 SetEvent(DoTerminate);
250 case SERVICE_CONTROL_INTERROGATE:
251 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
252 ServiceStatus.dwWin32ExitCode = NO_ERROR;
253 ServiceStatus.dwCheckPoint = 0;
254 ServiceStatus.dwWaitHint = 0;
255 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
256 SetServiceStatus(StatusHandle, &ServiceStatus);
258 /* XXX handle system shutdown */
259 /* XXX handle pause & continue */
265 ** Extended ServiceControlHandler that provides Event types
266 ** for monitoring Power events, for example.
269 afsd_ServiceControlHandlerEx(
277 DWORD dummyLen, doTrace;
279 DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
283 case SERVICE_CONTROL_SHUTDOWN:
284 case SERVICE_CONTROL_STOP:
285 ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
286 ServiceStatus.dwWin32ExitCode = NO_ERROR;
287 ServiceStatus.dwCheckPoint = 1;
288 ServiceStatus.dwWaitHint = 30000;
289 ServiceStatus.dwControlsAccepted = 0;
290 SetServiceStatus(StatusHandle, &ServiceStatus);
292 /* Write all dirty buffers back to server */
295 /* Force trace if requested */
296 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
297 AFSREG_CLT_SVC_PARAM_SUBKEY,
298 0, KEY_QUERY_VALUE, &parmKey);
299 if (code != ERROR_SUCCESS)
302 dummyLen = sizeof(doTrace);
303 code = RegQueryValueEx(parmKey, "TraceOnShutdown",
305 (BYTE *) &doTrace, &dummyLen);
306 RegCloseKey (parmKey);
307 if (code != ERROR_SUCCESS)
310 afsd_ForceTrace(FALSE);
311 buf_ForceTrace(FALSE);
316 SetEvent(WaitToTerminate);
318 SetEvent(DoTerminate);
323 case SERVICE_CONTROL_INTERROGATE:
324 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
325 ServiceStatus.dwWin32ExitCode = NO_ERROR;
326 ServiceStatus.dwCheckPoint = 0;
327 ServiceStatus.dwWaitHint = 0;
328 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;
329 SetServiceStatus(StatusHandle, &ServiceStatus);
330 afsi_log("SERVICE_CONTROL_INTERROGATE");
334 /* XXX handle system shutdown */
335 /* XXX handle pause & continue */
336 case SERVICE_CONTROL_POWEREVENT:
338 afsi_log("SERVICE_CONTROL_POWEREVENT");
340 ** dwEventType of this notification == WPARAM of WM_POWERBROADCAST
341 ** Return NO_ERROR == return TRUE for that message, i.e. accept request
342 ** Return any error code to deny request,
343 ** i.e. as if returning BROADCAST_QUERY_DENY
345 if (powerEventsRegistered) {
346 switch((int) dwEventType)
348 case PBT_APMQUERYSUSPEND:
349 afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND");
350 /* Write all dirty buffers back to server */
354 case PBT_APMQUERYSTANDBY:
355 afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY");
356 /* Write all dirty buffers back to server */
361 /* allow remaining case PBT_WhatEver */
363 afsi_log("SERVICE_CONTROL_APMSUSPEND");
367 afsi_log("SERVICE_CONTROL_APMSTANDBY");
370 case PBT_APMRESUMECRITICAL:
371 afsi_log("SERVICE_CONTROL_APMRESUMECRITICAL");
374 case PBT_APMRESUMESUSPEND:
375 afsi_log("SERVICE_CONTROL_APMRESUMESUSPEND");
378 case PBT_APMRESUMESTANDBY:
379 afsi_log("SERVICE_CONTROL_APMRESUMESTANDBY");
382 case PBT_APMBATTERYLOW:
383 afsi_log("SERVICE_CONTROL_APMBATTERYLOW");
386 case PBT_APMPOWERSTATUSCHANGE:
387 afsi_log("SERVICE_CONTROL_APMPOWERSTATUSCHANGE");
390 case PBT_APMOEMEVENT:
391 afsi_log("SERVICE_CONTROL_APMOEMEVENT");
394 case PBT_APMRESUMEAUTOMATIC:
395 afsi_log("SERVICE_CONTROL_APMRESUMEAUTOMATIC");
399 afsi_log("SERVICE_CONTROL_unknown");
405 case SERVICE_CONTROL_CUSTOM_DUMP:
407 afsi_log("SERVICE_CONTROL_CUSTOM_DUMP");
408 GenerateMiniDump(NULL);
412 } /* end switch(ctrlCode) */
416 /* There is similar code in client_config\drivemap.cpp GlobalMountDrive()
418 * Mount a drive into AFS if there global mapping
420 /* DEE Could check first if we are run as SYSTEM */
421 #define MAX_RETRIES 30
422 static void MountGlobalDrives(void)
424 char szAfsPath[_MAX_PATH];
425 char szDriveToMapTo[5];
429 DWORD dwIndex = 0, dwRetry = 0;
431 DWORD dwSubMountSize;
432 char szSubMount[256];
435 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
437 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
438 if (dwResult != ERROR_SUCCESS)
441 while (dwRetry < MAX_RETRIES) {
442 dwDriveSize = sizeof(szDriveToMapTo);
443 dwSubMountSize = sizeof(szSubMount);
444 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
445 if (dwResult != ERROR_MORE_DATA) {
446 if (dwResult != ERROR_SUCCESS) {
447 if (dwResult != ERROR_NO_MORE_ITEMS)
448 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
454 for ( ; dwRetry < MAX_RETRIES; dwRetry++)
457 memset (&nr, 0x00, sizeof(NETRESOURCE));
459 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
461 nr.dwScope = RESOURCE_GLOBALNET; /* ignored parameter */
462 nr.dwType=RESOURCETYPE_DISK;
463 nr.lpLocalName=szDriveToMapTo;
464 nr.lpRemoteName=szAfsPath;
465 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
466 nr.dwUsage = RESOURCEUSAGE_CONNECTABLE; /* ignored parameter */
468 dwResult = WNetAddConnection2(&nr,NULL,NULL,0);
469 afsi_log("GlobalAutoMap of %s to %s %s (%d)", szDriveToMapTo, szSubMount,
470 (dwResult == NO_ERROR) ? "succeeded" : "failed", dwResult);
471 if (dwResult == NO_ERROR) {
474 /* wait for smb server to come up */
475 Sleep((DWORD)1000 /* miliseconds */);
477 /* Disconnect any previous mappings */
478 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
481 /* FIXFIX: implement */
488 static void DismountGlobalDrives()
490 char szAfsPath[_MAX_PATH];
491 char szDriveToMapTo[5];
497 DWORD dwSubMountSize;
498 char szSubMount[256];
501 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
503 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey);
504 if (dwResult != ERROR_SUCCESS)
509 dwDriveSize = sizeof(szDriveToMapTo);
510 dwSubMountSize = sizeof(szSubMount);
511 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 0, &dwType, szSubMount, &dwSubMountSize);
512 if (dwResult != ERROR_MORE_DATA) {
513 if (dwResult != ERROR_SUCCESS) {
514 if (dwResult != ERROR_NO_MORE_ITEMS)
515 afsi_log("Failed to read GlobalAutoMapper values: %d\n", dwResult);
520 sprintf(szAfsPath,"\\\\%s\\%s",cm_NetbiosName,szSubMount);
522 dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
523 dwResult = WNetCancelConnection(szAfsPath, TRUE);
525 afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
528 /* FIXFIX: implement */
535 GetVersionInfo( CHAR * filename, CHAR * szOutput, DWORD dwOutput )
537 DWORD dwVersionHandle;
538 LPVOID pVersionInfo = 0;
540 LPDWORD pLangInfo = 0;
541 LPTSTR szVersion = 0;
543 TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
544 DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
547 afsi_log("GetFileVersionInfoSize failed");
548 return GetLastError();
551 pVersionInfo = malloc(size);
553 afsi_log("out of memory 1");
554 return ERROR_NOT_ENOUGH_MEMORY;
557 GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
558 if (retval = GetLastError())
560 afsi_log("GetFileVersionInfo failed: %d", retval);
564 VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
565 (LPVOID*)&pLangInfo, &len);
566 if (retval = GetLastError())
568 afsi_log("VerQueryValue 1 failed: %d", retval);
573 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
574 LOWORD(*pLangInfo), HIWORD(*pLangInfo));
576 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
577 if (retval = GetLastError())
579 /* try again with language 409 since the old binaries were tagged wrong */
581 TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
584 VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
585 if (retval = GetLastError()) {
586 afsi_log("VerQueryValue 2 failed: [%s] %d", szVerQ, retval);
590 snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
591 szOutput[dwOutput - 1] = 0;
600 static HINSTANCE hCrypt32;
601 static DWORD (WINAPI *pCertGetNameString)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags,
602 void* pvTypePara, LPTSTR pszNameString, DWORD cchNameString);
603 static BOOL (WINAPI *pCryptQueryObject)(DWORD dwObjectType, const void* pvObject, DWORD dwExpectedContentTypeFlags,
604 DWORD dwExpectedFormatTypeFlags, DWORD dwFlags,
605 DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType,
606 DWORD* pdwFormatType, HCERTSTORE* phCertStore,
607 HCRYPTMSG* phMsg, const void** ppvContext);
608 static BOOL (WINAPI *pCryptMsgGetParam)(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex,
609 void* pvData, DWORD* pcbData);
610 static PCCERT_CONTEXT (WINAPI *pCertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType,
611 DWORD dwFindFlags, DWORD dwFindType,
612 const void* pvFindPara,
613 PCCERT_CONTEXT pPrevCertContext);
614 static BOOL (WINAPI *pCertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
615 static BOOL (WINAPI *pCryptMsgClose)(HCRYPTMSG hCryptMsg);
616 static BOOL (WINAPI *pCertCompareCertificate)(DWORD dwCertEncodingType, PCERT_INFO pCertId1,
617 PCERT_INFO pCertId2);
618 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
620 void LoadCrypt32(void)
622 hCrypt32 = LoadLibrary("crypt32");
626 (FARPROC) pCertGetNameString = GetProcAddress( hCrypt32, "CertGetNameString" );
627 (FARPROC) pCryptQueryObject = GetProcAddress( hCrypt32, "CryptQueryObject" );
628 (FARPROC) pCryptMsgGetParam = GetProcAddress( hCrypt32, "CryptMsgGetParam" );
629 (FARPROC) pCertFindCertificateInStore = GetProcAddress( hCrypt32, "CertFindCertificateInStore" );
630 (FARPROC) pCertCloseStore = GetProcAddress( hCrypt32, "CertCloseStore" );
631 (FARPROC) pCryptMsgClose = GetProcAddress( hCrypt32, "CryptMsgClose" );
632 (FARPROC) pCertCompareCertificate = GetProcAddress( hCrypt32, "CertCompareCertificate" );
633 (FARPROC) pCertFreeCertificateContext = GetProcAddress( hCrypt32, "CertFreeCertificateContext" );
635 if ( !pCertGetNameString ||
636 !pCryptQueryObject ||
637 !pCryptMsgGetParam ||
638 !pCertFindCertificateInStore ||
641 !pCertCompareCertificate ||
642 !pCertFreeCertificateContext)
644 FreeLibrary(hCrypt32);
649 void UnloadCrypt32(void)
651 FreeLibrary(hCrypt32);
654 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
656 PCCERT_CONTEXT GetCertCtx(CHAR * filename)
658 wchar_t wfilename[260];
664 HCERTSTORE hStore = NULL;
665 HCRYPTMSG hMsg = NULL;
666 PCMSG_SIGNER_INFO pSignerInfo = NULL;
667 PCCERT_CONTEXT pCertContext = NULL;
670 if ( hCrypt32 == NULL )
673 ZeroMemory(&CertInfo, sizeof(CertInfo));
674 mbstowcs(wfilename, filename, 260);
676 fResult = pCryptQueryObject(CERT_QUERY_OBJECT_FILE,
678 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
679 CERT_QUERY_FORMAT_FLAG_BINARY,
689 afsi_log("CryptQueryObject failed for [%s] with error 0x%x",
695 fResult = pCryptMsgGetParam(hMsg,
696 CMSG_SIGNER_INFO_PARAM,
702 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
708 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
710 fResult = pCryptMsgGetParam(hMsg,
711 CMSG_SIGNER_INFO_PARAM,
717 afsi_log("CryptMsgGetParam failed for [%s] with error 0x%x",
723 CertInfo.Issuer = pSignerInfo->Issuer;
724 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
726 pCertContext = pCertFindCertificateInStore(hStore,
729 CERT_FIND_SUBJECT_CERT,
734 afsi_log("CertFindCertificateInStore for file [%s] failed with 0x%x",
742 LocalFree(pSignerInfo);
745 CertFreeCertificateContext(pCertContext);*/
748 pCertCloseStore(hStore,0);
751 pCryptMsgClose(hMsg);
756 BOOL VerifyTrust(CHAR * filename)
758 WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT fContextWSubject;
759 WIN_TRUST_SUBJECT_FILE fSubjectFile;
760 GUID trustAction = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
761 GUID subject = WIN_TRUST_SUBJTYPE_PE_IMAGE;
762 wchar_t wfilename[260];
764 BOOL success = FALSE;
766 LONG (WINAPI *pWinVerifyTrust)(HWND hWnd, GUID* pgActionID, WINTRUST_DATA* pWinTrustData) = NULL;
769 if (filename == NULL )
772 hWinTrust = LoadLibrary("wintrust");
776 if (((FARPROC) pWinVerifyTrust =
777 GetProcAddress( hWinTrust, "WinVerifyTrust" )) == NULL )
779 FreeLibrary(hWinTrust);
783 mbstowcs(wfilename, filename, 260);
785 fSubjectFile.hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
787 fSubjectFile.lpPath = wfilename;
788 fContextWSubject.hClientToken = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
789 FALSE, GetCurrentProcessId());
790 fContextWSubject.SubjectType = &subject;
791 fContextWSubject.Subject = &fSubjectFile;
793 ret = pWinVerifyTrust(INVALID_HANDLE_VALUE, &trustAction, (WINTRUST_DATA *)&fContextWSubject);
795 if ( fSubjectFile.hFile != INVALID_HANDLE_VALUE )
796 CloseHandle( fSubjectFile.hFile );
797 if ( fContextWSubject.hClientToken != INVALID_HANDLE_VALUE )
798 CloseHandle( fContextWSubject.hClientToken );
800 if (ret == ERROR_SUCCESS) {
803 DWORD gle = GetLastError();
805 case TRUST_E_PROVIDER_UNKNOWN:
806 afsi_log("VerifyTrust failed: \"Generic Verify V2\" Provider Unknown");
808 case TRUST_E_NOSIGNATURE:
809 afsi_log("VerifyTrust failed: Unsigned executable");
811 case TRUST_E_EXPLICIT_DISTRUST:
812 afsi_log("VerifyTrust failed: Certificate Marked as Untrusted by the user");
814 case TRUST_E_SUBJECT_NOT_TRUSTED:
815 afsi_log("VerifyTrust failed: File is not trusted");
817 case TRUST_E_BAD_DIGEST:
818 afsi_log("VerifyTrust failed: Executable has been modified");
820 case CRYPT_E_SECURITY_SETTINGS:
821 afsi_log("VerifyTrust failed: local security options prevent verification");
824 afsi_log("VerifyTrust failed: 0x%X", GetLastError());
828 FreeLibrary(hWinTrust);
832 void LogCertCtx(PCCERT_CONTEXT pCtx) {
834 LPTSTR szName = NULL;
836 if ( hCrypt32 == NULL )
839 // Get Issuer name size.
840 if (!(dwData = pCertGetNameString(pCtx,
841 CERT_NAME_SIMPLE_DISPLAY_TYPE,
842 CERT_NAME_ISSUER_FLAG,
846 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
850 // Allocate memory for Issuer name.
851 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
854 if (!(pCertGetNameString(pCtx,
855 CERT_NAME_SIMPLE_DISPLAY_TYPE,
856 CERT_NAME_ISSUER_FLAG,
860 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
864 // print Issuer name.
865 afsi_log("Issuer Name: %s", szName);
869 // Get Subject name size.
870 if (!(dwData = pCertGetNameString(pCtx,
871 CERT_NAME_SIMPLE_DISPLAY_TYPE,
876 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
880 // Allocate memory for subject name.
881 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
884 if (!(pCertGetNameString(pCtx,
885 CERT_NAME_SIMPLE_DISPLAY_TYPE,
890 afsi_log("CertGetNameString failed: 0x%x", GetLastError());
894 // Print Subject Name.
895 afsi_log("Subject Name: %s", szName);
903 BOOL AFSModulesVerify(void)
906 CHAR afsdVersion[128];
907 CHAR modVersion[128];
908 CHAR checkName[1024];
909 BOOL trustVerified = FALSE;
915 PCCERT_CONTEXT pCtxService = NULL;
917 DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
918 BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
919 DWORD dummyLen, code;
920 DWORD cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
921 DWORD verifyServiceSig = TRUE;
924 hPSAPI = LoadLibrary("psapi");
926 if ( hPSAPI == NULL )
929 if (!GetModuleFileName(NULL, filename, sizeof(filename)))
932 if (GetVersionInfo(filename, afsdVersion, sizeof(afsdVersion)))
935 afsi_log("%s version %s", filename, afsdVersion);
937 if (((FARPROC) pGetModuleFileNameExA =
938 GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
939 ((FARPROC) pEnumProcessModules =
940 GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
947 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
948 AFSREG_CLT_SVC_PARAM_SUBKEY,
949 0, KEY_QUERY_VALUE, &parmKey);
950 if (code == ERROR_SUCCESS) {
951 dummyLen = sizeof(cacheSize);
952 code = RegQueryValueEx(parmKey, "CacheSize", NULL, NULL,
953 (BYTE *) &cacheSize, &dummyLen);
954 RegCloseKey (parmKey);
957 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
958 0, KEY_QUERY_VALUE, &parmKey);
959 if (code == ERROR_SUCCESS) {
960 dummyLen = sizeof(verifyServiceSig);
961 code = RegQueryValueEx(parmKey, "VerifyServiceSignature", NULL, NULL,
962 (BYTE *) &verifyServiceSig, &dummyLen);
963 RegCloseKey (parmKey);
966 if (verifyServiceSig && cacheSize < 716800) {
967 trustVerified = VerifyTrust(filename);
969 afsi_log("Signature Verification disabled");
975 // get a certificate context for the signer of afsd_service.
976 pCtxService = GetCertCtx(filename);
978 LogCertCtx(pCtxService);
981 // Get a list of all the modules in this process.
982 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
983 FALSE, GetCurrentProcessId());
985 if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
987 afsi_log("Num of Process Modules: %d", (cbNeeded / sizeof(HMODULE)));
989 for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
991 char szModName[2048];
993 // Get the full path to the module's file.
994 if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
996 lstrcpy(checkName, szModName);
999 if ( strstr(checkName, "afspthread.dll") ||
1000 strstr(checkName, "afsauthent.dll") ||
1001 strstr(checkName, "afsrpc.dll") ||
1002 strstr(checkName, "libafsconf.dll") ||
1003 strstr(checkName, "libosi.dll") )
1005 if (GetVersionInfo(szModName, modVersion, sizeof(modVersion))) {
1010 afsi_log("%s version %s", szModName, modVersion);
1011 if (strcmp(afsdVersion,modVersion)) {
1012 afsi_log("Version mismatch: %s", szModName);
1015 if ( trustVerified ) {
1016 if ( !VerifyTrust(szModName) ) {
1017 afsi_log("Signature Verification failed: %s", szModName);
1020 else if (pCtxService) {
1021 PCCERT_CONTEXT pCtx = GetCertCtx(szModName);
1023 if (!pCtx || !pCertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1024 pCtxService->pCertInfo,
1026 afsi_log("Certificate mismatch: %s", szModName);
1034 pCertFreeCertificateContext(pCtx);
1043 pCertFreeCertificateContext(pCtxService);
1047 FreeLibrary(hPSAPI);
1049 CloseHandle(hProcess);
1054 control serviceex exists only on 2000/xp. These functions will be loaded dynamically.
1057 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerExFunc )( LPCTSTR , LPHANDLER_FUNCTION_EX , LPVOID );
1058 typedef SERVICE_STATUS_HANDLE ( * RegisterServiceCtrlHandlerFunc )( LPCTSTR , LPHANDLER_FUNCTION );
1060 RegisterServiceCtrlHandlerExFunc pRegisterServiceCtrlHandlerEx = NULL;
1061 RegisterServiceCtrlHandlerFunc pRegisterServiceCtrlHandler = NULL;
1064 afsd_Main(DWORD argc, LPTSTR *argv)
1076 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ |
1077 _CRTDBG_CHECK_CRT_DF /* | _CRTDBG_DELAY_FREE_MEM_DF */ );
1080 osi_InitPanic(afsd_notifier);
1081 osi_InitTraceOption();
1087 WaitToTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_WaitToTerminate"));
1088 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1089 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_WaitToTerminate"));
1092 DoTerminate = CreateEvent(NULL, TRUE, FALSE, TEXT("afsd_service_DoTerminate"));
1093 if ( GetLastError() == ERROR_ALREADY_EXISTS )
1094 afsi_log("Event Object Already Exists: %s", TEXT("afsd_service_DoTerminate"));
1098 hAdvApi32 = LoadLibrary("advapi32.dll");
1099 if (hAdvApi32 == NULL)
1101 afsi_log("Fatal: cannot load advapi32.dll");
1105 pRegisterServiceCtrlHandlerEx = (RegisterServiceCtrlHandlerExFunc)GetProcAddress(hAdvApi32, "RegisterServiceCtrlHandlerExA");
1106 if (pRegisterServiceCtrlHandlerEx)
1108 afsi_log("running on 2000+ - using RegisterServiceCtrlHandlerEx");
1109 StatusHandle = RegisterServiceCtrlHandlerEx(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandlerEx, NULL );
1113 StatusHandle = RegisterServiceCtrlHandler(AFS_DAEMON_SERVICE_NAME, afsd_ServiceControlHandler);
1116 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1117 ServiceStatus.dwServiceSpecificExitCode = 0;
1118 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1119 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1120 ServiceStatus.dwCheckPoint = 1;
1121 ServiceStatus.dwWaitHint = 30000;
1122 /* accept Power Events */
1123 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1124 SetServiceStatus(StatusHandle, &ServiceStatus);
1128 HANDLE h; char *ptbuf[1];
1129 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1130 ptbuf[0] = "AFS start pending";
1131 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1132 DeregisterEventSource(h);
1135 #ifdef REGISTER_POWER_NOTIFICATIONS
1142 /* see if we should handle power notifications */
1143 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1144 0, KEY_QUERY_VALUE, &hkParm);
1145 if (code == ERROR_SUCCESS) {
1146 dummyLen = sizeof(bpower);
1147 code = RegQueryValueEx(hkParm, "FlushOnHibernate", NULL, NULL,
1148 (BYTE *) &bpower, &dummyLen);
1150 if(code != ERROR_SUCCESS)
1153 RegCloseKey(hkParm);
1155 /* create thread used to flush cache */
1157 PowerNotificationThreadCreate();
1158 powerEventsRegistered = 1;
1163 /* Verify the versions of the DLLs which were loaded */
1164 if (!AFSModulesVerify()) {
1165 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1166 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1167 ServiceStatus.dwCheckPoint = 0;
1168 ServiceStatus.dwWaitHint = 0;
1169 ServiceStatus.dwControlsAccepted = 0;
1170 SetServiceStatus(StatusHandle, &ServiceStatus);
1173 HANDLE h; char *ptbuf[1];
1174 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1175 ptbuf[0] = "Incorrect module versions loaded";
1176 ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1177 DeregisterEventSource(h);
1180 /* exit if initialization failed */
1184 /* allow an exit to be called prior to any initialization */
1185 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1189 AfsdInitHook initHook = ( AfsdInitHook ) GetProcAddress(hHookDll, AFSD_INIT_HOOK);
1192 hookRc = initHook();
1194 FreeLibrary(hHookDll);
1197 if (hookRc == FALSE)
1199 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1200 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1201 ServiceStatus.dwCheckPoint = 0;
1202 ServiceStatus.dwWaitHint = 0;
1203 ServiceStatus.dwControlsAccepted = 0;
1204 SetServiceStatus(StatusHandle, &ServiceStatus);
1206 /* exit if initialization failed */
1211 /* allow another 15 seconds to start */
1212 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1213 ServiceStatus.dwServiceSpecificExitCode = 0;
1214 ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
1215 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1216 ServiceStatus.dwCheckPoint = 2;
1217 ServiceStatus.dwWaitHint = 20000;
1218 /* accept Power Events */
1219 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1220 SetServiceStatus(StatusHandle, &ServiceStatus);
1225 MainThreadId = GetCurrentThreadId();
1226 jmpret = setjmp(notifier_jmp);
1231 code = afsd_InitCM(&reason);
1233 afsi_log("afsd_InitCM failed: %s (code = %d)", reason, code);
1234 osi_panic(reason, __FILE__, __LINE__);
1238 ServiceStatus.dwCheckPoint++;
1239 ServiceStatus.dwWaitHint -= 5000;
1240 SetServiceStatus(StatusHandle, &ServiceStatus);
1242 code = afsd_InitDaemons(&reason);
1244 afsi_log("afsd_InitDaemons failed: %s (code = %d)", reason, code);
1245 osi_panic(reason, __FILE__, __LINE__);
1248 /* allow an exit to be called post rx initialization */
1249 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1253 AfsdRxStartedHook rxStartedHook = ( AfsdRxStartedHook ) GetProcAddress(hHookDll, AFSD_RX_STARTED_HOOK);
1256 hookRc = rxStartedHook();
1258 FreeLibrary(hHookDll);
1261 if (hookRc == FALSE)
1263 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1264 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1265 ServiceStatus.dwCheckPoint = 0;
1266 ServiceStatus.dwWaitHint = 0;
1267 ServiceStatus.dwControlsAccepted = 0;
1268 SetServiceStatus(StatusHandle, &ServiceStatus);
1270 /* exit if initialization failed */
1276 ServiceStatus.dwCheckPoint++;
1277 ServiceStatus.dwWaitHint -= 5000;
1278 SetServiceStatus(StatusHandle, &ServiceStatus);
1281 /* the following ifdef chooses the mode of operation for the service. to enable
1282 * a runtime flag (instead of compile-time), pioctl() would need to dynamically
1283 * determine the mode, in order to use the correct ioctl special-file path. */
1285 code = afsd_InitSMB(&reason, MessageBox);
1287 afsi_log("afsd_InitSMB failed: %s (code = %d)", reason, code);
1288 osi_panic(reason, __FILE__, __LINE__);
1291 code = ifs_Init(&reason);
1293 afsi_log("ifs_Init failed: %s (code = %d)", reason, code);
1294 osi_panic(reason, __FILE__, __LINE__);
1296 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1297 hAFSDWorkerThread[cnt] = CreateThread(NULL, 0, ifs_MainLoop, 0, 0, NULL);
1300 /* allow an exit to be called post smb initialization */
1301 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1305 AfsdSmbStartedHook smbStartedHook = ( AfsdSmbStartedHook ) GetProcAddress(hHookDll, AFSD_SMB_STARTED_HOOK);
1308 hookRc = smbStartedHook();
1310 FreeLibrary(hHookDll);
1313 if (hookRc == FALSE)
1315 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1316 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1317 ServiceStatus.dwCheckPoint = 0;
1318 ServiceStatus.dwWaitHint = 0;
1319 ServiceStatus.dwControlsAccepted = 0;
1320 SetServiceStatus(StatusHandle, &ServiceStatus);
1322 /* exit if initialization failed */
1327 MountGlobalDrives();
1330 ServiceStatus.dwCurrentState = SERVICE_RUNNING;
1331 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1332 ServiceStatus.dwCheckPoint = 0;
1333 ServiceStatus.dwWaitHint = 0;
1335 /* accept Power events */
1336 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PARAMCHANGE;
1337 SetServiceStatus(StatusHandle, &ServiceStatus);
1340 HANDLE h; char *ptbuf[1];
1341 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1342 ptbuf[0] = "AFS running";
1343 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
1344 DeregisterEventSource(h);
1348 /* allow an exit to be called when started */
1349 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1353 AfsdStartedHook startedHook = ( AfsdStartedHook ) GetProcAddress(hHookDll, AFSD_STARTED_HOOK);
1356 hookRc = startedHook();
1358 FreeLibrary(hHookDll);
1361 if (hookRc == FALSE)
1363 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1364 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1365 ServiceStatus.dwCheckPoint = 0;
1366 ServiceStatus.dwWaitHint = 0;
1367 ServiceStatus.dwControlsAccepted = 0;
1368 SetServiceStatus(StatusHandle, &ServiceStatus);
1370 /* exit if initialization failed */
1376 WaitForSingleObject(WaitToTerminate, INFINITE);
1378 WaitForMultipleObjects(WORKER_THREADS, hAFSDWorkerThread, TRUE, INFINITE);
1379 for (cnt = 0; cnt < WORKER_THREADS; cnt++)
1380 CloseHandle(hAFSDWorkerThread[cnt]);
1383 afsi_log("Received Termination Signal, Stopping Service");
1386 HANDLE h; char *ptbuf[1];
1387 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
1388 ptbuf[0] = "AFS quitting";
1389 ReportEvent(h, GlobalStatus ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
1390 0, 0, NULL, 1, 0, ptbuf, NULL);
1391 DeregisterEventSource(h);
1394 /* allow an exit to be called prior to stopping the service */
1395 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1399 AfsdStoppingHook stoppingHook = ( AfsdStoppingHook ) GetProcAddress(hHookDll, AFSD_STOPPING_HOOK);
1402 hookRc = stoppingHook();
1404 FreeLibrary(hHookDll);
1407 if (hookRc == FALSE)
1409 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1410 ServiceStatus.dwWin32ExitCode = NO_ERROR;
1411 ServiceStatus.dwCheckPoint = 0;
1412 ServiceStatus.dwWaitHint = 0;
1413 ServiceStatus.dwControlsAccepted = 0;
1414 SetServiceStatus(StatusHandle, &ServiceStatus);
1416 /* exit if initialization failed */
1422 #ifdef AFS_FREELANCE_CLIENT
1423 cm_FreelanceShutdown();
1424 afsi_log("Freelance Shutdown complete");
1427 DismountGlobalDrives();
1428 afsi_log("Global Drives dismounted");
1430 cm_DaemonShutdown();
1431 afsi_log("Daemon shutdown complete");
1434 afsi_log("Buffer shutdown complete");
1437 afsi_log("rx finalization complete");
1441 afsi_log("smb shutdown complete");
1446 cm_ShutdownMappedMemory();
1448 #ifdef REGISTER_POWER_NOTIFICATIONS
1449 /* terminate thread used to flush cache */
1450 if (powerEventsRegistered)
1451 PowerNotificationThreadExit();
1454 /* allow an exit to be called after stopping the service */
1455 hHookDll = LoadLibrary(AFSD_HOOK_DLL);
1459 AfsdStoppedHook stoppedHook = ( AfsdStoppedHook ) GetProcAddress(hHookDll, AFSD_STOPPED_HOOK);
1462 hookRc = stoppedHook();
1464 FreeLibrary(hHookDll);
1468 /* Remove the ExceptionFilter */
1469 SetUnhandledExceptionFilter(NULL);
1471 ServiceStatus.dwCurrentState = SERVICE_STOPPED;
1472 ServiceStatus.dwWin32ExitCode = GlobalStatus ? ERROR_EXCEPTION_IN_SERVICE : NO_ERROR;
1473 ServiceStatus.dwCheckPoint = 0;
1474 ServiceStatus.dwWaitHint = 0;
1475 ServiceStatus.dwControlsAccepted = 0;
1476 SetServiceStatus(StatusHandle, &ServiceStatus);
1479 DWORD __stdcall afsdMain_thread(void* notUsed)
1481 char * argv[2] = {AFS_DAEMON_SERVICE_NAME, NULL};
1482 afsd_Main(1, (LPTSTR*)argv);
1488 fprintf(stderr, "afsd_service.exe [--validate-cache <cache-path>]");
1492 main(int argc, char * argv[])
1494 static SERVICE_TABLE_ENTRY dispatchTable[] = {
1495 {AFS_DAEMON_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) afsd_Main},
1500 for (i = 1; i < argc; i++) {
1501 if (!stricmp(argv[i],"--validate-cache")) {
1502 if (++i != argc - 1) {
1507 return cm_ValidateMappedMemory(argv[i]);
1514 if (!StartServiceCtrlDispatcher(dispatchTable))
1516 LONG status = GetLastError();
1517 if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
1520 hAFSDMainThread = CreateThread(NULL, 0, afsdMain_thread, 0, 0, &tid);
1522 printf("Hit <Enter> to terminate OpenAFS Client Service\n");
1525 SetEvent(WaitToTerminate);
1527 SetEvent(DoTerminate);
1533 if ( hAFSDMainThread ) {
1534 WaitForSingleObject( hAFSDMainThread, INFINITE );
1535 CloseHandle( hAFSDMainThread );