[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[User]
## CVE: CVE-2016-4658

xpointer.c in libxml2 before 2.9.5 (as used in Apple iOS before 10, OS X before 10.12, tvOS before 10, and watchOS before 3, and other products) does not forbid namespace nodes in XPointer ranges, which allows remote attackers to execute arbitrary code or cause a denial of service (use-after-free and memory corruption) via a crafted XML document.

## Package
libxml2

## Files to modify
- buf.c
- include/libxml/tree.h
- xmlreader.c

## Target Source Code

### include/libxml/tree.h

#### region() [lines 37-124]
```c

typedef struct _xmlParserCtxt xmlParserCtxt;
typedef xmlParserCtxt *xmlParserCtxtPtr;

typedef struct _xmlSAXLocator xmlSAXLocator;
typedef xmlSAXLocator *xmlSAXLocatorPtr;

typedef struct _xmlSAXHandler xmlSAXHandler;
typedef xmlSAXHandler *xmlSAXHandlerPtr;

/* entities.h */
typedef struct _xmlEntity xmlEntity;
typedef xmlEntity *xmlEntityPtr;

/**
 * BASE_BUFFER_SIZE:
 *
 * default buffer size 4000.
 */
#define BASE_BUFFER_SIZE 4096

/**
 * LIBXML_NAMESPACE_DICT:
 *
 * Defines experimental behaviour:
 * 1) xmlNs gets an additional field @context (a xmlDoc)
 * 2) when creating a tree, xmlNs->href is stored in the dict of xmlDoc.
 */
/* #define LIBXML_NAMESPACE_DICT */

/**
 * xmlBufferAllocationScheme:
 *
 * A buffer allocation scheme can be defined to either match exactly the
 * need or double it's allocated size each time it is found too small.
 */

typedef enum {
    XML_BUFFER_ALLOC_DOUBLEIT,	/* double each time one need to grow */
    XML_BUFFER_ALLOC_EXACT,	/* grow only to the minimal size */
    XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer */
    XML_BUFFER_ALLOC_IO,	/* special allocation scheme used for I/O */
    XML_BUFFER_ALLOC_HYBRID	/* exact up to a threshold, and doubleit thereafter */
} xmlBufferAllocationScheme;

/**
 * xmlBuffer:
 *
 * A buffer structure, this old construct is limited to 2GB and
 * is being deprecated, use API with xmlBuf instead
 */
typedef struct _xmlBuffer xmlBuffer;
typedef xmlBuffer *xmlBufferPtr;
struct _xmlBuffer {
    xmlChar *content;		/* The buffer content UTF8 */
    unsigned int use;		/* The buffer size used */
    unsigned int size;		/* The buffer size */
    xmlBufferAllocationScheme alloc; /* The realloc method */
    xmlChar *contentIO;		/* in IO mode we may have a different base */
};

/**
 * xmlBuf:
 *
 * A buffer structure, new one, the actual structure internals are not public
 */

typedef struct _xmlBuf xmlBuf;

/**
 * xmlBufPtr:
 *
 * A pointer to a buffer structure, the actual structure internals are not
 * public
 */

typedef xmlBuf *xmlBufPtr;

/*
 * A few public routines for xmlBuf. As those are expected to be used
 * mostly internally the bulk of the routines are internal in buf.h
 */
XMLPUBFUN xmlChar* XMLCALL       xmlBufContent	(const xmlBufPtr buf);
XMLPUBFUN xmlChar* XMLCALL       xmlBufEnd      (const xmlBufPtr buf);
XMLPUBFUN size_t XMLCALL         xmlBufUse      (const xmlBufPtr buf);
XMLPUBFUN size_t XMLCALL         xmlBufShrink	(xmlBufPtr buf, size_t len);

/*
```

## Upstream Fix
```diff
From 213f1fe0d76d30eaed6e5853057defc43e6df2c9 Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Tue, 14 Apr 2015 17:41:48 +0800
Subject: [PATCH] CVE-2015-1819 Enforce the reader to run in constant memory

One of the operation on the reader could resolve entities
leading to the classic expansion issue. Make sure the
buffer used for xmlreader operation is bounded.
Introduce a new allocation type for the buffers for this effect.
---
 buf.c                 | 43 ++++++++++++++++++++++++++++++++++++++++++-
 include/libxml/tree.h |  3 ++-
 xmlreader.c           | 20 +++++++++++++++++++-
 3 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/buf.c b/buf.c
index 6efc7b677c..07922ff693 100644
--- a/buf.c
+++ b/buf.c
@@ -27,6 +27,7 @@
 #include <libxml/tree.h>
 #include <libxml/globals.h>
 #include <libxml/tree.h>
+#include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
 #include "buf.h"

 #define WITH_BUFFER_COMPAT
@@ -299,7 +300,8 @@ xmlBufSetAllocationScheme(xmlBufPtr buf,
     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
         (scheme == XML_BUFFER_ALLOC_EXACT) ||
         (scheme == XML_BUFFER_ALLOC_HYBRID) ||
-        (scheme == XML_BUFFER_ALLOC_IMMUTABLE)) {
+        (scheme == XML_BUFFER_ALLOC_IMMUTABLE) ||
+	(scheme == XML_BUFFER_ALLOC_BOUNDED)) {
 	buf->alloc = scheme;
         if (buf->buffer)
             buf->buffer->alloc = scheme;
@@ -458,6 +460,18 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
     size = buf->use + len + 100;
 #endif

+    if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+        /*
+	 * Used to provide parsing limits
+	 */
+        if ((buf->use + len >= XML_MAX_TEXT_LENGTH) ||
+	    (buf->size >= XML_MAX_TEXT_LENGTH)) {
+	    xmlBufMemoryError(buf, "buffer error: text too long\n");
+	    return(0);
+	}
+	if (size >= XML_MAX_TEXT_LENGTH)
+	    size = XML_MAX_TEXT_LENGTH;
+    }
     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
         size_t start_buf = buf->content - buf->contentIO;

@@ -739,6 +753,15 @@ xmlBufResize(xmlBufPtr buf, size_t size)
     CHECK_COMPAT(buf)

     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
+    if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+        /*
+	 * Used to provide parsing limits
+	 */
+        if (size >= XML_MAX_TEXT_LENGTH) {
+	    xmlBufMemoryError(buf, "buffer error: text too long\n");
+	    return(0);
+	}
+    }

     /* Don't resize if we don't have to */
     if (size < buf->size)
@@ -867,6 +890,15 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {

     needSize = buf->use + len + 2;
     if (needSize > buf->size){
+	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+	    /*
+	     * Used to provide parsing limits
+	     */
+	    if (needSize >= XML_MAX_TEXT_LENGTH) {
+		xmlBufMemoryError(buf, "buffer error: text too long\n");
+		return(-1);
+	    }
+	}
         if (!xmlBufResize(buf, needSize)){
 	    xmlBufMemoryError(buf, "growing buffer");
             return XML_ERR_NO_MEMORY;
@@ -938,6 +970,15 @@ xmlBufAddHead(xmlBufPtr buf, const xmlChar *str, int len) {
     }
     needSize = buf->use + len + 2;
     if (needSize > buf->size){
+	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+	    /*
+	     * Used to provide parsing limits
+	     */
+	    if (needSize >= XML_MAX_TEXT_LENGTH) {
+		xmlBufMemoryError(buf, "buffer error: text too long\n");
+		return(-1);
+	    }
+	}
         if (!xmlBufResize(buf, needSize)){
 	    xmlBufMemoryError(buf, "growing buffer");
             return XML_ERR_NO_MEMORY;
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 2f90717c1b..4a9b3bc634 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -76,7 +76,8 @@ typedef enum {
     XML_BUFFER_ALLOC_EXACT,	/* grow only to the minimal size */
     XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer */
     XML_BUFFER_ALLOC_IO,	/* special allocation scheme used for I/O */
-    XML_BUFFER_ALLOC_HYBRID	/* exact up to a threshold, and doubleit thereafter */
+    XML_BUFFER_ALLOC_HYBRID,	/* exact up to a threshold, and doubleit thereafter */
+    XML_BUFFER_ALLOC_BOUNDED	/* limit the upper size of the buffer */
 } xmlBufferAllocationScheme;

 /**
diff --git a/xmlreader.c b/xmlreader.c
index f19e123382..471e7e2a64 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -2091,6 +2091,9 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
 		"xmlNewTextReader : malloc failed\n");
 	return(NULL);
     }
+    /* no operation on a reader should require a huge buffer */
+    xmlBufSetAllocationScheme(ret->buffer,
+			      XML_BUFFER_ALLOC_BOUNDED);
     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
     if (ret->sax == NULL) {
 	xmlBufFree(ret->buffer);
@@ -3616,6 +3619,7 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) {
 	    return(((xmlNsPtr) node)->href);
         case XML_ATTRIBUTE_NODE:{
 	    xmlAttrPtr attr = (xmlAttrPtr) node;
+	    const xmlChar *ret;

 	    if ((attr->children != NULL) &&
 	        (attr->children->type == XML_TEXT_NODE) &&
@@ -3629,10 +3633,21 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) {
                                         "xmlTextReaderSetup : malloc failed\n");
                         return (NULL);
                     }
+		    xmlBufSetAllocationScheme(reader->buffer,
+		                              XML_BUFFER_ALLOC_BOUNDED);
                 } else
                     xmlBufEmpty(reader->buffer);
 	        xmlBufGetNodeContent(reader->buffer, node);
-		return(xmlBufContent(reader->buffer));
+		ret = xmlBufContent(reader->buffer);
+		if (ret == NULL) {
+		    /* error on the buffer best to reallocate */
+		    xmlBufFree(reader->buffer);
+		    reader->buffer = xmlBufCreateSize(100);
+		    xmlBufSetAllocationScheme(reader->buffer,
+		                              XML_BUFFER_ALLOC_BOUNDED);
+		    ret = BAD_CAST "";
+		}
+		return(ret);
 	    }
 	    break;
 	}
@@ -5131,6 +5146,9 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
                         "xmlTextReaderSetup : malloc failed\n");
         return (-1);
     }
+    /* no operation on a reader should require a huge buffer */
+    xmlBufSetAllocationScheme(reader->buffer,
+			      XML_BUFFER_ALLOC_BOUNDED);
     if (reader->sax == NULL)
 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
     if (reader->sax == NULL) {
```

Generate a backported patch for the SUSE target version.

[Assistant]
From 213f1fe0d76d30eaed6e5853057defc43e6df2c9 Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Tue, 14 Apr 2015 17:41:48 +0800
Subject: [PATCH] CVE-2015-1819 Enforce the reader to run in constant memory

One of the operation on the reader could resolve entities
leading to the classic expansion issue. Make sure the
buffer used for xmlreader operation is bounded.
Introduce a new allocation type for the buffers for this effect.
---
 buf.c                 | 43 ++++++++++++++++++++++++++++++++++++++++++-
 include/libxml/tree.h |  3 ++-
 xmlreader.c           | 20 +++++++++++++++++++-
 3 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/buf.c b/buf.c
index 6efc7b6..07922ff 100644
--- a/buf.c
+++ b/buf.c
@@ -27,6 +27,7 @@
 #include <libxml/tree.h>
 #include <libxml/globals.h>
 #include <libxml/tree.h>
+#include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
 #include "buf.h"

 #define WITH_BUFFER_COMPAT
@@ -299,7 +300,8 @@ xmlBufSetAllocationScheme(xmlBufPtr buf,
     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
         (scheme == XML_BUFFER_ALLOC_EXACT) ||
         (scheme == XML_BUFFER_ALLOC_HYBRID) ||
-        (scheme == XML_BUFFER_ALLOC_IMMUTABLE)) {
+        (scheme == XML_BUFFER_ALLOC_IMMUTABLE) ||
+	(scheme == XML_BUFFER_ALLOC_BOUNDED)) {
 	buf->alloc = scheme;
         if (buf->buffer)
             buf->buffer->alloc = scheme;
@@ -458,6 +460,18 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
     size = buf->use + len + 100;
 #endif

+    if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+        /*
+	 * Used to provide parsing limits
+	 */
+        if ((buf->use + len >= XML_MAX_TEXT_LENGTH) ||
+	    (buf->size >= XML_MAX_TEXT_LENGTH)) {
+	    xmlBufMemoryError(buf, "buffer error: text too long\n");
+	    return(0);
+	}
+	if (size >= XML_MAX_TEXT_LENGTH)
+	    size = XML_MAX_TEXT_LENGTH;
+    }
     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
         size_t start_buf = buf->content - buf->contentIO;

@@ -739,6 +753,15 @@ xmlBufResize(xmlBufPtr buf, size_t size)
     CHECK_COMPAT(buf)

     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
+    if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+        /*
+	 * Used to provide parsing limits
+	 */
+        if (size >= XML_MAX_TEXT_LENGTH) {
+	    xmlBufMemoryError(buf, "buffer error: text too long\n");
+	    return(0);
+	}
+    }

     /* Don't resize if we don't have to */
     if (size < buf->size)
