File opensc-fixed-out-of-bounds-reads.patch of Package opensc.9053

From 8fe377e93b4b56060e5bbfb6f3142ceaeca744fa Mon Sep 17 00:00:00 2001
From: Frank Morgner <frankmorgner@gmail.com>
Date: Fri, 25 May 2018 14:54:47 +0200
Subject: [PATCH] fixed out of bounds reads

Thanks to Eric Sesterhenn from X41 D-SEC GmbH
for reporting and suggesting security fixes.
---
 src/libopensc/asn1.c           |  1 +
 src/libopensc/card-asepcos.c   |  2 +-
 src/libopensc/card-authentic.c |  5 ++++-
 src/libopensc/card-cac.c       |  9 +++++++--
 src/libopensc/card-coolkey.c   |  2 +-
 src/libopensc/card-entersafe.c |  8 +++++---
 src/libopensc/card-epass2003.c | 35 ++++++++++++++++++----------------
 src/libopensc/card-gpk.c       |  3 +++
 src/libopensc/card-iasecc.c    |  2 +-
 src/libopensc/card-oberthur.c  |  7 +++++++
 src/libopensc/card-openpgp.c   |  6 ++++++
 src/libopensc/card-piv.c       |  9 +++++----
 src/libopensc/card-rtecp.c     |  2 +-
 src/libopensc/card-setcos.c    | 18 +++++++++++++++--
 src/libopensc/ef-gdo.c         |  2 +-
 src/libopensc/pkcs15-itacns.c  |  1 +
 src/libopensc/pkcs15-tcos.c    |  8 +++++---
 src/tools/opensc-tool.c        | 21 ++++++++++----------
 18 files changed, 95 insertions(+), 46 deletions(-)

Index: opensc-0.18.0/src/libopensc/asn1.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/asn1.c
+++ opensc-0.18.0/src/libopensc/asn1.c
@@ -103,6 +103,7 @@ int sc_asn1_read_tag(const u8 ** buf, si
 	len = *p & 0x7f;
 	if (*p++ & 0x80) {
 		unsigned int a = 0;
+		left--;
 		if (len > 4 || len > left)
 			return SC_ERROR_INVALID_ASN1_OBJECT;
 		left -= len;
Index: opensc-0.18.0/src/libopensc/card-asepcos.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-asepcos.c
+++ opensc-0.18.0/src/libopensc/card-asepcos.c
@@ -169,7 +169,7 @@ static int asepcos_parse_sec_attr(sc_car
 
 	while (len != 0) {
 		unsigned int amode, tlen = 3;
-		if (len < 5 && p[0] != 0x80 && p[1] != 0x01) {
+		if (len < 5 || p[0] != 0x80 || p[1] != 0x01) {
 			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid access mode encoding");
 			return SC_ERROR_INTERNAL;
 		}
Index: opensc-0.18.0/src/libopensc/card-authentic.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-authentic.c
+++ opensc-0.18.0/src/libopensc/card-authentic.c
@@ -557,6 +557,9 @@ authentic_set_current_files(struct sc_ca
 			sc_file_dup(&card->cache.current_df, file);
 
 			if (cur_df_path.len)   {
+				if (cur_df_path.len + card->cache.current_df->path.len > sizeof card->cache.current_df->path.value
+						|| cur_df_path.len > sizeof card->cache.current_df->path.value)
+					LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
 				memcpy(card->cache.current_df->path.value + cur_df_path.len,
 						card->cache.current_df->path.value,
 						card->cache.current_df->path.len);
@@ -985,7 +988,7 @@ authentic_process_fci(struct sc_card *ca
 	}
 
 	sc_log_hex(ctx, "ACL data", file->sec_attr, file->sec_attr_len);
-	for (ii = 0; ii < file->sec_attr_len / 2; ii++)  {
+	for (ii = 0; ii < file->sec_attr_len / 2 && ii < sizeof ops_DF; ii++)  {
 		unsigned char op = file->type == SC_FILE_TYPE_DF ? ops_DF[ii] : ops_EF[ii];
 		unsigned char acl = *(file->sec_attr + ii*2);
 		unsigned char cred_id = *(file->sec_attr + ii*2 + 1);
Index: opensc-0.18.0/src/libopensc/card-cac.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-cac.c
+++ opensc-0.18.0/src/libopensc/card-cac.c
@@ -682,12 +682,17 @@ static int cac_read_binary(sc_card_t *ca
 		cert_len = 0;
 		cert_ptr = NULL;
 		cert_type = 0;
-		for (tl_ptr = tl, val_ptr=val; tl_len >= 2;
-				val_len -= len, val_ptr += len, tl_len -= tl_head_len) {
+		for (tl_ptr = tl, val_ptr = val; tl_len >= 2;
+		    val_len -= len, val_ptr += len, tl_len -= tl_head_len) {
 			tl_start = tl_ptr;
 			if (sc_simpletlv_read_tag(&tl_ptr, tl_len, &tag, &len) != SC_SUCCESS)
 				break;
 			tl_head_len = tl_ptr - tl_start;
+
+			/* incomplete value */
+			if (val_len < len)
+				break;
+
 			if (tag == CAC_TAG_CERTIFICATE) {
 				cert_len = len;
 				cert_ptr = val_ptr;
Index: opensc-0.18.0/src/libopensc/card-coolkey.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-coolkey.c
+++ opensc-0.18.0/src/libopensc/card-coolkey.c
@@ -1466,7 +1466,7 @@ coolkey_find_attribute(sc_card_t *card,
 	for (i=0; i < attribute_count; i++) {
 		size_t record_len = coolkey_get_attribute_record_len(attr, object_record_type, buf_len);
 		/* make sure we have the complete record */
-		if (buf_len < record_len) {
+		if (buf_len < record_len || record_len < 4) {
 				return SC_ERROR_CORRUPTED_DATA;
 		}
 		/* does the attribute match the one we are looking for */
Index: opensc-0.18.0/src/libopensc/card-entersafe.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-entersafe.c
+++ opensc-0.18.0/src/libopensc/card-entersafe.c
@@ -1408,13 +1408,15 @@ static int entersafe_gen_key(sc_card_t *
 
 	data->modulus = malloc(len);
 	if (!data->modulus)
-		 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_OUT_OF_MEMORY);
+		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
 
 	p=rbuf;
-	assert(*p=='E');
+	if (*p!='E')
+		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
 	p+=2+p[1];
 	/* N */
-	assert(*p=='N');
+	if (*p!='N')
+		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
 	++p;
 	if(*p++>0x80)
 	{
Index: opensc-0.18.0/src/libopensc/card-epass2003.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-epass2003.c
+++ opensc-0.18.0/src/libopensc/card-epass2003.c
@@ -740,11 +740,11 @@ construct_mac_tlv(struct sc_card *card,
 		memcpy(mac_tlv + 2, &mac[mac_len - 16], 8);
 	}
 	else {
-		unsigned char iv[8] = { 0 };
+		unsigned char iv[EVP_MAX_IV_LENGTH] = { 0 };
 		unsigned char tmp[8] = { 0 };
 		des_encrypt_cbc(exdata->sk_mac, 8, icv, apdu_buf, mac_len, mac);
 		des_decrypt_cbc(&exdata->sk_mac[8], 8, iv, &mac[mac_len - 8], 8, tmp);
-		memset(iv, 0x00, 8);
+		memset(iv, 0x00, sizeof iv);
 		des_encrypt_cbc(exdata->sk_mac, 8, iv, tmp, 8, mac_tlv + 2);
 	}
 
@@ -903,9 +903,9 @@ epass2003_sm_wrap_apdu(struct sc_card *c
  * SW12(TLV)=0x99|0x02|SW1+SW2
  * MAC(TLV)=0x8e|0x08|MAC */
 static int
-decrypt_response(struct sc_card *card, unsigned char *in, unsigned char *out, size_t * out_len)
+decrypt_response(struct sc_card *card, unsigned char *in, size_t inlen, unsigned char *out, size_t * out_len)
 {
-	size_t in_len;
+	size_t cipher_len;
 	size_t i;
 	unsigned char iv[16] = { 0 };
 	unsigned char plaintext[4096] = { 0 };
@@ -922,37 +922,40 @@ decrypt_response(struct sc_card *card, u
 
 	/* parse cipher length */
 	if (0x01 == in[2] && 0x82 != in[1]) {
-		in_len = in[1];
+		cipher_len = in[1];
 		i = 3;
 	}
 	else if (0x01 == in[3] && 0x81 == in[1]) {
-		in_len = in[2];
+		cipher_len = in[2];
 		i = 4;
 	}
 	else if (0x01 == in[4] && 0x82 == in[1]) {
-		in_len = in[2] * 0x100;
-		in_len += in[3];
+		cipher_len = in[2] * 0x100;
+		cipher_len += in[3];
 		i = 5;
 	}
 	else {
 		return -1;
 	}
 
+	if (cipher_len < 2 || i+cipher_len > inlen || cipher_len > sizeof plaintext)
+		return -1;
+
 	/* decrypt */
 	if (KEY_TYPE_AES == exdata->smtype)
-		aes128_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], in_len - 1, plaintext);
+		aes128_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], cipher_len - 1, plaintext);
 	else
-		des3_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], in_len - 1, plaintext);
+		des3_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], cipher_len - 1, plaintext);
 
 	/* unpadding */
-	while (0x80 != plaintext[in_len - 2] && (in_len - 2 > 0))
-		in_len--;
+	while (0x80 != plaintext[cipher_len - 2] && (cipher_len - 2 > 0))
+		cipher_len--;
 
-	if (2 == in_len)
+	if (2 == cipher_len)
 		return -1;
 
-	memcpy(out, plaintext, in_len - 2);
-	*out_len = in_len - 2;
+	memcpy(out, plaintext, cipher_len - 2);
+	*out_len = cipher_len - 2;
 	return 0;
 }
 
@@ -974,7 +977,7 @@ epass2003_sm_unwrap_apdu(struct sc_card
 	r = sc_check_sw(card, sm->sw1, sm->sw2);
 	if (r == SC_SUCCESS) {
 		if (exdata->sm) {
-			if (0 != decrypt_response(card, sm->resp, plain->resp, &len))
+			if (0 != decrypt_response(card, sm->resp, sm->resplen, plain->resp, &len))
 				return SC_ERROR_CARD_CMD_FAILED;
 		}
 		else {
Index: opensc-0.18.0/src/libopensc/card-gpk.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-gpk.c
+++ opensc-0.18.0/src/libopensc/card-gpk.c
@@ -409,6 +409,9 @@ gpk_parse_fileinfo(sc_card_t *card,
 		if (sp[0] == 0x85) {
 			unsigned int	ac[3], n;
 
+			if (sp + 11 + 2*3 >= end)
+				break;
+
 			file->id = (sp[4] << 8) | sp[5];
 			file->size = (sp[8] << 8) | sp[9];
 			file->record_length = sp[7];
Index: opensc-0.18.0/src/libopensc/card-iasecc.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-iasecc.c
+++ opensc-0.18.0/src/libopensc/card-iasecc.c
@@ -2543,7 +2543,7 @@ iasecc_get_serialnr(struct sc_card *card
 	if (card->type == SC_CARD_TYPE_IASECC_SAGEM)   {
 		/* 5A 0A 92 50 00 20 10 10 25 00 01 3F */
 		/*            00 02 01 01 02 50 00 13  */
-		for (ii=0; ii < rbuf[1] - offs; ii++)
+		for (ii=0; (ii < rbuf[1] - offs) && (ii + offs + 2 < sizeof(rbuf)); ii++)
 			*(card->serialnr.value + ii) = ((rbuf[ii + offs + 1] & 0x0F) << 4)
 				+ ((rbuf[ii + offs + 2] & 0xF0) >> 4) ;
 		card->serialnr.len = ii;
Index: opensc-0.18.0/src/libopensc/card-oberthur.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-oberthur.c
+++ opensc-0.18.0/src/libopensc/card-oberthur.c
@@ -484,6 +484,9 @@ auth_select_file(struct sc_card *card, c
 
 	memcpy(&path, in_path, sizeof(struct sc_path));
 
+	if (!auth_current_df)
+		return SC_ERROR_OBJECT_NOT_FOUND;
+
 	sc_log(card->ctx, "in_path; type=%d, path=%s, out %p",
 			in_path->type, sc_print_path(in_path), file_out);
 	sc_log(card->ctx, "current path; type=%d, path=%s",
@@ -2121,6 +2124,10 @@ auth_read_binary(struct sc_card *card, u
 	bn[1].data = NULL;
 
 	LOG_FUNC_CALLED(card->ctx);
+
+	if (!auth_current_ef)
+		LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid auth_current_ef");
+
 	sc_log(card->ctx,
 	       "offset %i; size %"SC_FORMAT_LEN_SIZE_T"u; flags 0x%lX",
 	       offset, count, flags);
Index: opensc-0.18.0/src/libopensc/card-openpgp.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-openpgp.c
+++ opensc-0.18.0/src/libopensc/card-openpgp.c
@@ -934,6 +934,9 @@ pgp_enumerate_blob(sc_card_t *card, pgp_
 		const u8	*data = in;
 		pgp_blob_t	*new;
 
+		if (!in)
+			return SC_ERROR_OBJECT_NOT_VALID;
+
 		r = sc_asn1_read_tag(&data, blob->len - (in - blob->data),
 					&cla, &tag, &len);
 		if (r < 0 || data == NULL) {
@@ -942,6 +945,9 @@ pgp_enumerate_blob(sc_card_t *card, pgp_
 			return SC_ERROR_OBJECT_NOT_VALID;
 		}
 
+		if (data + len > blob->data + blob->len)
+			return SC_ERROR_OBJECT_NOT_VALID;
+
 		/* undo ASN1's split of tag & class */
 		for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) {
 			cla <<= 8;
Index: opensc-0.18.0/src/libopensc/card-piv.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-piv.c
+++ opensc-0.18.0/src/libopensc/card-piv.c
@@ -573,7 +573,7 @@ static int piv_general_io(sc_card_t *car
 		 * the buffer is bigger, so it will not produce "ASN1.tag too long!" */
 
 		body = rbuf;
-		if (sc_asn1_read_tag(&body, 0xffff, &cla_out, &tag_out, &bodylen) !=  SC_SUCCESS
+		if (sc_asn1_read_tag(&body, rbuflen, &cla_out, &tag_out, &bodylen) !=  SC_SUCCESS
 				|| body == NULL)  {
 			/* only early beta cards had this problem */
 			sc_log(card->ctx, "***** received buffer tag MISSING ");
@@ -3049,12 +3049,13 @@ static int piv_match_card_continued(sc_c
 			 *   73 66 74 65 20 63 64 31 34 34
 			 * will check for 73 66 74 65
 			 */
-			else if (card->reader->atr_info.hist_bytes_len >= 4 &&
-					!(memcmp(card->reader->atr_info.hist_bytes, "sfte", 4))) {
+			else if (card->reader->atr_info.hist_bytes_len >= 4
+					&& !(memcmp(card->reader->atr_info.hist_bytes, "sfte", 4))) {
 				type = SC_CARD_TYPE_PIV_II_GI_DE;
 			}
 
-			else if (card->reader->atr_info.hist_bytes[0] == 0x80u) { /* compact TLV */
+			else if (card->reader->atr_info.hist_bytes_len > 0
+					&& card->reader->atr_info.hist_bytes[0] == 0x80u) { /* compact TLV */
 				p = card->reader->atr_info.hist_bytes;
 				pe = p + card->reader->atr_info.hist_bytes_len;
 				p++; /* skip 0x80u byte */
Index: opensc-0.18.0/src/libopensc/card-rtecp.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-rtecp.c
+++ opensc-0.18.0/src/libopensc/card-rtecp.c
@@ -275,7 +275,7 @@ static int rtecp_select_file(sc_card_t *
 		set_acl_from_sec_attr(card, file);
 	else
 		r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
-	if (r)
+	if (r && !file_out)
 		sc_file_free(file);
 	else
 	{
Index: opensc-0.18.0/src/libopensc/card-setcos.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/card-setcos.c
+++ opensc-0.18.0/src/libopensc/card-setcos.c
@@ -789,6 +789,8 @@ static void parse_sec_attr_44(sc_file_t
 	/* Check all sub-AC definitions within the total AC */
 	while (len > 1) {				/* minimum length = 2 */
 		int	iACLen   = buf[iOffset] & 0x0F;
+		if ((size_t) iACLen > len)
+			break;
 
 		iPinCount = -1;			/* default no pin required */
 		iMethod = SC_AC_NONE;		/* default no authentication required */
@@ -806,7 +808,10 @@ static void parse_sec_attr_44(sc_file_t
 
 			/* Get KeyNumber if available */
 			if(iKeyLen) {
-				int iSC = buf[iOffset+iACLen];
+				int iSC;
+				if (len < 1+iACLen)
+					break;
+				iSC = buf[iOffset+iACLen];
 
 				switch( (iSC>>5) & 0x03 ){
 				case 0:
@@ -825,11 +830,15 @@ static void parse_sec_attr_44(sc_file_t
 
 			/* Get PinNumber if available */
 			if (iACLen > (1+iParmLen+iKeyLen)) {  /* check via total length if pin is present */
+				if (len < 1+1+1+iParmLen)
+					break;
 				iKeyRef = buf[iOffset+1+1+iParmLen];  /* PTL + AM-header + parameter-bytes */
 				iMethod = SC_AC_CHV;
 			}
 
 			/* Convert SETCOS command to OpenSC command group */
+			if (len < 1+2)
+				break;
 			switch(buf[iOffset+2]){
 			case 0x2A:			/* crypto operation */
 				iOperation = SC_AC_OP_CRYPTO;
@@ -863,7 +872,10 @@ static void parse_sec_attr_44(sc_file_t
 			iPinCount = iACLen - 1;		
 
 			if (buf[iOffset] & 0x20) {
-				int iSC = buf[iOffset + iACLen];
+				int iSC;
+				if (len < 1 + iACLen)
+					break;
+				iSC = buf[iOffset + iACLen];
 
 				switch( (iSC>>5) & 0x03 ) {
 				case 0:
@@ -884,6 +896,8 @@ static void parse_sec_attr_44(sc_file_t
 
 			/* Pin present ? */
 			if ( iPinCount > 0 ) {
+				if (len < 1 + 2)
+					break;
 				iKeyRef = buf[iOffset + 2];	/* pin ref */
 				iMethod = SC_AC_CHV;
 			}
Index: opensc-0.18.0/src/libopensc/ef-gdo.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/ef-gdo.c
+++ opensc-0.18.0/src/libopensc/ef-gdo.c
@@ -72,7 +72,7 @@ sc_parse_ef_gdo_content(const unsigned c
 		}
 
 		p += tag_len;
-		left -= (p - gdo);
+		left = gdo_len - (p - gdo);
 	}
 
 	if (!iccsn_found && iccsn_len)
Index: opensc-0.18.0/src/libopensc/pkcs15-itacns.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/pkcs15-itacns.c
+++ opensc-0.18.0/src/libopensc/pkcs15-itacns.c
@@ -550,6 +550,7 @@ static int itacns_add_data_files(sc_pkcs
 		sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
 			"Could not read EF_DatiPersonali: "
 			"keeping generic card name");
+		return SC_SUCCESS;
 	}
 
 	{
Index: opensc-0.18.0/src/libopensc/pkcs15-tcos.c
===================================================================
--- opensc-0.18.0.orig/src/libopensc/pkcs15-tcos.c
+++ opensc-0.18.0/src/libopensc/pkcs15-tcos.c
@@ -132,7 +132,7 @@ static int insert_key(
 		int i, rec_no=0;
 		if(prkey_info.path.len>=2) prkey_info.path.len-=2;
 		sc_append_file_id(&prkey_info.path, 0x5349);
-		if(sc_select_file(card, &prkey_info.path, NULL)!=SC_SUCCESS){
+		if(sc_select_file(card, &prkey_info.path, NULL)!=SC_SUCCESS || !f->prop_attr){
 			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
 				"Select(%s) failed\n",
 				sc_print_path(&prkey_info.path));
@@ -157,7 +157,8 @@ static int insert_key(
 			if(buf[i]==0xB8) can_crypt++;
 		}
 	} else {
-		if(sc_select_file(card, &prkey_info.path, &f)!=SC_SUCCESS){
+		if(sc_select_file(card, &prkey_info.path, &f)!=SC_SUCCESS
+			   	|| !f->prop_attr || f->prop_attr_len < 2){
 			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
 				"Select(%s) failed\n",
 				sc_print_path(&prkey_info.path));
@@ -245,7 +246,8 @@ static int insert_pin(
 			return 1;
 		}
 	} else {
-		if(sc_select_file(card, &pin_info.path, &f)!=SC_SUCCESS){
+		if(sc_select_file(card, &pin_info.path, &f)!=SC_SUCCESS
+			   	|| !f->prop_attr || f->prop_attr_len < 4){
 			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"Select(%s) failed\n", path);
 			return 1;
 		}
Index: opensc-0.18.0/src/tools/opensc-tool.c
===================================================================
--- opensc-0.18.0.orig/src/tools/opensc-tool.c
+++ opensc-0.18.0/src/tools/opensc-tool.c
@@ -451,7 +451,7 @@ static int enum_dir(sc_path_t path, int
 {
 	sc_file_t *file;
 	int r, file_type;
-	u8 files[SC_MAX_APDU_BUFFER_SIZE];
+	u8 files[SC_MAX_EXT_APDU_BUFFER_SIZE];
 
 	r = sc_select_file(card, &path, &file);
 	if (r) {
@@ -471,15 +471,16 @@ static int enum_dir(sc_path_t path, int
 		}
 		if (r == 0) {
 			printf("Empty directory\n");
-		} else
-		for (i = 0; i < r/2; i++) {
-			sc_path_t tmppath;
+		} else {
+			for (i = 0; i < r/2; i++) {
+				sc_path_t tmppath;
 
-			memset(&tmppath, 0, sizeof(tmppath));
-			memcpy(&tmppath, &path, sizeof(path));
-			memcpy(tmppath.value + tmppath.len, files + 2*i, 2);
-			tmppath.len += 2;
-			enum_dir(tmppath, depth + 1);
+				memset(&tmppath, 0, sizeof(tmppath));
+				memcpy(&tmppath, &path, sizeof(path));
+				memcpy(tmppath.value + tmppath.len, files + 2*i, 2);
+				tmppath.len += 2;
+				enum_dir(tmppath, depth + 1);
+			}
 		}
 	}
 	return 0;
openSUSE Build Service is sponsored by