windows-smb-dead-vc-gc-20080627
[openafs.git] / src / WINNT / afsd / afsicf.cpp
1 /*
2
3 Copyright 2004 by the Massachusetts Institute of Technology
4
5 All rights reserved.
6
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the name of the Massachusetts
12 Institute of Technology (M.I.T.) not be used in advertising or publicity
13 pertaining to distribution of the software without specific, written
14 prior permission.
15
16 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 SOFTWARE.
23
24 */
25
26 #define _WIN32_DCOM
27 #include <windows.h>
28 #include <netfw.h>
29 #include <objbase.h>
30 #include <oleauto.h>
31 #include "afsicf.h"
32
33 #ifdef TESTMAIN
34 #include<stdio.h>
35 #pragma comment(lib,"ole32.lib")
36 #pragma comment(lib,"oleaut32.lib")
37 #define DEBUGOUT(x) printf(x)
38 #define DEBUGOUTW(x) wprintf(x)
39 #else
40 #define DEBUGOUT(x) OutputDebugString(x)
41 #define DEBUGOUTW(x) OutputDebugStringW(x)
42 #endif
43
44 /* an IPv4, enabled port with global scope */
45 struct global_afs_port_type {
46     LPWSTR      name;
47     LONG        port;
48     NET_FW_IP_PROTOCOL protocol;
49 };
50
51 typedef struct global_afs_port_type global_afs_port_t;
52
53 global_afs_port_t afs_clientPorts[] = {
54     { L"AFS CacheManager Callback (UDP)", 7001, NET_FW_IP_PROTOCOL_UDP }
55 #ifdef AFS_TCP
56 ,   { L"AFS CacheManager Callback (TCP)", 7001, NET_FW_IP_PROTOCOL_TCP }
57 #endif
58 };
59
60 global_afs_port_t afs_serverPorts[] = {
61     { L"AFS File Server (UDP)", 7000, NET_FW_IP_PROTOCOL_UDP },
62 #ifdef AFS_TCP
63     { L"AFS File Server (TCP)", 7000, NET_FW_IP_PROTOCOL_TCP },
64 #endif
65     { L"AFS User & Group Database (UDP)", 7002, NET_FW_IP_PROTOCOL_UDP },
66 #ifdef AFS_TCP
67     { L"AFS User & Group Database (TCP)", 7002, NET_FW_IP_PROTOCOL_TCP },
68 #endif
69     { L"AFS Volume Location Database (UDP)", 7003, NET_FW_IP_PROTOCOL_UDP },
70 #ifdef AFS_TCP
71     { L"AFS Volume Location Database (TCP)", 7003, NET_FW_IP_PROTOCOL_TCP },
72 #endif
73     { L"AFS/Kerberos Authentication (UDP)", 7004, NET_FW_IP_PROTOCOL_UDP },
74 #ifdef AFS_TCP
75     { L"AFS/Kerberos Authentication (TCP)", 7004, NET_FW_IP_PROTOCOL_TCP },
76 #endif
77     { L"AFS Volume Mangement (UDP)", 7005, NET_FW_IP_PROTOCOL_UDP },
78 #ifdef AFS_TCP
79     { L"AFS Volume Mangement (TCP)", 7005, NET_FW_IP_PROTOCOL_TCP },
80 #endif
81     { L"AFS Error Interpretation (UDP)", 7006, NET_FW_IP_PROTOCOL_UDP },
82 #ifdef AFS_TCP
83     { L"AFS Error Interpretation (TCP)", 7006, NET_FW_IP_PROTOCOL_TCP },
84 #endif
85     { L"AFS Basic Overseer (UDP)", 7007, NET_FW_IP_PROTOCOL_UDP },
86 #ifdef AFS_TCP
87     { L"AFS Basic Overseer (TCP)", 7007, NET_FW_IP_PROTOCOL_TCP },
88 #endif
89     { L"AFS Server-to-server Updater (UDP)", 7008, NET_FW_IP_PROTOCOL_UDP },
90 #ifdef AFS_TCP
91     { L"AFS Server-to-server Updater (TCP)", 7008, NET_FW_IP_PROTOCOL_TCP },
92 #endif
93     { L"AFS Remote Cache Manager (UDP)", 7009, NET_FW_IP_PROTOCOL_UDP }
94 #ifdef AFS_TCP
95 ,    { L"AFS Remote Cache Manager (TCP)", 7009, NET_FW_IP_PROTOCOL_TCP }
96 #endif
97 };
98
99 HRESULT icf_OpenFirewallProfile(INetFwProfile ** fwProfile) {
100     HRESULT hr = S_OK;
101     INetFwMgr* fwMgr = NULL;
102     INetFwPolicy* fwPolicy = NULL;
103
104     *fwProfile = NULL;
105
106     // Create an instance of the firewall settings manager.
107     hr = CoCreateInstance(
108             __uuidof(NetFwMgr),
109             NULL,
110             CLSCTX_INPROC_SERVER,
111             __uuidof(INetFwMgr),
112             reinterpret_cast<void**>(static_cast<INetFwMgr**>(&fwMgr))
113             );
114     if (FAILED(hr))
115     {
116         DEBUGOUT(("Can't create fwMgr\n"));
117         goto error;
118     }
119
120     // Retrieve the local firewall policy.
121     hr = fwMgr->get_LocalPolicy(&fwPolicy);
122     if (FAILED(hr))
123     {
124         DEBUGOUT(("Cant get local policy\n"));
125         goto error;
126     }
127
128     // Retrieve the firewall profile currently in effect.
129     hr = fwPolicy->get_CurrentProfile(fwProfile);
130     if (FAILED(hr))
131     {
132         DEBUGOUT(("Can't get current profile\n"));
133         goto error;
134     }
135
136   error:
137
138     // Release the local firewall policy.
139     if (fwPolicy != NULL)
140     {
141         fwPolicy->Release();
142     }
143
144     // Release the firewall settings manager.
145     if (fwMgr != NULL)
146     {
147         fwMgr->Release();
148     }
149
150     return hr;
151 }
152
153 HRESULT icf_CheckAndAddPorts(INetFwProfile * fwProfile, global_afs_port_t * ports, int nPorts) {
154     INetFwOpenPorts * fwPorts = NULL;
155     INetFwOpenPort * fwPort = NULL;
156     HRESULT hr;
157     HRESULT rhr = S_OK; /* return value */
158     int i = 0;
159
160     hr = fwProfile->get_GloballyOpenPorts(&fwPorts);
161     if (FAILED(hr)) {
162         // Abort!
163         DEBUGOUT(("Can't get globallyOpenPorts\n"));
164         rhr = hr;
165         goto cleanup;
166     }
167
168     // go through the supplied ports
169     for (i=0; i<nPorts; i++) {
170         VARIANT_BOOL vbEnabled;
171         BSTR bstName = NULL;
172         BOOL bCreate = FALSE;
173         fwPort = NULL;
174
175         hr = fwPorts->Item(ports[i].port, ports[i].protocol, &fwPort);
176         if (SUCCEEDED(hr)) {
177             DEBUGOUTW((L"Found port for %S\n",ports[i].name));
178             hr = fwPort->get_Enabled(&vbEnabled);
179             if (SUCCEEDED(hr)) {
180                 if ( vbEnabled == VARIANT_FALSE ) {
181                     hr = fwPort->put_Enabled(VARIANT_TRUE);
182                     if (FAILED(hr)) {
183                         // failed. Mark as failure. Don't try to create the port either.
184                         rhr = hr;
185                     }
186                 } // else we are fine
187             } else {
188                 // Something is wrong with the port.
189                 // We try to create a new one thus overriding this faulty one.
190                 bCreate = TRUE;
191             }
192             fwPort->Release();
193             fwPort = NULL;
194         } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
195             DEBUGOUTW((L"Port not found for %S\n", ports[i].name));
196             bCreate = TRUE;
197         }
198
199         if (bCreate) {
200             DEBUGOUTW((L"Trying to create port %S\n",ports[i].name));
201             hr = CoCreateInstance( __uuidof(NetFwOpenPort),
202                                    NULL,
203                                    CLSCTX_INPROC_SERVER,
204                                    __uuidof(INetFwOpenPort),
205                                    reinterpret_cast<void**>
206                                    (static_cast<INetFwOpenPort**>(&fwPort))
207                                    );
208
209             if (FAILED(hr)) {
210                 DEBUGOUT(("Can't create port\n"));
211                 rhr = hr;
212             } else {
213                 DEBUGOUT(("Created port\n"));
214                 hr = fwPort->put_IpVersion( NET_FW_IP_VERSION_ANY );
215                 if (FAILED(hr)) {
216                     DEBUGOUT(("Can't set IpVersion\n"));
217                     rhr = hr;
218                     goto abandon_port;
219                 }
220
221                 hr = fwPort->put_Port( ports[i].port );
222                 if (FAILED(hr)) {
223                     DEBUGOUT(("Can't set Port\n"));
224                     rhr = hr;
225                     goto abandon_port;
226                 }
227
228                 hr = fwPort->put_Protocol( ports[i].protocol );
229                 if (FAILED(hr)) {
230                     DEBUGOUT(("Can't set Protocol\n"));
231                     rhr = hr;
232                     goto abandon_port;
233                 }
234
235                 hr = fwPort->put_Scope( NET_FW_SCOPE_ALL );
236                 if (FAILED(hr)) {
237                     DEBUGOUT(("Can't set Scope\n"));
238                     rhr = hr;
239                     goto abandon_port;
240                 }
241
242                 bstName = SysAllocString( ports[i].name );
243
244                 if (SysStringLen(bstName) == 0) {
245                     rhr = E_OUTOFMEMORY;
246                 } else {
247                     hr = fwPort->put_Name( bstName );
248                     if (FAILED(hr)) {
249                         DEBUGOUT(("Can't set Name\n"));
250                         rhr = hr;
251                         SysFreeString( bstName );
252                         goto abandon_port;
253                     }
254                 }
255
256                 SysFreeString( bstName );
257
258                 hr = fwPorts->Add( fwPort );
259                 if (FAILED(hr)) {
260                     DEBUGOUT(("Can't add port\n"));
261                     rhr = hr;
262                 } else
263                     DEBUGOUT(("Added port\n"));
264
265               abandon_port:             
266                 fwPort->Release();
267             }
268         }
269     } // loop through ports
270
271     fwPorts->Release();
272
273   cleanup:
274
275     if (fwPorts != NULL)
276         fwPorts->Release();
277
278     return rhr;
279 }       
280
281 long icf_CheckAndAddAFSPorts(int portset) {
282     HRESULT hr;
283     BOOL coInitialized = FALSE;
284     INetFwProfile * fwProfile = NULL;
285     global_afs_port_t * ports;
286     int nports;
287     long code = 0;
288
289     if (portset == AFS_PORTSET_CLIENT) {
290         ports = afs_clientPorts;
291         nports = sizeof(afs_clientPorts) / sizeof(*afs_clientPorts);
292     } else if (portset == AFS_PORTSET_SERVER) {
293         ports = afs_serverPorts;
294         nports = sizeof(afs_serverPorts) / sizeof(*afs_serverPorts);
295     } else
296         return 1; /* Invalid port set */
297
298     hr = CoInitializeEx( NULL,
299                          COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE
300                          );
301
302     if (SUCCEEDED(hr) || RPC_E_CHANGED_MODE == hr)
303     {
304        coInitialized = TRUE;
305     }
306     // not necessarily catastrophic if the call failed.  We'll try to
307     // continue as if it succeeded.
308
309     hr = icf_OpenFirewallProfile(&fwProfile);
310     if (FAILED(hr)) {
311         // Ok. That didn't work.  This could be because the machine we
312         // are running on doesn't have Windows Firewall.  We'll return
313         // a failure to the caller, which shouldn't be taken to mean
314         // it's catastrophic.
315         DEBUGOUT(("Can't open Firewall profile\n"));
316         code = 2;
317         goto cleanup;
318     }
319
320     // Now that we have a firewall profile, we can start checking
321     // and adding the ports that we want.
322     hr = icf_CheckAndAddPorts(fwProfile, ports, nports);
323     if (FAILED(hr))
324         code = 3;
325
326   cleanup:
327     if (coInitialized) {
328         CoUninitialize();
329     }
330
331     return code;
332 }
333
334
335 #ifdef TESTMAIN
336 int main(int argc, char **argv) {
337     printf("Starting...\n");
338     if (icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT))
339         printf("Failed\n");
340     else
341         printf("Succeeded\n");
342     printf("Done\n");
343     return 0;
344 }       
345 #endif