Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37814020
en ru br
Репозитории 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
www.altlinux.org/Changes

Группа :: Система/Серверы
Пакет: 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));
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin