OSDN Git Service

* utils.sgml (kill): Add SIGIO, SIGCLD, and SIGPWR.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / utils / bloda.cc
1 /* bloda.cc
2
3    Copyright 2007 Red Hat, Inc.
4
5    This file is part of Cygwin.
6
7    This software is a copyrighted work licensed under the terms of the
8    Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9    details. */
10
11 #define cygwin_internal cygwin_internal_dontuse
12 #include <stdio.h>
13 #include <assert.h>
14 #include <windows.h>
15 #include <ntdef.h>
16 #include <ddk/ntstatus.h>
17 #include <ddk/ntapi.h>
18 #undef cygwin_internal
19
20 #undef DEBUGGING
21 #ifdef DEBUGGING
22 #define dbg_printf(ARGS) printf ARGS ; fflush (NULL)
23 #else  /* !DEBUGGING */
24 #define dbg_printf(ARGS) do { } while (0)
25 #endif /* ?DEBUGGING */
26
27 /*  This module detects applications from the Big List of Dodgy Apps,
28   a list of applications that have at some given time been shown to
29   interfere with the operation of cygwin.  It detects the presence of
30   applications on the system by looking for any of four traces an
31   installation might leave: 1) registry keys, 2) files on disk
32   3) running executables 4) loaded dlls or drivers.
33
34   At the time of writing, the BLODA amounts to:-
35
36     Sonic Solutions burning software containing DLA component
37     Norton/MacAffee/Symantec antivirus or antispyware
38     Logitech webcam software with "Logitech process monitor" service
39     Kerio, Agnitum or ZoneAlarm Personal Firewall
40     Iolo System Mechanic/AntiVirus/Firewall
41     LanDesk
42     Windows Defender 
43     Embassy Trust Suite fingerprint reader software containing wxvault.dll
44     ByteMobile laptop optimization client\r
45 \r
46   A live version is now being maintained in the Cygwin FAQ, at\r
47     http://cygwin.com/faq/faq.using.html#faq.using.bloda\r
48
49 */
50
51 enum bad_app
52 {
53   SONIC,    NORTON,  MACAFFEE,    SYMANTEC,
54   LOGITECH, KERIO,   AGNITUM,     ZONEALARM,
55   IOLO,     LANDESK, WINDEFENDER, EMBASSYTS,
56   BYTEMOBILE
57 };
58
59 struct bad_app_info
60 {
61   enum bad_app app_id;
62   const char *details;
63   char found_it;
64 };
65
66 enum bad_app_det_method
67 {
68   HKLMKEY, HKCUKEY, FILENAME, PROCESSNAME, HOOKDLLNAME
69 };
70
71 struct bad_app_det
72 {
73   enum bad_app_det_method type;
74   const char *param;
75   enum bad_app app;
76 };
77
78 static const struct bad_app_det dodgy_app_detects[] =
79 {
80   { PROCESSNAME, "dlactrlw.exe",                                                 SONIC      },
81   { HOOKDLLNAME, "wxvault.dll",                                                  EMBASSYTS  },
82   { HKLMKEY,     "SYSTEM\\CurrentControlSet\\Services\\vsdatant",                ZONEALARM  },
83   { FILENAME,    "%windir%\\System32\\vsdatant.sys",                             ZONEALARM  },
84   { HKLMKEY,     "SYSTEM\\CurrentControlSet\\Services\\lvprcsrv",                LOGITECH   },
85   { PROCESSNAME, "LVPrcSrv.exe",                                                 LOGITECH   },
86   { FILENAME,    "%programfiles%\\common files\\logitech\\lvmvfm\\LVPrcSrv.exe", LOGITECH   },
87   { FILENAME,    "%windir%\\System32\\bmnet.dll",                                BYTEMOBILE },
88 }; 
89
90 static const size_t num_of_detects = sizeof (dodgy_app_detects) / sizeof (dodgy_app_detects[0]);
91
92 static struct bad_app_info big_list_of_dodgy_apps[] =
93 {
94   { SONIC,       "Sonic Solutions burning software containing DLA component"              },
95   { NORTON,      "Norton antivirus or antispyware software"                               },
96   { MACAFFEE,    "Macaffee antivirus or antispyware software"                             },
97   { SYMANTEC,    "Symantec antivirus or antispyware software"                             },
98   { LOGITECH,    "Logitech Process Monitor service"                                       },
99   { KERIO,       "Kerio Personal Firewall"                                                },
100   { AGNITUM,     "Agnitum Personal Firewall"                                              },
101   { ZONEALARM,   "ZoneAlarm Personal Firewall"                                            },
102   { IOLO,        "Iolo System Mechanic/AntiVirus/Firewall software"                       },
103   { LANDESK,     "Landesk"                                                                },
104   { WINDEFENDER, "Windows Defender"                                                       },
105   { EMBASSYTS,   "Embassy Trust Suite fingerprint reader software containing wxvault.dll" },
106   { BYTEMOBILE,  "ByteMobile laptop optimization client"                                  },
107 };
108
109 static const size_t num_of_dodgy_apps = sizeof (big_list_of_dodgy_apps) / sizeof (big_list_of_dodgy_apps[0]);
110
111 static PSYSTEM_PROCESSES
112 get_process_list (void)
113 {
114   int n_procs = 0x100;
115   PSYSTEM_PROCESSES pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist);
116
117   while (NtQuerySystemInformation (SystemProcessesAndThreadsInformation,
118     pslist, n_procs * sizeof *pslist, 0) == STATUS_INFO_LENGTH_MISMATCH)
119     {
120       n_procs *= 2;
121       free (pslist);
122       pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist);
123     }
124   return pslist;
125 }
126
127 static PSYSTEM_MODULE_INFORMATION
128 get_module_list (void)
129 {
130   int modsize = 0x1000;
131   PSYSTEM_MODULE_INFORMATION modlist = (PSYSTEM_MODULE_INFORMATION) malloc (modsize);
132
133   while (NtQuerySystemInformation (SystemModuleInformation,
134     modlist, modsize, NULL) == STATUS_INFO_LENGTH_MISMATCH)
135     {
136       modsize *= 2;
137       free (modlist);
138       modlist = (PSYSTEM_MODULE_INFORMATION) malloc (modsize);
139     }
140   return modlist;
141 }
142
143 static bool
144 find_process_in_list (PSYSTEM_PROCESSES pslist, PUNICODE_STRING psname)
145 {
146   while (1)
147     {
148       if (pslist->ProcessName.Length && pslist->ProcessName.Buffer)
149         {
150           dbg_printf (("%S\n", pslist->ProcessName.Buffer));
151           if (!_wcsicmp (pslist->ProcessName.Buffer, psname->Buffer))
152             return true;
153         }
154       if (!pslist->NextEntryDelta)
155         break;
156       pslist = (PSYSTEM_PROCESSES)(pslist->NextEntryDelta + (char *)pslist);
157     };
158   return false;
159 }
160
161 static bool
162 find_module_in_list (PSYSTEM_MODULE_INFORMATION modlist, const char * const modname)
163 {
164   PSYSTEM_MODULE_INFORMATION_ENTRY modptr = &modlist->Module[0];
165   DWORD count = modlist->Count;
166   while (count--)
167     {
168       dbg_printf (("name '%s' offset %d ", &modptr->ImageName[0], modptr->PathLength));
169       dbg_printf (("= '%s'\n", &modptr->ImageName[modptr->PathLength]));
170       if (!_stricmp (&modptr->ImageName[modptr->PathLength], modname))
171         return true;
172       modptr++;
173     }
174   return false;
175 }
176
177 static bool
178 expand_path (const char *path, char *outbuf)
179 {
180   char *dst = outbuf;
181   const char *end, *envval;
182   char envvar[MAX_PATH];
183   size_t len;
184
185   while ((dst - outbuf) < MAX_PATH)
186     {
187       if (*path != '%')
188         {
189           if ((*dst++ = *path++) != 0)
190             continue;
191           break;
192         }
193       /* Expand an environ var.  */
194       end = path + 1;
195       while (*end != '%')
196         {
197           /* Watch out for unterminated %  */
198           if (*end++ == 0)
199             {
200               end = NULL;
201               break;
202             }
203         }
204       /* If we didn't find the end, can't expand it.  */
205       if ((end == NULL) || (end == (path + 1)))
206         {
207           /* Unterminated % so copy verbatim.  */
208           *dst++ = *path++;
209           continue;
210         }
211       /* Expand the environment var into the new path.  */
212       if ((end - (path + 1)) >= MAX_PATH)
213         return -1;
214       memcpy (envvar, path + 1, end - (path + 1));
215       envvar[end - (path + 1)] = 0;
216       envval = getenv (envvar);
217       /* If not found, copy env var name verbatim.  */
218       if (envval == NULL)
219         {
220           *dst++ = *path++;
221           continue;
222         }
223       /* Check enough room before copying.  */
224       len = strlen (envval);
225       if ((dst + len - outbuf) >= MAX_PATH)
226         return false;
227       memcpy (dst, envval, len);
228       dst += len;
229       /* And carry on past the end of env var name.  */
230       path = end + 1;
231     }
232   return (dst - outbuf) < MAX_PATH;
233 }
234
235 static bool 
236 detect_dodgy_app (const struct bad_app_det *det, PSYSTEM_PROCESSES pslist, PSYSTEM_MODULE_INFORMATION modlist)
237 {
238   HANDLE fh;
239   HKEY hk;
240   UNICODE_STRING unicodename;
241   ANSI_STRING ansiname;
242   NTSTATUS rv;
243   bool found;
244   char expandedname[MAX_PATH];
245
246   switch (det->type)
247     {
248     case HKLMKEY:
249       dbg_printf (("Detect reg key hklm '%s'... ", det->param));
250       if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS)
251         {
252           RegCloseKey (hk);
253           dbg_printf (("found!\n"));
254           return true;
255         }
256       break;
257
258     case HKCUKEY:
259       dbg_printf (("Detect reg key hkcu '%s'... ", det->param));
260       if (RegOpenKeyEx (HKEY_CURRENT_USER, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS)
261         {
262           RegCloseKey (hk);
263           dbg_printf (("found!\n"));
264           return true;
265         }
266       break;
267
268     case FILENAME:
269       dbg_printf (("Detect filename '%s'... ", det->param));
270       if (!expand_path (det->param, expandedname))
271         {
272           printf ("Expansion failure!\n");
273           break;
274         }
275       dbg_printf (("('%s' after expansion)... ", expandedname));
276       fh = CreateFile (expandedname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE
277         | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
278       if (fh != INVALID_HANDLE_VALUE)
279         {
280           CloseHandle (fh);
281           dbg_printf (("found!\n"));
282           return true;
283         }
284       break;
285
286     case PROCESSNAME:
287       dbg_printf (("Detect proc name '%s'... ", det->param));
288       /* Equivalent of RtlInitAnsiString.  */
289       ansiname.Length = ansiname.MaximumLength = strlen (det->param);
290       ansiname.Buffer = (CHAR *) det->param;
291       rv = RtlAnsiStringToUnicodeString (&unicodename, &ansiname, TRUE);
292       if (rv != STATUS_SUCCESS)
293         {
294           printf ("Ansi to unicode conversion failure $%08x\n", (unsigned int) rv);
295           break;
296         }
297       found = find_process_in_list (pslist, &unicodename);
298       RtlFreeUnicodeString (&unicodename);
299       if (found)
300         {
301           dbg_printf (("found!\n"));
302           return true;
303         }
304       break;
305
306     case HOOKDLLNAME:
307       dbg_printf (("Detect hookdll '%s'... ", det->param));
308       if (find_module_in_list (modlist, det->param))
309         {
310           dbg_printf (("found!\n"));
311           return true;
312         }
313       break;
314
315     }
316   dbg_printf (("not found.\n"));
317   return false;
318 }
319
320 static struct bad_app_info *
321 find_dodgy_app_info (enum bad_app which_app)
322 {
323   size_t i;
324   for (i = 0; i < num_of_dodgy_apps; i++)
325     {
326       if (big_list_of_dodgy_apps[i].app_id == which_app)
327         return &big_list_of_dodgy_apps[i];
328     }
329   return NULL;
330 }
331
332 /* External entrypoint called from cygcheck.cc/dump_sysinfo.  */
333 void
334 dump_dodgy_apps (int verbose)
335 {
336   size_t i, n_det = 0;
337   PSYSTEM_PROCESSES pslist;
338   PSYSTEM_MODULE_INFORMATION modlist;
339
340   /* Read system info for detect testing.  */
341   pslist = get_process_list ();
342   modlist = get_module_list ();
343
344   /* Go with builtin list for now; later may enhance to
345   read dodgy apps from a file or download from an URL.  */
346   for (i = 0; i < num_of_dodgy_apps; i++)
347     {
348       big_list_of_dodgy_apps[i].found_it = false;
349     }
350
351   for (i = 0; i < num_of_detects; i++)
352     {
353       const struct bad_app_det *det = &dodgy_app_detects[i];
354       struct bad_app_info *found = find_dodgy_app_info (det->app);
355       bool detected = detect_dodgy_app (det, pslist, modlist);
356
357       /* Not found would mean we coded the lists bad. */
358       assert (found);
359       if (detected)
360         {
361           ++n_det;
362           found->found_it |= (1 << det->type);
363         }
364     }
365   if (n_det)
366     {
367       printf ("\nPotential app conflicts:\n\n");
368       for (i = 0; i < num_of_dodgy_apps; i++)
369         {
370           if (big_list_of_dodgy_apps[i].found_it)
371             {
372               printf ("%s%s", big_list_of_dodgy_apps[i].details, 
373                 verbose ? "\nDetected: " : ".\n");
374               if (!verbose)
375                 continue;
376               const char *sep = "";
377               if (big_list_of_dodgy_apps[i].found_it & (1 << HKLMKEY))
378                 {
379                   printf ("HKLM Registry Key");
380                   sep = ", ";
381                 }
382               if (big_list_of_dodgy_apps[i].found_it & (1 << HKCUKEY))
383                 {
384                   printf ("%sHKCU Registry Key", sep);
385                   sep = ", ";
386                 }
387               if (big_list_of_dodgy_apps[i].found_it & (1 << FILENAME))
388                 {
389                   printf ("%sNamed file", sep);
390                   sep = ", ";
391                 }
392               if (big_list_of_dodgy_apps[i].found_it & (1 << PROCESSNAME))
393                 {
394                   printf ("%sNamed process", sep);
395                   sep = ", ";
396                 }
397               if (big_list_of_dodgy_apps[i].found_it & (1 << HOOKDLLNAME))
398                 {
399                   printf ("%sLoaded hook DLL", sep);
400                 }
401               printf (".\n\n");
402             }
403         }
404     }
405   /* Tidy up allocations.  */
406   free (pslist);
407   free (modlist);
408 }
409