1 /**
2  ** @internal
3  ** yafcygwin.c
4  ** YAF cygwin
5  **
6  ** ------------------------------------------------------------------------
7  ** Copyright (C) 2011-2016 Carnegie Mellon University. All Rights Reserved.
8  ** ------------------------------------------------------------------------
9  ** Authors: Chris Inacio
10  ** ------------------------------------------------------------------------
11  ** @OPENSOURCE_HEADER_START@
12  ** Use of the YAF system and related source code is subject to the terms
13  ** of the following licenses:
14  **
15  ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991
16  ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
17  **
18  ** NO WARRANTY
19  **
20  ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
21  ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
22  ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
23  ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
24  ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
25  ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
26  ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
27  ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
28  ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
29  ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
30  ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
31  ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
32  ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
33  ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
34  ** DELIVERABLES UNDER THIS LICENSE.
35  **
36  ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
37  ** Mellon University, its trustees, officers, employees, and agents from
38  ** all claims or demands made against them (and any related losses,
39  ** expenses, or attorney's fees) arising out of, or relating to Licensee's
40  ** and/or its sub licensees' negligent use or willful misuse of or
41  ** negligent conduct or willful misconduct regarding the Software,
42  ** facilities, or other rights or assistance granted by Carnegie Mellon
43  ** University under this License, including, but not limited to, any
44  ** claims of product liability, personal injury, death, damage to
45  ** property, or violation of any laws or regulations.
46  **
47  ** Carnegie Mellon University Software Engineering Institute authored
48  ** documents are sponsored by the U.S. Department of Defense under
49  ** Contract FA8721-05-C-0003. Carnegie Mellon University retains
50  ** copyrights in all material produced under this contract. The U.S.
51  ** Government retains a non-exclusive, royalty-free license to publish or
52  ** reproduce these documents, or allow others to do so, for U.S.
53  ** Government purposes only pursuant to the copyright license under the
54  ** contract clause at 252.227.7013.
55  **
56  ** @OPENSOURCE_HEADER_END@
57  ** ------------------------------------------------------------------------
58  */
59 
60 /* Microsoft says to define _WIN32_WINNT to get the right
61    windows API version, but under Cygwin, you need to define
62    WINVER - which are related, (but not the same?).  They
63    are believed to be the same under Cygwin */
64 
65 #ifdef __CYGWIN__
66 #define _WIN32_WINNT 0x0600
67 #define WINVER 0x0600
68 #include <windows.h>
69 #endif
70 
71 #include <string.h>
72 #include <stddef.h>
73 #include <ctype.h>
74 #include <stdio.h>
75 
76 
77 #define INITIAL_BUFFER_SIZE     8192
78 #define BUFFER_INCREMENT_SIZE   4096
79 
80 /* for testing
81 #define NETSA_WINDOWSREG_REGHOME        "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
82 #define SILK_WINDOWSREG_DATA_DIR_KEY    "SystemRoot"
83 */
84 
85 /* registry location/key definitions */
86 #define NETSA_WINDOWSREG_REGHOME        "Software\\CERT\\NetSATools"
87 #define NETSA_WINDOWSREG_INSTALLDIR_KEY         "InstallDir"
88 #define SILK_WINDOWSREG_DATA_DIR_KEY            "SilkDataDir"
89 #define YAF_WINDOWSREG_CONF_DIR_KEY             "YafConfDir"
90 
91 #define SILK_DEFAULT_CYGWIN_DATA_DIR            "/cygdrive/c/data"
92 
93 #define CYGWIN_PATH_PREFIX                      "/cygdrive/"
94 
95 static char *winRegDataDir = NULL;
96 
97 
98 /**
99  * yfCygwinClean
100  *
101  * frees up allocated memory used as caching within this cygwin module
102  * provided for future memory leak testing
103  *
104  */
105 void
yfCygwinClean(void)106 yfCygwinClean (void)
107 {
108 
109     if (NULL != winRegDataDir) {
110         free(winRegDataDir);
111     }
112 
113     return;
114 }
115 
116 /**
117  *windowsToCygwinPath
118  *
119  * converts a "normal" windows path "C:\Windows\" into an equivalent
120  * cygwin path "/cygdrive/c/Windows/"
121  *
122  * @note this function creates callee deallocated memory
123  *
124  * @param winPath a character string containing a windows path
125  *
126  * @return a malloced string converted into a cygwin path, on error
127  *         this function returns NULL
128  */
129 static
130 char *
windowsToCygwinPath(const char * winPath)131 windowsToCygwinPath (const char *winPath)
132 {
133 
134     char *resultStr = NULL;
135     char *resultLoc = NULL;
136     const char *workLoc = winPath;
137 
138     resultStr = (char *) malloc(strlen(winPath)+strlen(CYGWIN_PATH_PREFIX)+1);
139     if (NULL == resultStr) {
140         return NULL;
141     }
142     resultLoc = resultStr;
143 
144     /* include the default prefix */
145     strcpy(resultLoc, CYGWIN_PATH_PREFIX);
146     resultLoc += strlen(CYGWIN_PATH_PREFIX);
147 
148     /* first, let's try to find the drive prefix, e.g. c: or d: or z: */
149     workLoc = strchr(winPath, ':');
150     if (NULL == workLoc) {
151         /* it's a relative path, run with it? */
152         free(resultStr);
153         return NULL;
154     }
155 
156     /* the character before workLoc should be the drive letter */
157     strncpy(resultLoc, (workLoc-1), 1);
158     *resultLoc++ = (char) tolower((int)*(workLoc-1));
159     workLoc++;
160 
161     /* now copy in the rest of the path, converting "\" into "/" */
162     while (*workLoc) {
163         if ('\\' == *workLoc) {
164             *resultLoc = '/';
165         } else {
166             *resultLoc = *workLoc;
167         }
168         resultLoc++; workLoc++;
169     }
170 
171     /* make sure resultLoc is terminated */
172     *resultLoc = '\0';
173 
174     /* safety check, did we run off the end of resultLoc */
175     if ((resultLoc - resultStr) > (strlen(winPath)+strlen(CYGWIN_PATH_PREFIX)+1)) {
176         abort();
177     }
178 
179     /* return the converted string */
180     return resultStr;
181 }
182 
183 
184 
185 /**
186  * yfGetCygwinConfDir
187  *
188  * Gets the yaf config directory defined at INSTALLATION time on
189  * Windows machines via reading the windows registry.
190  * Caches the result in a file static.
191  *
192  * @return constant string with the data directory name
193  *
194  * @note must call yfCygwinClean to get rid of the memory
195  *       for the cached result
196  */
197 const char *
yfGetCygwinConfDir()198 yfGetCygwinConfDir ()
199 {
200 
201     char *dataBuffer = NULL;
202     DWORD bufferSize = 0;
203     DWORD rc;
204 
205 
206     if (NULL != winRegDataDir) {
207         return winRegDataDir;
208     }
209 
210     /* allocate memory for the initial buffer,
211        likely this is big enough */
212     dataBuffer = (char *) malloc( sizeof(char) * INITIAL_BUFFER_SIZE);
213     if (NULL == dataBuffer) {
214         /* error couldn't allocate memory */
215         return NULL;
216     }
217     bufferSize = INITIAL_BUFFER_SIZE;
218 
219     /* keeping asking the registry for the value until we have
220        a buffer big enough to hold it */
221     do {
222         rc = RegGetValue ( HKEY_LOCAL_MACHINE,
223                            NETSA_WINDOWSREG_REGHOME,
224                            SILK_WINDOWSREG_DATA_DIR_KEY, RRF_RT_ANY,
225                            NULL, (PVOID)dataBuffer, &bufferSize);
226 
227         if (ERROR_MORE_DATA == rc) {
228             dataBuffer = (char *) realloc(dataBuffer,
229                                           (bufferSize + BUFFER_INCREMENT_SIZE));
230             if (NULL == dataBuffer) {
231                 return NULL;
232             }
233             bufferSize += BUFFER_INCREMENT_SIZE;
234         }
235     } while ( ERROR_MORE_DATA == rc);
236 
237     if ( ERROR_SUCCESS == rc ) {
238         if ( 0 == bufferSize ) {
239             /* What makes sense to do when we can't find the registry entry?
240                In this case, we return a "sane" default for windows
241             */
242             winRegDataDir = SILK_DEFAULT_CYGWIN_DATA_DIR;
243             free(dataBuffer);
244             return SILK_DEFAULT_CYGWIN_DATA_DIR;
245         } else {
246             winRegDataDir = windowsToCygwinPath(dataBuffer);
247             free(dataBuffer);
248             return winRegDataDir;
249         }
250 
251     } else {
252 
253         return NULL;
254     }
255 }
256