@@ -867,6 +890,15 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {

     needSize = buf->use + len + 2;
     if (needSize > buf->size){
+	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+	    /*
+	     * Used to provide parsing limits
+	     */
+	    if (needSize >= XML_MAX_TEXT_LENGTH) {
+		xmlBufMemoryError(buf, "buffer error: text too long\n");
+		return(-1);
+	    }
+	}
         if (!xmlBufResize(buf, needSize)){
 	    xmlBufMemoryError(buf, "growing buffer");
             return XML_ERR_NO_MEMORY;
@@ -938,6 +970,15 @@ xmlBufAddHead(xmlBufPtr buf, const xmlChar *str, int len) {
     }
     needSize = buf->use + len + 2;
     if (needSize > buf->size){
+	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+	    /*
+	     * Used to provide parsing limits
+	     */
+	    if (needSize >= XML_MAX_TEXT_LENGTH) {
+		xmlBufMemoryError(buf, "buffer error: text too long\n");
+		return(-1);
+	    }
+	}
         if (!xmlBufResize(buf, needSize)){
 	    xmlBufMemoryError(buf, "growing buffer");
             return XML_ERR_NO_MEMORY;
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 2f90717..4a9b3bc 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -76,7 +76,8 @@ typedef enum {
     XML_BUFFER_ALLOC_EXACT,	/* grow only to the minimal size */
     XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer */
     XML_BUFFER_ALLOC_IO,	/* special allocation scheme used for I/O */
-    XML_BUFFER_ALLOC_HYBRID	/* exact up to a threshold, and doubleit thereafter */
+    XML_BUFFER_ALLOC_HYBRID,	/* exact up to a threshold, and doubleit thereafter */
+    XML_BUFFER_ALLOC_BOUNDED	/* limit the upper size of the buffer */
 } xmlBufferAllocationScheme;

 /**
diff --git a/xmlreader.c b/xmlreader.c
index f19e123..471e7e2 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -2091,6 +2091,9 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
 		"xmlNewTextReader : malloc failed\n");
 	return(NULL);
     }
+    /* no operation on a reader should require a huge buffer */
+    xmlBufSetAllocationScheme(ret->buffer,
+			      XML_BUFFER_ALLOC_BOUNDED);
     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
     if (ret->sax == NULL) {
 	xmlBufFree(ret->buffer);
@@ -3616,6 +3619,7 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) {
 	    return(((xmlNsPtr) node)->href);
         case XML_ATTRIBUTE_NODE:{
 	    xmlAttrPtr attr = (xmlAttrPtr) node;
+	    const xmlChar *ret;

 	    if ((attr->children != NULL) &&
 	        (attr->children->type == XML_TEXT_NODE) &&
@@ -3629,10 +3633,21 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) {
                                         "xmlTextReaderSetup : malloc failed\n");
                         return (NULL);
                     }
+		    xmlBufSetAllocationScheme(reader->buffer,
+		                              XML_BUFFER_ALLOC_BOUNDED);
                 } else
                     xmlBufEmpty(reader->buffer);
 	        xmlBufGetNodeContent(reader->buffer, node);
-		return(xmlBufContent(reader->buffer));
+		ret = xmlBufContent(reader->buffer);
+		if (ret == NULL) {
+		    /* error on the buffer best to reallocate */
+		    xmlBufFree(reader->buffer);
+		    reader->buffer = xmlBufCreateSize(100);
+		    xmlBufSetAllocationScheme(reader->buffer,
+		                              XML_BUFFER_ALLOC_BOUNDED);
+		    ret = BAD_CAST "";
+		}
+		return(ret);
 	    }
 	    break;
 	}
@@ -5131,6 +5146,9 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
                         "xmlTextReaderSetup : malloc failed\n");
         return (-1);
     }
+    /* no operation on a reader should require a huge buffer */
+    xmlBufSetAllocationScheme(reader->buffer,
+			      XML_BUFFER_ALLOC_BOUNDED);
     if (reader->sax == NULL)
 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
     if (reader->sax == NULL) {
--
2.3.5


[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[User]
## CVE: CVE-2015-3197

ssl/s2_srvr.c in OpenSSL 1.0.1 before 1.0.1r and 1.0.2 before 1.0.2f does not prevent use of disabled ciphers, which makes it easier for man-in-the-middle attackers to defeat cryptographic protection mechanisms by performing computations on SSLv2 traffic, related to the get_client_master_key and get_client_hello functions.

## Package
openssl

## Files to modify
- openssl-1.0.1i/ssl/ssl_err.c
- openssl-1.0.1i.orig/ssl/ssl_locl.h
- openssl-1.0.1i.orig/ssl/ssl_sess.c
- openssl-1.0.1i.orig/ssl/s3_clnt.c
- openssl-1.0.1i/ssl/ssl_locl.h

## Target Source Code

### ssl/ssl.h

#### ERR_load_SSL_strings() [lines 2215-2301]
```c
#define SSL_F_SSL_CTX_USE_CERTIFICATE			 171
#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172
#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220
#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE		 173
#define SSL_F_SSL_CTX_USE_PRIVATEKEY			 174
#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1		 175
#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE		 176
#define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT		 272
#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY			 177
#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1		 178
#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE		 179
#define SSL_F_SSL_DO_HANDSHAKE				 180
#define SSL_F_SSL_GET_NEW_SESSION			 181
#define SSL_F_SSL_GET_PREV_SESSION			 217
#define SSL_F_SSL_GET_SERVER_SEND_CERT			 182
#define SSL_F_SSL_GET_SERVER_SEND_PKEY			 317
#define SSL_F_SSL_GET_SIGN_PKEY				 183
#define SSL_F_SSL_INIT_WBIO_BUFFER			 184
#define SSL_F_SSL_LOAD_CLIENT_CA_FILE			 185
#define SSL_F_SSL_NEW					 186
#define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT	 300
#define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT		 302
#define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT	 310
#define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT	 301
#define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT		 303
#define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT	 311
#define SSL_F_SSL_PEEK					 270
#define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT		 281
#define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT		 282
#define SSL_F_SSL_READ					 223
#define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
#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		 312
#define SSL_F_SSL_SESS_CERT_NEW				 225
#define SSL_F_SSL_SET_CERT				 191
#define SSL_F_SSL_SET_CIPHER_LIST			 271
#define SSL_F_SSL_SET_FD				 192
#define SSL_F_SSL_SET_PKEY				 193
#define SSL_F_SSL_SET_PURPOSE				 227
#define SSL_F_SSL_SET_RFD				 194
#define SSL_F_SSL_SET_SESSION				 195
#define SSL_F_SSL_SET_SESSION_ID_CONTEXT		 218
#define SSL_F_SSL_SET_SESSION_TICKET_EXT		 294
#define SSL_F_SSL_SET_TRUST				 228
#define SSL_F_SSL_SET_WFD				 196
#define SSL_F_SSL_SHUTDOWN				 224
#define SSL_F_SSL_SRP_CTX_INIT				 313
#define SSL_F_SSL_UNDEFINED_CONST_FUNCTION		 243
#define SSL_F_SSL_UNDEFINED_FUNCTION			 197
#define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
#define SSL_F_SSL_USE_CERTIFICATE			 198
#define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
#define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
#define SSL_F_SSL_USE_PRIVATEKEY			 201
#define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
#define SSL_F_SSL_USE_PRIVATEKEY_FILE			 203
#define SSL_F_SSL_USE_PSK_IDENTITY_HINT			 273
#define SSL_F_SSL_USE_RSAPRIVATEKEY			 204
#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1		 205
#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 206
#define SSL_F_SSL_VERIFY_CERT_CHAIN			 207
#define SSL_F_SSL_WRITE					 208
#define SSL_F_TLS1_CERT_VERIFY_MAC			 286
#define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209
#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT		 274
#define SSL_F_TLS1_ENC					 210
#define SSL_F_TLS1_EXPORT_KEYING_MATERIAL		 314
#define SSL_F_TLS1_HEARTBEAT				 315
#define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT		 275
#define SSL_F_TLS1_PR
/* ... truncated ... */
```

### ssl/s3_clnt.c

#### ssl3_get_new_session_ticket() [lines 2049-2141]
```c
	return(X509_NAME_cmp(*a,*b));
	}
#ifndef OPENSSL_NO_TLSEXT
int ssl3_get_new_session_ticket(SSL *s)
	{
	int ok,al,ret=0, ticklen;
	long n;
	const unsigned char *p;
	unsigned char *d;

	n=s->method->ssl_get_message(s,
		SSL3_ST_CR_SESSION_TICKET_A,
		SSL3_ST_CR_SESSION_TICKET_B,
		-1,
		16384,
		&ok);

	if (!ok)
		return((int)n);

	if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
		{
		s->s3->tmp.reuse_message=1;
		return(1);
		}
	if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET)
		{
		al=SSL_AD_UNEXPECTED_MESSAGE;
		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE);
		goto f_err;
		}
	if (n < 6)
		{
		/* need at least ticket_lifetime_hint + ticket length */
		al = SSL_AD_DECODE_ERROR;
		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
		goto f_err;
		}

	p=d=(unsigned char *)s->init_msg;
	n2l(p, s->session->tlsext_tick_lifetime_hint);
	n2s(p, ticklen);
	/* ticket_lifetime_hint + ticket_length + ticket */
	if (ticklen + 6 != n)
		{
		al = SSL_AD_DECODE_ERROR;
		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
		goto f_err;
		}
	if (s->session->tlsext_tick)
		{
		OPENSSL_free(s->session->tlsext_tick);
		s->session->tlsext_ticklen = 0;
		}
	s->session->tlsext_tick = OPENSSL_malloc(ticklen);
	if (!s->session->tlsext_tick)
		{
		SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	memcpy(s->session->tlsext_tick, p, ticklen);
	s->session->tlsext_ticklen = ticklen;
	/* There are two ways to detect a resumed ticket sesion.
	 * One is to set an appropriate session ID and then the server
	 * must return a match in ServerHello. This allows the normal
	 * client session ID matching to work and we know much
	 * earlier that the ticket has been accepted.
	 *
	 * The other way is to set zero length session ID when the
	 * ticket is presented and rely on the handshake to determine
	 * session resumption.
	 *
	 * We choose the former approach because this fits in with
	 * assumptions elsewhere in OpenSSL. The session ID is set
	 * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the
	 * ticket.
	 */
	EVP_Digest(p, ticklen,
			s->session->session_id, &s->session->session_id_length,
#ifndef OPENSSL_NO_SHA256
							EVP_sha256(), NULL);
#else
							EVP_sha1(), NULL);
#endif
	ret=1;
	return(ret);
f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
	return(-1);
	}

int ssl3_get_cert_status(SSL *s)
```

### ssl/ssl_err.c

#### region() [lines 206-292]
```c
{ERR_FUNC(SSL_F_SSL_CTRL),	"SSL_ctrl"},
{ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY),	"SSL_CTX_check_private_key"},
{ERR_FUNC(SSL_F_SSL_CTX_MAKE_PROFILES),	"SSL_CTX_MAKE_PROFILES"},
{ERR_FUNC(SSL_F_SSL_CTX_NEW),	"SSL_CTX_new"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_CIPHER_LIST),	"SSL_CTX_set_cipher_list"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE),	"SSL_CTX_set_client_cert_engine"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_PURPOSE),	"SSL_CTX_set_purpose"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT),	"SSL_CTX_set_session_id_context"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION),	"SSL_CTX_set_ssl_version"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_TRUST),	"SSL_CTX_set_trust"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE),	"SSL_CTX_use_certificate"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1),	"SSL_CTX_use_certificate_ASN1"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE),	"SSL_CTX_use_certificate_chain_file"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE),	"SSL_CTX_use_certificate_file"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY),	"SSL_CTX_use_PrivateKey"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1),	"SSL_CTX_use_PrivateKey_ASN1"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE),	"SSL_CTX_use_PrivateKey_file"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT),	"SSL_CTX_use_psk_identity_hint"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY),	"SSL_CTX_use_RSAPrivateKey"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1),	"SSL_CTX_use_RSAPrivateKey_ASN1"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),	"SSL_CTX_use_RSAPrivateKey_file"},
{ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE),	"SSL_do_handshake"},
{ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION),	"SSL_GET_NEW_SESSION"},
{ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION),	"SSL_GET_PREV_SESSION"},
{ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_CERT),	"SSL_GET_SERVER_SEND_CERT"},
{ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_PKEY),	"SSL_GET_SERVER_SEND_PKEY"},
{ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY),	"SSL_GET_SIGN_PKEY"},
{ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER),	"SSL_INIT_WBIO_BUFFER"},
{ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE),	"SSL_load_client_CA_file"},
{ERR_FUNC(SSL_F_SSL_NEW),	"SSL_new"},
{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT),	"SSL_PARSE_CLIENTHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT),	"SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT),	"SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT),	"SSL_PARSE_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT),	"SSL_PARSE_SERVERHELLO_USE_SRTP_EXT"},
{ERR_FUNC(SSL_F_SSL_PEEK),	"SSL_peek"},
{ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT),	"SSL_PREPARE_CLIENTHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT),	"SSL_PREPARE_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
{ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
{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
/* ... truncated ... */
```

### ssl/ssl_locl.h

#### ssl_sess_cert_free() [lines 796-882]
```c
		dtls1_ctrl, \
		ssl3_ctx_ctrl, \
		ssl3_get_cipher_by_char, \
		ssl3_put_cipher_by_char, \
		ssl3_pending, \
		ssl3_num_ciphers, \
		dtls1_get_cipher, \
		s_get_meth, \
		dtls1_default_timeout, \
		&DTLSv1_enc_data, \
		ssl_undefined_void_function, \
		ssl3_callback_ctrl, \
		ssl3_ctx_callback_ctrl, \
	}; \
	return &func_name##_data; \
	}

struct openssl_ssl_test_functions
	{
	int (*p_ssl_init_wbio_buffer)(SSL *s, int push);
	int (*p_ssl3_setup_buffers)(SSL *s);
	int (*p_tls1_process_heartbeat)(SSL *s);
	int (*p_dtls1_process_heartbeat)(SSL *s);
	};

#ifndef OPENSSL_UNIT_TEST

void ssl_clear_cipher_ctx(SSL *s);
int ssl_clear_bad_session(SSL *s);
CERT *ssl_cert_new(void);
CERT *ssl_cert_dup(CERT *cert);
int ssl_cert_inst(CERT **o);
void ssl_cert_free(CERT *c);
SESS_CERT *ssl_sess_cert_new(void);
void ssl_sess_cert_free(SESS_CERT *sc);
int ssl_set_peer_cert_type(SESS_CERT *c, int type);
int ssl_get_new_session(SSL *s, int session);
int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
				  ssl_cipher_id);
int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
			const SSL_CIPHER * const *bp);
STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
					       STACK_OF(SSL_CIPHER) **skp);
int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
                             int (*put_cb)(const SSL_CIPHER *, unsigned char *));
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
					     STACK_OF(SSL_CIPHER) **pref,
					     STACK_OF(SSL_CIPHER) **sorted,
					     const char *rule_str);
void ssl_update_cache(SSL *s, int mode);
int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
		       const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp);
int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md);
int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
int ssl_undefined_function(SSL *s);
int ssl_undefined_void_function(void);
int ssl_undefined_const_function(const SSL *s);
CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
X509 *ssl_get_server_send_cert(const SSL *);
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd);
int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
int ssl_verify_alarm_type(long type);
void ssl_load_ciphers(void);
int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len);

int ssl2_enc_init(SSL *s, int client);
int ssl2_generate_key_material(SSL *s);
void ssl2_enc(SSL *s,int send_data);
void ssl2_mac(SSL *s,unsigned char *mac,int send_data);
const SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p);
int ssl2_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
int ssl2_part_read(SSL *s, unsigned long f, int i);
int ssl2_do_write(SSL *s);
int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data);
void ssl2_return_
/* ... truncated ... */
```

### ssl/ssl_sess.c

#### region() [lines 185-271]
```c
	return(CRYPTO_get_ex_data(&s->ex_data,idx));
	}

SSL_SESSION *SSL_SESSION_new(void)
	{
	SSL_SESSION *ss;

	ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
	if (ss == NULL)
		{
		SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
		return(0);
		}
	memset(ss,0,sizeof(SSL_SESSION));

	ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
	ss->references=1;
	ss->timeout=60*5+4; /* 5 minute timeout by default */
	ss->time=(unsigned long)time(NULL);
	ss->prev=NULL;
	ss->next=NULL;
	ss->compress_meth=0;
#ifndef OPENSSL_NO_TLSEXT
	ss->tlsext_hostname = NULL;
#ifndef OPENSSL_NO_EC
	ss->tlsext_ecpointformatlist_length = 0;
	ss->tlsext_ecpointformatlist = NULL;
	ss->tlsext_ellipticcurvelist_length = 0;
	ss->tlsext_ellipticcurvelist = NULL;
#endif
#endif
	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
#ifndef OPENSSL_NO_PSK
	ss->psk_identity_hint=NULL;
	ss->psk_identity=NULL;
#endif
#ifndef OPENSSL_NO_SRP
	ss->srp_username=NULL;
#endif
	return(ss);
	}

const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
	{
	if(len)
		*len = s->session_id_length;
	return s->session_id;
	}

unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s)
	{
	return s->compress_meth;
	}

/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
 * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
 * until we have no conflict is going to complete in one iteration pretty much
 * "most" of the time (btw: understatement). So, if it takes us 10 iterations
 * and we still can't avoid a conflict - well that's a reasonable point to call
 * it quits. Either the RAND code is broken or someone is trying to open roughly
 * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
 * store that many sessions is perhaps a more interesting question ... */

#define MAX_SESS_ID_ATTEMPTS 10
static int def_generate_session_id(const SSL *ssl, unsigned char *id,
				unsigned int *id_len)
{
	unsigned int retry = 0;
	do
		if (RAND_pseudo_bytes(id, *id_len) <= 0)
			return 0;
	while(SSL_has_matching_session_id(ssl, id, *id_len) &&
		(++retry < MAX_SESS_ID_ATTEMPTS));
	if(retry < MAX_SESS_ID_ATTEMPTS)
		return 1;
	/* else - woops a session_id match */
	/* XXX We should also check the external cache --
	 * but the probability of a collision is negligible, and
	 * we could not prevent the concurrent creation of sessions
	 * with identical IDs since we currently don't have means
	 * to atomically check whether a session ID already exists
	 * and make a reservation for it if it does not
	 * (this problem applies to the internal cache as well).
	 */
	return 0;
}

```

## Upstream Fix
```diff
commit 98ece4eebfb6cd45cc8d550c6ac0022965071afc
Author: Matt Caswell <matt@openssl.org>
Date:   Mon May 18 16:27:48 2015 +0100

    Fix race condition in NewSessionTicket

    If a NewSessionTicket is received by a multi-threaded client when
    attempting to reuse a previous ticket then a race condition can occur
    potentially leading to a double free of the ticket data.

    CVE-2015-1791

    This also fixes RT#3808 where a session ID is changed for a session already
    in the client session cache. Since the session ID is the key to the cache
    this breaks the cache access.

    Parts of this patch were inspired by this Akamai change:
    https://github.com/akamai/openssl/commit/c0bf69a791239ceec64509f9f19fcafb2461b0d3

    Reviewed-by: Rich Salz <rsalz@openssl.org>

commit 907f04a30354615e54beaa2bc0b986083f7793ee
Author: Matt Caswell <matt@openssl.org>
Date:   Thu Jun 11 01:30:06 2015 +0100

    More ssl_session_dup fixes

    Fix error handling in ssl_session_dup, as well as incorrect setting up of
    the session ticket. Follow on from CVE-2015-1791.

    Thanks to LibreSSL project for reporting these issues.

    Conflicts:
    	ssl/ssl_sess.c

    Reviewed-by: Tim Hudson <tjh@openssl.org>

Index: openssl-1.0.1i/ssl/ssl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl.h	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl.h	2015-06-12 19:15:13.279975926 +0200
@@ -2254,6 +2254,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_READ					 223
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_DUP				 348
 #define SSL_F_SSL_SESSION_NEW				 189
 #define SSL_F_SSL_SESSION_PRINT_FP			 190
 #define SSL_F_SSL_SESSION_SET1_ID_CONTEXT		 312
Index: openssl-1.0.1i/ssl/s3_clnt.c
===================================================================
--- openssl-1.0.1i.orig/ssl/s3_clnt.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/s3_clnt.c	2015-06-12 19:15:13.279975926 +0200
@@ -2105,6 +2105,38 @@ int ssl3_get_new_session_ticket(SSL *s)
 		}

 	p=d=(unsigned char *)s->init_msg;
+
+    if (s->session->session_id_length > 0) {
+        int i = s->session_ctx->session_cache_mode;
+        SSL_SESSION *new_sess;
+        /*
+         * We reused an existing session, so we need to replace it with a new
+         * one
+         */
+        if (i & SSL_SESS_CACHE_CLIENT) {
+            /*
+             * Remove the old session from the cache
+             */
+            if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
+                if (s->session_ctx->remove_session_cb != NULL)
+                    s->session_ctx->remove_session_cb(s->session_ctx,
+                                                      s->session);
+            } else {
+                /* We carry on if this fails */
+                SSL_CTX_remove_session(s->session_ctx, s->session);
+            }
+        }
+
+        if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        SSL_SESSION_free(s->session);
+        s->session = new_sess;
+    }
+
 	n2l(p, s->session->tlsext_tick_lifetime_hint);
 	n2s(p, ticklen);
 	/* ticket_lifetime_hint + ticket_length + ticket */
Index: openssl-1.0.1i/ssl/ssl_err.c
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_err.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_err.c	2015-06-12 19:15:13.280975939 +0200
@@ -245,6 +245,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"},
 {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"},
Index: openssl-1.0.1i/ssl/ssl_locl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_locl.h	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_locl.h	2015-06-12 19:15:13.280975939 +0200
@@ -835,6 +835,7 @@ void ssl_sess_cert_free(SESS_CERT *sc);
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
 int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
 DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
 				  ssl_cipher_id);
Index: openssl-1.0.1i/ssl/ssl_sess.c
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_sess.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_sess.c	2015-06-12 19:26:20.502163556 +0200
@@ -224,6 +224,129 @@ SSL_SESSION *SSL_SESSION_new(void)
 	return(ss);
 	}

+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+    SSL_SESSION *dest;
+
+    dest = OPENSSL_malloc(sizeof(*src));
+    if (dest == NULL) {
+        goto err;
+    }
+    memcpy(dest, src, sizeof(*dest));
+
+     /* Set the various pointers to NULL so that we can call SSL_SESSION_free in
+     * the case of an error whilst halfway through constructing dest
+     */
+#ifndef OPENSSL_NO_PSK
+    dest->psk_identity_hint = NULL;
+    dest->psk_identity = NULL;
+#endif
+    dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+    dest->tlsext_hostname = NULL;
+# ifndef OPENSSL_NO_EC
+    dest->tlsext_ecpointformatlist = NULL;
+    dest->tlsext_ellipticcurvelist = NULL;
+# endif
+#endif
+    dest->tlsext_tick = NULL;
+#ifndef OPENSSL_NO_SRP
+    dest->srp_username = NULL;
+#endif
+    memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+    /* We deliberately don't copy the prev and next pointers */
+    dest->prev = NULL;
+    dest->next = NULL;
+
+    dest->references = 1;
+
+    if (src->sess_cert != NULL)
+        CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
+
+    if (src->peer != NULL)
+        CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+#ifndef OPENSSL_NO_PSK
+    if (src->psk_identity_hint) {
+        dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint);
+        if (dest->psk_identity_hint == NULL) {
+            goto err;
+        }
+    }
+    if (src->psk_identity) {
+        dest->psk_identity = BUF_strdup(src->psk_identity);
+        if (dest->psk_identity == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    if(src->ciphers != NULL) {
+        dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+        if (dest->ciphers == NULL)
+            goto err;
+    }
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+                                            &dest->ex_data, &src->ex_data)) {
+        goto err;
+    }
+
+#ifndef OPENSSL_NO_TLSEXT
+    if (src->tlsext_hostname) {
+        dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+        if (dest->tlsext_hostname == NULL) {
+            goto err;
+        }
+    }
+# ifndef OPENSSL_NO_EC
+    if (src->tlsext_ecpointformatlist) {
+        dest->tlsext_ecpointformatlist =
+            BUF_memdup(src->tlsext_ecpointformatlist,
+                       src->tlsext_ecpointformatlist_length);
+        if (dest->tlsext_ecpointformatlist == NULL)
+            goto err;
+    }
+    if (src->tlsext_ellipticcurvelist) {
+        dest->tlsext_ellipticcurvelist =
+            BUF_memdup(src->tlsext_ellipticcurvelist,
+                       src->t
... (truncated)
```

Generate a backported patch for the SUSE target version.

[Assistant]
commit 98ece4eebfb6cd45cc8d550c6ac0022965071afc
Author: Matt Caswell <matt@openssl.org>
Date:   Mon May 18 16:27:48 2015 +0100

    Fix race condition in NewSessionTicket

    If a NewSessionTicket is received by a multi-threaded client when
    attempting to reuse a previous ticket then a race condition can occur
    potentially leading to a double free of the ticket data.

    CVE-2015-1791

    This also fixes RT#3808 where a session ID is changed for a session already
    in the client session cache. Since the session ID is the key to the cache
    this breaks the cache access.

    Parts of this patch were inspired by this Akamai change:
    https://github.com/akamai/openssl/commit/c0bf69a791239ceec64509f9f19fcafb2461b0d3

    Reviewed-by: Rich Salz <rsalz@openssl.org>

commit 907f04a30354615e54beaa2bc0b986083f7793ee
Author: Matt Caswell <matt@openssl.org>
Date:   Thu Jun 11 01:30:06 2015 +0100

    More ssl_session_dup fixes

    Fix error handling in ssl_session_dup, as well as incorrect setting up of
    the session ticket. Follow on from CVE-2015-1791.

    Thanks to LibreSSL project for reporting these issues.

    Conflicts:
    	ssl/ssl_sess.c

    Reviewed-by: Tim Hudson <tjh@openssl.org>

Index: openssl-1.0.1i/ssl/ssl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl.h	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl.h	2015-06-12 19:15:13.279975926 +0200
@@ -2254,6 +2254,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_READ					 223
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_DUP				 348
 #define SSL_F_SSL_SESSION_NEW				 189
 #define SSL_F_SSL_SESSION_PRINT_FP			 190
 #define SSL_F_SSL_SESSION_SET1_ID_CONTEXT		 312
Index: openssl-1.0.1i/ssl/s3_clnt.c
===================================================================
--- openssl-1.0.1i.orig/ssl/s3_clnt.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/s3_clnt.c	2015-06-12 19:15:13.279975926 +0200
@@ -2105,6 +2105,38 @@ int ssl3_get_new_session_ticket(SSL *s)
 		}

 	p=d=(unsigned char *)s->init_msg;
+
+    if (s->session->session_id_length > 0) {
+        int i = s->session_ctx->session_cache_mode;
+        SSL_SESSION *new_sess;
+        /*
+         * We reused an existing session, so we need to replace it with a new
+         * one
+         */
+        if (i & SSL_SESS_CACHE_CLIENT) {
+            /*
+             * Remove the old session from the cache
+             */
+            if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
+                if (s->session_ctx->remove_session_cb != NULL)
+                    s->session_ctx->remove_session_cb(s->session_ctx,
+                                                      s->session);
+            } else {
+                /* We carry on if this fails */
+                SSL_CTX_remove_session(s->session_ctx, s->session);
+            }
+        }
+
+        if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        SSL_SESSION_free(s->session);
+        s->session = new_sess;
+    }
+
 	n2l(p, s->session->tlsext_tick_lifetime_hint);
 	n2s(p, ticklen);
 	/* ticket_lifetime_hint + ticket_length + ticket */
