diff src/lstream.c @ 5814:a216b3c2b09e

Add TLS support. See xemacs-patches message with ID <CAHCOHQk6FNm2xf=XiGEpPq43+7WOzNZ=SuD9V79o3wb9WVCTrQ@mail.gmail.com>.
author Jerry James <james@xemacs.org>
date Tue, 07 Oct 2014 21:16:10 -0600
parents d2c0ff38ad5c
children
line wrap: on
line diff
--- a/src/lstream.c	Thu Oct 02 10:19:00 2014 +0200
+++ b/src/lstream.c	Tue Oct 07 21:16:10 2014 -0600
@@ -28,6 +28,7 @@
 #include "buffer.h"
 #include "insdel.h"
 #include "lstream.h"
+#include "tls.h"
 
 #include "sysfile.h"
 
@@ -990,6 +991,25 @@
   Lstream_unread (lstr, &ch, 1);
 }
 
+/* Detect an active TLS session */
+
+int
+Lstream_tls_p (Lstream *lstr)
+{
+  return (lstr->imp->tls_p) ? (lstr->imp->tls_p) (lstr) : 0;
+}
+
+/* STARTTLS negotiation */
+
+int
+Lstream_tls_negotiate (Lstream *instr, Lstream *outstr, const Extbyte *host,
+		       Lisp_Object keylist)
+{
+  return (instr->imp->tls_negotiater)
+    ? (instr->imp->tls_negotiater) (instr, outstr, host, keylist)
+    : 0;
+}
+
 
 /************************ some stream implementations *********************/
 
@@ -1117,6 +1137,7 @@
 
 struct filedesc_stream
 {
+  tls_state_t *tls_state;
   int fd;
   int pty_max_bytes;
   Ibyte eof_char;
@@ -1142,11 +1163,12 @@
    ignored when writing); -1 for unlimited. */
 static Lisp_Object
 make_filedesc_stream_1 (int filedesc, int offset, int count, int flags,
-			const char *mode)
+			tls_state_t *state, const char *mode)
 {
   Lstream *lstr = Lstream_new (lstream_filedesc, mode);
   struct filedesc_stream *fstr = FILEDESC_STREAM_DATA (lstr);
-  fstr->fd = filedesc;
+  fstr->tls_state = state;
+  fstr->fd = state ? tls_get_fd (state) : filedesc;
   fstr->closing      = !!(flags & LSTR_CLOSING);
   fstr->allow_quit   = !!(flags & LSTR_ALLOW_QUIT);
   fstr->blocked_ok   = !!(flags & LSTR_BLOCKED_OK);
@@ -1154,7 +1176,7 @@
   fstr->blocking_error_p = 0;
   fstr->chars_sans_newline = 0;
   fstr->saved_errno = 0;
-  fstr->starting_pos = lseek (filedesc, offset, SEEK_CUR);
+  fstr->starting_pos = lseek (fstr->fd, offset, SEEK_CUR);
   fstr->current_pos = max (fstr->starting_pos, 0);
   if (count < 0)
     fstr->end_pos = -1;
@@ -1184,15 +1206,17 @@
  */
 
 Lisp_Object
-make_filedesc_input_stream (int filedesc, int offset, int count, int flags)
+make_filedesc_input_stream (int filedesc, int offset, int count, int flags,
+			    tls_state_t *state)
 {
-  return make_filedesc_stream_1 (filedesc, offset, count, flags, "r");
+  return make_filedesc_stream_1 (filedesc, offset, count, flags, state, "r");
 }
 
 Lisp_Object
-make_filedesc_output_stream (int filedesc, int offset, int count, int flags)
+make_filedesc_output_stream (int filedesc, int offset, int count, int flags,
+			     tls_state_t *state)
 {
-  return make_filedesc_stream_1 (filedesc, offset, count, flags, "w");
+  return make_filedesc_stream_1 (filedesc, offset, count, flags, state, "w");
 }
 
 static Bytecount
@@ -1203,9 +1227,11 @@
   str->saved_errno = 0;
   if (str->end_pos >= 0)
     size = min (size, (Bytecount) (str->end_pos - str->current_pos));
-  nread = str->allow_quit ?
-    read_allowing_quit (str->fd, data, size) :
-    retry_read (str->fd, data, size);
+  nread = str->tls_state
+    ? tls_read (str->tls_state, data, size, str->allow_quit)
+    : (str->allow_quit ?
+       read_allowing_quit (str->fd, data, size) :
+       retry_read (str->fd, data, size));
   if (nread > 0)
     str->current_pos += nread;
   if (nread == 0)
@@ -1268,9 +1294,11 @@
 
   /**** start of non-PTY-crap ****/
   if (size > 0)
-    retval = str->allow_quit ?
-      write_allowing_quit (str->fd, data, size) :
-      retry_write (str->fd, data, size);
+    retval = str->tls_state
+      ? tls_write (str->tls_state, data, size, str->allow_quit)
+      : (str->allow_quit ?
+	 write_allowing_quit (str->fd, data, size) :
+	 retry_write (str->fd, data, size));
   else
     retval = 0;
   if (retval < 0 && errno_would_block_p (errno) && str->blocked_ok)
@@ -1409,7 +1437,9 @@
 filedesc_closer (Lstream *stream)
 {
   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
-  if (str->closing)
+  if (str->tls_state)
+    return tls_close (str->tls_state);
+  else if (str->closing)
     return retry_close (str->fd);
   else
     return 0;
@@ -1439,6 +1469,32 @@
   return str->fd;
 }
 
+static int
+filedesc_tls_p (Lstream *stream)
+{
+  struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
+  return str->tls_state != NULL;
+}
+
+static int
+filedesc_tls_negotiater (Lstream *instream, Lstream *outstream,
+			 const Extbyte *host, Lisp_Object keylist)
+{
+  struct filedesc_stream *in_str, *out_str;
+
+  if (!LSTREAM_TYPE_P (outstream, filedesc))
+    invalid_argument ("STARTTLS applies to file descriptor streams only",
+		      wrap_lstream (outstream));
+
+  in_str = FILEDESC_STREAM_DATA (instream);
+  out_str = FILEDESC_STREAM_DATA (outstream);
+  in_str->tls_state = out_str->tls_state =
+    tls_negotiate (out_str->fd, host, keylist);
+  if (out_str->tls_state != NULL)
+    in_str->fd = out_str->fd = tls_get_fd (out_str->tls_state);
+  return out_str->tls_state != NULL;
+}
+
 /*********** read from a Lisp string ***********/
 
 #define LISP_STRING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, lisp_string)
@@ -1961,6 +2017,8 @@
   LSTREAM_HAS_METHOD (filedesc, rewinder);
   LSTREAM_HAS_METHOD (filedesc, seekable_p);
   LSTREAM_HAS_METHOD (filedesc, closer);
+  LSTREAM_HAS_METHOD (filedesc, tls_p);
+  LSTREAM_HAS_METHOD (filedesc, tls_negotiater);
 
   LSTREAM_HAS_METHOD (lisp_string, reader);
   LSTREAM_HAS_METHOD (lisp_string, rewinder);