2 * Copyright 2004 by the Massachusetts Institute of Technology
6 * Permission to use, copy, modify, and distribute this software and its
7 * documentation for any purpose and without fee is hereby granted,
8 * provided that the above copyright notice appear in all copies and that
9 * both that copyright notice and this permission notice appear in
10 * supporting documentation, and that the name of the Massachusetts
11 * Institute of Technology (M.I.T.) not be used in advertising or publicity
12 * pertaining to distribution of the software without specific, written
15 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 * M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 * Copyright 2011 by Your File System, Inc.
39 #pragma comment(lib,"ole32.lib")
40 #pragma comment(lib,"oleaut32.lib")
41 #define DEBUGOUT(x) printf(x)
42 #define DEBUGOUTW(x) wprintf(x)
44 #define DEBUGOUT(x) OutputDebugString(x)
45 #define DEBUGOUTW(x) OutputDebugStringW(x)
48 /* an IPv4, enabled port with global scope */
49 struct global_afs_port_type {
53 NET_FW_IP_PROTOCOL protocol;
56 typedef struct global_afs_port_type global_afs_port_t;
58 global_afs_port_t afs_clientPorts[] = {
59 { L"AFS CacheManager Callback (UDP)", 7001, L"7001", NET_FW_IP_PROTOCOL_UDP }
61 , { L"AFS CacheManager Callback (TCP)", 7001, L"7001", NET_FW_IP_PROTOCOL_TCP }
65 global_afs_port_t afs_serverPorts[] = {
66 { L"AFS File Server (UDP)", 7000, L"7000", NET_FW_IP_PROTOCOL_UDP },
68 { L"AFS File Server (TCP)", 7000, L"7000", NET_FW_IP_PROTOCOL_TCP },
70 { L"AFS User & Group Database (UDP)", 7002, L"7002", NET_FW_IP_PROTOCOL_UDP },
72 { L"AFS User & Group Database (TCP)", 7002, L"7002", NET_FW_IP_PROTOCOL_TCP },
74 { L"AFS Volume Location Database (UDP)", 7003, L"7003", NET_FW_IP_PROTOCOL_UDP },
76 { L"AFS Volume Location Database (TCP)", 7003, L"7003", NET_FW_IP_PROTOCOL_TCP },
78 { L"AFS/Kerberos Authentication (UDP)", 7004, L"7004", NET_FW_IP_PROTOCOL_UDP },
80 { L"AFS/Kerberos Authentication (TCP)", 7004, L"7004", NET_FW_IP_PROTOCOL_TCP },
82 { L"AFS Volume Mangement (UDP)", 7005, L"7005", NET_FW_IP_PROTOCOL_UDP },
84 { L"AFS Volume Mangement (TCP)", 7005, L"7005", NET_FW_IP_PROTOCOL_TCP },
86 { L"AFS Error Interpretation (UDP)", 7006, L"7006", NET_FW_IP_PROTOCOL_UDP },
88 { L"AFS Error Interpretation (TCP)", 7006, L"7006", NET_FW_IP_PROTOCOL_TCP },
90 { L"AFS Basic Overseer (UDP)", 7007, L"7007", NET_FW_IP_PROTOCOL_UDP },
92 { L"AFS Basic Overseer (TCP)", 7007, L"7007", NET_FW_IP_PROTOCOL_TCP },
94 { L"AFS Server-to-server Updater (UDP)", 7008, L"7008", NET_FW_IP_PROTOCOL_UDP },
96 { L"AFS Server-to-server Updater (TCP)", 7008, L"7008", NET_FW_IP_PROTOCOL_TCP },
98 { L"AFS Remote Cache Manager (UDP)", 7009, L"7009", NET_FW_IP_PROTOCOL_UDP }
100 , { L"AFS Remote Cache Manager (TCP)", 7009, L"7009", NET_FW_IP_PROTOCOL_TCP }
104 HRESULT icf_CheckAndAddPorts2(WCHAR * wServiceName, global_afs_port_t * ports, int nPorts)
106 INetFwPolicy2 *pNetFwPolicy2 = NULL;
107 INetFwRules *pFwRules = NULL;
108 INetFwRule *pFwRule = NULL;
109 WCHAR wFilename[1024] = L"C:\\Program Files\\OpenAFS\\Client\\Program\\afsd_service.exe";
111 long CurrentProfilesBitMask = 0;
115 GetModuleFileNameW(NULL, wFilename, 1024);
118 BSTR bstrRuleGroup = SysAllocString(L"OpenAFS Firewall Rules");
119 BSTR bstrRuleApplication = SysAllocString(wFilename);
120 BSTR bstrRuleService = SysAllocString(wServiceName);
121 BSTR bstrInterfaceTypes = SysAllocString(L"all");
123 HRESULT hrComInit = S_OK;
126 // Retrieve INetFwPolicy2
127 hr = CoCreateInstance( __uuidof(NetFwPolicy2),
129 CLSCTX_INPROC_SERVER,
130 __uuidof(INetFwPolicy2),
131 (void**)&pNetFwPolicy2);
134 DEBUGOUT(("Can't create NetFwPolicy2\n"));
138 // Retrieve INetFwRules
139 hr = pNetFwPolicy2->get_Rules(&pFwRules);
142 DEBUGOUT(("get_Rules failed\n"));
147 DEBUGOUT(("No port specified\n"));
149 for ( i=0; i < nPorts; i++)
151 BSTR bstrRuleName = SysAllocString(ports[i].name);
152 BSTR bstrRuleDescription = SysAllocString(ports[i].name);
153 BSTR bstrRuleLPorts = SysAllocString(ports[i].str_port);
155 hr = pFwRules->Item(bstrRuleName, &pFwRule);
158 // Create a new Firewall Rule object.
159 hr = CoCreateInstance( __uuidof(NetFwRule),
161 CLSCTX_INPROC_SERVER,
162 __uuidof(INetFwRule),
166 // Populate the Firewall Rule object
167 pFwRule->put_Name(bstrRuleName);
168 pFwRule->put_Description(bstrRuleDescription);
169 pFwRule->put_ApplicationName(bstrRuleApplication);
171 // Add the Firewall Rule
172 hr = pFwRules->Add(pFwRule);
175 DEBUGOUT(("Advanced Firewall Rule Add failed\n"));
179 DEBUGOUT(("Advanced Firewall Rule Add successful\n"));
182 // Do not assign the service name to the rule.
183 // Only specify the executable name. According to feedback
184 // in openafs-info, the service name filter blocks the rule.
186 pFwRule->put_ServiceName(NULL);
187 pFwRule->put_Protocol(ports[i].protocol);
188 pFwRule->put_LocalPorts(bstrRuleLPorts);
189 pFwRule->put_Grouping(bstrRuleGroup);
190 pFwRule->put_Profiles(NET_FW_PROFILE2_ALL);
191 pFwRule->put_Action(NET_FW_ACTION_ALLOW);
192 pFwRule->put_Enabled(VARIANT_TRUE);
193 pFwRule->put_EdgeTraversal(VARIANT_TRUE);
194 pFwRule->put_InterfaceTypes(bstrInterfaceTypes);
199 DEBUGOUT(("CoCreateInstance INetFwRule failed\n"));
204 DEBUGOUT(("INetFwRule already exists\n"));
206 hr = pFwRule->put_ServiceName(NULL);
209 DEBUGOUT(("INetFwRule Service Name Updated\n"));
212 hr = pFwRule->put_ApplicationName(bstrRuleApplication);
215 DEBUGOUT(("INetFwRule Application Name Updated\n"));
218 hr = pFwRule->put_EdgeTraversal(VARIANT_TRUE);
221 DEBUGOUT(("INetFwRule Edge Traversal Updated\n"));
224 hr = pFwRule->put_InterfaceTypes(bstrInterfaceTypes);
227 DEBUGOUT(("INetFwRule Interface Types Updated\n"));
230 hr = pFwRule->put_Protocol(ports[i].protocol);
233 DEBUGOUT(("INetFwRule Interface Protocol Updated\n"));
236 hr = pFwRule->put_LocalPorts(bstrRuleLPorts);
239 DEBUGOUT(("INetFwRule Interface Local Ports Updated\n"));
242 hr = pFwRule->put_Grouping(bstrRuleGroup);
245 DEBUGOUT(("INetFwRule Interface Grouping Updated\n"));
248 hr = pFwRule->put_Action(NET_FW_ACTION_ALLOW);
251 DEBUGOUT(("INetFwRule Interface Action Updated\n"));
255 SysFreeString(bstrRuleName);
256 SysFreeString(bstrRuleDescription);
257 SysFreeString(bstrRuleLPorts);
263 SysFreeString(bstrRuleGroup);
264 SysFreeString(bstrRuleApplication);
265 SysFreeString(bstrRuleService);
266 SysFreeString(bstrInterfaceTypes);
268 // Release the INetFwRule object
274 // Release the INetFwRules object
275 if (pFwRules != NULL)
280 // Release the INetFwPolicy2 object
281 if (pNetFwPolicy2 != NULL)
283 pNetFwPolicy2->Release();
287 if (SUCCEEDED(hrComInit))
296 HRESULT icf_OpenFirewallProfile(INetFwProfile ** fwProfile)
299 INetFwMgr* fwMgr = NULL;
300 INetFwPolicy* fwPolicy = NULL;
304 // Create an instance of the firewall settings manager.
305 hr = CoCreateInstance(
308 CLSCTX_INPROC_SERVER,
310 reinterpret_cast<void**>(static_cast<INetFwMgr**>(&fwMgr))
314 DEBUGOUT(("Can't create fwMgr\n"));
318 // Retrieve the local firewall policy.
319 hr = fwMgr->get_LocalPolicy(&fwPolicy);
322 DEBUGOUT(("Cant get local policy\n"));
326 // Retrieve the firewall profile currently in effect.
327 hr = fwPolicy->get_CurrentProfile(fwProfile);
330 DEBUGOUT(("Can't get current profile\n"));
336 // Release the local firewall policy.
337 if (fwPolicy != NULL)
342 // Release the firewall settings manager.
351 HRESULT icf_CheckAndAddPorts(INetFwProfile * fwProfile, global_afs_port_t * ports, int nPorts) {
352 INetFwOpenPorts * fwPorts = NULL;
353 INetFwOpenPort * fwPort = NULL;
355 HRESULT rhr = S_OK; /* return value */
358 hr = fwProfile->get_GloballyOpenPorts(&fwPorts);
361 DEBUGOUT(("Can't get globallyOpenPorts\n"));
366 // go through the supplied ports
367 for (i=0; i<nPorts; i++) {
368 VARIANT_BOOL vbEnabled;
370 BOOL bCreate = FALSE;
373 hr = fwPorts->Item(ports[i].n_port, ports[i].protocol, &fwPort);
375 DEBUGOUTW((L"Found port for %S\n",ports[i].name));
376 hr = fwPort->get_Enabled(&vbEnabled);
378 if ( vbEnabled == VARIANT_FALSE ) {
379 hr = fwPort->put_Enabled(VARIANT_TRUE);
381 // failed. Mark as failure. Don't try to create the port either.
384 } // else we are fine
386 // Something is wrong with the port.
387 // We try to create a new one thus overriding this faulty one.
392 } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
393 DEBUGOUTW((L"Port not found for %S\n", ports[i].name));
398 DEBUGOUTW((L"Trying to create port %S\n",ports[i].name));
399 hr = CoCreateInstance( __uuidof(NetFwOpenPort),
401 CLSCTX_INPROC_SERVER,
402 __uuidof(INetFwOpenPort),
403 reinterpret_cast<void**>
404 (static_cast<INetFwOpenPort**>(&fwPort))
408 DEBUGOUT(("Can't create port\n"));
411 DEBUGOUT(("Created port\n"));
412 hr = fwPort->put_IpVersion( NET_FW_IP_VERSION_ANY );
414 DEBUGOUT(("Can't set IpVersion\n"));
419 hr = fwPort->put_Port( ports[i].n_port );
421 DEBUGOUT(("Can't set Port\n"));
426 hr = fwPort->put_Protocol( ports[i].protocol );
428 DEBUGOUT(("Can't set Protocol\n"));
433 hr = fwPort->put_Scope( NET_FW_SCOPE_ALL );
435 DEBUGOUT(("Can't set Scope\n"));
440 bstName = SysAllocString( ports[i].name );
442 if (SysStringLen(bstName) == 0) {
445 hr = fwPort->put_Name( bstName );
447 DEBUGOUT(("Can't set Name\n"));
449 SysFreeString( bstName );
454 SysFreeString( bstName );
456 hr = fwPorts->Add( fwPort );
458 DEBUGOUT(("Can't add port\n"));
461 DEBUGOUT(("Added port\n"));
467 } // loop through ports
479 long icf_CheckAndAddAFSPorts(int port) {
481 BOOL coInitialized = FALSE;
482 INetFwProfile * fwProfile = NULL;
483 global_afs_port_t * ports;
484 WCHAR * wServiceName;
488 if (port == AFS_PORTSET_SERVER) {
489 ports = afs_serverPorts;
490 nports = sizeof(afs_serverPorts) / sizeof(*afs_serverPorts);
491 wServiceName = L"TransarcAFSServer";;
492 } else /* an actual client port */ {
495 if (_snwprintf_s(str_port, 32, 31, L"%u", port) < 0) {
496 DEBUGOUT(("Invalid port set\n"));
497 return 1; /* Invalid port set */
500 ports = afs_clientPorts;
501 nports = sizeof(afs_clientPorts) / sizeof(*afs_clientPorts);
503 afs_clientPorts[0].n_port = port;
504 afs_clientPorts[0].str_port = str_port;
505 wServiceName = L"TransarcAFSDaemon";
507 hr = CoInitializeEx( NULL,
508 COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE
511 if (SUCCEEDED(hr) || RPC_E_CHANGED_MODE == hr)
513 coInitialized = TRUE;
515 // not necessarily catastrophic if the call failed. We'll try to
516 // continue as if it succeeded.
518 hr = icf_CheckAndAddPorts2(wServiceName, ports, nports);
520 DEBUGOUT(("INetFwProfile2 failed, trying INetFwProfile\n"));
521 hr = icf_OpenFirewallProfile(&fwProfile);
523 // Ok. That didn't work. This could be because the machine we
524 // are running on doesn't have Windows Firewall. We'll return
525 // a failure to the caller, which shouldn't be taken to mean
526 // it's catastrophic.
527 DEBUGOUT(("Can't open Firewall profile\n"));
532 // Now that we have a firewall profile, we can start checking
533 // and adding the ports that we want.
534 hr = icf_CheckAndAddPorts(fwProfile, ports, nports);
549 int main(int argc, char **argv) {
550 printf("Starting...\n");
551 if (icf_CheckAndAddAFSPorts(7001))
554 printf("Succeeded\n");