Initial "opaque SSL" framework. If an application defines
authorDr. Stephen Henson <steve@openssl.org>
Fri, 29 Apr 2011 22:37:12 +0000 (22:37 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 29 Apr 2011 22:37:12 +0000 (22:37 +0000)
OPENSSL_NO_SSL_INTERN all ssl related structures are opaque
and internals cannot be directly accessed. Many applications
will need some modification to support this and most likely some
additional functions added to OpenSSL.

The advantage of this option is that any application supporting
it will still be binary compatible if SSL structures change.

14 files changed:
CHANGES
apps/apps.h
apps/ciphers.c
apps/s_client.c
apps/s_server.c
apps/sess_id.c
ssl/dtls1.h
ssl/ssl.h
ssl/ssl2.h
ssl/ssl3.h
ssl/ssl_ciph.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_sess.c

diff --git a/CHANGES b/CHANGES
index aa0fe51..30458ff 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
 
  Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]
 
+  *) New option OPENSSL_NO_SSL_INTERN. If an application can be compiled
+     with this defined it will not be affected by any changes to ssl internal
+     structures. Add several utility functions to allow openssl application
+     to work with OPENSSL_NO_SSL_INTERN defined.
+     [Steve Henson]
+
   *) Minor change to DRBG entropy callback semantics. In some cases
      there is no mutiple of the block length between min_len and
      max_len. Allow the callback to return more than max_len bytes
index 8bd3643..77d07da 100644 (file)
@@ -365,6 +365,8 @@ int raw_write_stdout(const void *,int);
 double app_tminterval (int stop,int usertime);
 #endif
 
+#define OPENSSL_NO_SSL_INTERN
+
 #ifndef OPENSSL_NO_NEXTPROTONEG
 unsigned char *next_protos_parse(unsigned short *outlen, const char *in);
 #endif
index 3d4c60d..5f2b739 100644 (file)
@@ -196,7 +196,7 @@ int MAIN(int argc, char **argv)
                        
                        if (Verbose)
                                {
-                               unsigned long id = c->id;
+                               unsigned long id = SSL_CIPHER_get_id(c);
                                int id0 = (int)(id >> 24);
                                int id1 = (int)((id >> 16) & 0xffL);
                                int id2 = (int)((id >> 8) & 0xffL);
index 8a57dcf..8e0e8cb 100644 (file)
@@ -1238,7 +1238,7 @@ re_start:
                        }
                }
 #endif                                              
-       if (c_Pause & 0x01) con->debug=1;
+       if (c_Pause & 0x01) SSL_set_debug(con, 1);
 
        if ( SSL_version(con) == DTLS1_VERSION)
                {
@@ -1287,7 +1287,7 @@ re_start:
 
        if (c_debug)
                {
-               con->debug=1;
+               SSL_set_debug(con, 1);
                BIO_set_callback(sbio,bio_dump_callback);
                BIO_set_callback_arg(sbio,(char *)bio_c_out);
                }
@@ -1972,7 +1972,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
                        BIO_number_read(SSL_get_rbio(s)),
                        BIO_number_written(SSL_get_wbio(s)));
                }
-       BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, "));
+       BIO_printf(bio,(SSL_cache_hit(s)?"---\nReused, ":"---\nNew, "));
        c=SSL_get_current_cipher(s);
        BIO_printf(bio,"%s, Cipher is %s\n",
                SSL_CIPHER_get_version(c),
index 97389cd..9233384 100644 (file)
@@ -2042,7 +2042,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
 
        if (s_debug)
                {
-               con->debug=1;
+               SSL_set_debug(con, 1);
                BIO_set_callback(SSL_get_rbio(con),bio_dump_callback);
                BIO_set_callback_arg(SSL_get_rbio(con),(char *)bio_s_out);
                }
@@ -2380,7 +2380,7 @@ static int init_ssl_connection(SSL *con)
                BIO_printf(bio_s_out, "\n");
                }
 #endif
-       if (con->hit) BIO_printf(bio_s_out,"Reused session-id\n");
+       if (SSL_cache_hit(con)) BIO_printf(bio_s_out,"Reused session-id\n");
        if (SSL_ctrl(con,SSL_CTRL_GET_FLAGS,0,NULL) &
                TLS1_FLAGS_TLS_PADDING_BUG)
                BIO_printf(bio_s_out,"Peer has incorrect TLSv1 block padding\n");