Index: openssl-1.0.1i/ssl/ssl_err.c
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_err.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_err.c	2015-06-12 19:15:13.280975939 +0200
@@ -245,6 +245,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"},
 {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"},
Index: openssl-1.0.1i/ssl/ssl_locl.h
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_locl.h	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_locl.h	2015-06-12 19:15:13.280975939 +0200
@@ -835,6 +835,7 @@ void ssl_sess_cert_free(SESS_CERT *sc);
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
 int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
 DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
 				  ssl_cipher_id);
Index: openssl-1.0.1i/ssl/ssl_sess.c
===================================================================
--- openssl-1.0.1i.orig/ssl/ssl_sess.c	2015-06-12 19:15:11.549954732 +0200
+++ openssl-1.0.1i/ssl/ssl_sess.c	2015-06-12 19:26:20.502163556 +0200
@@ -224,6 +224,129 @@ SSL_SESSION *SSL_SESSION_new(void)
 	return(ss);
 	}

+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+    SSL_SESSION *dest;
+
+    dest = OPENSSL_malloc(sizeof(*src));
+    if (dest == NULL) {
+        goto err;
+    }
+    memcpy(dest, src, sizeof(*dest));
+
+     /* Set the various pointers to NULL so that we can call SSL_SESSION_free in
+     * the case of an error whilst halfway through constructing dest
+     */
+#ifndef OPENSSL_NO_PSK
+    dest->psk_identity_hint = NULL;
+    dest->psk_identity = NULL;
+#endif
+    dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+    dest->tlsext_hostname = NULL;
+# ifndef OPENSSL_NO_EC
+    dest->tlsext_ecpointformatlist = NULL;
+    dest->tlsext_ellipticcurvelist = NULL;
+# endif
+#endif
+    dest->tlsext_tick = NULL;
+#ifndef OPENSSL_NO_SRP
+    dest->srp_username = NULL;
+#endif
+    memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+    /* We deliberately don't copy the prev and next pointers */
+    dest->prev = NULL;
+    dest->next = NULL;
+
+    dest->references = 1;
+
+    if (src->sess_cert != NULL)
+        CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
+
+    if (src->peer != NULL)
+        CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+#ifndef OPENSSL_NO_PSK
+    if (src->psk_identity_hint) {
+        dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint);
+        if (dest->psk_identity_hint == NULL) {
+            goto err;
+        }
+    }
+    if (src->psk_identity) {
+        dest->psk_identity = BUF_strdup(src->psk_identity);
+        if (dest->psk_identity == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    if(src->ciphers != NULL) {
+        dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+        if (dest->ciphers == NULL)
+            goto err;
+    }
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+                                            &dest->ex_data, &src->ex_data)) {
+        goto err;
+    }
+
+#ifndef OPENSSL_NO_TLSEXT
+    if (src->tlsext_hostname) {
+        dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+        if (dest->tlsext_hostname == NULL) {
+            goto err;
+        }
+    }
+# ifndef OPENSSL_NO_EC
+    if (src->tlsext_ecpointformatlist) {
+        dest->tlsext_ecpointformatlist =
+            BUF_memdup(src->tlsext_ecpointformatlist,
+                       src->tlsext_ecpointformatlist_length);
+        if (dest->tlsext_ecpointformatlist == NULL)
+            goto err;
+    }
+    if (src->tlsext_ellipticcurvelist) {
+        dest->tlsext_ellipticcurvelist =
+            BUF_memdup(src->tlsext_ellipticcurvelist,
+                       src->tlsext_ellipticcurvelist_length);
+        if (dest->tlsext_ellipticcurvelist == NULL)
+            goto err;
+    }
+# endif
+#endif
+
+    if (ticket != 0) {
+        dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
+        if(dest->tlsext_tick == NULL)
+            goto err;
+    } else {
+        dest->tlsext_tick_lifetime_hint = 0;
+        dest->tlsext_ticklen = 0;
+    }
+
+#ifndef OPENSSL_NO_SRP
+    if (src->srp_username) {
+        dest->srp_username = BUF_strdup(src->srp_username);
+        if (dest->srp_username == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    return dest;
+err:
+    SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+    SSL_SESSION_free(dest);
+    return NULL;
+}
+
+
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
 	{
 	if(len)


[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[User]
## CVE: CVE-2016-6250

Integer overflow in the ISO9660 writer in libarchive before 3.2.1 allows remote attackers to cause a denial of service (application crash) or execute arbitrary code via vectors related to verifying filename lengths when writing an ISO9660 archive, which trigger a buffer overflow.

## Package
libarchive

## Files to modify
- libarchive-3.1.2.orig/libarchive/archive_read.c
- libarchive/archive_read.c
- libarchive/test/test_read_too_many_filters.c

## Target Source Code

### Makefile.am

#### region() [lines 400-486]
```c
	libarchive/test/test_read_format_iso_xorriso.c		\
	libarchive/test/test_read_format_isojoliet_bz2.c	\
	libarchive/test/test_read_format_isojoliet_long.c	\
	libarchive/test/test_read_format_isojoliet_rr.c		\
	libarchive/test/test_read_format_isojoliet_versioned.c	\
	libarchive/test/test_read_format_isorr_bz2.c		\
	libarchive/test/test_read_format_isorr_ce.c		\
	libarchive/test/test_read_format_isorr_new_bz2.c	\
	libarchive/test/test_read_format_isorr_rr_moved.c	\
	libarchive/test/test_read_format_isozisofs_bz2.c	\
	libarchive/test/test_read_format_lha.c			\
	libarchive/test/test_read_format_lha_filename.c		\
	libarchive/test/test_read_format_mtree.c		\
	libarchive/test/test_read_format_pax_bz2.c		\
	libarchive/test/test_read_format_rar.c			\
	libarchive/test/test_read_format_raw.c			\
	libarchive/test/test_read_format_tar.c			\
	libarchive/test/test_read_format_tar_empty_filename.c	\
	libarchive/test/test_read_format_tar_filename.c		\
	libarchive/test/test_read_format_tbz.c			\
	libarchive/test/test_read_format_tgz.c			\
	libarchive/test/test_read_format_tlz.c			\
	libarchive/test/test_read_format_txz.c			\
	libarchive/test/test_read_format_tz.c			\
	libarchive/test/test_read_format_ustar_filename.c	\
	libarchive/test/test_read_format_xar.c			\
	libarchive/test/test_read_format_zip.c			\
	libarchive/test/test_read_format_zip_comment_stored.c	\
	libarchive/test/test_read_format_zip_filename.c		\
	libarchive/test/test_read_format_zip_mac_metadata.c	\
	libarchive/test/test_read_format_zip_sfx.c		\
	libarchive/test/test_read_large.c			\
	libarchive/test/test_read_pax_truncated.c		\
	libarchive/test/test_read_position.c			\
	libarchive/test/test_read_set_format.c			\
	libarchive/test/test_read_truncated.c			\
	libarchive/test/test_read_truncated_filter.c		\
	libarchive/test/test_sparse_basic.c			\
	libarchive/test/test_tar_filenames.c			\
	libarchive/test/test_tar_large.c			\
	libarchive/test/test_ustar_filenames.c			\
	libarchive/test/test_ustar_filename_encoding.c		\
	libarchive/test/test_write_disk.c			\
	libarchive/test/test_write_disk_appledouble.c		\
	libarchive/test/test_write_disk_failures.c		\
	libarchive/test/test_write_disk_hardlink.c		\
	libarchive/test/test_write_disk_hfs_compression.c	\
	libarchive/test/test_write_disk_lookup.c		\
	libarchive/test/test_write_disk_mac_metadata.c		\
	libarchive/test/test_write_disk_no_hfs_compression.c	\
	libarchive/test/test_write_disk_perms.c			\
	libarchive/test/test_write_disk_secure.c		\
	libarchive/test/test_write_disk_s
/* ... truncated ... */
```

### libarchive/archive_read.c

#### archive_read_open1() [lines 450-539]
```c
}

int
archive_read_open1(struct archive *_a)
{
	struct archive_read *a = (struct archive_read *)_a;
	struct archive_read_filter *filter, *tmp;
	int slot, e;
	unsigned int i;

	archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
	    "archive_read_open");
	archive_clear_error(&a->archive);

	if (a->client.reader == NULL) {
		archive_set_error(&a->archive, EINVAL,
		    "No reader function provided to archive_read_open");
		a->archive.state = ARCHIVE_STATE_FATAL;
		return (ARCHIVE_FATAL);
	}

	/* Open data source. */
	if (a->client.opener != NULL) {
		e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
		if (e != 0) {
			/* If the open failed, call the closer to clean up. */
			if (a->client.closer) {
				for (i = 0; i < a->client.nodes; i++)
					(a->client.closer)(&a->archive,
					    a->client.dataset[i].data);
			}
			return (e);
		}
	}

	filter = calloc(1, sizeof(*filter));
	if (filter == NULL)
		return (ARCHIVE_FATAL);
	filter->bidder = NULL;
	filter->upstream = NULL;
	filter->archive = a;
	filter->data = a->client.dataset[0].data;
	filter->open = client_open_proxy;
	filter->read = client_read_proxy;
	filter->skip = client_skip_proxy;
	filter->seek = client_seek_proxy;
	filter->close = client_close_proxy;
	filter->sswitch = client_switch_proxy;
	filter->name = "none";
	filter->code = ARCHIVE_FILTER_NONE;

	a->client.dataset[0].begin_position = 0;
	if (!a->filter || !a->bypass_filter_bidding)
	{
		a->filter = filter;
		/* Build out the input pipeline. */
		e = choose_filters(a);
		if (e < ARCHIVE_WARN) {
			a->archive.state = ARCHIVE_STATE_FATAL;
			return (ARCHIVE_FATAL);
		}
	}
	else
	{
		/* Need to add "NONE" type filter at the end of the filter chain */
		tmp = a->filter;
		while (tmp->upstream)
			tmp = tmp->upstream;
		tmp->upstream = filter;
	}

	if (!a->format)
	{
		slot = choose_format(a);
		if (slot < 0) {
			__archive_read_close_filters(a);
			a->archive.state = ARCHIVE_STATE_FATAL;
			return (ARCHIVE_FATAL);
		}
		a->format = &(a->formats[slot]);
	}

	a->archive.state = ARCHIVE_STATE_HEADER;

	/* Ensure libarchive starts from the first node in a multivolume set */
	client_switch_proxy(a->filter, 0);
	return (e);
}

/*
```

#### choose_filters() [lines 542-601]
```c
 * building the pipeline.
 */
static int
choose_filters(struct archive_read *a)
{
	int number_bidders, i, bid, best_bid;
	struct archive_read_filter_bidder *bidder, *best_bidder;
	struct archive_read_filter *filter;
	ssize_t avail;
	int r;

	for (;;) {
		n
/* ... truncated ... */
```

### libarchive/test/CMakeLists.txt

#### IF() [lines 111-197]
```c
    test_read_format_gtar_lzma.c
    test_read_format_gtar_sparse.c
    test_read_format_iso_Z.c
    test_read_format_iso_multi_extent.c
    test_read_format_iso_xorriso.c
    test_read_format_isojoliet_bz2.c
    test_read_format_isojoliet_long.c
    test_read_format_isojoliet_rr.c
    test_read_format_isojoliet_versioned.c
    test_read_format_isorr_bz2.c
    test_read_format_isorr_ce.c
    test_read_format_isorr_new_bz2.c
    test_read_format_isorr_rr_moved.c
    test_read_format_isozisofs_bz2.c
    test_read_format_lha.c
    test_read_format_lha_filename.c
    test_read_format_mtree.c
    test_read_format_pax_bz2.c
    test_read_format_rar.c
    test_read_format_raw.c
    test_read_format_tar.c
    test_read_format_tar_empty_filename.c
    test_read_format_tar_filename.c
    test_read_format_tbz.c
    test_read_format_tgz.c
    test_read_format_tlz.c
    test_read_format_txz.c
    test_read_format_tz.c
    test_read_format_ustar_filename.c
    test_read_format_xar.c
    test_read_format_zip.c
    test_read_format_zip_comment_stored.c
    test_read_format_zip_filename.c
    test_read_format_zip_mac_metadata.c
    test_read_format_zip_sfx.c
    test_read_large.c
    test_read_pax_truncated.c
    test_read_position.c
    test_read_set_format.c
    test_read_truncated.c
    test_read_truncated_filter.c
    test_sparse_basic.c
    test_tar_filenames.c
    test_tar_large.c
    test_ustar_filenames.c
    test_ustar_filename_encoding.c
    test_write_disk.c
    test_write_disk_appledouble.c
    test_write_disk_failures.c
    test_write_disk_hardlink.c
    test_write_disk_hfs_compression.c
    test_write_disk_lookup.c
    test_write_disk_mac_metadata.c
    test_write_disk_no_hfs_compression.c
    test_write_disk_perms.c
    test_write_disk_secure.c
    test_write_disk_sparse.c
    test_write_disk_symlink.c
    test_write_disk_times.c
    test_write_filter_b64encode.c
    test_write_filter_bzip2.c
    test_write_filter_compress.c
    test_write_filter_gzip.c
    test_write_filter_gzip_timestamp.c
    test_write_filter_lrzip.c
    test_write_filter_lzip.c
    test_write_filter_lzma.c
    test_write_filter_lzop.c
    test_write_filter_program.c
    test_write_filter_uuencode.c
    test_write_filter_xz.c
    test_write_format_7zip.c
    test_write_format_7zip_empty.c
    test_write_format_7zip_large.c
    test_write_format_ar.c
    test_write_format_cpio.c
    test_write_format_cpio_empty.c
    test_write_format_cpio_newc.c
    test_write_format_cpio_odc.c
    test_write_format_gn
/* ... truncated ... */
```

### Type definitions

```c
/* from archive_private.h */
struct archive {
	/*
	 * The magic/state values are used to sanity-check the
	 * client's usage.  If an API function is called at a
	 * ridiculous time, or the client passes us an invalid
	 * pointer, these values allow me to catch that.
	 */
	unsigned int	magic;
	unsigned int	state;

	/*
	 * Some public API functions depend on the "real" type of the
	 * archive object.
	 */
	struct archive_vtable *vtable;

	int		  archive_format;
	const char	 *archive_format_name;

	int	  compression_code;	/* Currently active compression. */
	const char *compression_name;

	/* Number of file entries processed. */
	int		  file_count;

	int		  archive_error_number;
	const char	 *error;
	struct archive_string	error_string;

	char *current_code;
	unsigned current_codepage; /* Current ACP(ANSI CodePage). */
	unsigned current_oemcp; /* Current OEMCP(OEM CodePage). */
	struct archive_string_conv *sconv;
};

/* from archive_read_private.h */
struct archive_read_filter_bidder {
	/* Configuration data for the bidder. */
	void *data;
	/* Name of the filter */
	const char *name;
	/* Taste the upstream filter to see if we handle this. */
	int (*bid)(struct archive_read_filter_bidder *,
	    struct archive_read_filter *);
	/* Initialize a newly-created filter. */
	int (*init)(struct archive_read_filter *);
	/* Set an option for the filter bidder. */
	int (*options)(struct archive_read_filter_bidder *,
	    const char *key, const char *value);
	/* Release the bidder's configuration data. */
	int (*free)(struct archive_read_filter_bidder *);
};

/* from archive_read_private.h */
struct archive_read_filter {
	int64_t position;
	/* Essentially all filters will need these values, so
	 * just declare them here. */
	struct archive_read_filter_bidder *bidder; /* My bidder. */
	struct archive_read_filter *upstream; /* Who I read from. */
	struct archive_read *archive; /* Associated archive. */
	/* Open a block for reading */
	int (*open)(struct archive_read_filter *self);
	/* Return next block. */
	ssize_t (*read)(struct archive_read_filter *, const void **);
	/* Skip forward this many bytes. */
	int64_t (*skip)(struct archive_read_filter *self, int64_t request);
	/* Seek to an absolute location. */
	int64_t (*seek)(struct archive_read_filter *self, int64_t offset, int whence);
	/* Close (just this filter) and free(self). */
	int (*close)(struct archive_read_filter *self);
	/* Function that handles switching from reading one block to the next/prev */
	int (*sswitch)(struct archive_read_filter *self, unsigned int iindex);
	/* My private data. */
	void *data;

	const char	*name;
	int		 code;

	/* Used by reblocking logic. */
	char		*buffer;
	size_t		 buffer_size;
	char		*next;		/* Current read location. */
	size_t		 avail;		/* Bytes in my buffer. */
	const void	*client_buff;	/* Client buffer information. */
	size_t		 client_total;
	const char	*client_next;
	size_t		 client_avail;
	char		 end_of_file;
	char		 closed;
	char		 fatal;
};
```

## Upstream Fix
```diff
commit 6e06b1c89dd0d16f74894eac4cfc1327a06ee4a0
Author: Tim Kientzle <kientzle@acm.org>
Date:   Sat Jan 10 12:24:58 2015 -0800

    Fix a potential crash issue discovered by Alexander Cherepanov:

    It seems bsdtar automatically handles stacked compression. This is a
    nice feature but it could be problematic when it's completely
    unlimited.  Most clearly it's illustrated with quines:

    $ curl -sRO http://www.maximumcompression.com/selfgz.gz
    $ (ulimit -v 10000000 && bsdtar -tvf selfgz.gz)
    bsdtar: Error opening archive: Can't allocate data for gzip decompression

    Without ulimit, bsdtar will eat all available memory. This could also
    be a problem for other applications using libarchive.

Index: libarchive-3.1.2/Makefile.am
===================================================================
--- libarchive-3.1.2.orig/Makefile.am
+++ libarchive-3.1.2/Makefile.am
@@ -439,6 +439,7 @@ libarchive_test_SOURCES=					\
 	libarchive/test/test_read_pax_truncated.c		\
 	libarchive/test/test_read_position.c			\
 	libarchive/test/test_read_set_format.c			\
+	libarchive/test/test_read_too_many_filters.c		\
 	libarchive/test/test_read_truncated.c			\
 	libarchive/test/test_read_truncated_filter.c		\
 	libarchive/test/test_sparse_basic.c			\
@@ -703,6 +704,7 @@ libarchive_test_EXTRA_DIST=\
 	libarchive/test/test_read_splitted_rar_ab.uu			\
 	libarchive/test/test_read_splitted_rar_ac.uu			\
 	libarchive/test/test_read_splitted_rar_ad.uu			\
+	libarchive/test/test_read_too_many_filters.gz.uu                \
 	libarchive/test/test_splitted_rar_seek_support_aa.uu		\
 	libarchive/test/test_splitted_rar_seek_support_ab.uu		\
 	libarchive/test/test_splitted_rar_seek_support_ac.uu		\
Index: libarchive-3.1.2/libarchive/archive_read.c
===================================================================
--- libarchive-3.1.2.orig/libarchive/archive_read.c
+++ libarchive-3.1.2/libarchive/archive_read.c
@@ -544,13 +544,13 @@ archive_read_open1(struct archive *_a)
 static int
 choose_filters(struct archive_read *a)
 {
-	int number_bidders, i, bid, best_bid;
+	int number_bidders, i, bid, best_bid, n;
 	struct archive_read_filter_bidder *bidder, *best_bidder;
 	struct archive_read_filter *filter;
 	ssize_t avail;
 	int r;

-	for (;;) {
+	for (n = 0; n < 25; ++n) {
 		number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);

 		best_bid = 0;
@@ -596,6 +596,9 @@ choose_filters(struct archive_read *a)
 			return (ARCHIVE_FATAL);
 		}
 	}
+	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+	    "Input requires too many filters for decoding");
+	return (ARCHIVE_FATAL);
 }

 /*
Index: libarchive-3.1.2/libarchive/test/CMakeLists.txt
===================================================================
--- libarchive-3.1.2.orig/libarchive/test/CMakeLists.txt
+++ libarchive-3.1.2/libarchive/test/CMakeLists.txt
@@ -150,6 +150,7 @@ IF(ENABLE_TEST)
     test_read_pax_truncated.c
     test_read_position.c
     test_read_set_format.c
+    test_read_too_many_filters.c
     test_read_truncated.c
     test_read_truncated_filter.c
     test_sparse_basic.c
Index: libarchive-3.1.2/libarchive/test/test_read_too_many_filters.c
===================================================================
--- /dev/null
+++ libarchive-3.1.2/libarchive/test/test_read_too_many_filters.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2003-2008,2015 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+DEFINE_TEST(test_read_too_many_filters)
+{
+	const char *name = "test_read_too_many_filters.gz";
+	struct archive *a;
+	int r;
+
+	assert((a = archive_read_new()) != NULL);
+	r = archive_read_support_filter_gzip(a);
+	if (r == ARCHIVE_WARN) {
+		skipping("gzip reading not fully supported on this platform");
+	}
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+	extract_reference_file(name);
+	assertEqualIntA(a, ARCHIVE_FATAL,
+	    archive_read_open_filename(a, name, 200));
+
+	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
Index: libarchive-3.1.2/libarchive/test/test_read_too_many_filters.gz.uu
===================================================================
--- /dev/null
+++ libarchive-3.1.2/libarchive/test/test_read_too_many_filters.gz.uu
@@ -0,0 +1,15 @@
+This is a valid gzip file that decompresses to itself, from
+  http://www.maximumcompression.com/selfgz.gz
+
+This is used in test_read_too_many_filters to try to
+crash libarchive by forcing it to spawn an unending
+list of gunzip filters.
+
+begin 644 test_read_too_many_filters.gz
+M'XL(
```

Generate a backported patch for the SUSE target version.

[Assistant]
commit 6e06b1c89dd0d16f74894eac4cfc1327a06ee4a0
Author: Tim Kientzle <kientzle@acm.org>
Date:   Sat Jan 10 12:24:58 2015 -0800

    Fix a potential crash issue discovered by Alexander Cherepanov:

    It seems bsdtar automatically handles stacked compression. This is a
    nice feature but it could be problematic when it's completely
    unlimited.  Most clearly it's illustrated with quines:

    $ curl -sRO http://www.maximumcompression.com/selfgz.gz
    $ (ulimit -v 10000000 && bsdtar -tvf selfgz.gz)
    bsdtar: Error opening archive: Can't allocate data for gzip decompression

    Without ulimit, bsdtar will eat all available memory. This could also
    be a problem for other applications using libarchive.

Index: libarchive-3.1.2/Makefile.am
===================================================================
--- libarchive-3.1.2.orig/Makefile.am
+++ libarchive-3.1.2/Makefile.am
@@ -439,6 +439,7 @@ libarchive_test_SOURCES=					\
 	libarchive/test/test_read_pax_truncated.c		\
 	libarchive/test/test_read_position.c			\
 	libarchive/test/test_read_set_format.c			\
+	libarchive/test/test_read_too_many_filters.c		\
 	libarchive/test/test_read_truncated.c			\
 	libarchive/test/test_read_truncated_filter.c		\
 	libarchive/test/test_sparse_basic.c			\
@@ -703,6 +704,7 @@ libarchive_test_EXTRA_DIST=\
 	libarchive/test/test_read_splitted_rar_ab.uu			\
 	libarchive/test/test_read_splitted_rar_ac.uu			\
 	libarchive/test/test_read_splitted_rar_ad.uu			\
+	libarchive/test/test_read_too_many_filters.gz.uu                \
 	libarchive/test/test_splitted_rar_seek_support_aa.uu		\
 	libarchive/test/test_splitted_rar_seek_support_ab.uu		\
 	libarchive/test/test_splitted_rar_seek_support_ac.uu		\
Index: libarchive-3.1.2/libarchive/archive_read.c
===================================================================
--- libarchive-3.1.2.orig/libarchive/archive_read.c
+++ libarchive-3.1.2/libarchive/archive_read.c
@@ -544,13 +544,13 @@ archive_read_open1(struct archive *_a)
 static int
 choose_filters(struct archive_read *a)
 {
-	int number_bidders, i, bid, best_bid;
+	int number_bidders, i, bid, best_bid, n;
 	struct archive_read_filter_bidder *bidder, *best_bidder;
 	struct archive_read_filter *filter;
 	ssize_t avail;
 	int r;

-	for (;;) {
+	for (n = 0; n < 25; ++n) {
 		number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);

 		best_bid = 0;
@@ -596,6 +596,9 @@ choose_filters(struct archive_read *a)
 			return (ARCHIVE_FATAL);
 		}
 	}
+	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+	    "Input requires too many filters for decoding");
+	return (ARCHIVE_FATAL);
 }

 /*
Index: libarchive-3.1.2/libarchive/test/CMakeLists.txt
===================================================================
--- libarchive-3.1.2.orig/libarchive/test/CMakeLists.txt
+++ libarchive-3.1.2/libarchive/test/CMakeLists.txt
@@ -150,6 +150,7 @@ IF(ENABLE_TEST)
     test_read_pax_truncated.c
     test_read_position.c
     test_read_set_format.c
+    test_read_too_many_filters.c
     test_read_truncated.c
     test_read_truncated_filter.c
     test_sparse_basic.c
Index: libarchive-3.1.2/libarchive/test/test_read_too_many_filters.c
===================================================================
--- /dev/null
+++ libarchive-3.1.2/libarchive/test/test_read_too_many_filters.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2003-2008,2015 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+DEFINE_TEST(test_read_too_many_filters)
+{
+	const char *name = "test_read_too_many_filters.gz";
+	struct archive *a;
+	int r;
+
+	assert((a = archive_read_new()) != NULL);
+	r = archive_read_support_filter_gzip(a);
+	if (r == ARCHIVE_WARN) {
+		skipping("gzip reading not fully supported on this platform");
+	}
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+	extract_reference_file(name);
+	assertEqualIntA(a, ARCHIVE_FATAL,
+	    archive_read_open_filename(a, name, 200));
+
+	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
Index: libarchive-3.1.2/libarchive/test/test_read_too_many_filters.gz.uu
===================================================================
--- /dev/null
+++ libarchive-3.1.2/libarchive/test/test_read_too_many_filters.gz.uu
@@ -0,0 +1,15 @@
+This is a valid gzip file that decompresses to itself, from
+  http://www.maximumcompression.com/selfgz.gz
+
+This is used in test_read_too_many_filters to try to
+crash libarchive by forcing it to spawn an unending
+list of gunzip filters.
+
+begin 644 test_read_too_many_filters.gz
+M'XL(`````````P`/`/#_'XL(`````````P`/`/#_````__\```#__X)QH5P`
+M`!X`X?\```#__P```/__@G&A7```'@#A_P```/__````__\```#__P```/__
+M````__\```#__\(FAF`!`!0`Z_\```#__P```/__PB:&8`$`%`#K_\(FAF`!
+M`!0`Z_^9(#6-B"@Q,C,T`K/`+```%`#K_P*SP"P``!0`Z_]"B"'$`````/__
+>`P!#2DTAT@```$*((<0`````__\#`$-*32'2````
+`
+end


[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[Assistant]
origin: http://download.lighttpd.net/lighttpd/security/lighttpd_sa_2013_01.txt
commit 1af871fcef97574c71870309d572d6b1026ee605
Author: Stefan Bühler <stbuehler@web.de>
Date:   Tue Nov 5 15:29:07 2013 +0000

    [ssl] fix SNI handling; only use key+cert+verify-client from SNI specific config (fixes #2525, CVE-2013-4508)

    pull all ssl.ca-file values into all SSL_CTXs, but use only the local
    ssl.ca-file for verify-client; correct SNI name is no requirement,
    so enforcing verification for a subset of SNI names doesn't actually
    protect those.

    From: Stefan Bühler <stbuehler@web.de>

    git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2913 152afb58-edef-0310-8abb-c4023f1b3aa9

Index: lighttpd-1.4.31/src/base.h
===================================================================
--- lighttpd-1.4.31.orig/src/base.h	2011-11-30 19:43:35.000000000 +0000
+++ lighttpd-1.4.31/src/base.h	2013-11-13 02:43:16.910532167 +0000
@@ -319,7 +319,11 @@
 	off_t *global_bytes_per_second_cnt_ptr; /*  */

 #ifdef USE_OPENSSL
-	SSL_CTX *ssl_ctx;
+	SSL_CTX *ssl_ctx; /* not patched */
+	/* SNI per host: with COMP_SERVER_SOCKET, COMP_HTTP_SCHEME, COMP_HTTP_HOST */
+	EVP_PKEY *ssl_pemfile_pkey;
+	X509 *ssl_pemfile_x509;
+	STACK_OF(X509_NAME) *ssl_ca_file_cert_names;
 #endif
 } specific_config;

