"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "scponly.c" between
scponly-20110526.tgz and scponly-4.8.tgz

About: scponly is an alternative "shell" of sorts for system administrators who would like to provide access to remote users to both read and write local files without providing any remote execution privileges (a wrapper around "ssh"). Commands like chmod, pwd, chown, etc. are allowed for sftp.

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

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS