1 |
slords |
1.1 |
diff -u stunnel-3.22/client.c stunnel-3.22-sg/client.c |
2 |
|
|
--- stunnel-3.22/client.c Sun Dec 23 14:41:32 2001 |
3 |
|
|
+++ stunnel-3.22-sg/client.c Wed May 29 02:51:34 2002 |
4 |
|
|
@@ -220,7 +220,9 @@ |
5 |
|
|
else |
6 |
|
|
c->ip=0; |
7 |
|
|
/* Setup c->remote_fd, now */ |
8 |
|
|
- if(options.option&OPT_REMOTE) |
9 |
|
|
+ if (options.option&OPT_FDS) |
10 |
|
|
+ fd=options.use_fd; |
11 |
|
|
+ else if(options.option&OPT_REMOTE) |
12 |
|
|
fd=connect_remote(c); |
13 |
|
|
else /* NOT in remote mode */ |
14 |
|
|
fd=connect_local(c); |
15 |
|
|
@@ -845,9 +847,9 @@ |
16 |
|
|
|
17 |
|
|
int fdprintf(int fd, char *format, ...) { |
18 |
|
|
va_list arglist; |
19 |
|
|
- char line[STRLEN], logline[STRLEN]; |
20 |
|
|
+ char line[STRLEN]; |
21 |
|
|
+ int len; |
22 |
|
|
char crlf[]="\r\n"; |
23 |
|
|
- int len, ptr, written, towrite; |
24 |
|
|
|
25 |
|
|
va_start(arglist, format); |
26 |
|
|
#ifdef HAVE_VSNPRINTF |
27 |
|
|
@@ -858,58 +860,87 @@ |
28 |
|
|
va_end(arglist); |
29 |
|
|
safeconcat(line, crlf); |
30 |
|
|
len+=2; |
31 |
|
|
- for(ptr=0, towrite=len; towrite>0; ptr+=written, towrite-=written) { |
32 |
|
|
- switch(waitforsocket(fd, 1 /* write */)) { |
33 |
|
|
- case -1: /* Error */ |
34 |
|
|
- sockerror("select"); |
35 |
|
|
- return -1; |
36 |
|
|
- case 0: /* Timeout */ |
37 |
|
|
- log(LOG_ERR, "Select timeout (fdprintf)"); |
38 |
|
|
- return -1; |
39 |
|
|
- } |
40 |
|
|
- written=writesocket(fd, line+ptr, towrite); |
41 |
|
|
- if(written<0) { |
42 |
|
|
- sockerror("writesocket (fdprintf)"); |
43 |
|
|
- return -1; |
44 |
|
|
- } |
45 |
|
|
- } |
46 |
|
|
- safecopy(logline, line); |
47 |
|
|
- safestring(logline); |
48 |
|
|
- log(LOG_DEBUG, " -> %s", logline); |
49 |
|
|
- return len; |
50 |
|
|
+ if (fdwrite(fd,line,len) < 0) |
51 |
|
|
+ return -1; |
52 |
|
|
+ else |
53 |
|
|
+ return len; |
54 |
|
|
} |
55 |
|
|
|
56 |
|
|
-int fdscanf(int fd, char *format, char *buffer) { |
57 |
|
|
- char line[STRLEN], logline[STRLEN]; |
58 |
|
|
+int fdputs(int fd, char *line) { |
59 |
|
|
+ char crlf[]="\r\n"; |
60 |
|
|
+ |
61 |
|
|
+ if (fdwrite(fd, line, strlen(line)) < 0) |
62 |
|
|
+ return -1; |
63 |
|
|
+ return fdwrite(fd,crlf,strlen(crlf)); |
64 |
|
|
+} |
65 |
|
|
+ |
66 |
|
|
+int fdwrite(int fd, char *buffer, int len) { |
67 |
|
|
+ char logline[STRLEN]; |
68 |
|
|
+ int ptr, written, towrite; |
69 |
|
|
+ |
70 |
|
|
+ for(ptr=0, towrite=len; towrite>0; ptr+=written, towrite-=written) { |
71 |
|
|
+ switch(waitforsocket(fd, 1 /* write */)) { |
72 |
|
|
+ case -1: /* Error */ |
73 |
|
|
+ sockerror("select"); |
74 |
|
|
+ return -1; |
75 |
|
|
+ case 0: /* Timeout */ |
76 |
|
|
+ log(LOG_ERR, "Select timeout (fdwrite)"); |
77 |
|
|
+ return -1; |
78 |
|
|
+ } |
79 |
|
|
+ |
80 |
|
|
+ written=writesocket(fd, buffer+ptr, towrite); |
81 |
|
|
+ if(written<0) { |
82 |
|
|
+ sockerror("writesocket (fdwrite)"); |
83 |
|
|
+ return -1; |
84 |
|
|
+ } |
85 |
|
|
+ } |
86 |
|
|
+ safecopy(logline, buffer); |
87 |
|
|
+ safestring(logline); |
88 |
|
|
+ log(LOG_DEBUG, " -> %s", logline); |
89 |
|
|
+ return 0; |
90 |
|
|
+} |
91 |
|
|
+ |
92 |
|
|
+int fdgets(int fd, char *buffer) { |
93 |
|
|
+ char logline[STRLEN]; |
94 |
|
|
int ptr; |
95 |
|
|
|
96 |
|
|
- for(ptr=0; ptr<STRLEN-1; ptr++) { |
97 |
|
|
+ for(ptr=0; ptr<STRLEN-1;) { |
98 |
|
|
switch(waitforsocket(fd, 0 /* read */)) { |
99 |
|
|
case -1: /* Error */ |
100 |
|
|
sockerror("select"); |
101 |
|
|
return -1; |
102 |
|
|
case 0: /* Timeout */ |
103 |
|
|
- log(LOG_ERR, "Select timeout (fdscanf)"); |
104 |
|
|
+ log(LOG_ERR, "Select timeout (fdgets)"); |
105 |
|
|
return -1; |
106 |
|
|
} |
107 |
|
|
- switch(readsocket(fd, line+ptr, 1)) { |
108 |
|
|
+ switch(readsocket(fd, buffer+ptr, 1)) { |
109 |
|
|
case -1: /* error */ |
110 |
|
|
- sockerror("readsocket (fdscanf)"); |
111 |
|
|
+ sockerror("readsocket (fdgets)"); |
112 |
|
|
return -1; |
113 |
|
|
case 0: /* EOF */ |
114 |
|
|
- log(LOG_ERR, "Unexpected socket close (fdscanf)"); |
115 |
|
|
+ log(LOG_ERR, "Unexpected socket close (fdgets)"); |
116 |
|
|
return -1; |
117 |
|
|
} |
118 |
|
|
- if(line[ptr]=='\r') |
119 |
|
|
+ if(buffer[ptr]=='\r') |
120 |
|
|
continue; |
121 |
|
|
- if(line[ptr]=='\n') |
122 |
|
|
+ if(buffer[ptr]=='\n') |
123 |
|
|
break; |
124 |
|
|
+ ptr++; |
125 |
|
|
} |
126 |
|
|
- line[ptr]='\0'; |
127 |
|
|
- safecopy(logline, line); |
128 |
|
|
+ buffer[ptr]='\0'; |
129 |
|
|
+ safecopy(logline, buffer); |
130 |
|
|
safestring(logline); |
131 |
|
|
log(LOG_DEBUG, " <- %s", logline); |
132 |
|
|
- return sscanf(line, format, buffer); |
133 |
|
|
+ return 0; |
134 |
|
|
+} |
135 |
|
|
+ |
136 |
|
|
+int fdscanf(int fd, char *format, char *buffer) { |
137 |
|
|
+ char line[STRLEN]; |
138 |
|
|
+ |
139 |
|
|
+ if (fdgets(fd, line) < 0) |
140 |
|
|
+ return -1; |
141 |
|
|
+ |
142 |
|
|
+ return sscanf(line, format, buffer); |
143 |
|
|
} |
144 |
|
|
|
145 |
|
|
static int waitforsocket(int fd, int dir) { |
146 |
|
|
diff -u stunnel-3.22/options.c stunnel-3.22-sg/options.c |
147 |
|
|
--- stunnel-3.22/options.c Sun Dec 23 15:08:51 2001 |
148 |
|
|
+++ stunnel-3.22-sg/options.c Wed May 15 03:55:41 2002 |
149 |
|
|
@@ -84,8 +84,13 @@ |
150 |
|
|
options.random_bytes=RANDOM_BYTES; |
151 |
|
|
options.output_file=NULL; |
152 |
|
|
options.local_ip=NULL; |
153 |
|
|
+ options.chroot_dir=NULL; |
154 |
|
|
opterr=0; |
155 |
|
|
- while ((c = getopt(argc, argv, "A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:O:E:R:WB:VP:S:o:I:")) != EOF) |
156 |
|
|
+ while ((c = getopt(argc, argv, "A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:O:E:R:WB:VP:S:o:I:" |
157 |
|
|
+ "F:" |
158 |
|
|
+ "/:" |
159 |
|
|
+ "i" |
160 |
|
|
+ )) != EOF) |
161 |
|
|
switch (c) { |
162 |
|
|
case 'A': |
163 |
|
|
safecopy(options.cert_file,optarg); |
164 |
|
|
@@ -140,6 +145,16 @@ |
165 |
|
|
case 'f': |
166 |
|
|
options.option|=OPT_FOREGROUND; |
167 |
|
|
break; |
168 |
|
|
+ case 'F': |
169 |
|
|
+ options.option|=OPT_FDS; |
170 |
|
|
+ options.use_fd=atoi(optarg); |
171 |
|
|
+ break; |
172 |
|
|
+ case 'i': |
173 |
|
|
+ options.option|=OPT_SUID_FIRST; |
174 |
|
|
+ break; |
175 |
|
|
+ case '/': |
176 |
|
|
+ options.chroot_dir=optarg; |
177 |
|
|
+ break; |
178 |
|
|
case 'T': |
179 |
|
|
options.option|=OPT_TRANSPARENT; |
180 |
|
|
break; |
181 |
|
|
@@ -257,8 +272,8 @@ |
182 |
|
|
print_info(); |
183 |
|
|
} |
184 |
|
|
#endif |
185 |
|
|
- if(!(options.option&(OPT_REMOTE|OPT_PROGRAM))) { |
186 |
|
|
- log(LOG_ERR, "Either -r, -l (or -L) option must be used"); |
187 |
|
|
+ if(!(options.option&(OPT_REMOTE|OPT_PROGRAM|OPT_FDS))) { |
188 |
|
|
+ log(LOG_ERR, "Either -r, -l (or -L), or -F option must be used"); |
189 |
|
|
print_info(); |
190 |
|
|
} |
191 |
|
|
if((options.option&OPT_REMOTE) && (options.option&OPT_PROGRAM) |
192 |
|
|
@@ -331,9 +346,12 @@ |
193 |
|
|
"[-S sources] " |
194 |
|
|
"[-t timeout] " |
195 |
|
|
"\n\t" |
196 |
|
|
- "[-u ident_username] " |
197 |
|
|
"[-s setuid_user] " |
198 |
|
|
"[-g setgid_group] " |
199 |
|
|
+ "[-i] " |
200 |
|
|
+ "[-/ chroot-dir] " |
201 |
|
|
+ "\n\t" |
202 |
|
|
+ "[-u ident_username] " |
203 |
|
|
"[-n protocol]" |
204 |
|
|
"\n\t" |
205 |
|
|
"[-R randfile] " |
206 |
|
|
@@ -345,7 +363,7 @@ |
207 |
|
|
#ifndef USE_WIN32 |
208 |
|
|
"[-P { dir/ | filename | none } ] " |
209 |
|
|
"\n\t[-d [host:]port [-f] ] " |
210 |
|
|
- "\n\t[-r [host:]port | { -l | -L } program [-- args] ] " |
211 |
|
|
+ "\n\t[-r [host:]port | { -l | -L } program [-- args] | -F fd-num ] " |
212 |
|
|
#else |
213 |
|
|
"\n\t-d [host:]port -r [host:]port" |
214 |
|
|
#endif |
215 |
|
|
@@ -360,6 +378,7 @@ |
216 |
|
|
#ifndef USE_WIN32 |
217 |
|
|
"\n -l program\texecute local inetd-type program" |
218 |
|
|
"\n -L program\topen local pty and execute program" |
219 |
|
|
+ "\n -F fd-num\tuse the already-open socket on file descriptor fd-num" |
220 |
|
|
#endif |
221 |
|
|
"\n" |
222 |
|
|
"\n -c\t\tclient mode (remote service uses SSL)" |
223 |
|
|
@@ -388,6 +407,8 @@ |
224 |
|
|
#ifndef USE_WIN32 |
225 |
|
|
"\n -s username\tsetuid() to username in daemon mode" |
226 |
|
|
"\n -g groupname\tsetgid() to groupname in daemon mode" |
227 |
|
|
+ "\n -i\t\tsetuid() and/or setgid() immediately" |
228 |
|
|
+ "\n -/ chroot-dir\tchroot() to chroot-dir immediately after starting" |
229 |
|
|
"\n -P arg\tspecify pid file { dir/ | filename | none }" |
230 |
|
|
#endif |
231 |
|
|
"\n -C list\tset permitted SSL ciphers" |
232 |
|
|
diff -u stunnel-3.22/protocol.c stunnel-3.22-sg/protocol.c |
233 |
|
|
--- stunnel-3.22/protocol.c Thu Dec 20 02:52:37 2001 |
234 |
|
|
+++ stunnel-3.22-sg/protocol.c Wed May 29 03:33:35 2002 |
235 |
|
|
@@ -36,9 +36,11 @@ |
236 |
|
|
static int smb_client(CLI *); |
237 |
|
|
static int smb_server(CLI *); |
238 |
|
|
static int smtp_client(CLI *); |
239 |
|
|
-static int smtp_server(CLI *); |
240 |
|
|
+static int smtp_server(CLI *, int allow_downgrade); |
241 |
|
|
static int pop3_client(CLI *); |
242 |
|
|
-static int pop3_server(CLI *); |
243 |
|
|
+static int pop3_server(CLI *, int allow_downgrade); |
244 |
|
|
+static int imap_client(CLI *); |
245 |
|
|
+static int imap_server(CLI *, int allow_downgrade); |
246 |
|
|
static int nntp_client(CLI *); |
247 |
|
|
static int nntp_server(CLI *); |
248 |
|
|
static int telnet_client(CLI *); |
249 |
|
|
@@ -58,17 +60,35 @@ |
250 |
|
|
else |
251 |
|
|
return smb_server(c); |
252 |
|
|
} |
253 |
|
|
- if(!strcmp(protocol, "smtp")) { |
254 |
|
|
+ if(!strncmp(protocol, "smtp",4)) { |
255 |
|
|
if(client) |
256 |
|
|
return smtp_client(c); |
257 |
|
|
- else |
258 |
|
|
- return smtp_server(c); |
259 |
|
|
+ else { |
260 |
|
|
+ if (protocol[4] == '-') |
261 |
|
|
+ return smtp_server(c,1); |
262 |
|
|
+ else if (protocol[4] == '\0') |
263 |
|
|
+ return smtp_server(c,0); |
264 |
|
|
+ } |
265 |
|
|
} |
266 |
|
|
- if(!strcmp(protocol, "pop3")) { |
267 |
|
|
+ if(!strncmp(protocol, "pop3",4)) { |
268 |
|
|
if(client) |
269 |
|
|
return pop3_client(c); |
270 |
|
|
- else |
271 |
|
|
- return pop3_server(c); |
272 |
|
|
+ else { |
273 |
|
|
+ if (protocol[4] == '-') |
274 |
|
|
+ return pop3_server(c,1); |
275 |
|
|
+ else if (protocol[4] == '\0') |
276 |
|
|
+ return pop3_server(c,0); |
277 |
|
|
+ } |
278 |
|
|
+ } |
279 |
|
|
+ if(!strncmp(protocol, "imap",4)) { |
280 |
|
|
+ if(client) |
281 |
|
|
+ return imap_client(c); |
282 |
|
|
+ else { |
283 |
|
|
+ if (protocol[4] == '-') |
284 |
|
|
+ return imap_server(c,1); |
285 |
|
|
+ else if (protocol[4] == '\0') |
286 |
|
|
+ return imap_server(c,0); |
287 |
|
|
+ } |
288 |
|
|
} |
289 |
|
|
if(!strcmp(protocol, "nntp")) { |
290 |
|
|
if(client) |
291 |
|
|
@@ -131,33 +151,181 @@ |
292 |
|
|
return 0; |
293 |
|
|
} |
294 |
|
|
|
295 |
|
|
-static int smtp_server(CLI *c) { |
296 |
|
|
+#define PP_BUFSIZE 8192 |
297 |
|
|
+static int plaintext_proxy(CLI *c) |
298 |
|
|
+{ |
299 |
|
|
+ fd_set rd_set, wr_set; |
300 |
|
|
+ char rbuf[PP_BUFSIZE]; |
301 |
|
|
+ int rbufend,rdone; |
302 |
|
|
+ char lbuf[PP_BUFSIZE]; |
303 |
|
|
+ int lbufend,ldone; |
304 |
|
|
+ struct timeval tv; |
305 |
|
|
+ int ready; |
306 |
|
|
+ int fdmax; |
307 |
|
|
+ int howmuch, sofar; |
308 |
|
|
+ |
309 |
|
|
+ fdmax = c->remote_fd; |
310 |
|
|
+ if (c->local_wfd > fdmax) |
311 |
|
|
+ fdmax = c->local_wfd; |
312 |
|
|
+ if (c->local_rfd > fdmax) |
313 |
|
|
+ fdmax = c->local_rfd; |
314 |
|
|
+ fdmax++; |
315 |
|
|
+ |
316 |
|
|
+ lbufend = rbufend = 0; |
317 |
|
|
+ rdone = ldone = 0; |
318 |
|
|
+ |
319 |
|
|
+ tv.tv_sec = 86400; |
320 |
|
|
+ tv.tv_usec = 0; |
321 |
|
|
+ while( !( (rdone || ldone) && (!rbufend && !lbufend) ) ) { |
322 |
|
|
+ log(LOG_DEBUG,"rdone=%d, ldone=%d, rbufend=%d, lbufend=%d",rdone,ldone,rbufend,lbufend); |
323 |
|
|
+ FD_ZERO(&rd_set); |
324 |
|
|
+ FD_ZERO(&wr_set); |
325 |
|
|
+ if (rbufend) |
326 |
|
|
+ FD_SET((c->local_wfd),&wr_set); |
327 |
|
|
+ else if (!rdone) |
328 |
|
|
+ FD_SET(c->remote_fd,&rd_set); |
329 |
|
|
+ |
330 |
|
|
+ if (lbufend) |
331 |
|
|
+ FD_SET(c->remote_fd,&wr_set); |
332 |
|
|
+ else if (!ldone) |
333 |
|
|
+ FD_SET(c->local_rfd,&rd_set); |
334 |
|
|
+ |
335 |
|
|
+ do { /* Skip "Interrupted system call" errors */ |
336 |
|
|
+ ready=select(fdmax, &rd_set, &wr_set, NULL, &tv); |
337 |
|
|
+ } while(ready<0 && get_last_socket_error()==EINTR); |
338 |
|
|
+ |
339 |
|
|
+ if(ready<0) { /* Break the connection for others */ |
340 |
|
|
+ sockerror("select"); |
341 |
|
|
+ c->error=1; |
342 |
|
|
+ return 1; |
343 |
|
|
+ } |
344 |
|
|
+ if(!ready) { /* Timeout */ |
345 |
|
|
+ log(LOG_DEBUG, "select timeout - connection reset"); |
346 |
|
|
+ c->error=1; |
347 |
|
|
+ return 1; |
348 |
|
|
+ } |
349 |
|
|
+ |
350 |
|
|
+ if (lbufend > 0) { |
351 |
|
|
+ if (FD_ISSET(c->remote_fd,&wr_set)) |
352 |
|
|
+ { |
353 |
|
|
+ sofar = 0; |
354 |
|
|
+ while (sofar < lbufend) { |
355 |
|
|
+ if ((howmuch=write(c->remote_fd,lbuf+sofar,lbufend-sofar)) < 0) { |
356 |
|
|
+ sockerror("write"); |
357 |
|
|
+ c->error=1; |
358 |
|
|
+ return 1; |
359 |
|
|
+ } |
360 |
|
|
+ sofar += howmuch; |
361 |
|
|
+ } |
362 |
|
|
+ lbufend = 0; |
363 |
|
|
+ } |
364 |
|
|
+ } else { |
365 |
|
|
+ if (FD_ISSET(c->local_rfd,&rd_set)) { |
366 |
|
|
+ if ( (lbufend = read(c->local_rfd,lbuf,PP_BUFSIZE)) < 0) { |
367 |
|
|
+ sockerror("read"); |
368 |
|
|
+ c->error = 1; |
369 |
|
|
+ return 1; |
370 |
|
|
+ } |
371 |
|
|
+ if (lbufend == 0) /* EOF */ |
372 |
|
|
+ { |
373 |
|
|
+ log(LOG_DEBUG,"EOF reading from local"); |
374 |
|
|
+ ldone=1; |
375 |
|
|
+ } |
376 |
|
|
+ } |
377 |
|
|
+ } |
378 |
|
|
+ |
379 |
|
|
+ if (rbufend > 0) { |
380 |
|
|
+ if (FD_ISSET(c->local_wfd, &wr_set)) { |
381 |
|
|
+ sofar = 0; |
382 |
|
|
+ while (sofar < rbufend) { |
383 |
|
|
+ if ( (howmuch = write(c->local_wfd, rbuf + sofar, rbufend - sofar)) < 0) { |
384 |
|
|
+ sockerror("write"); |
385 |
|
|
+ c->error=1; |
386 |
|
|
+ return 1; |
387 |
|
|
+ } |
388 |
|
|
+ sofar += howmuch; |
389 |
|
|
+ } |
390 |
|
|
+ rbufend = 0; |
391 |
|
|
+ } |
392 |
|
|
+ } else { |
393 |
|
|
+ if (FD_ISSET(c->remote_fd,&rd_set)) { |
394 |
|
|
+ if ( (rbufend = read(c->remote_fd,rbuf,PP_BUFSIZE)) < 0) { |
395 |
|
|
+ sockerror("read"); |
396 |
|
|
+ c->error = 1; |
397 |
|
|
+ return 1; |
398 |
|
|
+ } |
399 |
|
|
+ if (rbufend == 0) /* EOF */ { |
400 |
|
|
+ log(LOG_DEBUG,"EOF reading from remote"); |
401 |
|
|
+ rdone=1; |
402 |
|
|
+ } |
403 |
|
|
+ } |
404 |
|
|
+ } |
405 |
|
|
+ } |
406 |
|
|
+ |
407 |
|
|
+ log(LOG_DEBUG, "plaintext_proxy finished normally."); |
408 |
|
|
+ return 0; |
409 |
|
|
+} |
410 |
|
|
+ |
411 |
|
|
+static int smtp_server(CLI *c, int allow_downgrade) { |
412 |
|
|
char line[STRLEN]; |
413 |
|
|
+ int read_ret; |
414 |
|
|
|
415 |
|
|
if(RFC2487(c->local_rfd)==0) |
416 |
|
|
return 0; /* Return if RFC 2487 is not used */ |
417 |
|
|
|
418 |
|
|
- if(fdscanf(c->remote_fd, "220%[^\n]", line)!=1) { |
419 |
|
|
+ if(fdscanf(c->remote_fd, "220%[^\r\n]", line)!=1) { |
420 |
|
|
log(LOG_ERR, "Unknown server welcome"); |
421 |
|
|
return -1; |
422 |
|
|
} |
423 |
|
|
if(fdprintf(c->local_wfd, "220%s + stunnel", line)<0) |
424 |
|
|
return -1; |
425 |
|
|
- if(fdscanf(c->local_rfd, "EHLO %[^\n]", line)!=1) { |
426 |
|
|
- log(LOG_ERR, "Unknown client EHLO"); |
427 |
|
|
- return -1; |
428 |
|
|
- } |
429 |
|
|
- if(fdprintf(c->local_wfd, "250-%s Welcome", line)<0) |
430 |
|
|
- return -1; |
431 |
|
|
- if(fdprintf(c->local_wfd, "250 STARTTLS")<0) |
432 |
|
|
- return -1; |
433 |
|
|
- if(fdscanf(c->local_rfd, "STARTTLS", line)<0) { |
434 |
|
|
- log(LOG_ERR, "STARTTLS expected"); |
435 |
|
|
- return -1; |
436 |
|
|
+ |
437 |
|
|
+ /* See if we get an EHLO command */ |
438 |
|
|
+ if (((read_ret=fdgets(c->local_rfd, line)) >= 0) && |
439 |
|
|
+ (strlen(line) >= 4) && |
440 |
|
|
+ (!line[4] || isspace(line[4])) && |
441 |
|
|
+ (strncasecmp(line,"ehlo",4) == 0) ) { |
442 |
|
|
+ if (fdputs(c->remote_fd,line) < 0) |
443 |
|
|
+ return -1; |
444 |
|
|
+ while ( (fdgets(c->remote_fd, line) >= 0) |
445 |
|
|
+ && (line[3] == '-') ) { |
446 |
|
|
+ if (fdputs(c->local_wfd,line) < 0) |
447 |
|
|
+ return -1; |
448 |
|
|
+ } |
449 |
|
|
+ line[3] = '-'; |
450 |
|
|
+ if (fdputs(c->local_wfd,line) < 0) |
451 |
|
|
+ return -1; |
452 |
|
|
+ if (fdputs(c->local_wfd,"250 STARTTLS") < 0) |
453 |
|
|
+ return -1; |
454 |
|
|
+ |
455 |
|
|
+ /* See if we get a STARTTLS command */ |
456 |
|
|
+ if (((read_ret=fdgets(c->local_rfd, line)) >= 0) && |
457 |
|
|
+ (strlen(line) >= 8) && |
458 |
|
|
+ (!line[8] || isspace(line[8])) && |
459 |
|
|
+ (strncasecmp(line,"starttls",8) == 0) ) { |
460 |
|
|
+ if (!line[8]) { |
461 |
|
|
+ /* Technically, we should shut down the SMTP connection and get |
462 |
|
|
+ * a new one, but screw it for now. */ |
463 |
|
|
+ if(fdputs(c->local_wfd, "220 Go ahead") >= 0) |
464 |
|
|
+ return 0; |
465 |
|
|
+ } else { |
466 |
|
|
+ fdputs(c->local_wfd,"501 Syntax error (no parameters allowed; STARTTLS disabled) (#5.5.4)"); |
467 |
|
|
+ return -1; |
468 |
|
|
+ } |
469 |
|
|
+ |
470 |
|
|
+ } |
471 |
|
|
+ } |
472 |
|
|
+ if (read_ret < 0) |
473 |
|
|
+ return -1; |
474 |
|
|
+ if (allow_downgrade) { |
475 |
|
|
+ if (fdputs(c->remote_fd,line) < 0) |
476 |
|
|
+ return -1; |
477 |
|
|
+ exit(plaintext_proxy(c)); |
478 |
|
|
+ } |
479 |
|
|
+ else { |
480 |
|
|
+ fdputs(c->local_wfd,"421 Encryption required; must use STARTTLS"); |
481 |
|
|
+ return -1; |
482 |
|
|
} |
483 |
|
|
- if(fdprintf(c->local_wfd, "220 Go ahead", line)<0) |
484 |
|
|
- return -1; |
485 |
|
|
- return 0; |
486 |
|
|
} |
487 |
|
|
|
488 |
|
|
static int pop3_client(CLI *c) { |
489 |
|
|
@@ -182,31 +350,157 @@ |
490 |
|
|
return 0; |
491 |
|
|
} |
492 |
|
|
|
493 |
|
|
-static int pop3_server(CLI *c) { |
494 |
|
|
+static int pop3_server(CLI *c, int allow_downgrade) { |
495 |
|
|
char line[STRLEN]; |
496 |
|
|
|
497 |
|
|
- if(fdscanf(c->remote_fd, "%[^\n]", line)<0) |
498 |
|
|
- return -1; |
499 |
|
|
+ if(fdscanf(c->remote_fd, "%[^\r\n]", line)<0) |
500 |
|
|
+ return -1; |
501 |
|
|
+ |
502 |
|
|
if(fdprintf(c->local_wfd, "%s + stunnel", line)<0) |
503 |
|
|
return -1; |
504 |
|
|
- if(fdscanf(c->local_rfd, "%[^\n]", line)<0) |
505 |
|
|
+ |
506 |
|
|
+ while(1) { |
507 |
|
|
+ if(fdgets(c->local_rfd, line)<0) |
508 |
|
|
return -1; |
509 |
|
|
- if(!strncmp(line, "CAPA", 4)) { /* Client wants RFC 2449 extensions */ |
510 |
|
|
- if(fdprintf(c->local_wfd, "-ERR Stunnel does not support capabilities")<0) |
511 |
|
|
- return -1; |
512 |
|
|
- if(fdscanf(c->local_rfd, "%[^\n]", line)<0) |
513 |
|
|
- return -1; |
514 |
|
|
+ if(strncasecmp(line, "CAPA", 4) == 0) { /* Client wants RFC 2449 extensions */ |
515 |
|
|
+ fdputs(c->remote_fd,line); |
516 |
|
|
+ if (fdgets(c->remote_fd,line) < 0) |
517 |
|
|
+ return -1; |
518 |
|
|
+ if (line[0] == '+') { |
519 |
|
|
+ if (fdputs(c->local_wfd,line) < 0) |
520 |
|
|
+ return -1; |
521 |
|
|
+ while ( (fdgets(c->remote_fd,line) >= 0) |
522 |
|
|
+ && ( (strlen(line) > 1) || (line[0] != '.') ) ) { |
523 |
|
|
+ if (fdputs(c->local_wfd,line) < 0) |
524 |
|
|
+ return -1; |
525 |
|
|
+ } |
526 |
|
|
+ } else { |
527 |
|
|
+ if (fdputs(c->local_wfd,"+OK Stunnel capability list follows") < 0) |
528 |
|
|
+ return -1; |
529 |
|
|
+ } |
530 |
|
|
+ if (fdputs(c->local_wfd,"STLS") < 0) |
531 |
|
|
+ return -1; |
532 |
|
|
+ if (fdputs(c->local_wfd,".") < 0) |
533 |
|
|
+ return -1; |
534 |
|
|
+ } else if (strncasecmp(line, "STLS", 4) == 0) { |
535 |
|
|
+ if(fdputs(c->local_wfd, "+OK stunnel starting TLS negotiation")<0) |
536 |
|
|
+ return -1; |
537 |
|
|
+ return 0; |
538 |
|
|
+ } |
539 |
|
|
+ else { |
540 |
|
|
+ if (fdputs(c->remote_fd,line) < 0) |
541 |
|
|
+ return -1; |
542 |
|
|
+ if (allow_downgrade) |
543 |
|
|
+ exit(plaintext_proxy(c)); |
544 |
|
|
+ else { |
545 |
|
|
+ fdputs(c->local_wfd,"-Encryption required; must use STLS"); |
546 |
|
|
+ return -1; |
547 |
|
|
+ } |
548 |
|
|
+ } |
549 |
|
|
} |
550 |
|
|
- if(strncmp(line, "STLS", 4)) { |
551 |
|
|
- log(LOG_ERR, "Client does not want TLS"); |
552 |
|
|
+} |
553 |
|
|
+ |
554 |
|
|
+static int imap_client(CLI *c) { |
555 |
|
|
+ char line[STRLEN]; |
556 |
|
|
+ |
557 |
|
|
+ if(fdgets(c->remote_fd, line)<0) |
558 |
|
|
+ return -1; |
559 |
|
|
+ if(strncasecmp(line,"* OK ",4)) { |
560 |
|
|
+ log(LOG_ERR, "Unknown server welcome"); |
561 |
|
|
return -1; |
562 |
|
|
} |
563 |
|
|
- if(fdprintf(c->local_wfd, "+OK Stunnel starts TLS negotiation")<0) |
564 |
|
|
+ if(fdputs(c->local_wfd, line)<0) |
565 |
|
|
return -1; |
566 |
|
|
- |
567 |
|
|
+ if(fdprintf(c->remote_fd, "a STARTTLS")<0) |
568 |
|
|
+ return -1; |
569 |
|
|
+ if(fdgets(c->remote_fd, line)<0) |
570 |
|
|
+ return -1; |
571 |
|
|
+ if(strncasecmp(line,"a OK ",5)) { |
572 |
|
|
+ log(LOG_ERR, "Server does not support TLS"); |
573 |
|
|
+ return -1; |
574 |
|
|
+ } |
575 |
|
|
return 0; |
576 |
|
|
} |
577 |
|
|
|
578 |
|
|
+static int imap_server(CLI *c, int allow_downgrade) { |
579 |
|
|
+ char line[STRLEN]; |
580 |
|
|
+ char procline[STRLEN]; |
581 |
|
|
+ char *tag, *cmd; |
582 |
|
|
+ int do_if_fail = 0; |
583 |
|
|
+ |
584 |
|
|
+ if (fdgets(c->remote_fd,line) < 0) |
585 |
|
|
+ return -1; |
586 |
|
|
+ |
587 |
|
|
+ if(fdprintf(c->local_wfd, "%s + stunnel", line)<0) |
588 |
|
|
+ return -1; |
589 |
|
|
+ |
590 |
|
|
+ while(1) { |
591 |
|
|
+ if(fdgets(c->local_rfd, line)<0) |
592 |
|
|
+ return -1; |
593 |
|
|
+ safecopy(procline, line); |
594 |
|
|
+ tag = procline; |
595 |
|
|
+ if (!(cmd=strchr(procline,' '))) { |
596 |
|
|
+ do_if_fail = 1; |
597 |
|
|
+ break; |
598 |
|
|
+ } |
599 |
|
|
+ *cmd='\0'; |
600 |
|
|
+ cmd++; |
601 |
|
|
+ if(strncasecmp(cmd, "CAPABILITY", 11) == 0) { |
602 |
|
|
+ fdputs(c->remote_fd,line); |
603 |
|
|
+ if (fdgets(c->remote_fd,line) < 0) |
604 |
|
|
+ return -1; |
605 |
|
|
+ if (strncasecmp(line,"* CAPABILITY",12) == 0) { |
606 |
|
|
+ safeconcat(line," STARTTLS"); |
607 |
|
|
+ fdputs(c->local_wfd,line); |
608 |
|
|
+ } else { |
609 |
|
|
+ do_if_fail = 2; |
610 |
|
|
+ break; |
611 |
|
|
+ } |
612 |
|
|
+ if (fdgets(c->remote_fd,line) < 0) |
613 |
|
|
+ return -1; |
614 |
|
|
+ if ( (strncasecmp(line,tag,strlen(tag)) != 0) || |
615 |
|
|
+ (line[strlen(tag)] != ' ') || |
616 |
|
|
+ (strncasecmp(line+strlen(tag)+1,"OK",2) != 0) ) |
617 |
|
|
+ { |
618 |
|
|
+ do_if_fail = 2; |
619 |
|
|
+ break; |
620 |
|
|
+ } |
621 |
|
|
+ if (fdputs(c->local_wfd,line) < 0) |
622 |
|
|
+ return -1; |
623 |
|
|
+ } |
624 |
|
|
+ else if (strncasecmp(cmd, "STARTTLS", 8) == 0) { |
625 |
|
|
+ if (fdwrite(c->local_wfd,tag,strlen(tag)) < 0) |
626 |
|
|
+ return -1; |
627 |
|
|
+ if (fdwrite(c->local_wfd," ",1) < 0) |
628 |
|
|
+ return -1; |
629 |
|
|
+ if (fdputs(c->local_wfd,"OK Begin TLS negotiation now") < 0) |
630 |
|
|
+ return -1; |
631 |
|
|
+ |
632 |
|
|
+ return 0; |
633 |
|
|
+ } else { |
634 |
|
|
+ do_if_fail = 1; |
635 |
|
|
+ break; |
636 |
|
|
+ } |
637 |
|
|
+ } |
638 |
|
|
+ |
639 |
|
|
+ if (allow_downgrade) { |
640 |
|
|
+ if (do_if_fail == 1) { |
641 |
|
|
+ if (fdputs(c->remote_fd,line) < 0) |
642 |
|
|
+ return -1; |
643 |
|
|
+ } else if (do_if_fail == 2) { |
644 |
|
|
+ if (fdputs(c->local_wfd,line) < 0) |
645 |
|
|
+ return -1; |
646 |
|
|
+ } |
647 |
|
|
+ exit(plaintext_proxy(c)); |
648 |
|
|
+ } |
649 |
|
|
+ else { |
650 |
|
|
+ fdputs(c->local_wfd,"-Encryption required; must use STLS"); |
651 |
|
|
+ return -1; |
652 |
|
|
+ } |
653 |
|
|
+ |
654 |
|
|
+} |
655 |
|
|
+ |
656 |
|
|
+ |
657 |
|
|
static int nntp_client(CLI *c) { |
658 |
|
|
char line[STRLEN]; |
659 |
|
|
|
660 |
|
|
diff -u stunnel-3.22/prototypes.h stunnel-3.22-sg/prototypes.h |
661 |
|
|
--- stunnel-3.22/prototypes.h Sun Nov 11 14:16:01 2001 |
662 |
|
|
+++ stunnel-3.22-sg/prototypes.h Wed May 29 02:15:43 2002 |
663 |
|
|
@@ -41,7 +41,10 @@ |
664 |
|
|
/* Prototypes for client.c */ |
665 |
|
|
void *client(void *); |
666 |
|
|
/* descriptor versions of fprintf/fscanf */ |
667 |
|
|
+int fdwrite(int fd, char *buffer, int len); |
668 |
|
|
+int fdputs(int fd, char *line); |
669 |
|
|
int fdprintf(int, char *, ...); |
670 |
|
|
+int fdgets(int fd, char *buffer); |
671 |
|
|
int fdscanf(int, char *, char *); |
672 |
|
|
|
673 |
|
|
/* Prototypes for log.c */ |
674 |
|
|
@@ -79,6 +82,8 @@ |
675 |
|
|
#define OPT_REMOTE 0x20 |
676 |
|
|
#define OPT_TRANSPARENT 0x40 |
677 |
|
|
#define OPT_PTY 0x80 |
678 |
|
|
+#define OPT_FDS 0x100 |
679 |
|
|
+#define OPT_SUID_FIRST 0x200 |
680 |
|
|
|
681 |
|
|
typedef struct { |
682 |
|
|
char pem[STRLEN]; /* pem (priv key/cert) filename */ |
683 |
|
|
@@ -111,6 +116,8 @@ |
684 |
|
|
int cert_defaults; |
685 |
|
|
char *output_file; |
686 |
|
|
u32 *local_ip; |
687 |
|
|
+ int use_fd; |
688 |
|
|
+ char *chroot_dir; |
689 |
|
|
} server_options; |
690 |
|
|
|
691 |
|
|
typedef enum { |
692 |
|
|
Only in stunnel-3.22-sg: prototypes.h~ |
693 |
|
|
Only in stunnel-3.22-sg: pty.o |
694 |
|
|
diff -u stunnel-3.22/ssl.c stunnel-3.22-sg/ssl.c |
695 |
|
|
--- stunnel-3.22/ssl.c Sun Dec 23 14:46:03 2001 |
696 |
|
|
+++ stunnel-3.22-sg/ssl.c Wed May 15 03:54:39 2002 |
697 |
|
|
@@ -46,6 +46,7 @@ |
698 |
|
|
#include <openssl/ssl.h> |
699 |
|
|
#include <openssl/err.h> |
700 |
|
|
#include <openssl/rand.h> |
701 |
|
|
+#include <openssl/conf.h> |
702 |
|
|
#else |
703 |
|
|
#include <lhash.h> |
704 |
|
|
#include <ssl.h> |
705 |
|
|
@@ -71,7 +72,6 @@ |
706 |
|
|
SSL_CTX *ctx; /* global SSL context */ |
707 |
|
|
|
708 |
|
|
void context_init() { /* init SSL */ |
709 |
|
|
- |
710 |
|
|
if(!init_prng()) |
711 |
|
|
log(LOG_INFO, "PRNG seeded successfully"); |
712 |
|
|
SSLeay_add_ssl_algorithms(); |
713 |
|
|
Only in stunnel-3.22-sg: ssl.c~ |
714 |
|
|
Only in stunnel-3.22-sg: ssl.o |
715 |
|
|
Only in stunnel-3.22-sg: sthreads.o |
716 |
|
|
Only in stunnel-3.22-sg: stunnel |
717 |
|
|
diff -u stunnel-3.22/stunnel.c stunnel-3.22-sg/stunnel.c |
718 |
|
|
--- stunnel-3.22/stunnel.c Thu Dec 20 02:53:54 2001 |
719 |
|
|
+++ stunnel-3.22-sg/stunnel.c Tue May 28 04:03:39 2002 |
720 |
|
|
@@ -54,6 +54,8 @@ |
721 |
|
|
static void create_pid(); |
722 |
|
|
static void delete_pid(); |
723 |
|
|
#endif |
724 |
|
|
+void do_setugid(char *user, char *group); |
725 |
|
|
+int is_alldigits(char *s); |
726 |
|
|
|
727 |
|
|
/* Socket functions */ |
728 |
|
|
static int listen_local(); |
729 |
|
|
@@ -119,6 +121,24 @@ |
730 |
|
|
if(!(options.option&OPT_FOREGROUND)) |
731 |
|
|
options.foreground=0; |
732 |
|
|
log_open(); |
733 |
|
|
+ if (options.chroot_dir) |
734 |
|
|
+ { |
735 |
|
|
+ log(LOG_DEBUG,"chroot(%s)",options.chroot_dir); |
736 |
|
|
+ if (chroot(options.chroot_dir) < 0) |
737 |
|
|
+ { |
738 |
|
|
+ ioerror("chroot"); |
739 |
|
|
+ exit(1); |
740 |
|
|
+ } |
741 |
|
|
+ |
742 |
|
|
+ if (chdir("/") < 0) |
743 |
|
|
+ { |
744 |
|
|
+ ioerror("chdir"); |
745 |
|
|
+ exit(1); |
746 |
|
|
+ } |
747 |
|
|
+ } |
748 |
|
|
+ if ( options.option&OPT_SUID_FIRST && |
749 |
|
|
+ (options.setuid_user || options.setgid_group)) |
750 |
|
|
+ do_setugid(options.setuid_user,options.setgid_group); |
751 |
|
|
log(LOG_NOTICE, "Using '%s' as tcpwrapper service name", options.servname); |
752 |
|
|
|
753 |
|
|
/* check if certificate exists */ |
754 |
|
|
@@ -371,49 +391,9 @@ |
755 |
|
|
exit(1); |
756 |
|
|
} |
757 |
|
|
|
758 |
|
|
-#ifndef USE_WIN32 |
759 |
|
|
- if(options.setgid_group) { |
760 |
|
|
- struct group *gr; |
761 |
|
|
- gid_t gr_list[1]; |
762 |
|
|
- |
763 |
|
|
- gr=getgrnam(options.setgid_group); |
764 |
|
|
- if(!gr) { |
765 |
|
|
- log(LOG_ERR, "Failed to get GID for group %s", |
766 |
|
|
- options.setgid_group); |
767 |
|
|
- exit(1); |
768 |
|
|
- } |
769 |
|
|
- if(setgid(gr->gr_gid)) { |
770 |
|
|
- sockerror("setgid"); |
771 |
|
|
- exit(1); |
772 |
|
|
- } |
773 |
|
|
- gr_list[0]=gr->gr_gid; |
774 |
|
|
- if(setgroups(1, gr_list)) { |
775 |
|
|
- sockerror("setgroups"); |
776 |
|
|
- exit(1); |
777 |
|
|
- } |
778 |
|
|
- } |
779 |
|
|
- |
780 |
|
|
- if(options.setuid_user) { |
781 |
|
|
- struct passwd *pw; |
782 |
|
|
- |
783 |
|
|
- pw=getpwnam(options.setuid_user); |
784 |
|
|
- if(!pw) { |
785 |
|
|
- log(LOG_ERR, "Failed to get UID for user %s", |
786 |
|
|
- options.setuid_user); |
787 |
|
|
- exit(1); |
788 |
|
|
- } |
789 |
|
|
-#ifndef USE_WIN32 |
790 |
|
|
- /* gotta chown that pid file, or we can't remove it. */ |
791 |
|
|
- if ( options.pidfile[0] && chown( options.pidfile, pw->pw_uid, -1) ) { |
792 |
|
|
- log(LOG_ERR, "Failed to chown pidfile %s", options.pidfile); |
793 |
|
|
- } |
794 |
|
|
-#endif |
795 |
|
|
- if(setuid(pw->pw_uid)) { |
796 |
|
|
- sockerror("setuid"); |
797 |
|
|
- exit(1); |
798 |
|
|
- } |
799 |
|
|
- } |
800 |
|
|
-#endif /* USE_WIN32 */ |
801 |
|
|
+ if (!(options.option&OPT_SUID_FIRST) && |
802 |
|
|
+ (options.setuid_user || options.setgid_group)) |
803 |
|
|
+ do_setugid(options.setuid_user,options.setgid_group); |
804 |
|
|
|
805 |
|
|
return ls; |
806 |
|
|
} |
807 |
|
|
@@ -682,4 +662,79 @@ |
808 |
|
|
return retval; |
809 |
|
|
} |
810 |
|
|
|
811 |
|
|
+void do_setugid(char *user, char *group) |
812 |
|
|
+ { |
813 |
|
|
+ uid_t uid; |
814 |
|
|
+ gid_t gid; |
815 |
|
|
+ |
816 |
|
|
+#ifndef USE_WIN32 |
817 |
|
|
+ if(group) { |
818 |
|
|
+ struct group *gr; |
819 |
|
|
+ gid_t gr_list[1]; |
820 |
|
|
+ |
821 |
|
|
+ if (is_alldigits(group)) |
822 |
|
|
+ { |
823 |
|
|
+ gid=atoi(group); |
824 |
|
|
+ } |
825 |
|
|
+ else |
826 |
|
|
+ { |
827 |
|
|
+ gr=getgrnam(group); |
828 |
|
|
+ if(!gr) { |
829 |
|
|
+ log(LOG_ERR, "Failed to get GID for group %s", |
830 |
|
|
+ group); |
831 |
|
|
+ exit(1); |
832 |
|
|
+ } |
833 |
|
|
+ gid = gr->gr_gid; |
834 |
|
|
+ } |
835 |
|
|
+ |
836 |
|
|
+ if(setgid(gid)) { |
837 |
|
|
+ sockerror("setgid"); |
838 |
|
|
+ exit(1); |
839 |
|
|
+ } |
840 |
|
|
+ gr_list[0]=gid; |
841 |
|
|
+ if(setgroups(1, gr_list)) { |
842 |
|
|
+ sockerror("setgroups"); |
843 |
|
|
+ exit(1); |
844 |
|
|
+ } |
845 |
|
|
+ } |
846 |
|
|
+#endif |
847 |
|
|
+ |
848 |
|
|
+ if(user) { |
849 |
|
|
+ struct passwd *pw; |
850 |
|
|
+ |
851 |
|
|
+ if (is_alldigits(user)) |
852 |
|
|
+ { |
853 |
|
|
+ uid = atoi(user); |
854 |
|
|
+ } |
855 |
|
|
+ else |
856 |
|
|
+ { |
857 |
|
|
+ pw=getpwnam(user); |
858 |
|
|
+ if(!pw) { |
859 |
|
|
+ log(LOG_ERR, "Failed to get UID for user %s", |
860 |
|
|
+ user); |
861 |
|
|
+ exit(1); |
862 |
|
|
+ } |
863 |
|
|
+ uid=pw->pw_uid; |
864 |
|
|
+ } |
865 |
|
|
+ |
866 |
|
|
+#ifndef USE_WIN32 |
867 |
|
|
+ /* gotta chown that pid file, or we can't remove it. */ |
868 |
|
|
+ if ( options.pidfile[0] && chown( options.pidfile, uid, -1) ) { |
869 |
|
|
+ log(LOG_ERR, "Failed to chown pidfile %s", options.pidfile); |
870 |
|
|
+ } |
871 |
|
|
+#endif |
872 |
|
|
+ if(setuid(uid)) { |
873 |
|
|
+ sockerror("setuid"); |
874 |
|
|
+ exit(1); |
875 |
|
|
+ } |
876 |
|
|
+ } |
877 |
|
|
+ } |
878 |
|
|
+ |
879 |
|
|
+int is_alldigits(char *s) { |
880 |
|
|
+ while (*s) |
881 |
|
|
+ if (!isdigit(*s++)) |
882 |
|
|
+ return 0; |
883 |
|
|
+ return 1; |
884 |
|
|
+} |
885 |
|
|
+ |
886 |
|
|
/* End of stunnel.c */ |