Browse code

tls: update & fix repeated send & delayed send

Update to the new tls encode callback api. This fixes the
following bugs:
- bug on tls partial write and repeated tcp send (in some cases
the tcp send function does not expect to be called again in the
same state and might overwrite the response that has to be sent
to tcp_main resulting in the worst case in a possible unwatched
connection).
- missing tls callback when trying to send on a connection with
already queued data (without the api change a 3rd type of send
tls callback would have been needed).

Andrei Pelinescu-Onciul authored on 23/06/2010 21:31:57
Showing 3 changed files
... ...
@@ -235,8 +235,7 @@ struct module_exports exports = {
235 235
 
236 236
 static struct tls_hooks tls_h = {
237 237
 	tls_read_f,
238
-	tls_do_send_f,
239
-	tls_1st_send_f,
238
+	tls_encode_f,
240 239
 	tls_h_tcpconn_init,
241 240
 	tls_h_tcpconn_clean,
242 241
 	tls_h_close,
... ...
@@ -558,7 +558,6 @@ void tls_h_tcpconn_clean(struct tcp_connection *c)
558 558
  */
559 559
 void tls_h_close(struct tcp_connection *c, int fd)
560 560
 {
561
-	unsigned char rd_buf[TLS_RD_MBUF_SZ];
562 561
 	unsigned char wr_buf[TLS_WR_MBUF_SZ];
563 562
 	struct tls_mbuf rd, wr;
564 563
 	
... ...
@@ -577,7 +576,7 @@ void tls_h_close(struct tcp_connection *c, int fd)
577 576
 				lock_release(&c->write_lock);
578 577
 				return;
579 578
 			}
580
-			tls_mbuf_init(&rd, rd_buf, sizeof(rd_buf));
579
+			tls_mbuf_init(&rd, 0, 0); /* no read */
581 580
 			tls_mbuf_init(&wr, wr_buf, sizeof(wr_buf));
582 581
 			if (tls_set_mbufs(c, &rd, &wr)==0) {
583 582
 				tls_shutdown(c); /* shudown only on succesfull set fd */
... ...
@@ -604,55 +603,50 @@ typedef int (*tcp_low_level_send_t)(int fd, struct tcp_connection *c,
604 603
 
605 604
 
606 605
 
607
-/** tls generic send function.
608
- * It is used by tls_do_send_f and tls_1st_send_f (which are wrappers
609
- * arround it).
610
- * WARNING: it must _not_ be called with c->write_lock held!
606
+/** tls encrypt before sending function.
607
+ * It is a callback that will be called by the tcp code, before a send
608
+ * on TLS would be attempted. It should replace the input buffer with a
609
+ * new static buffer containing the TLS processed data.
610
+ * WARNING: it must always be called with c->write_lock held!
611 611
  * @param c - tcp connection
612
- * @param fd - valid file descriptor for the tcp connection
613
- * @param buf - data
614
- * @param len - data size
615
- * @param send_flags
616
- * @param resp - filled with a cmd. for tcp_main (@see tcpconn_do_send() for
617
- *               more details)
618
- * @param tcp_do_send_f - callback for doing the tcp send (resp must
619
- *                passed to it)
620
- * 
621
- * @return >=0 on success, < 0 on error && * resp == CON_ERROR.
612
+ * @param pbuf - pointer to buffer (value/result, on success it will be
613
+ *               replaced with a static buffer).
614
+ * @param plen - pointer to buffer size (value/result, on success it will be
615
+ *               replaced with the size of the replacement buffer.
616
+ * @return *plen on success (>=0), < 0 on error.
622 617
  */
623
-static int tls_generic_send(int fd, struct tcp_connection *c,
624
-						const char *buf, unsigned int len,
625
-						snd_flags_t send_flags, long* resp,
626
-						tcp_low_level_send_t tcp_do_send_f)
618
+int tls_encode_f(struct tcp_connection *c,
619
+						const char* *pbuf, unsigned int* plen)
627 620
 {
628 621
 	int n, offs;
629 622
 	SSL* ssl;
630 623
 	struct tls_extra_data* tls_c;
631
-	unsigned char wr_buf[TLS_WR_MBUF_SZ];
624
+	static unsigned char wr_buf[TLS_WR_MBUF_SZ];
632 625
 	struct tls_mbuf rd, wr;
633 626
 	int ssl_error;
634 627
 	char* err_src;
628
+	const char* buf;
629
+	unsigned int len;
635 630
 	int x;
636 631
 	
637
-	TLS_WR_TRACE("(%d, %p, %p, %d, send_flags, %p, %p) start (%s:%d* -> %s)\n",
638
-					fd, c, buf, len, resp, tcp_do_send_f,
639
-					ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port,
632
+	buf = *pbuf;
633
+	len = *plen;
634
+	TLS_WR_TRACE("(%p, %p, %d) start (%s:%d* -> %s)\n",
635
+					c, buf, len, ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port,
640 636
 					su2a(&c->rcv.src_su, sizeof(c->rcv.src_su)));
641
-	*resp = CONN_NOP;
642 637
 	n = 0;
643 638
 	offs = 0;
644 639
 	ssl_error = SSL_ERROR_NONE;
645 640
 	err_src = "TLS write:";
646
-	lock_get(&c->write_lock);
647 641
 	if (unlikely(tls_fix_connection(c) < 0)) {
648 642
 		/* c->extra_data might be null => exit immediately */
649 643
 		ERR("tls_fix_connection failed\n");
650
-		lock_release(&c->write_lock);
651
-		*resp = CONN_ERROR;
652 644
 		return -1;
653 645
 	}
654 646
 	tls_c = (struct tls_extra_data*)c->extra_data;
655 647
 	ssl = tls_c->ssl;
648
+	tls_mbuf_init(&rd, 0, 0); /* no read */
649
+	tls_mbuf_init(&wr, wr_buf, sizeof(wr_buf));
656 650
 	/* clear text already queued (WANTS_READ) queue directly*/
657 651
 	if (unlikely(tls_write_wants_read(tls_c))) {
658 652
 		TLS_WR_TRACE("(%p) WANTS_READ queue present => queueing"
... ...
@@ -664,13 +658,11 @@ static int tls_generic_send(int fd, struct tcp_connection *c,
664 658
 		}
665 659
 		goto end;
666 660
 	}
667
-	tls_mbuf_init(&rd, 0, 0); /* no read */
668
-redo_wr:
669
-	tls_mbuf_init(&wr, wr_buf, sizeof(wr_buf));
670 661
 	if (unlikely(tls_set_mbufs(c, &rd, &wr) < 0)) {
671 662
 		ERR("tls_set_mbufs failed\n");
672 663
 		goto error;
673 664
 	}
665
+redo_wr:
674 666
 	if (unlikely(tls_c->state == S_TLS_CONNECTING)) {
675 667
 		n = tls_connect(c, &ssl_error);
676 668
 		TLS_WR_TRACE("(%p) tls_connect() => %d (err=%d)\n", c, n, ssl_error);
... ...
@@ -704,22 +696,6 @@ redo_wr:
704 696
 	}
705 697
 	TLS_WR_TRACE("(%p) SSL_write(%p + %d, %d) => %d (err=%d)\n",
706 698
 					c, buf, offs, len - offs, n, ssl_error);
707
-	if (wr.used ) {
708
-		TLS_WR_TRACE("(%p) sending (tcp) %d bytes\n", c, wr.used);
709
-		/* something was written */
710
-		if (unlikely( n < (len -offs)  && n >= 0)) {
711
-			/* if partial tls write, don't force close the tcp connection */
712
-			tcpconn_set_send_flags(c, send_flags); /* set the original flags */
713
-			send_flags.f &= ~SND_F_CON_CLOSE;
714
-		}
715
-		if (unlikely(tcp_do_send_f(fd, c, (char*)wr.buf, wr.used,
716
-											send_flags, resp, 1) < 0)){
717
-			tls_set_mbufs(c, 0, 0);
718
-			TLS_WR_TRACE("(%p) tcp_do_send_f[%p] error sending %d bytes\n", c,
719
-							tcp_do_send_f, wr.used );
720
-			goto error_send;
721
-		}
722
-	}
723 699
 	/* check for possible ssl errors */
724 700
 	if (unlikely(n <= 0)){
725 701
 		switch(ssl_error) {
... ...
@@ -794,76 +770,28 @@ redo_wr:
794 770
 	}
795 771
 	tls_set_mbufs(c, 0, 0);
796 772
 end:
797
-	lock_release(&c->write_lock);
798
-	TLS_WR_TRACE("(%p) end (offs %d) => %d (*resp = %ld)\n",
799
-					c, len, len, *resp);
800
-	return len;
773
+	*pbuf = (const char*)wr.buf;
774
+	*plen = wr.used;
775
+	TLS_WR_TRACE("(%p) end (offs %d) => %d \n",
776
+					c, offs, *plen);
777
+	return *plen;
801 778
 error:
802
-error_send:
779
+/*error_send:*/
803 780
 error_wq_full:
804 781
 bug:
805 782
 	tls_set_mbufs(c, 0, 0);
806
-	lock_release(&c->write_lock);
807
-	TLS_WR_TRACE("(%p) end error (offs %d) => (prev *resp = %ld)\n",
808
-					c, offs, *resp);
809
-	*resp = CONN_ERROR;
783
+	TLS_WR_TRACE("(%p) end error (offs %d, %d encoded) => -1\n",
784
+					c, offs, wr.used);
810 785
 	return -1;
811 786
 ssl_eof:
812 787
 	c->state = S_CONN_EOF;
813
-	lock_release(&c->write_lock);
788
+	c->flags |= F_CONN_FORCE_EOF;
789
+	*pbuf = (const char*)wr.buf;
790
+	*plen = wr.used;
814 791
 	DBG("TLS connection has been closed\n");
815
-	TLS_WR_TRACE("(%p) end EOF (offs %d) => (prev *resp = %ld)\n",
816
-					c, offs, *resp);
817
-	*resp = CONN_EOF;
818
-	return -1;
819
-}
820
-
821
-
822
-
823
-/** tls do_send callback.
824
- * It is called for all sends (by the tcp send code), except the first send
825
- * on an async connection (@see tls_1st_send).
826
- * WARNING: it must _not_ be called with c->write_lock held!
827
- * @param c - tcp connection
828
- * @param fd - valid file descriptor for the tcp connection
829
- * @param buf - data
830
- * @param len - data size
831
- * @param send_flags
832
- * @param resp - filled with a cmd. for tcp_main (@see tcpconn_do_send() for
833
- *               more details)
834
- * 
835
- * @return >=0 on success, < 0 on error && * resp == CON_ERROR.
836
- */
837
-int tls_do_send_f(int fd, struct tcp_connection *c,
838
-						const char *buf, unsigned int len,
839
-						snd_flags_t send_flags, long* resp)
840
-{
841
-	return tls_generic_send(fd, c, buf, len, send_flags, resp,
842
-							tcpconn_do_send);
843
-}
844
-
845
-
846
-
847
-/** tls 1st_send callback.
848
- * It is called for the first send on an async tcp connection
849
- * (should be non-blocking).
850
- * WARNING: it must _not_ be called with c->write_lock held!
851
- * @param c - tcp connection
852
- * @param fd - valid file descriptor for the tcp connection
853
- * @param buf - data
854
- * @param len - data size
855
- * @param send_flags
856
- * @param resp - filled with a cmd. for tcp_main (@see tcpconn_1st_send() for
857
- *               more details)
858
- * 
859
- * @return >=0 on success, < 0 on error && * resp == CON_ERROR.
860
- */
861
-int tls_1st_send_f(int fd, struct tcp_connection *c,
862
-						const char *buf, unsigned int len,
863
-						snd_flags_t send_flags, long* resp)
864
-{
865
-	return tls_generic_send(fd, c, buf, len, send_flags, resp,
866
-							tcpconn_1st_send);
792
+	TLS_WR_TRACE("(%p) end EOF (offs %d) => (%d\n",
793
+					c, offs, *plen);
794
+	return *plen;
867 795
 }
868 796
 
869 797
 
... ...
@@ -1105,8 +1033,6 @@ continue_ssl_read:
1105 1033
 			if (unlikely(n <= 0)) {
1106 1034
 				ssl_error = SSL_get_error(ssl, n);
1107 1035
 				err_src = "TLS read:";
1108
-				TLS_RD_TRACE("(%p, %p) SSL_read() err=%d\n",
1109
-								c, flags, ssl_error);
1110 1036
 				/*  errors handled below, outside the lock */
1111 1037
 			} else {
1112 1038
 				ssl_error = SSL_ERROR_NONE;
... ...
@@ -1115,7 +1041,7 @@ continue_ssl_read:
1115 1041
 				bytes_free -=n;
1116 1042
 			}
1117 1043
 			TLS_RD_TRACE("(%p, %p) SSL_read() => %d (err=%d) ssl_read=%d"
1118
-							"*flags=%d tls_c->flags=%d\n",
1044
+							" *flags=%d tls_c->flags=%d\n",
1119 1045
 							c, flags, n, ssl_error, ssl_read, *flags,
1120 1046
 							tls_c->flags);
1121 1047
 ssl_read_skipped:
... ...
@@ -83,13 +83,8 @@ void tls_h_tcpconn_clean(struct tcp_connection *c);
83 83
  */
84 84
 void tls_h_close(struct tcp_connection *c, int fd);
85 85
 
86
-int tls_do_send_f(int fd, struct tcp_connection *c,
87
-						const char *buf, unsigned int len,
88
-						snd_flags_t send_flags, long* resp);
89
-
90
-int tls_1st_send_f(int fd, struct tcp_connection *c,
91
-						const char *buf, unsigned int len,
92
-						snd_flags_t send_flags, long* resp);
86
+int tls_encode_f(struct tcp_connection *c,
87
+					const char ** pbuf, unsigned int* plen);
93 88
 
94 89
 int tls_read_f(struct tcp_connection *c, int* flags);
95 90