Index: lighttpd-1.4.31/src/configfile.c
===================================================================
--- lighttpd-1.4.31.orig/src/configfile.c	2011-12-06 20:01:49.000000000 +0000
+++ lighttpd-1.4.31/src/configfile.c	2013-11-13 02:43:16.910532167 +0000
@@ -336,9 +336,13 @@

 	PATCH(ssl_pemfile);
 #ifdef USE_OPENSSL
-	PATCH(ssl_ctx);
+	PATCH(ssl_pemfile_x509);
+	PATCH(ssl_pemfile_pkey);
 #endif
 	PATCH(ssl_ca_file);
+#ifdef USE_OPENSSL
+	PATCH(ssl_ca_file_cert_names);
+#endif
 	PATCH(ssl_cipher_list);
 	PATCH(ssl_dh_file);
 	PATCH(ssl_ec_curve);
@@ -405,10 +409,14 @@
 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) {
 				PATCH(ssl_pemfile);
 #ifdef USE_OPENSSL
-				PATCH(ssl_ctx);
+				PATCH(ssl_pemfile_x509);
+				PATCH(ssl_pemfile_pkey);
 #endif
 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) {
 				PATCH(ssl_ca_file);
+#ifdef USE_OPENSSL
+				PATCH(ssl_ca_file_cert_names);
+#endif
 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.honor-cipher-order"))) {
 				PATCH(ssl_honor_cipher_order);
 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) {
Index: lighttpd-1.4.31/src/network.c
===================================================================
--- lighttpd-1.4.31.orig/src/network.c	2011-12-27 13:45:02.000000000 +0000
+++ lighttpd-1.4.31/src/network.c	2013-11-13 02:43:16.910532167 +0000
@@ -112,20 +112,46 @@
 	config_patch_connection(srv, con, COMP_HTTP_SCHEME);
 	config_patch_connection(srv, con, COMP_HTTP_HOST);

-	if (NULL == con->conf.ssl_ctx) {
-		/* ssl_ctx <=> pemfile was set <=> ssl_ctx got patched: so this should never happen */
+	if (NULL == con->conf.ssl_pemfile_x509 || NULL == con->conf.ssl_pemfile_pkey) {
+		/* x509/pkey available <=> pemfile was set <=> pemfile got patched: so this should never happen, unless you nest $SERVER["socket"] */
 		log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
-			"null SSL_CTX for TLS server name", con->tlsext_server_name);
+			"no certificate/private key for TLS server name", con->tlsext_server_name);
 		return SSL_TLSEXT_ERR_ALERT_FATAL;
 	}

