File: 13-upstream-chroot-user-opts.patch

package info (click to toggle)
httptunnel 3.3%2Bdfsg-4
  • links: PTS
  • area: main
  • in suites: bookworm, bullseye, buster, stretch
  • size: 924 kB
  • ctags: 457
  • sloc: ansic: 4,707; sh: 330; makefile: 26
file content (207 lines) | stat: -rw-r--r-- 6,033 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
Description: Add --chroot and --user options
 This allows chrooting the server, and running it with a different uid
 & gid.
Origin: upstream
Bug-Debian: https://bugs.debian.org/477401
Forwarded: not-needed

---
Origin: <vendor|upstream|other>, <url of original patch>

--- httptunnel-3.3+dfsg.orig/ChangeLog
+++ httptunnel-3.3+dfsg/ChangeLog
@@ -1,3 +1,9 @@
+2003-01-10  Lars Brinkhoff  <lars@nocrew.org>
+
+	From Marco Michelino <michelinux@tin.it>:
+	* hts.c (usage, parse_arguments, main): add --chroot and --user
+	options.
+
 2001-06-12  lars brinkhoff  <lars@nocrew.org>
 
 	* tunnel.h: Improved documentation for tunnel programming
--- httptunnel-3.3+dfsg.orig/hts.c
+++ httptunnel-3.3+dfsg/hts.c
@@ -13,6 +13,10 @@ two-way data path tunneled in HTTP reque
 #include <signal.h>
 #include <sys/poll_.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
 
 #include "common.h"
 
@@ -31,6 +35,8 @@ typedef struct
   int strict_content_length;
   int keep_alive;
   int max_connection_age;
+  char *root;
+  char *user;
 } Arguments;
 
 int debug_level = 0;
@@ -61,9 +67,11 @@ usage (FILE *f, const char *me)
 #endif
 "  -M, --max-connection-age SEC   maximum time a connection will stay\n"
 "                                 open is SEC seconds (default is %d)\n"
+"  -r, --chroot ROOT              change root to ROOT\n"
 "  -s, --stdin-stdout             use stdin/stdout for communication\n"
 "                                 (implies --no-daemon)\n"
 "  -S, --strict-content-length    always write Content-Length bytes in requests\n"
+"  -u, --user USER                change user to USER\n"
 "  -V, --version                  output version information and exit\n"
 "  -w, --no-daemon                don't fork into the background\n"
 "  -p, --pid-file LOCATION        write a PID file to LOCATION\n"
@@ -93,6 +101,8 @@ parse_arguments (int argc, char **argv,
   arg->strict_content_length = FALSE;
   arg->keep_alive = DEFAULT_KEEP_ALIVE;
   arg->max_connection_age = DEFAULT_CONNECTION_MAX_TIME;
+  arg->user = NULL;
+  arg->root = NULL;
   
   for (;;)
     {
@@ -100,24 +110,26 @@ parse_arguments (int argc, char **argv,
       static struct option long_options[] =
       {
 	{ "help", no_argument, 0, 'h' },
-	{ "stdin-stdout", no_argument, 0, 's' },
-	{ "strict-content-length", no_argument, 0, 'S' },
 	{ "version", no_argument, 0, 'V' },
 	{ "no-daemon", no_argument, 0, 'w' },
+	{ "user", required_argument, 0, 'u' },
 #ifdef DEBUG_MODE
 	{ "debug", required_argument, 0, 'D' },
 	{ "logfile", required_argument, 0, 'l' },
 #endif
+	{ "chroot", required_argument, 0, 'r' },
+	{ "stdin-stdout", no_argument, 0, 's' },
 	{ "device", required_argument, 0, 'd' },
 	{ "pid-file", required_argument, 0, 'p' },
 	{ "keep-alive", required_argument, 0, 'k' },
 	{ "forward-port", required_argument, 0, 'F' },
 	{ "content-length", required_argument, 0, 'c' },
+	{ "strict-content-length", no_argument, 0, 'S' },
 	{ "max-connection-age", required_argument, 0, 'M' },
 	{ 0, 0, 0, 0 }
       };
 
-      static const char *short_options = "c:d:F:hk:M:p:sSVw"
+      static const char *short_options = "c:d:F:hk:M:p:sSVwu:r:"
 #ifdef DEBUG_MODE
 	"D:l:"
 #endif
@@ -187,6 +199,10 @@ parse_arguments (int argc, char **argv,
 	  arg->max_connection_age = atoi (optarg);
 	  break;
 
+	case 'r':
+	  arg->root = optarg;
+	  break;
+
 	case 's':
 	  arg->use_std=TRUE;
 	  arg->use_daemon=FALSE;
@@ -196,6 +212,10 @@ parse_arguments (int argc, char **argv,
 	  arg->strict_content_length = TRUE;
 	  break;
 
+	case 'u':
+	  arg->user = optarg;
+	  break;
+
 	case 'V':
 	  printf ("hts (%s) %s\n", PACKAGE, VERSION);
 	  exit (0);
@@ -278,6 +298,8 @@ main (int argc, char **argv)
   Arguments arg;
   Tunnel *tunnel;
   FILE *pid_file;
+  uid_t uid;
+  gid_t gid;
 
   parse_arguments (argc, argv, &arg);
 
@@ -307,11 +329,13 @@ main (int argc, char **argv)
   log_notice ("  debug_level = %d", debug_level);
   log_notice ("  pid_filename = %s",
 	      arg.pid_filename ? arg.pid_filename : "(null)");
+  log_notice ("  chroot = %s", arg.root ? arg.root : "(null)");
+  log_notice ("  user = %s", arg.user ? arg.user : "(null)");
 
   tunnel = tunnel_new_server (arg.host, arg.port, arg.content_length);
   if (tunnel == NULL)
     {
-      log_error ("couldn't create tunnel", argv[0]);
+      log_error ("couldn't create tunnel");
       log_exit (1);
     }
 
@@ -353,6 +377,65 @@ main (int argc, char **argv)
          }
      }
 
+  /* If requested to change user, get new uid and gid before chroot so we */
+  /* don't need /etc/passwd & company in the chroot jail */
+  if (arg.user)
+    {
+      struct passwd *pwd = getpwnam (arg.user);
+      if (pwd == NULL)
+        {
+          log_error ("couldn't find user");
+          log_exit (1);
+	}
+      uid = pwd->pw_uid;
+      gid = pwd->pw_gid;
+      if (setgroups (0, (const gid_t *)0) < 0)
+        {
+          log_error ("couldn't drop supplementary groups privileges");
+          log_exit (1);
+	}
+      if (setgid (gid) < 0)
+        {
+          log_error ("couldn't change primary group");
+          log_exit (1);
+	}
+      if (initgroups (arg.user, gid) < 0)
+        {
+	  /* non critical error */
+          log_error ("couldn't add supplementary groups");
+	}
+    }
+
+  /* Change root if requested */
+  if (arg.root)
+    {
+      if (chroot (arg.root) < 0)
+        {
+          log_error ("couldn't change root");
+          log_exit (1);
+	}
+      if (chdir ("/") < 0)
+        {
+          log_error ("couldn't change dir to new root");
+          log_exit (1);
+	}
+      if (fclose (stdin) || fclose (stdout) || fclose (stderr))
+        {
+          log_error ("couldn't close stdin, stdout and/or stderr");
+          log_exit (1);
+	}
+    }
+
+  /* Change user if requested */
+  if (arg.user)
+    {
+      if (setuid (uid) < 0)
+        {
+          log_error ("couldn't change user");
+          log_exit (1);
+	}
+    }
+
   for (;;)
     {
       time_t last_tunnel_write;