Download | Plain Text | No Line Numbers


  1. --- FILES 14 Jun 2002 08:47:30 -0000 1.1.1.1
  2. +++ FILES 5 Apr 2004 15:34:57 -0000 1.2
  3. @@ -216,6 +216,7 @@
  4. warn-auto.sh
  5. warn-shsgr
  6. x86cpuid.c
  7. +fixcrio.1
  8. dns_ip6.c
  9. dns_ipq6.c
  10. dns_nd6.c
  11. --- Makefile 14 Jun 2002 08:47:30 -0000 1.1.1.1
  12. +++ Makefile 5 Apr 2004 15:34:57 -0000 1.3
  13. @@ -1,5 +1,13 @@
  14. # Don't edit Makefile! Use conf-* for configuration.
  15.  
  16. +DEFINES=-DWITH_SSL
  17. +#add -DWITH_SSL to enable ssl support
  18. +
  19. +# LIBS for additional libraries and INCS for additional includes
  20. +LIBS=-lcrypto -lssl
  21. +#INCS=-I/usr/local/include
  22. +OPENSSLBIN=openssl
  23. +
  24. SHELL=/bin/sh
  25.  
  26. default: it
  27. @@ -755,7 +763,7 @@
  28. load tcpserver.o rules.o remoteinfo6.o timeoutconn6.o cdb.a dns.a \
  29. time.a unix.a byte.a socket.lib
  30. ./load tcpserver rules.o remoteinfo6.o timeoutconn6.o cdb.a \
  31. - dns.a time.a unix.a byte.a `cat socket.lib`
  32. + dns.a time.a unix.a byte.a $(LIBS) `cat socket.lib`
  33.  
  34. tcpserver.o: \
  35. compile tcpserver.c uint16.h str.h byte.h fmt.h scan.h ip4.h fd.h \
  36. @@ -764,7 +772,7 @@
  37. socket.h uint16.h ndelay.h remoteinfo.h stralloc.h uint16.h rules.h \
  38. stralloc.h sig.h dns.h stralloc.h iopause.h taia.h tai.h uint64.h \
  39. taia.h uint32.h
  40. - ./compile tcpserver.c
  41. + ./compile $(DEFINES) $(INCS) tcpserver.c
  42.  
  43. time.a: \
  44. makelib iopause.o tai_pack.o taia_add.o taia_approx.o taia_frac.o \
  45. @@ -967,3 +975,18 @@
  46.  
  47. clean:
  48. rm -f `cat TARGETS`
  49. +
  50. +cert:
  51. + ${OPENSSLBIN} req -new -x509 -nodes \
  52. + -out cert.pem -days 366 \
  53. + -keyout cert.pem
  54. +
  55. +cert-req:
  56. + ${OPENSSLBIN} req -new -nodes \
  57. + -out req.pem \
  58. + -keyout cert.pem
  59. + @echo
  60. + @echo "Send req.pem to your CA to obtain signed_req.pem, and do:"
  61. + @echo "cat signed_req.pem >> `head -1 conf-qmail`/control/cert.pem"
  62. +
  63. +
  64. --- /dev/null 1 Jan 1970 00:00:00 -0000
  65. +++ fixcrio.1 5 Apr 2004 15:34:57 -0000 1.1
  66. @@ -0,0 +1,15 @@
  67. +.TH fixcrio 1
  68. +.SH NAME
  69. +fixcrio \- make sure that there is a CR before each LF
  70. +.SH SYNOPSIS
  71. +.B fixcrio
  72. +.I program
  73. +[
  74. +.I arg ...
  75. +]
  76. +.SH DESCRIPTION
  77. +.B fixcrio
  78. +inserts CR at the end of each line of input where a CR is not already present.
  79. +It does not insert CR at the end of a partial final line.
  80. +.SH "SEE ALSO"
  81. +addcr(1)
  82. --- hier.c 14 Jun 2002 08:47:32 -0000 1.1.1.1
  83. +++ hier.c 5 Apr 2004 15:34:57 -0000 1.2
  84. @@ -26,6 +26,7 @@
  85. c(auto_home,"bin","fixcrio",-1,-1,0755);
  86. c(auto_home,"bin","rblsmtpd",-1,-1,0755);
  87.  
  88. + c(auto_home,"man/man1","fixcrio.1",-1,-1,0644);
  89. c(auto_home,"man/man1","tcpclient.1",-1,-1,0644);
  90. c(auto_home,"man/man1","tcpserver.1",-1,-1,0644);
  91. c(auto_home,"man/man1","tcprules.1",-1,-1,0644);
  92. }
  93. --- tcprules.c 14 Jun 2002 08:47:30 -0000 1.1.1.1
  94. +++ tcprules.c 16 Mar 2004 15:12:26 -0000 1.2
  95. @@ -94,6 +94,7 @@
  96. int len;
  97. int fd;
  98. int i;
  99. + int e;
  100. char ch;
  101.  
  102. fn = argv[1];
  103. @@ -154,8 +155,16 @@
  104. while (len)
  105. switch(*x) {
  106. case ',':
  107. + e = byte_chr(x + 1,len - 1,',');
  108. i = byte_chr(x,len,'=');
  109. - if (i == len) die_bad();
  110. + if (i > e) {
  111. + if (e < 2 || x[1] != '!') die_bad();
  112. + if (!stralloc_catb(&data,"-",1)) nomem();
  113. + if (!stralloc_catb(&data,x + 2,e - 1)) nomem();
  114. + if (!stralloc_0(&data)) nomem();
  115. + x += e + 1; len -= e + 1;
  116. + break;
  117. + }
  118. if (!stralloc_catb(&data,"+",1)) nomem();
  119. if (!stralloc_catb(&data,x + 1,i)) nomem();
  120. x += i + 1; len -= i + 1;
  121. --- tcprulescheck.c 14 Jun 2002 08:47:30 -0000 1.1.1.1
  122. +++ tcprulescheck.c 16 Mar 2004 15:12:27 -0000 1.2
  123. @@ -22,6 +22,11 @@
  124. buffer_puts(buffer_1,data + 1);
  125. buffer_puts(buffer_1,"\n");
  126. break;
  127. + case '-':
  128. + buffer_puts(buffer_1,"unset environment variable ");
  129. + buffer_puts(buffer_1,data + 1);
  130. + buffer_puts(buffer_1,"\n");
  131. + break;
  132. }
  133. ++next0;
  134. data += next0; datalen -= next0;
  135. --- tcpserver.1.orig 1 Jan 1970 00:00:00 -0000
  136. +++ tcpserver.1 6 Apr 2004 11:49:45 -0000 1.2
  137. @@ -4,7 +4,7 @@
  138. .SH SYNOPSIS
  139. .B tcpserver
  140. [
  141. -.B \-146jpPhHrRoOdDqQv
  142. +.B \-146UXpPhHrRoOdDqQsSv
  143. ]
  144. [
  145. .B \-c\fIlimit
  146. @@ -31,6 +31,9 @@
  147. .B \-t\fItimeout
  148. ]
  149. [
  150. +.B \-n\fIcertfile
  151. +]
  152. +[
  153. .B \-I\fIinterface
  154. ]
  155. .I host
  156. @@ -204,11 +207,31 @@
  157. (Default.)
  158. Print error messages.
  159. .TP
  160. +.B \-s
  161. +Enable SSL/TLS mode. This modus needs a SSL enabled build and a certificat.
  162. +.TP
  163. +.B \-S
  164. +(Default.)
  165. +Don't enable SSL/TLS mode.
  166. +.TP
  167. +.B \-n\fIcertfile
  168. +Instead of the default ./cert.pem certificate us the specified
  169. +.IR certfile .
  170. +.TP
  171. .B \-v
  172. Verbose.
  173. Print all available messages.
  174. .SH "DATA-GATHERING OPTIONS"
  175. .TP
  176. +.B \-X
  177. +With
  178. +.BR -x\fIcdb ,
  179. +allow connections even if
  180. +.I cdb
  181. +does not exist.
  182. +Normally the connection gets dropped.
  183. +.SH "DATA-GATHERING OPTIONS"
  184. +.TP
  185. .B \-p
  186. Paranoid.
  187. After looking up the remote host name,
  188. @@ -256,6 +279,13 @@
  189. after
  190. .I timeout
  191. seconds. Default: 26.
  192. +.SH ENVIRONMENT
  193. +.TP
  194. +.B SSL_CIPHER
  195. +Specifies the ciphers that should be used in SSL/TLS mode.
  196. +See
  197. +.I openssl(1)
  198. +for more information.
  199. .SH "SEE ALSO"
  200. argv0(1),
  201. fixcr(1),
  202. @@ -264,3 +294,4 @@
  203. tcprules(1),
  204. listen(2),
  205. tcp-environ(5)
  206. +openssl(1)
  207. --- tcpserver.c 14 Jun 2002 08:47:30 -0000 1.1.1.1
  208. +++ tcpserver.c 1 Apr 2005 15:13:15 -0000 1.8
  209. @@ -1,6 +1,8 @@
  210. #include <sys/types.h>
  211. #include <sys/param.h>
  212. #include <netdb.h>
  213. +#include <openssl/ssl.h>
  214. +#include <fcntl.h>
  215. #include "uint16.h"
  216. #include "str.h"
  217. #include "byte.h"
  218. @@ -39,6 +40,13 @@
  219. int flagparanoid = 0;
  220. unsigned long timeout = 26;
  221. uint32 netif = 0;
  222. +#ifdef WITH_SSL
  223. +int flagssl = 0;
  224. +struct stralloc certfile = {0};
  225. +#define CERTFILE "./cert.pem"
  226. +
  227. +void translate(SSL*, int, int, unsigned int);
  228. +#endif
  229.  
  230. static stralloc tcpremoteinfo;
  231.  
  232. @@ -130,6 +138,9 @@
  233. env(data + 1,data + 1 + split + 1);
  234. }
  235. break;
  236. + case '-':
  237. + env(data + 1, (char *)0);
  238. + break;
  239. }
  240. ++next0;
  241. data += next0; datalen -= next0;
  242. @@ -271,6 +282,7 @@
  243.  
  244. void usage(void)
  245. {
  246. +#ifndef WITH_SSL
  247. strerr_warn1("\
  248. tcpserver: usage: tcpserver \
  249. [ -461UXpPhHrRoOdDqQv ] \
  250. @@ -282,8 +294,23 @@
  251. [ -b backlog ] \
  252. [ -l localname ] \
  253. [ -t timeout ] \
  254. +host port program",0);
  255. +#else
  256. + strerr_warn1("\
  257. +tcpserver: usage: tcpserver \
  258. +[ -461UXpPhHrRoOdDqQsSv ] \
  259. +[ -c limit ] \
  260. +[ -x rules.cdb ] \
  261. +[ -B banner ] \
  262. +[ -g gid ] \
  263. +[ -u uid ] \
  264. +[ -b backlog ] \
  265. +[ -l localname ] \
  266. +[ -t timeout ] \
  267. +[ -n certfile ] \
  268. [ -I interface ] \
  269. host port program",0);
  270. +#endif
  271. _exit(100);
  272. }
  273.  
  274. @@ -334,7 +361,20 @@
  275. int s;
  276. int t;
  277.  
  278. +#ifdef WITH_SSL
  279. + BIO *sbio;
  280. + SSL *ssl;
  281. + SSL_CTX *ctx;
  282. + int pi2c[2], pi4c[2];
  283. +
  284. + ctx = NULL;
  285. +
  286. + if (!stralloc_copys(&certfile, CERTFILE) || !stralloc_0(&certfile) )
  287. + strerr_die2x(111,FATAL,"out of memory");
  288. + while ((opt = getopt(argc,argv,"46dDvqQhHrRsS1UXx:t:u:g:l:b:B:c:n:I:pPoO")) != opteof)
  289. +#else
  290. while ((opt = getopt(argc,argv,"46dDvqQhHrR1UXx:t:u:g:l:b:B:c:I:pPoO")) != opteof)
  291. +#endif
  292. switch(opt) {
  293. case 'b': scan_ulong(optarg,&backlog); break;
  294. case 'c': scan_ulong(optarg,&limit); break;
  295. @@ -364,6 +404,14 @@
  296. case '4': noipv6 = 1; break;
  297. case '6': forcev6 = 1; break;
  298. case 'l': localhost = optarg; break;
  299. +#ifdef WITH_SSL
  300. + case 's': flagssl = 1; break;
  301. + case 'S': flagssl = 0; break;
  302. + case 'n': if (!stralloc_copys(&certfile, optarg) ||
  303. + !stralloc_0(&certfile) )
  304. + strerr_die2x(111,FATAL,"out of memory");
  305. + break;
  306. +#endif
  307. default: usage();
  308. }
  309. argc -= optind;
  310. @@ -371,6 +419,11 @@
  311.  
  312. if (!verbosity)
  313. buffer_2->fd = -1;
  314. +
  315. + if (limit == 0)
  316. + strerr_die2x(100,FATAL,"limit may not be set to 0");
  317. + if (limit > 65000)
  318. + strerr_die2x(100,FATAL,"limit way to high");
  319.  
  320. hostname = *argv++;
  321. if (!hostname) usage();
  322. @@ -412,6 +465,25 @@
  323. noipv6=1;
  324. }
  325.  
  326. +#ifdef WITH_SSL
  327. + if (flagssl == 1) {
  328. + /* setup SSL context (load key and cert into ctx) */
  329. + SSL_library_init();
  330. + ctx=SSL_CTX_new(SSLv23_server_method());
  331. + if (!ctx) strerr_die2x(111,FATAL,"unable to create SSL context");
  332. +
  333. + /* set prefered ciphers */
  334. + if (env_get("SSL_CIPHER"))
  335. + if (SSL_CTX_set_cipher_list(ctx, env_get("SSL_CIPHER")) == 0)
  336. + strerr_die2x(111,FATAL,"unable to set cipher list");
  337. +
  338. + if(SSL_CTX_use_RSAPrivateKey_file(ctx, certfile.s, SSL_FILETYPE_PEM) != 1)
  339. + strerr_die2x(111,FATAL,"unable to load RSA private key");
  340. + if(SSL_CTX_use_certificate_chain_file(ctx, certfile.s) != 1)
  341. + strerr_die2x(111,FATAL,"unable to load certificate");
  342. + }
  343. +#endif
  344. +
  345. s = socket_tcp6();
  346. if (s == -1)
  347. strerr_die2sys(111,FATAL,"unable to create socket: ");
  348. @@ -461,6 +533,39 @@
  349. sig_unblock(sig_child);
  350. sig_uncatch(sig_term);
  351. sig_uncatch(sig_pipe);
  352. +#ifdef WITH_SSL
  353. + if (flagssl == 1) {
  354. + if (pipe(pi2c) != 0)
  355. + strerr_die2sys(111,DROP,"unable to create pipe: ");
  356. + if (pipe(pi4c) != 0)
  357. + strerr_die2sys(111,DROP,"unable to create pipe: ");
  358. + switch(fork()) {
  359. + case 0:
  360. + close(0); close(1);
  361. + close(pi2c[1]);
  362. + close(pi4c[0]);
  363. + if ((fd_move(0,pi2c[0]) == -1) || (fd_move(1,pi4c[1]) == -1))
  364. + strerr_die2sys(111,DROP,"unable to set up descriptors: ");
  365. + /* signals are allready set in the parent */
  366. + pathexec(argv);
  367. + strerr_die4sys(111,DROP,"unable to run ",*argv,": ");
  368. + case -1:
  369. + strerr_die2sys(111,DROP,"unable to fork: ");
  370. + default:
  371. + ssl = SSL_new(ctx);
  372. + if (!ssl)
  373. + strerr_die2x(111,DROP,"unable to set up SSL session");
  374. + sbio = BIO_new_socket(0,BIO_NOCLOSE);
  375. + if (!sbio)
  376. + strerr_die2x(111,DROP,"unable to set up BIO socket");
  377. + SSL_set_bio(ssl,sbio,sbio);
  378. + close(pi2c[0]);
  379. + close(pi4c[1]);
  380. + translate(ssl, pi2c[1], pi4c[0], 3600);
  381. + _exit(0);
  382. + }
  383. + }
  384. +#endif
  385. pathexec(argv);
  386. strerr_die4sys(111,DROP,"unable to run ",*argv,": ");
  387. case -1:
  388. @@ -470,3 +575,186 @@
  389. close(t);
  390. }
  391. }
  392. +
  393. +#ifdef WITH_SSL
  394. +int ssl_timeoutio(int (*func)(), long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
  395. +{
  396. + int n;
  397. + const long end = t + time(NULL);
  398. +
  399. + do {
  400. + fd_set fds;
  401. + struct timeval tv;
  402. +
  403. + const int r = buf ? func(ssl, buf, len) : func(ssl);
  404. + if (r > 0)
  405. + return r;
  406. +
  407. + t = end - time(NULL);
  408. + if (t < 0)
  409. + break;
  410. + tv.tv_sec = t;
  411. + tv.tv_usec = 0;
  412. +
  413. + FD_ZERO(&fds);
  414. + switch (SSL_get_error(ssl, r))
  415. + {
  416. + default:
  417. + return r; /* some other error */
  418. + case SSL_ERROR_WANT_READ:
  419. + FD_SET(rfd, &fds);
  420. + n = select(rfd + 1, &fds, NULL, NULL, &tv);
  421. + break;
  422. + case SSL_ERROR_WANT_WRITE:
  423. + FD_SET(wfd, &fds);
  424. + n = select(wfd + 1, NULL, &fds, NULL, &tv);
  425. + break;
  426. + }
  427. +
  428. + /* n is the number of descriptors that changed status */
  429. + }
  430. + while (n > 0);
  431. +
  432. + if (n != -1) errno = error_timeout;
  433. + return -1;
  434. +}
  435. +
  436. +int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl)
  437. +{
  438. + int r;
  439. +
  440. + /* if connection is established, keep NDELAY */
  441. + if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1)
  442. + return -1;
  443. + r = ssl_timeoutio(SSL_accept, t, rfd, wfd, ssl, NULL, 0);
  444. +
  445. + if (r <= 0) {
  446. + ndelay_off(rfd);
  447. + ndelay_off(wfd);
  448. + }
  449. + else
  450. + SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
  451. +
  452. + return r;
  453. +}
  454. +
  455. +int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
  456. +{
  457. + if (!buf)
  458. + return 0;
  459. + if (SSL_pending(ssl))
  460. + return SSL_read(ssl, buf, len);
  461. + return ssl_timeoutio(SSL_read, t, rfd, wfd, ssl, buf, len);
  462. +}
  463. +
  464. +int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
  465. +{
  466. + if (!buf)
  467. + return 0;
  468. + return ssl_timeoutio(SSL_write, t, rfd, wfd, ssl, buf, len);
  469. +}
  470. +
  471. +static int allwrite(int fd, char *buf, int len)
  472. +{
  473. + int w;
  474. +
  475. + while (len) {
  476. + w = write(fd,buf,len);
  477. + if (w == -1) {
  478. + if (errno == error_intr) continue;
  479. + return -1; /* note that some data may have been written */
  480. + }
  481. + if (w == 0) ; /* luser's fault */
  482. + buf += w;
  483. + len -= w;
  484. + }
  485. + return 0;
  486. +}
  487. +
  488. +static int allwritessl(long t, int rfd, int wfd, SSL* ssl, char *buf, int len)
  489. +{
  490. + int w;
  491. +
  492. + while (len) {
  493. + w = ssl_timeoutwrite(t, rfd, wfd, ssl, buf, len);
  494. + if (w == -1) {
  495. + if (errno == error_intr) continue;
  496. + return -1; /* note that some data may have been written */
  497. + }
  498. + if (w == 0) ; /* luser's fault */
  499. + buf += w;
  500. + len -= w;
  501. + }
  502. + return 0;
  503. +}
  504. +
  505. +char tbuf[2048];
  506. +
  507. +void translate(SSL* ssl, int clearout, int clearin, unsigned int iotimeout)
  508. +{
  509. + struct taia now;
  510. + struct taia deadline;
  511. + iopause_fd iop[2];
  512. + int flagexitasap;
  513. + int iopl;
  514. + int sslout, sslin;
  515. + int n, r;
  516. +
  517. + sslin = SSL_get_fd(ssl);
  518. + sslout = SSL_get_fd(ssl);
  519. + if (sslin == -1 || sslout == -1)
  520. + strerr_die2x(111,DROP,"unable to set up SSL connection");
  521. +
  522. + flagexitasap = 0;
  523. +
  524. + if (ssl_timeoutaccept(timeout, sslin, sslout, ssl) <= 0)
  525. + strerr_die2x(111,DROP,"unable to accept SSL connection");
  526. +
  527. + while (!flagexitasap) {
  528. + taia_now(&now);
  529. + taia_uint(&deadline,iotimeout);
  530. + taia_add(&deadline,&now,&deadline);
  531. +
  532. + /* fill iopause struct */
  533. + iopl = 2;
  534. + iop[0].fd = sslin;
  535. + iop[0].events = IOPAUSE_READ;
  536. + iop[1].fd = clearin;
  537. + iop[1].events = IOPAUSE_READ;
  538. +
  539. + /* do iopause read */
  540. + iopause(iop,iopl,&deadline,&now);
  541. + if (iop[0].revents) {
  542. + do {
  543. + /* data on sslin */
  544. + n = ssl_timeoutread(iotimeout, sslin, sslout, ssl, tbuf, sizeof(tbuf));
  545. + if ( n < 0 )
  546. + strerr_die2sys(111,DROP,"unable to read form network: ");
  547. + if ( n == 0 )
  548. + flagexitasap = 1;
  549. + r = allwrite(clearout, tbuf, n);
  550. + if ( r < 0 )
  551. + strerr_die2sys(111,DROP,"unable to write to client: ");
  552. + /*
  553. + * if the data payload was longer than sizeof(tbuf) then SSL will have
  554. + * bytes processed and pending. We need to pick them up and write them
  555. + * to clearout.
  556. + */
  557. + } while (SSL_pending(ssl));
  558. + }
  559. + if (iop[1].revents) {
  560. + /* data on clearin */
  561. + n = read(clearin, tbuf, sizeof(tbuf));
  562. + if ( n < 0 )
  563. + strerr_die2sys(111,DROP,"unable to read form client: ");
  564. + if ( n == 0 )
  565. + flagexitasap = 1;
  566. + r = allwritessl(iotimeout, sslin, sslout, ssl, tbuf, n);
  567. + if ( r < 0 )
  568. + strerr_die2sys(111,DROP,"unable to write to network: ");
  569. + }
  570. + if (!iop[0].revents && !iop[1].revents)
  571. + strerr_die2x(0, DROP,"timeout reached without input");
  572. + }
  573. +}
  574. +#endif
  575.