New functions SSL[_CTX]_{set,get}_mode; the initial set of mode flags is
authorBodo Möller <bodo@openssl.org>
Fri, 2 Jul 1999 13:55:32 +0000 (13:55 +0000)
committerBodo Möller <bodo@openssl.org>
Fri, 2 Jul 1999 13:55:32 +0000 (13:55 +0000)
SSL_MODE_ENABLE_PARTIAL_WRITE, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER.

CHANGES
ssl/s2_pkt.c
ssl/s3_pkt.c
ssl/ssl.h
ssl/ssl_lib.c

diff --git a/CHANGES b/CHANGES
index ef3c4b860bd2f39d9749bfb59bf49be18b885c02..b9d808d35efaff3c33423c4f615939dd465451c5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,22 @@
 
  Changes between 0.9.3a and 0.9.4
 
+  *) Introduce "mode" for SSL structures (with defaults in SSL_CTX),
+     which largely parallels "options", but is for changing API behaviour,
+     whereas "options" are about protocol behaviour.
+     Initial "mode" flags (still experimental) are:
+
+     SSL_MODE_ENABLE_PARTIAL_WRITE   Allow SSL_write to report success when
+                                     a single record has been written.
+     SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER  Don't insist that SSL_write
+                                     retries use the same buffer location.
+                                     (But all of the contents must be
+                                     copied!)
+     [Bodo Moeller]
+
+  *) Bugfix: SSL_set_mode ignored its parameter, only SSL_CTX_set_mode
+     worked.
+
   *) Fix problems with no-hmac etc.
      [Ulf Möller, pointed out by Brian Wellington <bwelling@tislabs.com>]
 
index 73c96f3c3618e81f98bfd09be8469c8fbf5ef83d..39d8010bdeccd24a5a25f5539462abf1cbad6130 100644 (file)
@@ -391,8 +391,12 @@ int ssl2_write(SSL *s, const void *_buf, int len)
                        s->s2->wnum=tot;
                        return(i);
                        }
-               if (i == (int)n) return(tot+i);
-
+               if ((i == (int)n) ||
+                       (s->mode | SSL_MODE_ENABLE_PARTIAL_WRITE))
+                       {
+                       return(tot+i);
+                       }
+               
                n-=i;
                tot+=i;
                }
@@ -406,7 +410,9 @@ static int write_pending(SSL *s, const unsigned char *buf, unsigned int len)
 
        /* check that they have given us the same buffer to
         * write */
-       if ((s->s2->wpend_tot > (int)len) || (s->s2->wpend_buf != buf))
+       if ((s->s2->wpend_tot > (int)len) ||
+               ((s->s2->wpend_buf != buf) &&
+                (!s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)))
                {
                SSLerr(SSL_F_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY);
                return(-1);
index 4a195095d919490d4c877a7f35f981d6f04d6d52..c9dc7cc6160ed2cb2060cbb6a2743d555f01c1ab 100644 (file)
@@ -468,7 +468,12 @@ int ssl3_write_bytes(SSL *s, int type, const void *_buf, int len)
                if (type == SSL3_RT_HANDSHAKE)
                        ssl3_finish_mac(s,&(buf[tot]),i);
 
-               if (i == (int)n) return(tot+i);
+               if ((i == (int)n) ||
+                       (type == SSL3_RT_APPLICATION_DATA &&
+                       (s->mode | SSL_MODE_ENABLE_PARTIAL_WRITE)))
+                       {
+                       return(tot+i);
+                       }
 
                n-=i;
                tot+=i;
@@ -596,7 +601,9 @@ static int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
        int i;
 
 /* XXXX */
-       if ((s->s3->wpend_tot > (int)len) || (s->s3->wpend_buf != buf)
+       if ((s->s3->wpend_tot > (int)len)
+               || ((s->s3->wpend_buf != buf) &&
+                       (!s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))
                || (s->s3->wpend_type != type))
                {
                SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY);
index d75d18dd2641ecb4e3f8165c5d57345e3a42cd85..e4478542b7063903a2ea29b17dcef338c988816c 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -295,18 +295,39 @@ typedef struct ssl_session_st
 #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG         0x80000000L
 #define SSL_OP_ALL                                     0x000FFFFFL
 
+#define SSL_OP_NO_SSLv2                                        0x01000000L
+#define SSL_OP_NO_SSLv3                                        0x02000000L
+#define SSL_OP_NO_TLSv1                                        0x04000000L
+
+/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
+ * when just a single record has been written): */
+#define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001L
+/* Make it possible to retry SSL_write() with changed buffer location
+ * (buffer contents must stay the same!); this is not the default to avoid
+ * the misconception that non-blocking SSL_write() behaves like
+ * non-blocking write(): */
+#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
+
+/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
+ * they cannot be used to clear bits. */
+
 #define SSL_CTX_set_options(ctx,op) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_OPTIONS,op,NULL)
 #define SSL_CTX_get_options(ctx) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_OPTIONS,0,NULL)
 #define SSL_set_options(ssl,op) \
-       SSL_ctrl(ssl,SSL_CTRL_OPTIONS,0,NULL)
+       SSL_ctrl(ssl,SSL_CTRL_OPTIONS,op,NULL)
 #define SSL_get_options(ssl) \
         SSL_ctrl(ssl,SSL_CTRL_OPTIONS,0,NULL)
 
-#define SSL_OP_NO_SSLv2                                        0x01000000L
-#define SSL_OP_NO_SSLv3                                        0x02000000L
-#define SSL_OP_NO_TLSv1                                        0x04000000L
+#define SSL_CTX_set_mode(ctx,op) \
+       SSL_CTX_ctrl(ctx,SSL_CTRL_MODE,op,NULL)
+#define SSL_CTX_get_mode(ctx) \
+       SSL_CTX_ctrl(ctx,SSL_CTRL_MODE,0,NULL)
+#define SSL_set_mode(ssl,op) \
+       SSL_ctrl(ssl,SSL_CTRL_MODE,op,NULL)
+#define SSL_get_mode(ssl) \
+        SSL_ctrl(ssl,SSL_CTRL_MODE,0,NULL)
 
 #define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT     (1024*20)
 
@@ -327,6 +348,7 @@ struct ssl_ctx_st
        {
        SSL_METHOD *method;
        unsigned long options;
+       unsigned long mode;
 
        STACK_OF(SSL_CIPHER) *cipher_list;
        /* same as above but sorted for lookup */
@@ -605,7 +627,8 @@ struct ssl_st
        STACK_OF(X509_NAME) *client_CA;
 
        int references;
-       unsigned long options;
+       unsigned long options; /* protocol behaviour */
+       unsigned long mode; /* API behaviour */
        int first_packet;
        int client_version;     /* what was passed, used for
                                 * SSLv3/TLS rolback check */
@@ -780,6 +803,7 @@ struct ssl_st
 #define SSL_CTRL_SESS_TIMEOUTS                 30
 #define SSL_CTRL_SESS_CACHE_FULL               31
 #define SSL_CTRL_OPTIONS                       32
+#define SSL_CTRL_MODE                  33
 
 #define SSL_CTRL_GET_READ_AHEAD                        40
 #define SSL_CTRL_SET_READ_AHEAD                        41
index 95e8405cd7d1919baeb5e2d0fc2afa39b0d13213..89c5481fd8c9651806a712b56995cbd70a35ae99 100644 (file)
@@ -215,6 +215,7 @@ SSL *SSL_new(SSL_CTX *ctx)
        s->references=1;
        s->server=(ctx->method->ssl_accept == ssl_undefined_function)?0:1;
        s->options=ctx->options;
+       s->mode=ctx->mode;
        SSL_clear(s);
 
        CRYPTO_new_ex_data(ssl_meth,(char *)s,&s->ex_data);
@@ -695,6 +696,8 @@ long SSL_ctrl(SSL *s,int cmd,long larg,char *parg)
                return(l);
        case SSL_CTRL_OPTIONS:
                return(s->options|=larg);
+       case SSL_CTRL_MODE:
+               return(s->mode|=larg);
        default:
                return(s->method->ssl_ctrl(s,cmd,larg,parg));
                }
@@ -752,6 +755,8 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,char *parg)
                return(ctx->stats.sess_cache_full);
        case SSL_CTRL_OPTIONS:
                return(ctx->options|=larg);
+       case SSL_CTRL_MODE:
+               return(ctx->mode|=larg);
        default:
                return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg));
                }