Репозитории ALT
S: | 0.6.1-alt2 |
5.1: | 0.6-alt2 |
4.1: | 0.5.3k-alt3.M41.1 |
4.0: | 0.5.3k-alt3.M40.1 |
Группа :: Система/Серверы
Пакет: 3proxy
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: 3proxy-0.6.1-alt-droproot.patch
Скачать
Скачать
Makefile.Linux | 4 +-
Makefile.unix | 4 +-
src/3proxy.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
src/proxy.h | 2 +
src/proxymain.c | 92 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 210 insertions(+), 15 deletions(-)
diff --git a/Makefile.Linux b/Makefile.Linux
index 17513f2..ed787ce 100644
--- a/Makefile.Linux
+++ b/Makefile.Linux
@@ -11,7 +11,7 @@
BUILDDIR =
CC = gcc
-CFLAGS = -Wall -g -O2 -c -pthread -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -DWITH_POLL
+CFLAGS = -std=gnu99 -Wall -g -O2 -c -pthread -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -DWITH_POLL
COUT = -o
LN = gcc
DCFLAGS = -fpic
@@ -19,7 +19,7 @@ LDFLAGS = -Wall -O2 -pthread
DLFLAGS = -shared
DLSUFFICS = .ld.so
# -lpthreads may be reuqired on some platforms instead of -pthreads
-LIBS = -ldl
+LIBS = -ldl -lcap
LNOUT = -o
EXESUFFICS =
OBJSUFFICS = .o
diff --git a/Makefile.unix b/Makefile.unix
index 1be4eba..06ef321 100644
--- a/Makefile.unix
+++ b/Makefile.unix
@@ -12,7 +12,7 @@ BUILDDIR =
CC = gcc
# you may need -L/usr/pkg/lib for older NetBSD versions
-CFLAGS = -Wall -g -O2 -c -pthread -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -DWITH_POLL
+CFLAGS = -std=gnu99 -Wall -g -O2 -c -pthread -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -DWITH_POLL
COUT = -o
LN = gcc
LDFLAGS = -Wall -O2 -pthread
@@ -21,7 +21,7 @@ LDFLAGS = -Wall -O2 -pthread
DCFLAGS = -fpic
DLFLAGS = -shared
DLSUFFICS = .ld.so
-LIBS =
+LIBS = -lcap
LNOUT = -o
EXESUFFICS =
OBJSUFFICS = .o
diff --git a/src/3proxy.c b/src/3proxy.c
index 193b5ed..0e480e0 100644
--- a/src/3proxy.c
+++ b/src/3proxy.c
@@ -18,6 +18,11 @@
#define DEFAULTCONFIG conf.stringtable[25]
#endif
+char *opt_user = NULL;
+char *opt_pidfile = NULL;
+char *opt_conffile = NULL;
+int opt_daemon = 0;
+
typedef int (*MAINFUNC)(int, char**);
pthread_mutex_t bandlim_mutex;
@@ -623,6 +628,14 @@ int start_proxy_thread(struct child * chp){
return 0;
}
+static int h_alt(int argc, unsigned char ** argv)
+ {
+ char *cmd = (char *)argv[0];
+ fprintf(stderr, "ALTLinux 3proxy does not recognize '%s' command.\n", cmd);
+ fprintf(stderr, "Use cmdline instead. See README.ALT for details.\n");
+ return 0;
+ }
+
static int h_proxy(int argc, unsigned char ** argv){
struct child ch;
@@ -774,9 +787,8 @@ static int h_service(int argc, unsigned char **argv){
}
static int h_daemon(int argc, unsigned char **argv){
- if(!conf.demon)daemonize();
- conf.demon = 1;
- return 0;
+ opt_daemon = 1;
+ return 0;
}
static int h_config(int argc, unsigned char **argv){
@@ -1652,9 +1664,9 @@ static int h_chroot(int argc, unsigned char **argv){
struct commands specificcommands[]={
#ifndef _WIN32
- {specificcommands+1, "setuid", h_setuid, 2, 2},
- {specificcommands+2, "setgid", h_setgid, 2, 2},
- {specificcommands+3, "chroot", h_chroot, 2, 2},
+ {specificcommands+1, "setuid", h_alt, 2, 2},
+ {specificcommands+2, "setgid", h_alt, 2, 2},
+ {specificcommands+3, "chroot", h_alt, 2, 2},
#endif
{NULL, "", h_noop, 1, 0}
};
@@ -1691,7 +1703,7 @@ struct commands commandhandlers[]={
{commandhandlers+29, "nsrecord", h_nsrecord, 3, 3},
{commandhandlers+30, "dialer", h_dialer, 2, 2},
{commandhandlers+31, "system", h_system, 2, 2},
- {commandhandlers+32, "pidfile", h_pidfile, 2, 2},
+ {commandhandlers+32, "pidfile", h_alt, 2, 2},
{commandhandlers+33, "monitor", h_monitor, 2, 2},
{commandhandlers+34, "parent", h_parent, 5, 0},
{commandhandlers+35, "allow", h_ace, 1, 0},
@@ -1776,6 +1788,48 @@ int readconfig(FILE * fp){
}
+void usage()
+ {
+ fprintf(stderr, "Usage: 3proxy [-c conffile] [-u username/uid] [-d] [-p pidfile]\n");
+ fprintf(stderr, "\n%s %s\n%s\n", conf.stringtable[2], conf.stringtable[3], copyright);
+ }
+
+static int parse_cmdline(int argc, char *argv[])
+ {
+ int opt = 0;
+ while(1)
+ {
+ opt = getopt(argc, argv, "du:c:p:");
+ switch(opt)
+ {
+ case 'd': // daemonize
+ opt_daemon = 1;
+ break;
+
+ case 'u': // username
+ opt_user = strdup(optarg);
+ break;
+
+ case 'c': // config file
+ opt_conffile = strdup(optarg);
+ break;
+
+ case 'p': // pidfile
+ opt_pidfile = strdup(optarg);
+ break;
+
+ case ':': // option value not found
+ case '?': // option or value not found
+ usage();
+ return -1;
+
+ }
+
+ if(opt == -1)
+ return 0;
+ }
+ }
+
int main(int argc, char * argv[]) {
@@ -1892,27 +1946,61 @@ int main(int argc, char * argv[]) {
service = 1;
argc = 2;
}
-#endif
conf.conffile = mystrdup((argc==2)?argv[1]:(char*)DEFAULTCONFIG);
+#else
+ parse_cmdline(argc, argv);
+ conf.conffile = opt_conffile ? opt_conffile : DEFAULTCONFIG;
+
+ FILE *pidfile = NULL;
+ if(opt_pidfile)
+ {
+ pidfile = fopen(opt_pidfile, "w");
+ if(!pidfile)
+ {
+ fprintf(stderr, "open pidfile %s failed", opt_pidfile);
+ exit(1);
+ }
+ }
+
+ /* chroot */
+ if(chrootp){
+ char *p;
+ if(chroot(chrootp)) {
+ fprintf(stderr, "Unable to chroot %s", chrootp);
+ return(1);
+ }
+
+ /* strip slashes */
+ p = chrootp + strlen((char *)chrootp) ;
+ while (p > chrootp && p[-1] == '/'){
+ p--;
+ *p = 0;
+ }
+ }
+
+ /* setuid with cap_net_bind */
+ if(opt_user)
+ drop_root(opt_user);
+
+#endif
if(conf.conffile && *conf.conffile != '-') {
fp = confopen();
#ifndef _WIN32
if(!fp) fp = stdin;
#endif
}
+#ifdef _WIN32
if(argc > 2 || !(fp)) {
fprintf(stderr, "Usage: %s [conffile]\n", argv[0]);
-#ifdef _WIN32
fprintf(stderr, "\n\t%s --install [conffile]\n\tto install as service\n"
"\n\t%s --remove\n\tto remove service\n", argv[0], argv[0]);
-#else
fprintf(stderr, "\n if conffile is missing, configuration is expected from stdin\n");
-#endif
fprintf(stderr, "\n%s %s\n%s\n", conf.stringtable[2], conf.stringtable[3], copyright);
return 1;
}
+#endif
pthread_mutex_init(&bandlim_mutex, NULL);
pthread_mutex_init(&hash_mutex, NULL);
@@ -1943,8 +2031,21 @@ int main(int argc, char * argv[]) {
#else
+ if(opt_daemon)
+ {
+ daemonize();
+ conf.demon = 1;
+ }
+
+ if(opt_pidfile)
+ {
+ fprintf(pidfile, "%d\n", getpid());
+ fclose(pidfile);
+ }
+
signal(SIGCONT, mysigpause);
signal(SIGTERM, mysigterm);
+ signal(SIGINT, mysigterm);
signal(SIGUSR1, mysigusr1);
signal(SIGPIPE, SIG_IGN);
cyclestep();
diff --git a/src/proxy.h b/src/proxy.h
index d26b16b..15ec48d 100644
--- a/src/proxy.h
+++ b/src/proxy.h
@@ -305,5 +305,7 @@ extern struct commands commandhandlers[];
#define WEBBANNERS 35
+void drop_root(const char *username);
+
#endif
diff --git a/src/proxymain.c b/src/proxymain.c
index ab5b543..548c381 100644
--- a/src/proxymain.c
+++ b/src/proxymain.c
@@ -16,6 +16,12 @@
extern int haveerror;
#endif
+#include <unistd.h>
+#include <sys/capability.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/prctl.h>
int MODULEMAINFUNC (int argc, char** argv){
@@ -38,6 +44,7 @@ int MODULEMAINFUNC (int argc, char** argv){
#ifndef _WIN32
" -I inetd mode (requires real socket, doesn't work with TTY)\n"
" -l@IDENT log to syslog IDENT\n"
+ " -Uuser user name for changing to\n";
#endif
" -d go to background (daemon)\n"
#else
@@ -99,6 +106,13 @@ int MODULEMAINFUNC (int argc, char** argv){
for (i=1; i<argc; i++) {
if(*argv[i]=='-') {
switch(argv[i][1]) {
+#ifdef STDMAIN
+#ifndef _WIN32
+ case 'U':
+ drop_root(argv[i] + 2);
+ break;
+#endif
+#endif
case 'd':
if(!conf.demon)daemonize();
conf.demon = 1;
@@ -448,6 +462,84 @@ int MODULEMAINFUNC (int argc, char** argv){
}
+void drop_root(const char *username)
+ {
+ struct passwd *pw;
+ uid_t uid;
+ gid_t gid;
+
+ if(!username) return;
+ if (!*username) return;
+
+ int is_num = 1;
+
+ for(char *ptr = (char *)username; *ptr; ptr++)
+ if(!(is_num = isdigit(*ptr)))
+ break;
+
+ if(is_num)
+ uid = atoi(username);
+ else
+ {
+ if (!(pw = getpwnam(username)))
+ {
+ fprintf(stderr, "Failed to lower privileges: getpwnam: %s", username);
+ exit(1);
+ }
+
+ uid = pw->pw_uid;
+ gid = pw->pw_gid;
+ }
+
+ if(uid == 0) // setuid to root, nonsense but allowed
+ return;
+
+// tzset();
+
+ if(initgroups(username, gid))
+ {
+ fprintf(stderr, "Failed to lower privileges: initgroups: %s/%u", username, (unsigned) gid);
+ exit(1);
+ }
+
+ endpwent();
+
+ if (setgid(gid))
+ {
+ fprintf(stderr, "Failed to lower privileges: setgid: %s/%u", username, (unsigned) gid);
+ exit(1);
+ }
+
+ if (prctl(PR_SET_KEEPCAPS, 1))
+ {
+ fprintf(stderr, "Failed to lower privileges: prctl");
+ exit(1);
+ }
+
+ if (setreuid(uid, uid))
+ {
+ fprintf(stderr, "Failed to lower privileges: setreuid: %s/%u",
+ username, (unsigned) uid);
+ exit(1);
+ }
+
+ cap_t caps = cap_from_text("cap_net_bind_service=ep");
+
+ if (!caps)
+ {
+ fprintf(stderr, "Failed to lower privileges: cap_from_text");
+ exit(1);
+ }
+
+ if (cap_set_proc(caps) < 0)
+ {
+ fprintf(stderr, "Failed to lower privileges: cap_set_proc");
+ exit(1);
+ }
+
+ cap_free(caps);
+ }
+
void srvinit(struct srvparam * srv, struct clientparam *param){
memset(srv, 0, sizeof(struct srvparam));