295 lines
9.6 KiB
C
295 lines
9.6 KiB
C
/*********************************************************************\
|
|
* Copyright (c) 2003 by Radim Kolar (hsn@cybermail.net) *
|
|
* Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu) *
|
|
* *
|
|
* You may copy or modify this file in any manner you wish, provided *
|
|
* that this notice is always included, and that you hold the author *
|
|
* harmless for any loss or damage resulting from the installation or *
|
|
* use of this software. *
|
|
\*********************************************************************/
|
|
|
|
#include "tweak.h"
|
|
#include <stdio.h>
|
|
#ifdef STDC_HEADERS
|
|
#include <stdlib.h>
|
|
#endif
|
|
#include <ctype.h>
|
|
#include "server_def.h"
|
|
#include "s_extern.h"
|
|
#include "co_extern.h"
|
|
#include "my-string.h"
|
|
|
|
static int conf_read = 0;
|
|
|
|
int daemonize = 1;
|
|
int use_prebuild_dirlists =
|
|
#ifdef OS_CYGWIN
|
|
0;
|
|
#else
|
|
1;
|
|
#endif
|
|
int grab_enabled = 1;
|
|
int ver_enabled = 1;
|
|
int read_only = 0;
|
|
unsigned short udp_port = 21;
|
|
int dbug = 0;
|
|
uid_t run_uid = 0;
|
|
gid_t run_gid = 0;
|
|
int priv_mode = 0;
|
|
int no_unnamed = 0;
|
|
int logging = 0;
|
|
int use_access_files = 1;
|
|
int use_directory_mtime =
|
|
#ifdef OS_CYGWIN
|
|
0;
|
|
#else
|
|
1;
|
|
#endif
|
|
unsigned int maxthcallowed = 0;
|
|
unsigned short packetsize = UBUF_SPACE;
|
|
time_t retry_timeout = 3;
|
|
time_t session_timeout = 60;
|
|
time_t stat_cache_timeout = 25;
|
|
char *logname = NULL;
|
|
char *tlogname = NULL;
|
|
char *pidlogname = NULL;
|
|
char *dumpname = NULL;
|
|
char *home_dir = NULL;
|
|
char *tmp_dir = NULL;
|
|
int homedir_restricted = 1;
|
|
int permit_passwordless_owners = 0;
|
|
char *readme_file = NULL;
|
|
unsigned int dir_cache_limit = DEFAULT_DIRLISTCACHE_SIZE;
|
|
unsigned int stat_cache_limit = DEFAULT_DIRSTATCACHE_SIZE;
|
|
mode_t upload_umask = 0033;
|
|
mode_t system_umask = 0077;
|
|
|
|
/****************************************************************************
|
|
* Set this value to the maximum number of open files you wish your system *
|
|
* to keep around at any given time. The smaller this number is, the more *
|
|
* likely the server is to be opening and closing files, but the less file *
|
|
* descriptors need to be taken up by the server itself *
|
|
* Five seems to work reasonably well on my system *
|
|
****************************************************************************/
|
|
unsigned int fp_cache_limit=10;
|
|
|
|
|
|
static void log_set PROTO2(int, flag, int, neg)
|
|
{
|
|
if(neg) logging &= ~flag;
|
|
else logging |= flag;
|
|
}
|
|
|
|
static int get_boolean PROTO1(const char, *q)
|
|
{
|
|
if(strcmp(q, "0") == 0) return 0;
|
|
else
|
|
if(strcasecmp(q, "no") == 0) return 0;
|
|
else
|
|
if(strcasecmp(q, "off") == 0) return 0;
|
|
else
|
|
if(strcasecmp(q, "on") == 0) return 1;
|
|
else
|
|
if(strcasecmp(q, "yes") == 0) return 1;
|
|
else
|
|
if(strcmp(q, "1") == 0) return 1;
|
|
else
|
|
|
|
fprintf(stderr,"Bogus boolean value '%s'. Exiting.\n",q);
|
|
exit(1);
|
|
return -1;
|
|
}
|
|
|
|
static void read_configuration PROTO1(const char *, name)
|
|
{
|
|
FILE *fp;
|
|
char buf[1024], *p, *q;
|
|
|
|
fp = fopen(name,"r");
|
|
if(!fp) {
|
|
fprintf(stderr, "Warning: Unable to open configuration file: %s.\n", name);
|
|
return;
|
|
}
|
|
while(fgets(buf, sizeof(buf), fp)) {
|
|
if(buf[0] == '\n' || buf[0] == '#') continue;
|
|
buf[strlen(buf)-1] = '\0'; /* strip off the newline */
|
|
p = buf; while(*p && isspace(*p)) p++;
|
|
q = p; while(*q && !isspace(*q)) q++;
|
|
if(!*p || !*q) {
|
|
fprintf(stderr,"Bogus line in configuration file: %s. Exiting.\n",name);
|
|
exit(1);
|
|
}
|
|
*q = '\0'; q++;
|
|
if(strcasecmp(p, "conf") == 0) {
|
|
if(conf_read) {
|
|
fprintf(stderr, "No recursion of conf commands allowed. Skipping.\n");
|
|
continue;
|
|
}
|
|
conf_read = 1;
|
|
fclose(fp);
|
|
read_configuration(q);
|
|
return;
|
|
} else if(strcasecmp(p, "readme") == 0) {
|
|
if(readme_file) free(readme_file);
|
|
readme_file = strdup(q);
|
|
} else if(strcasecmp(p, "homedir") == 0) {
|
|
if(home_dir) free(home_dir);
|
|
home_dir = strdup(q);
|
|
} else if(strcasecmp(p, "tmpdir") == 0) {
|
|
if(tmp_dir) free(tmp_dir);
|
|
tmp_dir = strdup(q);
|
|
} else if(strcasecmp(p, "logfile") == 0) {
|
|
if(logname) free(logname);
|
|
logname = strdup(q);
|
|
} else if(strcasecmp(p, "xferlog") == 0) {
|
|
if(tlogname) free(tlogname);
|
|
tlogname = strdup(q);
|
|
} else if(strcasecmp(p, "pidlogname") == 0) {
|
|
if(pidlogname) free(pidlogname);
|
|
pidlogname = strdup(q);
|
|
} else if(strcasecmp(p, "dumpfile") == 0) {
|
|
if(dumpname) free(dumpname);
|
|
dumpname = strdup(q);
|
|
} else if(strcasecmp(p, "host") == 0) {
|
|
add_ipline(q,&iptab);
|
|
} else if(strcasecmp(p, "log") == 0) {
|
|
char *r;
|
|
int neg;
|
|
do {
|
|
/* skip to next token */
|
|
r = q; while(*r && !isspace(*r)) r++;
|
|
if (*r) { *r++ = 0 ; while(*r && isspace(*r)) r++; }
|
|
if(strcasecmp(q, "none") == 0) {
|
|
logging = L_NONE;
|
|
break;
|
|
} else if(strcasecmp(q, "all") == 0) {
|
|
logging = L_ALL;
|
|
} else {
|
|
if(*q == '!') { neg = 1; q++;} else neg = 0;
|
|
if(strcasecmp(q, "transfers") == 0) {
|
|
log_set(L_GETFILE, neg);
|
|
log_set(L_INSTALL, neg);
|
|
} else if(strcasecmp(q, "version") == 0) log_set(L_VER, neg);
|
|
else if(strcasecmp(q, "errors") == 0) log_set(L_ERR, neg);
|
|
else if(strcasecmp(q, "getdir") == 0) log_set(L_GETDIR, neg);
|
|
else if(strcasecmp(q, "getfile") == 0) log_set(L_GETFILE, neg);
|
|
else if(strcasecmp(q, "upload") == 0) log_set(L_UPLOAD, neg);
|
|
else if(strcasecmp(q, "install") == 0) log_set(L_INSTALL, neg);
|
|
else if(strcasecmp(q, "delfile") == 0) log_set(L_DELFILE, neg);
|
|
else if(strcasecmp(q, "deldir") == 0) log_set(L_DELDIR, neg);
|
|
else if(strcasecmp(q, "setpro") == 0) log_set(L_SETPRO, neg);
|
|
else if(strcasecmp(q, "getpro") == 0) log_set(L_GETPRO, neg);
|
|
else if(strcasecmp(q, "makedir") == 0) log_set(L_MAKEDIR, neg);
|
|
else if(strcasecmp(q, "grabfile") == 0) log_set(L_GRABFILE, neg);
|
|
else if(strcasecmp(q, "readonly") == 0) log_set(L_RDONLY, neg);
|
|
else if(strcasecmp(q, "stat") == 0) log_set(L_STAT, neg);
|
|
else if(strcasecmp(q, "rename") == 0) log_set(L_RENAME, neg);
|
|
}
|
|
q = r;
|
|
} while (*q);
|
|
} else if(strcasecmp(p, "port") == 0) {
|
|
udp_port = atoi(q);
|
|
}
|
|
else if(strcasecmp(p, "packetsize") == 0) {
|
|
packetsize = atoi(q);
|
|
if(packetsize <= 64 || packetsize > UBUF_SPACE ) packetsize = UBUF_SPACE;
|
|
}
|
|
else if(strcasecmp(p, "filecache") == 0) {
|
|
fp_cache_limit = atoi(q);
|
|
if(fp_cache_limit < 10 ) fp_cache_limit = 10;
|
|
}
|
|
else if(strcasecmp(p, "dircache") == 0) {
|
|
dir_cache_limit = atoi(q);
|
|
if( dir_cache_limit < 16 ) dir_cache_limit = DEFAULT_DIRLISTCACHE_SIZE;
|
|
}
|
|
else if(strcasecmp(p, "statcache") == 0) {
|
|
stat_cache_limit = atoi(q);
|
|
if( stat_cache_limit < 10 ) stat_cache_limit = DEFAULT_DIRSTATCACHE_SIZE;
|
|
}
|
|
else if(strcasecmp(p, "retry") == 0) {
|
|
retry_timeout = atoi(q);
|
|
if(retry_timeout < 1 ) retry_timeout = 3;
|
|
}
|
|
else if(strcasecmp(p, "timeout") == 0) {
|
|
session_timeout = atoi(q);
|
|
if(session_timeout <= 5 ) session_timeout = 60;
|
|
}
|
|
else if(strcasecmp(p, "statcache_timeout") == 0) {
|
|
session_timeout = atoi(q);
|
|
if(stat_cache_timeout <= 0 ) stat_cache_timeout = 20;
|
|
}
|
|
else if(strcasecmp(p, "thruput") == 0) {
|
|
if(strcasecmp(q, "off") == 0) maxthcallowed = 0;
|
|
else maxthcallowed = atoi(q);
|
|
} else if(strcasecmp(p, "setuid") == 0) {
|
|
if(strcasecmp(q, "off") == 0) run_uid = 0;
|
|
else run_uid = atoi(q);
|
|
} else if(strcasecmp(p, "setgid") == 0) {
|
|
if(strcasecmp(q, "off") == 0) run_gid = 0;
|
|
else run_gid = atoi(q);
|
|
} else if(strcasecmp(p, "umask") == 0) {
|
|
upload_umask = strtol(q,NULL,8);
|
|
} else if(strcasecmp(p, "serverumask") == 0) {
|
|
system_umask = strtol(q,NULL,8);
|
|
} else if(strcasecmp(p, "daemonize") == 0) {
|
|
daemonize = get_boolean(q);
|
|
} else if(strcasecmp(p, "debug") == 0) {
|
|
dbug = get_boolean(q);
|
|
} else if(strcasecmp(p, "restricted") == 0) {
|
|
priv_mode = get_boolean(q);
|
|
} else if(strcasecmp(p, "homedir_restricted") == 0) {
|
|
homedir_restricted = get_boolean(q);
|
|
} else if(strcasecmp(p, "grabcommand") == 0) {
|
|
grab_enabled = get_boolean(q);
|
|
} else if(strcasecmp(p, "vercommand") == 0) {
|
|
ver_enabled = get_boolean(q);
|
|
} else if(strcasecmp(p, "permit_passwordless_owners") == 0) {
|
|
permit_passwordless_owners = get_boolean(q);
|
|
} else if(strcasecmp(p, "reverse_name") == 0) {
|
|
no_unnamed = get_boolean(q);
|
|
} else if(strcasecmp(p, "use_prebuild_dirlists") == 0) {
|
|
use_prebuild_dirlists = get_boolean(q);
|
|
} else if(strcasecmp(p, "use_access_files") == 0) {
|
|
use_access_files = get_boolean(q);
|
|
} else if(strcasecmp(p, "use_directory_mtime") == 0) {
|
|
use_directory_mtime = get_boolean(q);
|
|
} else if(strcasecmp(p, "read_only") == 0) {
|
|
read_only = get_boolean(q);
|
|
} else {
|
|
fprintf(stderr, "Invalid command (%s) in config file, skipping.\n", p);
|
|
}
|
|
}
|
|
fclose(fp);
|
|
}
|
|
|
|
void load_configuration PROTO1(const char *,config_file)
|
|
{
|
|
if(config_file == NULL) return;
|
|
|
|
/* destroy_configuration(); */
|
|
/* destroying iptab should be enough */
|
|
if(iptab)
|
|
{
|
|
free_ip_table(iptab);
|
|
iptab = NULL;
|
|
}
|
|
|
|
read_configuration(config_file);
|
|
}
|
|
|
|
void destroy_configuration PROTO0((void))
|
|
{
|
|
if(readme_file) free(readme_file);
|
|
if(home_dir) free(home_dir);
|
|
if(logname) free(logname);
|
|
if(tlogname) free(tlogname);
|
|
if(pidlogname) free(pidlogname);
|
|
if(tmp_dir) free(tmp_dir);
|
|
if(dumpname) free(dumpname);
|
|
if(iptab) free_ip_table(iptab);
|
|
|
|
readme_file = home_dir = logname = tmp_dir = dumpname = NULL;
|
|
iptab = NULL;
|
|
pidlogname = NULL;
|
|
}
|