-	/* switch to new SSL_CTX in reaction to a client's server_name extension */
-	if (con->conf.ssl_ctx != SSL_set_SSL_CTX(ssl, con->conf.ssl_ctx)) {
-		log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
-			"failed to set SSL_CTX for TLS server name", con->tlsext_server_name);
+	/* first set certificate! setting private key checks whether certificate matches it */
+	if (!SSL_use_certificate(ssl, con->conf.ssl_pemfile_x509)) {
+		log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:",
+			"failed to set certificate for TLS server name", con->tlsext_server_name,
+			ERR_error_string(ERR_get_error(), NULL));
+		return SSL_TLSEXT_ERR_ALERT_FATAL;
+	}
+
+	if (!SSL_use_PrivateKey(ssl, con->conf.ssl_pemfile_pkey)) {
+		log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:",
+			"failed to set private key for TLS server name", con->tlsext_server_name,
+			ERR_error_string(ERR_get_error(), NULL));
 		return SSL_TLSEXT_ERR_ALERT_FATAL;
 	}

+	if (con->conf.ssl_verifyclient) {
+		if (NULL == con->conf.ssl_ca_file_cert_names) {
+			log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:",
+				"can't verify client without ssl.ca-file for TLS server name", con->tlsext_server_name,
+				ERR_error_string(ERR_get_error(), NULL));
+			return SSL_TLSEXT_ERR_ALERT_FATAL;
+		}
+
+		SSL_set_client_CA_list(ssl, SSL_dup_CA_list(con->conf.ssl_ca_file_cert_names));
+		/* forcing verification here is really not that useful - a client could just connect without SNI */
+		SSL_set_verify(
+			ssl,
+			SSL_VERIFY_PEER | (con->conf.ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
+			NULL
+		);
+		SSL_set_verify_depth(ssl, con->conf.ssl_verifyclient_depth);
+	}
+
 	return SSL_TLSEXT_ERR_OK;
 }
 #endif
