scponly.c (scponly-20110526.tgz) | : | scponly.c (scponly-4.8.tgz) | ||
---|---|---|---|---|
skipping to change at line 31 | skipping to change at line 31 | |||
int debuglevel=0; | int debuglevel=0; | |||
int winscp_mode=0; | int winscp_mode=0; | |||
int chrooted=0; | int chrooted=0; | |||
char username[MAX_USERNAME]; | char username[MAX_USERNAME]; | |||
char homedir[FILENAME_MAX]; | char homedir[FILENAME_MAX]; | |||
char chrootdir[FILENAME_MAX]; | char chrootdir[FILENAME_MAX]; | |||
char *safeenv[MAX_ENV]; | char *safeenv[MAX_ENV]; | |||
/* will point to syslog or a noop */ | /* will point to syslog or a noop */ | |||
void (*debug)(int priority, const char* format, ...); | void (*debug)(int priority, const char* format, ...); | |||
int (*scponly_getopt_long)( | ||||
int argc, | ||||
char * const argv[], | ||||
const char *optstring, | ||||
const struct option *longopts, | ||||
int *longindex | ||||
); | ||||
cmd_t commands[] = | cmd_t commands[] = | |||
{ | { | |||
#ifdef ENABLE_SFTP | #ifdef ENABLE_SFTP | |||
{ PROG_SFTP_SERVER, 1 }, | { PROG_SFTP_SERVER, 1 }, | |||
#endif /*ENABLE_SFTP*/ | #endif /*ENABLE_SFTP*/ | |||
#ifdef ENABLE_SCP2 | #ifdef ENABLE_SCP2 | |||
{ PROG_LS, 1 }, | { PROG_LS, 1 }, | |||
{ PROG_CHMOD, 1 }, | { PROG_CHMOD, 1 }, | |||
{ PROG_CHOWN, 1 }, | { PROG_CHOWN, 1 }, | |||
skipping to change at line 88 | skipping to change at line 81 | |||
#endif /*QUOTA_COMPAT*/ | #endif /*QUOTA_COMPAT*/ | |||
#ifdef SVN_COMPAT | #ifdef SVN_COMPAT | |||
{ PROG_SVN, 1 }, | { PROG_SVN, 1 }, | |||
#endif /*ENABLE_SVN*/ | #endif /*ENABLE_SVN*/ | |||
#ifdef SVNSERV_COMPAT | #ifdef SVNSERV_COMPAT | |||
{ PROG_SVNSERV, 1 }, | { PROG_SVNSERV, 1 }, | |||
#endif /*ENABLE_SVNSERV*/ | #endif /*ENABLE_SVNSERV*/ | |||
{ NULL } | NULL | |||
}; | }; | |||
/* | /* | |||
* The array of longopts to be used for validation | * The array of longopts to be used for validation | |||
* longopts := (name, has_args, *flag, val) | * longopts := (name, has_args, *flag, val) | |||
*/ | */ | |||
struct option empty_longopts[] = { | struct option empty_longopts[] = { | |||
{ NULL, 0, NULL, 0 }, | { NULL, 0, NULL, 0 }, | |||
}; | }; | |||
#ifdef RSYNC_COMPAT | #ifdef RSYNC_COMPAT | |||
struct option rsync_longopts[] = { | struct option rsync_longopts[] = { | |||
/* options we need to know about that are safe */ | /* I use 'e' for val here because that's what's listed in cmd_arg_t->bada | |||
{"server", 0, 0, (int)'s'}, | rg */ | |||
/* the following options have behaviors we don't want to see */ | {"rsh", 1, 0, (int)'e'}, | |||
{"rsh", 1, 0, (int)'r'}, | ||||
/* the following are disabled because they use daemon mode */ | /* the following are disabled because they use daemon mode */ | |||
{"daemon", 0, 0, (int)'d'}, | {"daemon", 0, 0, (int)'e'}, | |||
{"rsync-path", 1, 0, (int)'d'}, | {"rsync-path", 1, 0, (int)'e'}, | |||
{"address", 1, 0, (int)'d'}, | {"address", 1, 0, (int)'e'}, | |||
{"port", 1, 0, (int)'d'}, | {"port", 1, 0, (int)'e'}, | |||
{"sockopts", 1, 0, (int)'d'}, | {"sockopts", 1, 0, (int)'e'}, | |||
{"config", 1, 0, (int)'d'}, | {"config", 1, 0, (int)'e'}, | |||
{"no-detach", 0, 0, (int)'d'}, | {"no-detach", 0, 0, (int)'e'}, | |||
{ NULL, 0, NULL, 0 }, | { NULL, 0, NULL, 0 }, | |||
}; | }; | |||
#endif | #endif | |||
#ifdef SVNSERV_COMPAT | #ifdef SVNSERV_COMPAT | |||
struct option svnserv_longopts[] = { | struct option svnserv_longopts[] = { | |||
/* bad */ | /* bad */ | |||
{"daemon", 0, NULL, (int)'d' }, | {"daemon", 0, NULL, (int)'d' }, | |||
{"listen-port", 1, NULL, (int)'d' }, | {"listen-port", 1, NULL, (int)'d' }, | |||
{"listen-host", 1, NULL, (int)'d' }, | {"listen-host", 1, NULL, (int)'d' }, | |||
skipping to change at line 163 | skipping to change at line 154 | |||
cmd_arg_t dangerous_args[] = | cmd_arg_t dangerous_args[] = | |||
{ | { | |||
/* | /* | |||
* 'oplist' only neccesary where 'use getopt' is 1 | * 'oplist' only neccesary where 'use getopt' is 1 | |||
* 'strict optlist' only applicable where 'use getopt?' is 1 | * 'strict optlist' only applicable where 'use getopt?' is 1 | |||
* 'badarg' is a string to look for if not in rsync mode, if in rsyn c mode a list of invalid options | * 'badarg' is a string to look for if not in rsync mode, if in rsyn c mode a list of invalid options | |||
* | * | |||
* program name use getopt? strict optlist? badarg optlist longopts\n | * program name use getopt? strict optlist? badarg optlist longopts\n | |||
*/ | */ | |||
#ifdef ENABLE_SFTP | #ifdef ENABLE_SFTP | |||
{ PROG_SFTP_SERVER, 1, 1, NULL, "f:l:u:", empty_longopts }, | { PROG_SFTP_SERVER, 1, 1, NULL, "f:l:", empty_longopts }, | |||
#endif | #endif | |||
#ifdef ENABLE_SCP2 | #ifdef ENABLE_SCP2 | |||
{ PROG_SCP, 1, 1, "SoF", "dfl:prtvBCc:i:P:q1246S:o:F:", empty_long opts }, | { PROG_SCP, 1, 1, "SoF", "dfl:prtvBCc:i:P:q1246S:o:F:", empty_long opts }, | |||
#endif | #endif | |||
#ifdef RSYNC_COMPAT | #ifdef RSYNC_COMPAT | |||
{ PROG_RSYNC, 1, 0, "rde", "e::", rsync_longopts }, | { PROG_RSYNC, 1, 0, "e", "e:", rsync_longopts }, | |||
#endif | #endif | |||
#ifdef UNISON_COMPAT | #ifdef UNISON_COMPAT | |||
{ PROG_UNISON, 0, 0, "-rshcmd", NULL, empty_longopts }, | { PROG_UNISON, 0, 0, "-rshcmd", NULL, empty_longopts }, | |||
{ PROG_UNISON, 0, 0, "-sshcmd", NULL, empty_longopts }, | { PROG_UNISON, 0, 0, "-sshcmd", NULL, empty_longopts }, | |||
{ PROG_UNISON, 0, 0, "-servercmd", NULL, empty_longopts }, | { PROG_UNISON, 0, 0, "-servercmd", NULL, empty_longopts }, | |||
{ PROG_UNISON, 0, 0, "-addversionno",NULL, empty_longopts }, | { PROG_UNISON, 0, 0, "-addversionno",NULL, empty_longopts }, | |||
#endif | #endif | |||
#ifdef SVNSERV_COMPAT | #ifdef SVNSERV_COMPAT | |||
{ PROG_SVNSERV, 1, 1, "diTX", "dihr:RtTX", svnserv_longopts }, | { PROG_SVNSERV, 1, 1, "diTX", "dihr:RtTX", svnserv_longopts }, | |||
#endif | #endif | |||
#ifdef SVN_COMPAT | #ifdef SVN_COMPAT | |||
{ PROG_SVN, 1, 0, "Xx", "NvxuRr:qm:F:", svn_longo pts }, | { PROG_SVN, 1, 0, "Xx", "NvxuRr:qm:F:", svn_longo pts }, | |||
#endif | #endif | |||
#ifdef QUOTA_COMPAT | #ifdef QUOTA_COMPAT | |||
{ PROG_QUOTA, 1, 1, NULL, "-F:guvsilqQ", empty_longopts }, | { PROG_QUOTA, 1, 1, NULL, "-F:guvsilqQ", empty_longopts }, | |||
#endif | #endif | |||
{ NULL } | NULL | |||
}; | }; | |||
/* | /* | |||
* SFTP logging requires that the following environment variables be | * SFTP logging requires that the following environment variables be | |||
* defined in order to work: | * defined in order to work: | |||
* | * | |||
* LOG_SFTP | * LOG_SFTP | |||
* USER | * USER | |||
* SFTP_UMASK | * SFTP_UMASK | |||
* SFTP_PERMIT_CHMOD | * SFTP_PERMIT_CHMOD | |||
skipping to change at line 228 | skipping to change at line 219 | |||
int process_ssh_request(char *request); | int process_ssh_request(char *request); | |||
int process_pre_chroot_request(char **av); | int process_pre_chroot_request(char **av); | |||
int winscp_regular_request(char *request); | int winscp_regular_request(char *request); | |||
int winscp_transit_request(char *request); | int winscp_transit_request(char *request); | |||
int process_winscp_requests(void); | int process_winscp_requests(void); | |||
int main (int argc, char **argv) | int main (int argc, char **argv) | |||
{ | { | |||
FILE *debugfile; | FILE *debugfile; | |||
int logopts = LOG_PID|LOG_NDELAY; | int logopts = LOG_PID|LOG_NDELAY; | |||
int chars_read = 0; | ||||
#ifdef CHROOT_CHECKDIR | ||||
struct stat homedirstat; | struct stat homedirstat; | |||
#endif | ||||
/* | /* | |||
* set debuglevel. any nonzero number will result in debugging info to l og | * set debuglevel. any nonzero number will result in debugging info to l og | |||
*/ | */ | |||
if (NULL!=(debugfile=fopen(DEBUGFILE,"r"))) | if (NULL!=(debugfile=fopen(DEBUGFILE,"r"))) | |||
{ | { | |||
chars_read = fscanf(debugfile,"%d",&debuglevel); | fscanf(debugfile,"%u",&debuglevel); | |||
if (chars_read < 1) | ||||
debuglevel = 0; | ||||
fclose(debugfile); | fclose(debugfile); | |||
} | } | |||
#ifndef UNIX_COMPAT | #ifndef UNIX_COMPAT | |||
if (debuglevel > 1) /* debuglevel 1 will still log to syslog */ | if (debuglevel > 1) /* debuglevel 1 will still log to syslog */ | |||
logopts |= LOG_PERROR; | logopts |= LOG_PERROR; | |||
#endif | #endif | |||
#ifdef UNIX_COMPAT | #ifdef UNIX_COMPAT | |||
openlog(PACKAGE_NAME, logopts, LOG_AUTH); | openlog(PACKAGE_NAME, logopts, LOG_AUTH); | |||
#elif IRIX_COMPAT | #elif IRIX_COMPAT | |||
skipping to change at line 263 | skipping to change at line 249 | |||
if (debuglevel > 1) /* debuglevel 1 will still log to syslog */ | if (debuglevel > 1) /* debuglevel 1 will still log to syslog */ | |||
logopts |= LOG_PERROR; | logopts |= LOG_PERROR; | |||
openlog(PACKAGE_NAME, logopts, LOG_AUTHPRIV); | openlog(PACKAGE_NAME, logopts, LOG_AUTHPRIV); | |||
#endif | #endif | |||
if (debuglevel > 0) | if (debuglevel > 0) | |||
debug = syslog; | debug = syslog; | |||
else | else | |||
debug = noop_syslog; | debug = noop_syslog; | |||
#ifdef HAVE_GETOPT_H | ||||
scponly_getopt_long = getopt_long; | ||||
#else | ||||
debug(LOG_INFO, "using netbsd's bundled getopt_long"); | ||||
scponly_getopt_long = netbsd_getopt_long; | ||||
#endif | ||||
#ifdef CHROOTED_NAME | #ifdef CHROOTED_NAME | |||
/* | /* | |||
* is this a chroot'ed scponly installation? | * is this a chroot'ed scponly installation? | |||
*/ | */ | |||
#ifdef WINSCP_COMPAT | #ifdef WINSCP_COMPAT | |||
if ((argc==3 && (0==strncmp(argv[0],CHROOTED_NAME,FILENAME_MAX)) ) || | if ((argc==3 && (0==strncmp(argv[0],CHROOTED_NAME,FILENAME_MAX)) ) || | |||
( argc==1 && (0==strncmp(&argv[0][1],CHROOTED_NAME,FILENAME_MAX ) ))) | ( argc==1 && (0==strncmp(&argv[0][1],CHROOTED_NAME,FILENAME_MAX ) ))) | |||
#else | #else | |||
if (0==strncmp(argv[0],CHROOTED_NAME,FILENAME_MAX)) | if (0==strncmp(argv[0],CHROOTED_NAME,FILENAME_MAX)) | |||
skipping to change at line 436 | skipping to change at line 415 | |||
debug(LOG_ERR, "chdir: %m"); | debug(LOG_ERR, "chdir: %m"); | |||
syslog (LOG_ERR, "couldn't chdir to %s [%s]", chdir_path, logstamp()); | syslog (LOG_ERR, "couldn't chdir to %s [%s]", chdir_path, logstamp()); | |||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | |||
} | } | |||
} | } | |||
#endif /* CHROOTED_NAME */ | #endif /* CHROOTED_NAME */ | |||
debug(LOG_DEBUG, "setting uid to %u", getuid()); | debug(LOG_DEBUG, "setting uid to %u", getuid()); | |||
if (-1==(seteuid(getuid()))) | if (-1==(seteuid(getuid()))) | |||
{ | { | |||
syslog(LOG_ERR, "couldn't revert to my real uid. seteuid: %m"); | syslog (LOG_ERR, "couldn't revert to my real uid. seteuid: %m"); | |||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | |||
} | } | |||
#ifdef WINSCP_COMPAT | #ifdef WINSCP_COMPAT | |||
if (argc==1) | if (argc==1) | |||
{ | { | |||
debug(LOG_DEBUG, "entering WinSCP compatibility mode [%s]",logsta mp()); | debug(LOG_DEBUG, "entering WinSCP compatibility mode [%s]",logsta mp()); | |||
if (-1==process_winscp_requests()) | if (-1==process_winscp_requests()) | |||
{ | { | |||
syslog(LOG_ERR, "failed WinSCP compatibility mode [%s]", logstamp()); | syslog(LOG_ERR, "failed WinSCP compatibility mode [%s]", logstamp()); | |||
End of changes. 12 change blocks. | ||||
36 lines changed or deleted | 16 lines changed or added |