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