@@ -495,9 +521,100 @@
 	NETWORK_BACKEND_SOLARIS_SENDFILEV
 } network_backend_t;

+#ifdef USE_OPENSSL
+static X509* x509_load_pem_file(server *srv, const char *file) {
+	BIO *in;
+	X509 *x = NULL;
+
+	in = BIO_new(BIO_s_file());
+	if (NULL == in) {
+		log_error_write(srv, __FILE__, __LINE__, "S", "SSL: BIO_new(BIO_s_file()) failed");
+		goto error;
+	}
+
+	if (BIO_read_filename(in,file) <= 0) {
+		log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: BIO_read_filename('", file,"') failed");
+		goto error;
+	}
+	x = PEM_read_bio_X509(in, NULL, NULL, NULL);
+
+	if (NULL == x) {
+		log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: couldn't read X509 certificate from '", file,"'");
+		goto error;
+	}
+
+	BIO_free(in);
+	return x;
+
+error:
+	if (NULL != x) X509_free(x);
+	if (NULL != in) BIO_free(in);
+	return NULL;
+}
+
+static EVP_PKEY* evp_pkey_load_pem_file(server *srv, const char *file) {
+	BIO *in;
+	EVP_PKEY *x = NULL;
+
+	in=BIO_new(BIO_s_file());
+	if (NULL == in) {
+		log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BIO_new(BIO_s_file()) failed");
+		goto error;
+	}
+
+	if (BIO_read_filename(in,file) <= 0) {
+		log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: BIO_read_filename('", file,"') failed");
+		goto error;
+	}
+	x = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
+
+	if (NULL == x) {
+		log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: couldn't read private key from '", file,"'");
+		goto error;
+	}
+
+	BIO_free(in);
+	return x;
+
+error:
+	if (NULL != x) EVP_PKEY_free(x);
+	if (NULL != in) BIO_free(in);
+	return NULL;
+}
+
+static int network_openssl_load_pemfile(server *srv, size_t ndx) {
+	specific_config *s = srv->config_storage[ndx];
+
+#ifdef OPENSSL_NO_TLSEXT
+	{
+		data_config *dc = (data_config *)srv->config_context->data[i];
+		if ((ndx > 0 && (COMP_SERVER_SOCKET != dc->comp || dc->cond != CONFIG_COND_EQ))
+			|| !s->is_ssl) {
+			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+					"ssl.pemfile only works in SSL socket binding context as openssl version does not support TLS extensions");
+			return -1;
+		}
+	}
+#endif
+
+	if (NULL == (s->ssl_pemfile_x509 = x509_load_pem_file(srv, s->ssl_pemfile->ptr))) return -1;
+	if (NULL == (s->ssl_pemfile_pkey = evp_pkey_load_pem_file(srv, s->ssl_pemfile->ptr))) return -1;
+
+	if (!X509_check_private_key(s->ssl_pemfile_x509, s->ssl_pemfile_pkey)) {
+		log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
+				"Private key does not match the certificate public key, reason:",
+				ERR_error_string(ERR_get_error(), NULL),
+				s->ssl_pemfile);
+		return -1;
+	}
+
+	return 0;
+}
+#endif
+
 int network_init(server *srv) {
 	buffer *b;
-	size_t i;
+	size_t i, j;
 	network_backend_t backend;

 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
@@ -582,18 +699,7 @@
 		long ssloptions =
 			SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;

-		if (buffer_is_empty(s->ssl_pemfile)) continue;
-
-#ifdef OPENSSL_NO_TLSEXT
-		{
-			data_config *dc = (data_config *)srv->config_context->data[i];
-			if (COMP_HTTP_HOST == dc->comp) {
-			    log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
-					    "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
-			    return -1;
-			}
-		}
-#endif
+		if (buffer_is_empty(s->ssl_pemfile) && buffer_is_empty(s->ssl_ca_file)) continue;

 		if (srv->ssl_is_init == 0) {
 			SSL_load_error_strings();
@@ -608,6 +714,29 @@
 			}
 		}

