1 /* preffw.c
2  *
3  * Copyright (c) 1992-2001 by Mike Gleason.
4  * All rights reserved.
5  *
6  */
7 
8 #include "syshdrs.h"
9 
10 #include "pref.h"
11 #include "util.h"
12 
13 /* How many times they've run this program. */
14 int gNumProgramRuns = 0;
15 
16 /* Firewall/proxy configuration parameters. */
17 int gFirewallType;
18 char gFirewallHost[64];
19 char gFirewallUser[32];
20 char gFirewallPass[32];
21 char gFirewallExceptionList[256];
22 unsigned int gFirewallPort;
23 int gFirewallPrefsLoaded = 0;
24 
25 /* Active or passive FTP?  (PORT or PASV?)  Or both? */
26 int gDataPortMode;
27 
28 /* Hack so the user/admin can set passive in the firewall
29  * prefs file.
30  */
31 int gFwDataPortMode = -1;
32 
33 extern FTPLibraryInfo gLib;
34 extern char gOurDirectoryPath[], gUser[], gVersion[];
35 
36 
37 /* Save a sample configuration file for the firewall/proxy setup. */
38 void
WriteDefaultFirewallPrefs(FILE * fp)39 WriteDefaultFirewallPrefs(FILE *fp)
40 {
41 	char *cp;
42 	time_t now;
43 
44 	FTPInitializeOurHostName(&gLib);
45 	cp = strchr(gLib.ourHostName, '.');
46 
47 	(void) fprintf(fp, "%s", "\
48 # NcFTP firewall preferences\n\
49 # ==========================\n\
50 #\n\
51 ");
52 
53 	(void) fprintf(fp, "%s", "\
54 # If you need to use a proxy for FTP, you can configure it below.\n\
55 # If you do not need one, leave the ``firewall-type'' variable set\n\
56 # to 0.  Any line that does not begin with the ``#'' character is\n\
57 # considered a configuration command line.\n\
58 ");
59 	(void) fprintf(fp, "%s", "\
60 #\n\
61 # NOTE:  NcFTP does NOT support HTTP proxies that do FTP, such as \"squid\"\n\
62 #        or Netscape Proxy Server.  Why?  Because you have to communicate with\n\
63 #        them using HTTP, and this is a FTP only program.\n\
64 ");
65 	(void) fprintf(fp, "%s", "\
66 #\n\
67 # Types of firewalls:\n\
68 # ------------------\n\
69 #\n\
70 #    type 1:  Connect to firewall host, but send \"USER user@real.host.name\"\n\
71 #\n\
72 ");
73 	(void) fprintf(fp, "%s", "\
74 #    type 2:  Connect to firewall, login with \"USER fwuser\" and\n\
75 #             \"PASS fwpassword\", and then \"USER user@real.host.name\"\n\
76 #\n\
77 #    type 3:  Connect to and login to firewall, and then use\n\
78 #             \"SITE real.host.name\", followed by the regular USER and PASS.\n\
79 #\n\
80 ");
81 	(void) fprintf(fp, "%s", "\
82 #    type 4:  Connect to and login to firewall, and then use\n\
83 #             \"OPEN real.host.name\", followed by the regular USER and PASS.\n\
84 #\n\
85 #    type 5:  Connect to firewall host, but send\n\
86 #             \"USER user@fwuser@real.host.name\" and\n\
87 #             \"PASS pass@fwpass\" to login.\n\
88 #\n\
89 ");
90 	(void) fprintf(fp, "%s", "\
91 #    type 6:  Connect to firewall host, but send\n\
92 #             \"USER fwuser@real.host.name\" and\n\
93 #             \"PASS fwpass\" followed by a regular\n\
94 #             \"USER user\" and\n\
95 #             \"PASS pass\" to complete the login.\n\
96 #\n\
97 ");
98 	(void) fprintf(fp, "%s", "\
99 #    type 7:  Connect to firewall host, but send\n\
100 #             \"USER user@real.host.name fwuser\" and\n\
101 #             \"PASS pass\" followed by\n\
102 #             \"ACCT fwpass\" to complete the login.\n\
103 #\n\
104 #    type 0:  Do NOT use a firewall (most users will choose this).\n\
105 #\n\
106 firewall-type=0\n\
107 #\n\
108 #\n\
109 #\n\
110 ");
111 	(void) fprintf(fp, "%s", "\
112 # The ``firewall-host'' variable should be the IP address or hostname of\n\
113 # your firewall server machine.\n\
114 #\n\
115 ");
116 
117 	if (cp == NULL) {
118 		(void) fprintf(fp, "firewall-host=firewall.domain.com\n");
119 	} else {
120 		(void) fprintf(fp, "firewall-host=firewall%s\n", cp);
121 	}
122 
123 	(void) fprintf(fp, "%s", "\
124 #\n\
125 #\n\
126 #\n\
127 # The ``firewall-user'' variable tells NcFTP what to use as the user ID\n\
128 # when it logs in to the firewall before connecting to the outside world.\n\
129 #\n\
130 ");
131 	(void) fprintf(fp, "firewall-user=%s\n", gUser);
132 	(void) fprintf(fp, "%s", "\
133 #\n\
134 #\n\
135 #\n\
136 # The ``firewall-password'' variable is the password associated with\n\
137 # the firewall-user ID.  If you set this here, be sure to change the\n\
138 # permissions on this file so that no one (except the superuser) can\n\
139 # see your password.  You may also leave this commented out, and then\n\
140 # NcFTP will prompt you each time for the password.\n\
141 ");
142 	(void) fprintf(fp, "%s", "\
143 #\n\
144 firewall-password=fwpass\n\
145 #\n\
146 #\n\
147 #\n\
148 # Your firewall may require you to connect to a non-standard port for\n\
149 # outside FTP services, instead of the internet standard port number (21).\n\
150 #\n\
151 firewall-port=21\n\
152 ");
153 	(void) fprintf(fp, "%s", "\
154 #\n\
155 #\n\
156 #\n\
157 # You probably do not want to FTP to the firewall for hosts on your own\n\
158 # domain.  You can set ``firewall-exception-list'' to a list of domains\n\
159 # or hosts where the firewall should not be used.  For example, if your\n\
160 # domain was ``probe.net'' you could set this to ``.probe.net''.\n\
161 #\n\
162 ");
163 	(void) fprintf(fp, "%s", "\
164 # If you leave this commented out, the default behavior is to attempt to\n\
165 # lookup the current domain, and exclude hosts for it.  Otherwise, set it\n\
166 # to a list of comma-delimited domains or hostnames.  The special token\n\
167 # ``localdomain'' is used for unqualified hostnames, so if you want hosts\n\
168 # without explicit domain names to avoid the firewall, be sure to include\n\
169 # that in your list.\n\
170 #\n\
171 ");
172 
173 	if (cp != NULL) {
174 		(void) fprintf(fp, "firewall-exception-list=%s,localhost,localdomain\n", cp);
175 	} else {
176 		(void) fprintf(fp, "firewall-exception-list=.probe.net,localhost,foo.bar.com,localdomain\n");
177 	}
178 
179 	(void) fprintf(fp, "%s", "\
180 #\n\
181 #\n\
182 #\n\
183 # You may also specify passive mode here.  Normally this is set in the\n\
184 # regular $HOME/.ncftp/prefs file.  This must be set to one of\n\
185 # \"on\", \"off\", or \"optional\", which mean always use PASV,\n\
186 # always use PORT, and try PASV then PORT, respectively.\n\
187 #\n\
188 #passive=on\n");
189 
190 	time(&now);
191 	(void) fprintf(fp, "\
192 #\n\
193 #\n\
194 #\n\
195 # NOTE:  This file was created for you on %s\
196 #        by NcFTP %.5s.  Removing this file will cause the next run of NcFTP\n\
197 #        to generate a new one, possibly with more configurable options.\n",
198 	ctime(&now),
199 	gVersion + 11);
200 	(void) fprintf(fp, "\
201 #\n\
202 # ALSO:  A %s file, if present, is processed before this file,\n\
203 #        and a %s file, if present, is processed after.\n",
204 		kGlobalFirewallPrefFileName,
205 		kGlobalFixedFirewallPrefFileName
206 	);
207 }	/* CreateDefaultFirewallPrefs */
208 
209 
210 
211 
212 void
ProcessFirewallPrefFile(FILE * fp)213 ProcessFirewallPrefFile(FILE *fp)
214 {
215 	char line[256];
216 	char *tok1, *tok2;
217 	int n;
218 
219 	/* Opened the firewall preferences file. */
220 	line[sizeof(line) - 1] = '\0';
221 	while (fgets(line, sizeof(line) - 1, fp) != NULL) {
222 		tok1 = strtok(line, " =\t\r\n");
223 		if ((tok1 == NULL) || (tok1[0] == '#'))
224 			continue;
225 		tok2 = strtok(NULL, "\r\n");
226 		if (tok2 == NULL)
227 			continue;
228 		if (ISTREQ(tok1, "firewall-type")) {
229 			n = atoi(tok2);
230 			if ((n > 0) && (n <= kFirewallLastType))
231 				gFirewallType = n;
232 		} else if (ISTREQ(tok1, "firewall-host")) {
233 			(void) STRNCPY(gFirewallHost, tok2);
234 		} else if (ISTREQ(tok1, "firewall-port")) {
235 			n = atoi(tok2);
236 			if (n > 0)
237 				gFirewallPort = (unsigned int) n;
238 		} else if (ISTREQ(tok1, "firewall-user")) {
239 			(void) STRNCPY(gFirewallUser, tok2);
240 		} else if (ISTREQ(tok1, "firewall-pass")) {
241 			(void) STRNCPY(gFirewallPass, tok2);
242 		} else if (ISTREQ(tok1, "firewall-password")) {
243 			(void) STRNCPY(gFirewallPass, tok2);
244 		} else if (ISTREQ(tok1, "firewall-exception-list")) {
245 			(void) STRNCPY(gFirewallExceptionList, tok2);
246 		} else if (ISTREQ(tok1, "passive")) {
247 			if (ISTREQ(tok2, "optional")) {
248 				gDataPortMode = gFwDataPortMode = kFallBackToSendPortMode;
249 			} else if (ISTREQ(tok2, "on")) {
250 				gDataPortMode = gFwDataPortMode = kPassiveMode;
251 			} else if (ISTREQ(tok2, "off")) {
252 				gDataPortMode = gFwDataPortMode = kSendPortMode;
253 			} else if ((int) isdigit(tok2[0])) {
254 				gDataPortMode = gFwDataPortMode = atoi(tok2);
255 			}
256 		}
257 	}
258 }	/* ProcessFirewallPrefFile */
259 
260 
261 
262 
263 /* Load those options specific to the firewall/proxy settings.  These are
264  * kept in a different file so that other programs can read it and not
265  * have to worry about the other junk in the prefs file.
266  */
267 void
LoadFirewallPrefs(int forceReload)268 LoadFirewallPrefs(int forceReload)
269 {
270 	FILE *fp, *fp2;
271 	char pathName[256];
272 	char *cp;
273 	int userFile = 0;
274 	int sysFile = 0;
275 
276 	if ((gFirewallPrefsLoaded != 0) && (forceReload == 0))
277 		return;
278 	gFirewallPrefsLoaded = 1;
279 
280 	if (gOurDirectoryPath[0] == '\0')
281 		return;		/* Don't create in root directory. */
282 	(void) OurDirectoryPath(pathName, sizeof(pathName), kFirewallPrefFileName);
283 
284 	/* Set default values. */
285 	gFirewallType = kFirewallNotInUse;
286 	gFirewallPort = 0;
287 	gFirewallHost[0] = '\0';
288 	gFirewallUser[0] = '\0';
289 	gFirewallPass[0] = '\0';
290 	gFirewallExceptionList[0] = '\0';
291 
292 	fp2 = fopen(kGlobalFirewallPrefFileName, FOPEN_READ_TEXT);
293 	if (fp2 != NULL) {
294 		/* Initialize to system-wide defaults. */
295 		ProcessFirewallPrefFile(fp2);
296 		(void) fclose(fp2);
297 		sysFile++;
298 	}
299 
300 	fp = fopen(pathName, FOPEN_READ_TEXT);
301 	if (fp != NULL) {
302 		/* Do user's firewall file. */
303 		ProcessFirewallPrefFile(fp);
304 		(void) fclose(fp);
305 		userFile = 1;
306 	}
307 
308 	fp2 = fopen(kGlobalFixedFirewallPrefFileName, FOPEN_READ_TEXT);
309 	if (fp2 != NULL) {
310 		/* Override with system-wide settings. */
311 		ProcessFirewallPrefFile(fp2);
312 		(void) fclose(fp2);
313 		sysFile++;
314 	}
315 
316 	if ((userFile == 0) && (sysFile == 0)) {
317 		/* Create a blank one, if
318 		 * there were no system-wide files.
319 		 */
320 		fp = fopen(pathName, FOPEN_WRITE_TEXT);
321 		if (fp != NULL) {
322 			WriteDefaultFirewallPrefs(fp);
323 			(void) fclose(fp);
324 			(void) _chmod(pathName, 00600);
325 			gNumProgramRuns = 1;
326 		}
327 	}
328 
329 	if (gFirewallExceptionList[0] == '\0') {
330 		FTPInitializeOurHostName(&gLib);
331 		cp = strchr(gLib.ourHostName, '.');
332 
333 		if (cp != NULL) {
334 			(void) STRNCPY(gFirewallExceptionList, cp);
335 			(void) STRNCAT(gFirewallExceptionList, ",localdomain");
336 		}
337 	}
338 }	/* LoadFirewallPrefs */
339