1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 Change History (most recent first):
19 $Log: Firewall.cpp,v $
20 Revision 1.4 2006/08/14 23:26:07 cheshire
21 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
23 Revision 1.3 2005/09/29 06:33:54 herscher
24 <rdar://problem/4278931> Fix compilation error when using latest Microsoft Platform SDK.
26 Revision 1.2 2004/09/15 09:39:53 shersche
27 Retry the method INetFwPolicy::get_CurrentProfile on error
29 Revision 1.1 2004/09/13 07:32:31 shersche
30 Wrapper for Windows Firewall API code
35 // <rdar://problem/4278931> Doesn't compile correctly with latest Platform SDK
37 #if !defined(_WIN32_DCOM)
42 #if !defined(_WSPIAPI_COUNTOF)
43 # define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
54 static const int kMaxTries
= 30;
55 static const int kRetrySleepPeriod
= 1 * 1000; // 1 second
59 mDNSFirewallInitialize(OUT INetFwProfile
** fwProfile
)
61 INetFwMgr
* fwMgr
= NULL
;
62 INetFwPolicy
* fwPolicy
= NULL
;
66 _ASSERT(fwProfile
!= NULL
);
70 // Use COM to get a reference to the firewall settings manager. This
71 // call will fail on anything other than XP SP2
73 err
= CoCreateInstance( __uuidof(NetFwMgr
), NULL
, CLSCTX_INPROC_SERVER
, __uuidof(INetFwMgr
), (void**)&fwMgr
);
74 require(SUCCEEDED(err
), exit
);
76 // Use the reference to get the local firewall policy
78 err
= fwMgr
->get_LocalPolicy(&fwPolicy
);
79 require(SUCCEEDED(err
), exit
);
81 // Use the reference to get the extant profile. Empirical evidence
82 // suggests that there is the potential for a race condition when a system
83 // service whose startup type is automatic calls this method.
84 // This is true even when the service declares itself to be dependent
85 // on the firewall service. Re-trying the method will succeed within
90 err
= fwPolicy
->get_CurrentProfile(fwProfile
);
94 Sleep(kRetrySleepPeriod
);
97 while (err
&& (numRetries
++ < kMaxTries
));
99 require(SUCCEEDED(err
), exit
);
105 // Release temporary COM objects
107 if (fwPolicy
!= NULL
)
124 IN INetFwProfile
* fwProfile
127 // Call Release on the COM reference.
129 if (fwProfile
!= NULL
)
131 fwProfile
->Release();
137 mDNSFirewallAppIsEnabled
139 IN INetFwProfile
* fwProfile
,
140 IN
const wchar_t * fwProcessImageFileName
,
141 OUT BOOL
* fwAppEnabled
144 BSTR fwBstrProcessImageFileName
= NULL
;
145 VARIANT_BOOL fwEnabled
;
146 INetFwAuthorizedApplication
* fwApp
= NULL
;
147 INetFwAuthorizedApplications
* fwApps
= NULL
;
148 OSStatus err
= kNoErr
;
150 _ASSERT(fwProfile
!= NULL
);
151 _ASSERT(fwProcessImageFileName
!= NULL
);
152 _ASSERT(fwAppEnabled
!= NULL
);
154 *fwAppEnabled
= FALSE
;
156 // Get the list of authorized applications
158 err
= fwProfile
->get_AuthorizedApplications(&fwApps
);
159 require(SUCCEEDED(err
), exit
);
161 fwBstrProcessImageFileName
= SysAllocString(fwProcessImageFileName
);
162 require_action(SysStringLen(fwBstrProcessImageFileName
) > 0, exit
, err
= kNoMemoryErr
);
166 err
= fwApps
->Item(fwBstrProcessImageFileName
, &fwApp
);
170 // It's listed, but is it enabled?
172 err
= fwApp
->get_Enabled(&fwEnabled
);
173 require(SUCCEEDED(err
), exit
);
175 if (fwEnabled
!= VARIANT_FALSE
)
179 *fwAppEnabled
= TRUE
;
187 // Deallocate the BSTR
189 SysFreeString(fwBstrProcessImageFileName
);
191 // Release the COM objects
210 IN INetFwProfile
* fwProfile
,
211 IN
const wchar_t * fwProcessImageFileName
,
212 IN
const wchar_t * fwName
216 BSTR fwBstrName
= NULL
;
217 BSTR fwBstrProcessImageFileName
= NULL
;
218 INetFwAuthorizedApplication
* fwApp
= NULL
;
219 INetFwAuthorizedApplications
* fwApps
= NULL
;
222 _ASSERT(fwProfile
!= NULL
);
223 _ASSERT(fwProcessImageFileName
!= NULL
);
224 _ASSERT(fwName
!= NULL
);
226 // First check to see if the application is already authorized.
227 err
= mDNSFirewallAppIsEnabled( fwProfile
, fwProcessImageFileName
, &fwAppEnabled
);
228 require_noerr(err
, exit
);
230 // Only add the application if it isn't enabled
234 // Get the list of authorized applications
236 err
= fwProfile
->get_AuthorizedApplications(&fwApps
);
237 require(SUCCEEDED(err
), exit
);
239 // Create an instance of an authorized application.
241 err
= CoCreateInstance( __uuidof(NetFwAuthorizedApplication
), NULL
, CLSCTX_INPROC_SERVER
, __uuidof(INetFwAuthorizedApplication
), (void**)&fwApp
);
242 require(SUCCEEDED(err
), exit
);
244 fwBstrProcessImageFileName
= SysAllocString(fwProcessImageFileName
);
245 require_action(SysStringLen(fwBstrProcessImageFileName
) > 0, exit
, err
= kNoMemoryErr
);
247 // Set the executable file name
249 err
= fwApp
->put_ProcessImageFileName(fwBstrProcessImageFileName
);
250 require(SUCCEEDED(err
), exit
);
252 fwBstrName
= SysAllocString(fwName
);
253 require_action(SysStringLen(fwBstrName
) > 0, exit
, err
= kNoMemoryErr
);
255 // Set the friendly name
257 err
= fwApp
->put_Name(fwBstrName
);
258 require(SUCCEEDED(err
), exit
);
260 // Now add the application
262 err
= fwApps
->Add(fwApp
);
263 require(SUCCEEDED(err
), exit
);
270 // Deallocate the BSTR objects
272 SysFreeString(fwBstrName
);
273 SysFreeString(fwBstrProcessImageFileName
);
275 // Release the COM objects
298 INetFwProfile
* fwProfile
= NULL
;
299 HRESULT comInit
= E_FAIL
;
300 OSStatus err
= kNoErr
;
304 comInit
= CoInitializeEx( 0, COINIT_APARTMENTTHREADED
| COINIT_DISABLE_OLE1DDE
);
306 // Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
307 // initialized with a different mode.
309 if (comInit
!= RPC_E_CHANGED_MODE
)
312 require(SUCCEEDED(err
), exit
);
315 // Connect to the firewall
317 err
= mDNSFirewallInitialize(&fwProfile
);
318 require_noerr(err
, exit
);
320 // Add us to the list of exempt programs
322 err
= mDNSFirewallAddApp( fwProfile
, executable
, name
);
323 require_noerr(err
, exit
);
327 // Disconnect from the firewall
329 mDNSFirewallCleanup(fwProfile
);
333 if (SUCCEEDED(comInit
))