summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSWindows/SystemService/Firewall.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mDNSResponder/mDNSWindows/SystemService/Firewall.cpp')
-rwxr-xr-xmDNSResponder/mDNSWindows/SystemService/Firewall.cpp484
1 files changed, 484 insertions, 0 deletions
diff --git a/mDNSResponder/mDNSWindows/SystemService/Firewall.cpp b/mDNSResponder/mDNSWindows/SystemService/Firewall.cpp
new file mode 100755
index 00000000..c7c96d09
--- /dev/null
+++ b/mDNSResponder/mDNSWindows/SystemService/Firewall.cpp
@@ -0,0 +1,484 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// <rdar://problem/4278931> Doesn't compile correctly with latest Platform SDK
+
+#if !defined(_WIN32_DCOM)
+# define _WIN32_DCOM
+#endif
+
+
+#include "Firewall.h"
+#include <windows.h>
+#include <crtdbg.h>
+#include <netfw.h>
+#include <objbase.h>
+#include <oleauto.h>
+
+
+static const int kMaxTries = 30;
+static const int kRetrySleepPeriod = 1 * 1000; // 1 second
+
+
+static OSStatus
+mDNSFirewallInitialize(OUT INetFwProfile ** fwProfile)
+{
+ INetFwMgr * fwMgr = NULL;
+ INetFwPolicy * fwPolicy = NULL;
+ int numRetries = 0;
+ HRESULT err = kNoErr;
+
+ _ASSERT(fwProfile != NULL);
+
+ *fwProfile = NULL;
+
+ // Use COM to get a reference to the firewall settings manager. This
+ // call will fail on anything other than XP SP2
+
+ err = CoCreateInstance( __uuidof(NetFwMgr), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwMgr), (void**)&fwMgr );
+ require(SUCCEEDED(err) && ( fwMgr != NULL ), exit);
+
+ // Use the reference to get the local firewall policy
+
+ err = fwMgr->get_LocalPolicy(&fwPolicy);
+ require(SUCCEEDED(err) && ( fwPolicy != NULL ), exit);
+
+ // Use the reference to get the extant profile. Empirical evidence
+ // suggests that there is the potential for a race condition when a system
+ // service whose startup type is automatic calls this method.
+ // This is true even when the service declares itself to be dependent
+ // on the firewall service. Re-trying the method will succeed within
+ // a few seconds.
+
+ do
+ {
+ err = fwPolicy->get_CurrentProfile(fwProfile);
+
+ if (err)
+ {
+ Sleep(kRetrySleepPeriod);
+ }
+ }
+ while (err && (numRetries++ < kMaxTries));
+
+ require(SUCCEEDED(err), exit);
+
+ err = kNoErr;
+
+exit:
+
+ // Release temporary COM objects
+
+ if (fwPolicy != NULL)
+ {
+ fwPolicy->Release();
+ }
+
+ if (fwMgr != NULL)
+ {
+ fwMgr->Release();
+ }
+
+ return err;
+}
+
+
+static void
+mDNSFirewallCleanup
+ (
+ IN INetFwProfile * fwProfile
+ )
+{
+ // Call Release on the COM reference.
+
+ if (fwProfile != NULL)
+ {
+ fwProfile->Release();
+ }
+}
+
+
+static OSStatus
+mDNSFirewallAppIsEnabled
+ (
+ IN INetFwProfile * fwProfile,
+ IN const wchar_t * fwProcessImageFileName,
+ OUT BOOL * fwAppEnabled
+ )
+{
+ BSTR fwBstrProcessImageFileName = NULL;
+ VARIANT_BOOL fwEnabled;
+ INetFwAuthorizedApplication * fwApp = NULL;
+ INetFwAuthorizedApplications* fwApps = NULL;
+ OSStatus err = kNoErr;
+
+ _ASSERT(fwProfile != NULL);
+ _ASSERT(fwProcessImageFileName != NULL);
+ _ASSERT(fwAppEnabled != NULL);
+
+ *fwAppEnabled = FALSE;
+
+ // Get the list of authorized applications
+
+ err = fwProfile->get_AuthorizedApplications(&fwApps);
+ require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
+
+ fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
+ require_action( ( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
+
+ // Look for us
+
+ err = fwApps->Item(fwBstrProcessImageFileName, &fwApp);
+
+ if (SUCCEEDED(err) && ( fwApp != NULL ) )
+ {
+ // It's listed, but is it enabled?
+
+ err = fwApp->get_Enabled(&fwEnabled);
+ require(SUCCEEDED(err), exit);
+
+ if (fwEnabled != VARIANT_FALSE)
+ {
+ // Yes, it's enabled
+
+ *fwAppEnabled = TRUE;
+ }
+ }
+
+ err = kNoErr;
+
+exit:
+
+ // Deallocate the BSTR
+
+ if ( fwBstrProcessImageFileName != NULL )
+ {
+ SysFreeString(fwBstrProcessImageFileName);
+ }
+
+ // Release the COM objects
+
+ if (fwApp != NULL)
+ {
+ fwApp->Release();
+ }
+
+ if (fwApps != NULL)
+ {
+ fwApps->Release();
+ }
+
+ return err;
+}
+
+
+static OSStatus
+mDNSFirewallAddApp
+ (
+ IN INetFwProfile * fwProfile,
+ IN const wchar_t * fwProcessImageFileName,
+ IN const wchar_t * fwName
+ )
+{
+ BOOL fwAppEnabled;
+ BSTR fwBstrName = NULL;
+ BSTR fwBstrProcessImageFileName = NULL;
+ INetFwAuthorizedApplication * fwApp = NULL;
+ INetFwAuthorizedApplications* fwApps = NULL;
+ OSStatus err = S_OK;
+
+ _ASSERT(fwProfile != NULL);
+ _ASSERT(fwProcessImageFileName != NULL);
+ _ASSERT(fwName != NULL);
+
+ // First check to see if the application is already authorized.
+ err = mDNSFirewallAppIsEnabled( fwProfile, fwProcessImageFileName, &fwAppEnabled );
+ require_noerr(err, exit);
+
+ // Only add the application if it isn't enabled
+
+ if (!fwAppEnabled)
+ {
+ // Get the list of authorized applications
+
+ err = fwProfile->get_AuthorizedApplications(&fwApps);
+ require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
+
+ // Create an instance of an authorized application.
+
+ err = CoCreateInstance( __uuidof(NetFwAuthorizedApplication), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwAuthorizedApplication), (void**)&fwApp );
+ require(SUCCEEDED(err) && ( fwApp != NULL ), exit);
+
+ fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
+ require_action(( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
+
+ // Set the executable file name
+
+ err = fwApp->put_ProcessImageFileName(fwBstrProcessImageFileName);
+ require(SUCCEEDED(err), exit);
+
+ fwBstrName = SysAllocString(fwName);
+ require_action( ( fwBstrName != NULL ) && ( SysStringLen(fwBstrName) > 0 ), exit, err = kNoMemoryErr);
+
+ // Set the friendly name
+
+ err = fwApp->put_Name(fwBstrName);
+ require(SUCCEEDED(err), exit);
+
+ // Now add the application
+
+ err = fwApps->Add(fwApp);
+ require(SUCCEEDED(err), exit);
+ }
+
+ err = kNoErr;
+
+exit:
+
+ // Deallocate the BSTR objects
+
+ if ( fwBstrName != NULL )
+ {
+ SysFreeString(fwBstrName);
+ }
+
+ if ( fwBstrProcessImageFileName != NULL )
+ {
+ SysFreeString(fwBstrProcessImageFileName);
+ }
+
+ // Release the COM objects
+
+ if (fwApp != NULL)
+ {
+ fwApp->Release();
+ }
+
+ if (fwApps != NULL)
+ {
+ fwApps->Release();
+ }
+
+ return err;
+}
+
+
+
+
+
+static OSStatus
+
+mDNSFirewallIsFileAndPrintSharingEnabled
+
+ (
+
+ IN INetFwProfile * fwProfile,
+
+ OUT BOOL * fwServiceEnabled
+
+ )
+
+{
+
+ VARIANT_BOOL fwEnabled;
+
+ INetFwService* fwService = NULL;
+
+ INetFwServices* fwServices = NULL;
+
+ OSStatus err = S_OK;
+
+
+
+ _ASSERT(fwProfile != NULL);
+
+ _ASSERT(fwServiceEnabled != NULL);
+
+
+
+ *fwServiceEnabled = FALSE;
+
+
+
+ // Retrieve the globally open ports collection.
+
+ err = fwProfile->get_Services(&fwServices);
+
+ require( SUCCEEDED( err ), exit );
+
+
+
+ // Attempt to retrieve the globally open port.
+
+ err = fwServices->Item(NET_FW_SERVICE_FILE_AND_PRINT, &fwService);
+
+ require( SUCCEEDED( err ), exit );
+
+
+
+ // Find out if the globally open port is enabled.
+
+ err = fwService->get_Enabled(&fwEnabled);
+
+ require( SUCCEEDED( err ), exit );
+
+ if (fwEnabled != VARIANT_FALSE)
+
+ {
+
+ *fwServiceEnabled = TRUE;
+
+ }
+
+
+
+exit:
+
+
+
+ // Release the globally open port.
+
+ if (fwService != NULL)
+
+ {
+
+ fwService->Release();
+
+ }
+
+
+
+ // Release the globally open ports collection.
+
+ if (fwServices != NULL)
+
+ {
+
+ fwServices->Release();
+
+ }
+
+
+
+ return err;
+
+}
+
+
+OSStatus
+mDNSAddToFirewall
+ (
+ LPWSTR executable,
+ LPWSTR name
+ )
+{
+ INetFwProfile * fwProfile = NULL;
+ HRESULT comInit = E_FAIL;
+ OSStatus err = kNoErr;
+
+ // Initialize COM.
+
+ comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
+
+ // Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
+ // initialized with a different mode.
+
+ if (comInit != RPC_E_CHANGED_MODE)
+ {
+ err = comInit;
+ require(SUCCEEDED(err), exit);
+ }
+
+ // Connect to the firewall
+
+ err = mDNSFirewallInitialize(&fwProfile);
+ require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
+
+ // Add us to the list of exempt programs
+
+ err = mDNSFirewallAddApp( fwProfile, executable, name );
+ require_noerr(err, exit);
+
+exit:
+
+ // Disconnect from the firewall
+
+ if ( fwProfile != NULL )
+ {
+ mDNSFirewallCleanup(fwProfile);
+ }
+
+ // De-initialize COM
+
+ if (SUCCEEDED(comInit))
+ {
+ CoUninitialize();
+ }
+
+ return err;
+}
+
+
+BOOL
+mDNSIsFileAndPrintSharingEnabled( BOOL * retry )
+{
+ INetFwProfile * fwProfile = NULL;
+ HRESULT comInit = E_FAIL;
+ BOOL enabled = FALSE;
+ OSStatus err = kNoErr;
+
+ // Initialize COM.
+
+ *retry = FALSE;
+ comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
+
+ // Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
+ // initialized with a different mode.
+
+ if (comInit != RPC_E_CHANGED_MODE)
+ {
+ *retry = TRUE;
+ err = comInit;
+ require(SUCCEEDED(err), exit);
+ }
+
+ // Connect to the firewall
+
+ err = mDNSFirewallInitialize(&fwProfile);
+ require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
+
+ err = mDNSFirewallIsFileAndPrintSharingEnabled( fwProfile, &enabled );
+ require_noerr( err, exit );
+
+exit:
+
+ // Disconnect from the firewall
+
+ if ( fwProfile != NULL )
+ {
+ mDNSFirewallCleanup(fwProfile);
+ }
+
+ // De-initialize COM
+
+ if (SUCCEEDED(comInit))
+ {
+ CoUninitialize();
+ }
+
+ return enabled;
+}