+		if (!buffer_is_empty(s->ssl_pemfile)) {
+#ifdef OPENSSL_NO_TLSEXT
+			data_config *dc = (data_config *)srv->config_context->data[i];
+			if (COMP_HTTP_HOST == dc->comp) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+						"can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
+				return -1;
+			}
+#endif
+			if (network_openssl_load_pemfile(srv, i)) return -1;
+		}
+
+
+		if (!buffer_is_empty(s->ssl_ca_file)) {
+			s->ssl_ca_file_cert_names = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
+			if (NULL == s->ssl_ca_file_cert_names) {
+				log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+						ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
+			}
+		}
+
+		if (buffer_is_empty(s->ssl_pemfile) || !s->is_ssl) continue;
+
 		if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
 			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
 					ERR_error_string(ERR_get_error(), NULL));
@@ -707,45 +836,42 @@
 #endif
 #endif

-		if (!buffer_is_empty(s->ssl_ca_file)) {
-			if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
-				log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
-						ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
-				return -1;
-			}
-			if (s->ssl_verifyclient) {
-				STACK_OF(X509_NAME) *certs = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
-				if (!certs) {
+		/* load all ssl.ca-files specified in the config into each SSL_CTX to be prepared for SNI */
+		for (j = 0; j < srv->config_context->used; j++) {
+			specific_config *s1 = srv->config_storage[j];
+
+			if (!buffer_is_empty(s1->ssl_ca_file)) {
+				if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s1->ssl_ca_file->ptr, NULL)) {
 					log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
-							ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
-				}
-				if (SSL_CTX_set_session_id_context(s->ssl_ctx, (void*) &srv, sizeof(srv)) != 1) {
-					log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
-						ERR_error_string(ERR_get_error(), NULL));
+							ERR_error_string(ERR_get_error(), NULL), s1->ssl_ca_file);
 					return -1;
 				}
-				SSL_CTX_set_client_CA_list(s->ssl_ctx, certs);
-				SSL_CTX_set_verify(
-					s->ssl_ctx,
-					SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
-					NULL
+			}
+		}
+
+		if (s->ssl_verifyclient) {
+			if (NULL == s->ssl_ca_file_cert_names) {
+				log_error_write(srv, __FILE__, __LINE__, "s",
+					"SSL: You specified ssl.verifyclient.activate but no ca_file"
 				);
-				SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
+				return -1;
 			}
-		} else if (s->ssl_verifyclient) {
-			log_error_write(
-				srv, __FILE__, __LINE__, "s",
-				"SSL: You specified ssl.verifyclient.activate but no ca_file"
+			SSL_CTX_set_client_CA_list(s->ssl_ctx, SSL_dup_CA_list(s->ssl_ca_file_cert_names));
+			SSL_CTX_set_verify(
+				s->ssl_ctx,
+				SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
+				NULL
 			);
+			SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
 		}

-		if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
+		if (SSL_CTX_use_certificate(s->ssl_ctx, s->ssl_pemfile_x509) < 0) {
 			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
 					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
 			return -1;
 		}

-		if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
+		if (SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey) < 0) {
 			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
 					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
 			return -1;
@@ -842,7 +968,6 @@
 	for (i = 1; i < srv->config_context->used; i++) {
 		data_config *dc = (data_config *)srv->config_context->data[i];
 		specific_config *s = srv->config_storage[i];
-		size_t j;

 		/* not our stage */
 		if (COMP_SERVER_SOCKET != dc->comp) continue;
Index: lighttpd-1.4.31/src/server.c
===================================================================
--- lighttpd-1.4.31.orig/src/server.c	2012-04-28 15:39:38.000000000 +0000
+++ lighttpd-1.4.31/src/server.c	2013-11-13 02:43:16.910532167 +0000
@@ -314,6 +314,9 @@
 			buffer_free(s->ssl_verifyclient_username);
 #ifdef USE_OPENSSL
 			SSL_CTX_free(s->ssl_ctx);
+			EVP_PKEY_free(s->ssl_pemfile_pkey);
+			X509_free(s->ssl_pemfile_x509);
+			if (NULL != s->ssl_ca_file_cert_names) sk_X509_NAME_pop_free(s->ssl_ca_file_cert_names, X509_NAME_free);
 #endif
 			free(s);
 		}


[System]
You are a security patch backporting assistant for SUSE/openSUSE.

Given a CVE description and an upstream fix, adapt the patch to work with
the target SUSE package version. Output the backported patch in unified
diff format. If the upstream fix applies directly, output it unchanged.

[User]
## CVE: CVE-2012-0113

Unspecified vulnerability in the MySQL Server component in Oracle MySQL 5.1.x and 5.5.x allows remote authenticated users to affect confidentiality and availability via unknown vectors, a different vulnerability than CVE-2012-0118.

## Package
mariadb

## Upstream Fix
```diff
PATCH-P0-FIX-SUSE: Tweak default configuration

This patch adds log file locations and socket location as they should be in
SuSE to the default configuration files.

Maintainer: Michal Hrusecky <mhrusecky@suse.cz>

Index: support-files/my-huge.cnf.sh
===================================================================
--- support-files/my-huge.cnf.sh.orig
+++ support-files/my-huge.cnf.sh
@@ -132,7 +132,15 @@ o#innodb_log_group_home_dir = @localstat
 #innodb_flush_log_at_trx_commit = 1
 #innodb_lock_wait_timeout = 50

+# The safe_mysqld script
+[safe_mysqld]
+log-error=/var/log/mysql/mysqld.log
+socket		= @MYSQL_UNIX_ADDR@
+
+# !includedir /etc/mysql
+
 [mysqldump]
+socket		= @MYSQL_UNIX_ADDR@
 quick
 max_allowed_packet = 16M

Index: support-files/my-large.cnf.sh
===================================================================
--- support-files/my-large.cnf.sh.orig
+++ support-files/my-large.cnf.sh
@@ -132,7 +132,15 @@ server-id	= 1
 #innodb_flush_log_at_trx_commit = 1
 #innodb_lock_wait_timeout = 50

+# The safe_mysqld script
+[safe_mysqld]
+log-error=/var/log/mysql/mysqld.log
+socket		= @MYSQL_UNIX_ADDR@
+
+# !includedir /etc/mysql
+
 [mysqldump]
+socket		= @MYSQL_UNIX_ADDR@
 quick
 max_allowed_packet = 16M

Index: support-files/my-medium.cnf.sh
===================================================================
--- support-files/my-medium.cnf.sh.orig
+++ support-files/my-medium.cnf.sh
@@ -28,6 +28,8 @@ socket		= @MYSQL_UNIX_ADDR@
 [mysqld]
 port		= @MYSQL_TCP_PORT@
 socket		= @MYSQL_UNIX_ADDR@
+# Change following line if you want to store your database elsewhere
+datadir	= /var/lib/mysql
 skip-external-locking
 key_buffer_size = 16M
 max_allowed_packet = 1M
@@ -130,7 +132,15 @@ server-id	= 1
 #innodb_flush_log_at_trx_commit = 1
 #innodb_lock_wait_timeout = 50

+# The safe_mysqld script
+[safe_mysqld]
+log-error	= /var/log/mysql/mysqld.log
+socket		= @MYSQL_UNIX_ADDR@
+
+# !includedir /etc/mysql
+
 [mysqldump]
+socket		= @MYSQL_UNIX_ADDR@
 quick
 max_allowed_packet = 16M

Index: support-files/my-small.cnf.sh
===================================================================
--- support-files/my-small.cnf.sh.orig
+++ support-files/my-small.cnf.sh
@@ -65,7 +65,15 @@ server-id	= 1
 #innodb_flush_log_at_trx_commit = 1
 #innodb_lock_wait_timeout = 50

+# The safe_mysqld script
+[safe_mysqld]
+log-error	= /var/log/mysql/mysqld.log
+socket		= @MYSQL_UNIX_ADDR@
+
+# !includedir /etc/mysql
+
 [mysqldump]
+socket		= @MYSQL_UNIX_ADDR@
 quick
 max_allowed_packet = 16M
```

Generate a backported patch for the SUSE target version.

[Assistant]
PATCH-P0-FIX-SUSE: Tweak default configuration

This patch adds log file locations and socket location as they should be in
SuSE to the default configuration files.

Maintainer: Michal Hrusecky <mhrusecky@suse.cz>

Index: support-files/my-huge.cnf.sh
===================================================================
--- support-files/my-huge.cnf.sh.orig
+++ support-files/my-huge.cnf.sh
@@ -132,7 +132,15 @@ o#innodb_log_group_home_dir = @localstat
 #innodb_flush_log_at_trx_commit = 1
 #innodb_lock_wait_timeout = 50

+# The safe_mysqld script
+[safe_mysqld]
+log-error=/var/log/mysql/mysqld.log
+socket		= @MYSQL_UNIX_ADDR@
+
+# !includedir /etc/mysql
+
 [mysqldump]
+socket		= @MYSQL_UNIX_ADDR@
 quick
 max_allowed_packet = 16M

Index: support-files/my-large.cnf.sh
===================================================================
--- support-files/my-large.cnf.sh.orig
+++ support-files/my-large.cnf.sh
@@ -132,7 +132,15 @@ server-id	= 1
 #innodb_flush_log_at_trx_commit = 1
 #innodb_lock_wait_timeout = 50

+# The safe_mysqld script
+[safe_mysqld]
+log-error=/var/log/mysql/mysqld.log
+socket		= @MYSQL_UNIX_ADDR@
+
+# !includedir /etc/mysql
+
 [mysqldump]
+socket		= @MYSQL_UNIX_ADDR@
 quick
 max_allowed_packet = 16M

Index: support-files/my-medium.cnf.sh
===================================================================
--- support-files/my-medium.cnf.sh.orig
+++ support-files/my-medium.cnf.sh
@@ -28,6 +28,8 @@ socket		= @MYSQL_UNIX_ADDR@
 [mysqld]
 port		= @MYSQL_TCP_PORT@
 socket		= @MYSQL_UNIX_ADDR@
+# Change following line if you want to store your database elsewhere
+datadir	= /var/lib/mysql
 skip-external-locking
 key_buffer_size = 16M
 max_allowed_packet = 1M
@@ -130,7 +132,15 @@ server-id	= 1
 #innodb_flush_log_at_trx_commit = 1
 #innodb_lock_wait_timeout = 50

+# The safe_mysqld script
+[safe_mysqld]
+log-error	= /var/log/mysql/mysqld.log
+socket		= @MYSQL_UNIX_ADDR@
+
+# !includedir /etc/mysql
+
 [mysqldump]
+socket		= @MYSQL_UNIX_ADDR@
 quick
 max_allowed_packet = 16M

Index: support-files/my-small.cnf.sh
===================================================================
--- support-files/my-small.cnf.sh.orig
+++ support-files/my-small.cnf.sh
@@ -65,7 +65,15 @@ server-id	= 1
 #innodb_flush_log_at_trx_commit = 1
 #innodb_lock_wait_timeout = 50

+# The safe_mysqld script
+[safe_mysqld]
+log-error	= /var/log/mysql/mysqld.log
+socket		= @MYSQL_UNIX_ADDR@
+
+# !includedir /etc/mysql
+
 [mysqldump]
+socket		= @MYSQL_UNIX_ADDR@
 quick
 max_allowed_packet = 16M