- long length)
- {
- int version,ssl_version=0,i;
- long id;
- ASN1_INTEGER ai,*aip;
- ASN1_OCTET_STRING os,*osp;
- M_ASN1_D2I_vars(a,SSL_SESSION *,SSL_SESSION_new);
-
- aip= &ai;
- osp= &os;
-
- M_ASN1_D2I_Init();
- M_ASN1_D2I_start_sequence();
-
- ai.data=NULL; ai.length=0;
- M_ASN1_D2I_get_x(ASN1_INTEGER,aip,d2i_ASN1_INTEGER);
- version=(int)ASN1_INTEGER_get(aip);
- if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; }
-
- /* we don't care about the version right now :-) */
- M_ASN1_D2I_get_x(ASN1_INTEGER,aip,d2i_ASN1_INTEGER);
- ssl_version=(int)ASN1_INTEGER_get(aip);
- ret->ssl_version=ssl_version;
- if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; }
-
- os.data=NULL; os.length=0;
- M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
- if (ssl_version == SSL2_VERSION)
- {
- if (os.length != 3)
- {
- c.error=SSL_R_CIPHER_CODE_WRONG_LENGTH;
- goto err;
- }
- id=0x02000000L|
- ((unsigned long)os.data[0]<<16L)|
- ((unsigned long)os.data[1]<< 8L)|
- (unsigned long)os.data[2];
- }
- else if ((ssl_version>>8) >= SSL3_VERSION_MAJOR)
- {
- if (os.length != 2)
- {
- c.error=SSL_R_CIPHER_CODE_WRONG_LENGTH;
- goto err;
- }
- id=0x03000000L|
- ((unsigned long)os.data[0]<<8L)|
- (unsigned long)os.data[1];
- }
- else
- {
- c.error=SSL_R_UNKNOWN_SSL_VERSION;
- goto err;
- }
-
- ret->cipher=NULL;
- ret->cipher_id=id;
-
- M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
- if ((ssl_version>>8) >= SSL3_VERSION_MAJOR)
- i=SSL3_MAX_SSL_SESSION_ID_LENGTH;
- else /* if (ssl_version>>8 == SSL2_VERSION_MAJOR) */
- i=SSL2_MAX_SSL_SESSION_ID_LENGTH;
-
- if (os.length > i)
- os.length = i;
- if (os.length > (int)sizeof(ret->session_id)) /* can't happen */
- os.length = sizeof(ret->session_id);
-
- ret->session_id_length=os.length;
- OPENSSL_assert(os.length <= (int)sizeof(ret->session_id));
- memcpy(ret->session_id,os.data,os.length);
-
- M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
- if (os.length > SSL_MAX_MASTER_KEY_LENGTH)
- ret->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;
- else
- ret->master_key_length=os.length;
- memcpy(ret->master_key,os.data,ret->master_key_length);
-
- os.length=0;
-
-#ifndef OPENSSL_NO_KRB5
- os.length=0;
- M_ASN1_D2I_get_opt(osp,d2i_ASN1_OCTET_STRING,V_ASN1_OCTET_STRING);
- if (os.data)
- {
- if (os.length > SSL_MAX_KRB5_PRINCIPAL_LENGTH)
- ret->krb5_client_princ_len=0;
- else
- ret->krb5_client_princ_len=os.length;
- memcpy(ret->krb5_client_princ,os.data,ret->krb5_client_princ_len);
- OPENSSL_free(os.data);
- os.data = NULL;
- os.length = 0;
- }
- else
- ret->krb5_client_princ_len=0;
-#endif /* OPENSSL_NO_KRB5 */
-
- M_ASN1_D2I_get_IMP_opt(osp,d2i_ASN1_OCTET_STRING,0,V_ASN1_OCTET_STRING);
- if (os.length > SSL_MAX_KEY_ARG_LENGTH)
- ret->key_arg_length=SSL_MAX_KEY_ARG_LENGTH;
- else
- ret->key_arg_length=os.length;
- memcpy(ret->key_arg,os.data,ret->key_arg_length);
- if (os.data != NULL) OPENSSL_free(os.data);
-
- ai.length=0;
- M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,1);
- if (ai.data != NULL)
- {
- ret->time=ASN1_INTEGER_get(aip);
- OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
- }
- else
- ret->time=(unsigned long)time(NULL);
-
- ai.length=0;
- M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,2);
- if (ai.data != NULL)
- {
- ret->timeout=ASN1_INTEGER_get(aip);
- OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
- }
- else
- ret->timeout=3;
-
- if (ret->peer != NULL)
- {
- X509_free(ret->peer);
- ret->peer=NULL;
- }
- M_ASN1_D2I_get_EXP_opt(ret->peer,d2i_X509,3);
-
- os.length=0;
- os.data=NULL;
- M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,4);
-
- if(os.data != NULL)
- {
- if (os.length > SSL_MAX_SID_CTX_LENGTH)
- {
- c.error=SSL_R_BAD_LENGTH;
- goto err;
- }
- else
- {
- ret->sid_ctx_length=os.length;
- memcpy(ret->sid_ctx,os.data,os.length);
- }
- OPENSSL_free(os.data); os.data=NULL; os.length=0;
- }
- else
- ret->sid_ctx_length=0;
-
- ai.length=0;
- M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,5);
- if (ai.data != NULL)
- {
- ret->verify_result=ASN1_INTEGER_get(aip);
- OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
- }
- else
- ret->verify_result=X509_V_OK;
-
-#ifndef OPENSSL_NO_TLSEXT
- os.length=0;
- os.data=NULL;
- M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,6);
- if (os.data)
- {
- ret->tlsext_hostname = BUF_strndup((char *)os.data, os.length);
- OPENSSL_free(os.data);
- os.data = NULL;
- os.length = 0;
- }
- else
- ret->tlsext_hostname=NULL;
-#endif /* OPENSSL_NO_TLSEXT */
+ long length)
+{
+ long id;
+ unsigned int tmpl;
+ const unsigned char *p = *pp;
+ SSL_SESSION_ASN1 *as = NULL;
+ SSL_SESSION *ret = NULL;
+
+ as = d2i_SSL_SESSION_ASN1(NULL, &p, length);
+ /* ASN.1 code returns suitable error */
+ if (as == NULL)
+ goto err;
+
+ if (!a || !*a) {
+ ret = SSL_SESSION_new();
+ if (ret == NULL)
+ goto err;
+ } else {
+ ret = *a;
+ }
+
+ if (as->version != SSL_SESSION_ASN1_VERSION) {
+ SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNKNOWN_SSL_VERSION);
+ goto err;
+ }
+
+ if ((as->ssl_version >> 8) != SSL3_VERSION_MAJOR
+ && (as->ssl_version >> 8) != DTLS1_VERSION_MAJOR
+ && as->ssl_version != DTLS1_BAD_VER) {
+ SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNSUPPORTED_SSL_VERSION);
+ goto err;
+ }
+
+ ret->ssl_version = (int)as->ssl_version;
+
+ if (as->cipher->length != 2) {
+ SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_CIPHER_CODE_WRONG_LENGTH);
+ goto err;
+ }
+
+ id = 0x03000000L | ((unsigned long)as->cipher->data[0] << 8L)
+ | (unsigned long)as->cipher->data[1];
+
+ ret->cipher = NULL;
+ ret->cipher_id = id;
+
+ if (!ssl_session_memcpy(ret->session_id, &ret->session_id_length,
+ as->session_id, SSL3_MAX_SSL_SESSION_ID_LENGTH))
+ goto err;
+
+ if (!ssl_session_memcpy(ret->master_key, &tmpl,
+ as->master_key, SSL_MAX_MASTER_KEY_LENGTH))
+ goto err;
+
+ ret->master_key_length = tmpl;
+
+ if (as->time != 0)
+ ret->time = as->time;
+ else
+ ret->time = (unsigned long)time(NULL);
+
+ if (as->timeout != 0)
+ ret->timeout = as->timeout;
+ else
+ ret->timeout = 3;
+
+ X509_free(ret->peer);
+ ret->peer = as->peer;
+ as->peer = NULL;
+
+ if (!ssl_session_memcpy(ret->sid_ctx, &ret->sid_ctx_length,
+ as->session_id_context, SSL_MAX_SID_CTX_LENGTH))
+ goto err;
+
+ /* NB: this defaults to zero which is X509_V_OK */
+ ret->verify_result = as->verify_result;
+
+ if (!ssl_session_strndup(&ret->tlsext_hostname, as->tlsext_hostname))
+ goto err;