@@ -2499,7 +2499,7 @@ static int www_body(char *hostname, int s, unsigned char *context)
 
        if (s_debug)
                {
-               con->debug=1;
+               SSL_set_debug(con, 1);
                BIO_set_callback(SSL_get_rbio(con),bio_dump_callback);
                BIO_set_callback_arg(SSL_get_rbio(con),(char *)bio_s_out);
                }
@@ -2585,7 +2585,7 @@ static int www_body(char *hostname, int s, unsigned char *context)
                                goto err;
                                }
                        /* EVIL HACK! */
-                       con->state = SSL_ST_ACCEPT;
+                       SSL_set_state(con, SSL_ST_ACCEPT);
                        i=SSL_do_handshake(con);
                        BIO_printf(bio_s_out, "SSL_do_handshake -> %d\n",i);
                        if (i <= 0)
@@ -2651,7 +2651,7 @@ static int www_body(char *hostname, int s, unsigned char *context)
                                        }
                                BIO_puts(io,"\n");
                                }
-                       BIO_printf(io,((con->hit)
+                       BIO_printf(io,(SSL_cache_hit(con)
                                ?"---\nReused, "
                                :"---\nNew, "));
                        c=SSL_get_current_cipher(con);
@@ -2908,7 +2908,7 @@ static int generate_session_id(const SSL *ssl, unsigned char *id,
 typedef struct simple_ssl_session_st
        {
        unsigned char *id;
-       int idlen;
+       unsigned int idlen;
        unsigned char *der;
        int derlen;
        struct simple_ssl_session_st *next;
@@ -2923,10 +2923,10 @@ static int add_session(SSL *ssl, SSL_SESSION *session)
 
        sess = OPENSSL_malloc(sizeof(simple_ssl_session));
 
-       sess->idlen = session->session_id_length;
+       sess->idlen = SSL_SESSION_get_id_len(session);
        sess->derlen = i2d_SSL_SESSION(session, NULL);
 
-       sess->id = BUF_memdup(session->session_id, sess->idlen);
+       sess->id = BUF_memdup(SSL_SESSION_get0_id(session), sess->idlen);
 
        sess->der = OPENSSL_malloc(sess->derlen);
        p = sess->der;
@@ -2945,7 +2945,7 @@ static SSL_SESSION *get_session(SSL *ssl, unsigned char *id, int idlen,
        *do_copy = 0;
        for (sess = first; sess; sess = sess->next)
                {
-               if (idlen == sess->idlen && !memcmp(sess->id, id, idlen))
+               if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen))
                        {
                        const unsigned char *p = sess->der;
                        BIO_printf(bio_err, "Lookup session: cache hit\n");
@@ -2959,8 +2959,8 @@ static SSL_SESSION *get_session(SSL *ssl, unsigned char *id, int idlen,
 static void del_session(SSL_CTX *sctx, SSL_SESSION *session)
        {
        simple_ssl_session *sess, *prev = NULL;
-       unsigned char *id = session->session_id;
-       int idlen = session->session_id_length;
+       const unsigned char *id = SSL_SESSION_get0_id(session);
+       unsigned int idlen = SSL_SESSION_get_id_len(session);
        for (sess = first; sess; sess = sess->next)
                {
                if (idlen == sess->idlen && !memcmp(sess->id, id, idlen))
index b99179f..b16686c 100644 (file)
@@ -90,6 +90,7 @@ int MAIN(int, char **);
 int MAIN(int argc, char **argv)
        {
        SSL_SESSION *x=NULL;
+       X509 *peer = NULL;
        int ret=1,i,num,badops=0;
        BIO *out=NULL;
        int informat,outformat;
@@ -163,16 +164,17 @@ bad:
        ERR_load_crypto_strings();
        x=load_sess_id(infile,informat);
        if (x == NULL) { goto end; }
+       peer = SSL_SESSION_get0_peer(x);
 
        if(context)
            {
-           x->sid_ctx_length=strlen(context);
-           if(x->sid_ctx_length > SSL_MAX_SID_CTX_LENGTH)
+           size_t ctx_len = strlen(context);
+           if(ctx_len > SSL_MAX_SID_CTX_LENGTH)
                {
                BIO_printf(bio_err,"Context too long\n");
                goto end;
                }
-           memcpy(x->sid_ctx,context,x->sid_ctx_length);
+           SSL_SESSION_set1_id_context(x, (unsigned char *)context, ctx_len);
            }
 
 #ifdef undef
@@ -231,10 +233,10 @@ bad:
 
                if (cert)
                        {
-                       if (x->peer == NULL)
+                       if (peer == NULL)
                                BIO_puts(out,"No certificate present\n");
                        else
-                               X509_print(out,x->peer);
+                               X509_print(out,peer);
                        }
                }
 
@@ -253,12 +255,12 @@ bad:
                        goto end;
                        }
                }
-       else if (!noout && (x->peer != NULL)) /* just print the certificate */
+       else if (!noout && (peer != NULL)) /* just print the certificate */
                {
                if      (outformat == FORMAT_ASN1)
-                       i=(int)i2d_X509_bio(out,x->peer);
+                       i=(int)i2d_X509_bio(out,peer);
                else if (outformat == FORMAT_PEM)
-                       i=PEM_write_bio_X509(out,x->peer);
+                       i=PEM_write_bio_X509(out,peer);
                else    {
                        BIO_printf(bio_err,"bad output format specified for outfile\n");
                        goto end;
index 14a755c..6317da9 100644 (file)
@@ -105,6 +105,8 @@ extern "C" {
 #define DTLS1_AL_HEADER_LENGTH                   2
 #endif
 
+#ifndef OPENSSL_NO_SSL_INTERN
+
 
 typedef struct dtls1_bitmap_st
        {
@@ -253,6 +255,7 @@ typedef struct dtls1_record_data_st
        SSL3_RECORD    rrec;
        } DTLS1_RECORD_DATA;
 
+#endif
 
 /* Timeout multipliers (timeout slice is defined in apps/timeouts.h */
 #define DTLS1_TMO_READ_COUNT                      2
index 49faba7..c3c0a1b 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -359,9 +359,20 @@ extern "C" {
  * in SSL_CTX. */
 typedef struct ssl_st *ssl_crock_st;
 typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
+typedef struct ssl_method_st SSL_METHOD;
+typedef struct ssl_cipher_st SSL_CIPHER;
+typedef struct ssl_session_st SSL_SESSION;
+
+DECLARE_STACK_OF(SSL_CIPHER)
+
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
+
+
+#ifndef OPENSSL_NO_SSL_INTERN
 
 /* used to hold info on the particular ciphers used */
-typedef struct ssl_cipher_st
+struct ssl_cipher_st
        {
        int valid;
        const char *name;               /* text name */
@@ -378,15 +389,11 @@ typedef struct ssl_cipher_st
        unsigned long algorithm2;       /* Extra flags */
        int strength_bits;              /* Number of bits really used */
        int alg_bits;                   /* Number of bits for algorithm */
-       } SSL_CIPHER;
-
-DECLARE_STACK_OF(SSL_CIPHER)
+       };
 
-typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
-typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
 
 /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
-typedef struct ssl_method_st
+struct ssl_method_st
        {
        int version;
        int (*ssl_new)(SSL *s);
@@ -419,7 +426,7 @@ typedef struct ssl_method_st
        int (*ssl_version)(void);
        long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
        long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
-       } SSL_METHOD;
+       };
 
 /* Lets make this into an ASN.1 type structure as follows
  * SSL_SESSION_ID ::= SEQUENCE {
@@ -444,7 +451,7 @@ typedef struct ssl_method_st
  * Look in ssl/ssl_asn1.c for more details
  * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
  */
-typedef struct ssl_session_st
+struct ssl_session_st
        {
        int ssl_version;        /* what ssl version session info is
                                 * being kept in here? */
@@ -522,8 +529,9 @@ typedef struct ssl_session_st
 #ifndef OPENSSL_NO_SRP
        char *srp_username;
 #endif
-       } SSL_SESSION;
+       };
 
+#endif
 
 #define SSL_OP_MICROSOFT_SESS_ID_BUG                   0x00000001L
 #define SSL_OP_NETSCAPE_CHALLENGE_BUG                  0x00000002L
@@ -655,6 +663,8 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int con
 
 #ifndef OPENSSL_NO_SRP
 
+#ifndef OPENSSL_NO_SSL_INTERN
+
 typedef struct srp_ctx_st
        {
        /* param for all the callbacks */
@@ -677,6 +687,8 @@ typedef struct srp_ctx_st
        unsigned long srp_Mask;
        } SRP_CTX;
 
+#endif
+
 /* see tls_srp.c */
 int SSL_SRP_CTX_init(SSL *s);
 int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx);
@@ -714,7 +726,11 @@ int SRP_have_to_put_srp_username(SSL *s);
 typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
                                unsigned int *id_len);
 
-typedef struct ssl_comp_st
+typedef struct ssl_comp_st SSL_COMP;
+
+#ifndef OPENSSL_NO_SSL_INTERN
+
+struct ssl_comp_st
        {
        int id;
        const char *name;
@@ -723,7 +739,7 @@ typedef struct ssl_comp_st
 #else
        char *method;
 #endif
-       } SSL_COMP;
+       };
 
 DECLARE_STACK_OF(SSL_COMP)
 DECLARE_LHASH_OF(SSL_SESSION);
@@ -941,6 +957,8 @@ struct ssl_ctx_st
 #endif
        };
 
+#endif
+
 #define SSL_SESS_CACHE_OFF                     0x0000
 #define SSL_SESS_CACHE_CLIENT                  0x0001
 #define SSL_SESS_CACHE_SERVER                  0x0002
@@ -1057,6 +1075,8 @@ const char *SSL_get_psk_identity(const SSL *s);
 #define SSL_MAC_FLAG_READ_MAC_STREAM 1
 #define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
 
+#ifndef OPENSSL_NO_SSL_INTERN
+
 struct ssl_st
        {
        /* protocol version
@@ -1301,6 +1321,8 @@ struct ssl_st
 #endif /* OPENSSL_NO_TLSEXT */
        };
 
+#endif
+
 #ifdef __cplusplus
 }
 #endif
@@ -1611,6 +1633,7 @@ const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
 int    SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits);
 char * SSL_CIPHER_get_version(const SSL_CIPHER *c);
 const char *   SSL_CIPHER_get_name(const SSL_CIPHER *c);
+unsigned long  SSL_CIPHER_get_id(const SSL_CIPHER *c);
 
 int    SSL_get_fd(const SSL *s);
 int    SSL_get_rfd(const SSL *s);
@@ -1676,6 +1699,11 @@ long     SSL_SESSION_set_time(SSL_SESSION *s, long t);
 long   SSL_SESSION_get_timeout(const SSL_SESSION *s);
 long   SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
 void   SSL_copy_session_id(SSL *to,const SSL *from);
+unsigned int SSL_SESSION_get_id_len(SSL_SESSION *s);
+const unsigned char *SSL_SESSION_get0_id(SSL_SESSION *s);
+X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
+int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx,
+                              unsigned int sid_ctx_len);
 
 SSL_SESSION *SSL_SESSION_new(void);
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
@@ -1867,6 +1895,7 @@ void SSL_set_info_callback(SSL *ssl,
                           void (*cb)(const SSL *ssl,int type,int val));
 void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
 int SSL_state(const SSL *ssl);
+void SSL_set_state(SSL *ssl, int state);
 
 void SSL_set_verify_result(SSL *ssl,long v);
 long SSL_get_verify_result(const SSL *ssl);
@@ -1977,6 +2006,9 @@ void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
 void SSL_set_not_resumable_session_callback(SSL *ssl,
        int (*cb)(SSL *ssl, int is_forward_secure));
 
+void SSL_set_debug(SSL *s, int debug);
+int SSL_cache_hit(SSL *s);
+       
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
@@ -2154,6 +2186,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT                    188
 #define SSL_F_SSL_SESSION_NEW                           189
 #define SSL_F_SSL_SESSION_PRINT_FP                      190
+#define SSL_F_SSL_SESSION_SET1_ID_CONTEXT               306
 #define SSL_F_SSL_SESS_CERT_NEW                                 225
 #define SSL_F_SSL_SET_CERT                              191
 #define SSL_F_SSL_SET_CIPHER_LIST                       271
index 99a52ea..eb25dcb 100644 (file)
@@ -155,6 +155,8 @@ extern "C" {
 #define  CERT          char
 #endif
 
+#ifndef OPENSSL_NO_SSL_INTERN
+
 typedef struct ssl2_state_st
        {
        int three_byte_header;
@@ -219,6 +221,8 @@ typedef struct ssl2_state_st
                } tmp;
        } SSL2_STATE;
 
+#endif
+
 /* SSLv2 */
 /* client */
 #define SSL2_ST_SEND_CLIENT_HELLO_A            (0x10|SSL_ST_CONNECT)
index 4ff7c80..ab63140 100644 (file)
@@ -339,6 +339,8 @@ extern "C" {
 #define SSL3_AD_CERTIFICATE_UNKNOWN    46
 #define SSL3_AD_ILLEGAL_PARAMETER      47      /* fatal */
 
+#ifndef OPENSSL_NO_SSL_INTERN
+
 typedef struct ssl3_record_st
        {
 /*r */ int type;               /* type of record */
@@ -360,6 +362,8 @@ typedef struct ssl3_buffer_st
        int left;               /* how many bytes left */
        } SSL3_BUFFER;
 
+#endif
+
 #define SSL3_CT_RSA_SIGN                       1
 #define SSL3_CT_DSS_SIGN                       2
 #define SSL3_CT_RSA_FIXED_DH                   3
@@ -380,6 +384,8 @@ typedef struct ssl3_buffer_st
 #define TLS1_FLAGS_TLS_PADDING_BUG             0x0008
 #define TLS1_FLAGS_SKIP_CERT_VERIFY            0x0010
 
+#ifndef OPENSSL_NO_SSL_INTERN
+
 typedef struct ssl3_state_st
        {
        long flags;
@@ -520,6 +526,7 @@ typedef struct ssl3_state_st
         int send_connection_binding; /* TODOEKR */
        } SSL3_STATE;
 
+#endif
 
 /* SSLv3 */
 /*client */
index bbab6a9..84829e5 100644 (file)
@@ -1660,6 +1660,11 @@ int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits)
        return(ret);
        }
 
+unsigned long SSL_CIPHER_get_id(const SSL_CIPHER *c)
+       {
+       return c->id;
+       }
+
 SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n)
        {
        SSL_COMP *ctmp;
index f9475db..af52856 100644 (file)
@@ -238,6 +238,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),       "SSL_RSA_PUBLIC_ENCRYPT"},
 {ERR_FUNC(SSL_F_SSL_SESSION_NEW),      "SSL_SESSION_new"},
 {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP), "SSL_SESSION_print_fp"},
+{ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT),  "SSL_SESSION_set1_id_context"},
 {ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW),    "SSL_SESS_CERT_NEW"},
 {ERR_FUNC(SSL_F_SSL_SET_CERT), "SSL_SET_CERT"},
 {ERR_FUNC(SSL_F_SSL_SET_CIPHER_LIST),  "SSL_set_cipher_list"},
index 7fb4bdf..6f70bdf 100644 (file)
@@ -2934,6 +2934,11 @@ int SSL_state(const SSL *ssl)
        return(ssl->state);
        }
 
+void SSL_set_state(SSL *ssl, int state)
+       {
+       ssl->state = state;
+       }
+
 void SSL_set_verify_result(SSL *ssl,long arg)
        {
        ssl->verify_result=arg;
@@ -3205,6 +3210,16 @@ void ssl_clear_hash_ctx(EVP_MD_CTX **hash)
        *hash=NULL;
 }
 
+void SSL_set_debug(SSL *s, int debug)
+       {
+       s->debug = debug;
+       }
+
+int SSL_cache_hit(SSL *s)
+       {
+       return s->hit;
+       }
+
 #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16)
 #include "../crypto/bio/bss_file.c"
 #endif
index a3ce652..3f0b195 100644 (file)
@@ -836,6 +836,35 @@ long SSL_SESSION_set_time(SSL_SESSION *s, long t)
        return(t);
        }
 
+unsigned int SSL_SESSION_get_id_len(SSL_SESSION *s)
+       {
+       return s->session_id_length;
+       }
+
+const unsigned char *SSL_SESSION_get0_id(SSL_SESSION *s)
+       {
+       return s->session_id;
+       }
+
+X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
+       {
+       return s->peer;
+       }
+
+int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx,
+                              unsigned int sid_ctx_len)
+    {
+    if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH)
+       {
+       SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+       return 0;
+       }
+    s->sid_ctx_length=sid_ctx_len;
+    memcpy(s->sid_ctx,sid_ctx,sid_ctx_len);
+
+    return 1;
+    }
+
 long SSL_CTX_set_timeout(SSL_CTX *s, long t)
        {
        long l;