[gnutls-dev] [PATCH] error handling large CA files

Ian Peters itp@ximian.com
Wed Mar 12 03:48:02 2003


--=-YxLKElOogtn7nNzqZUTd
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

On Tue, 2003-03-11 at 16:41, Ian Peters wrote:
> The attached patch fixes these three functions to read passed file into
> a heap-allocated buffer, parse the memory, and then free the buffer. 
> You'll probably want to tweak things to fit into gnutls better
> stylistically.

Of course, -this- attached patch does the same, but doesn't leak file
descriptors.  :-)

Ian

--=-YxLKElOogtn7nNzqZUTd
Content-Disposition: attachment; filename=gnutls-0.8.4-large-ca-file.patch
Content-Type: text/x-patch; name=gnutls-0.8.4-large-ca-file.patch; charset=UTF-8
Content-Transfer-Encoding: 7bit

diff -Nru -x '*~' -x '*.o' -x '*.orig' -x '*.rej' gnutls-0.8.4.orig/lib/gnutls_x509.c gnutls-0.8.4/lib/gnutls_x509.c
--- gnutls-0.8.4.orig/lib/gnutls_x509.c	2003-02-04 07:52:24.000000000 -0500
+++ gnutls-0.8.4/lib/gnutls_x509.c	2003-03-11 21:43:53.000000000 -0500
@@ -1602,26 +1602,68 @@
 }
 
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+extern int errno;
+static int read_file(const char *filename, char **data, int *len)
+{
+	int fd;
+	struct stat s;
+	char *buf;
+	unsigned int bytes_read = 0;
+
+	if ((fd = open( filename, O_RDONLY)) < 0) {
+		gnutls_assert();
+		return GNUTLS_E_FILE_ERROR;
+	}
+
+	if ((fstat( fd, &s)) < 0) {
+		gnutls_assert();
+		close(fd);
+		return GNUTLS_E_FILE_ERROR;
+	}
+
+	buf = gnutls_malloc(s.st_size + 1);
+	buf[s.st_size] = 0;
+
+	while (bytes_read < s.st_size) {
+		int ret;
+		ret = read( fd, buf + bytes_read, s.st_size - bytes_read);
+		if (ret < 0 && errno != EINTR && errno != EAGAIN) {
+			gnutls_assert();
+			gnutls_free(buf);
+			close(fd);
+			return GNUTLS_E_FILE_ERROR;
+		}
+		bytes_read += ret;
+	}
+
+	close(fd);
+
+	*data = buf;
+	*len = s.st_size + 1;
+	return 0;
+}
+
 /* Reads a certificate file
  */
 static int read_cert_file(gnutls_certificate_credentials res, const char *certfile,
 	gnutls_x509_certificate_format type)
 {
 	int siz;
-	char x[MAX_FILE_SIZE];
-	FILE *fd1;
-
-	fd1 = fopen(certfile, "rb");
-	if (fd1 == NULL)
-		return GNUTLS_E_FILE_ERROR;
-
-	siz = fread(x, 1, sizeof(x)-1, fd1);
-	fclose(fd1);
-
-	x[siz] = 0;
+	char *x;
+	int ret;
 
-	return read_cert_mem( res, x, siz, type);
+	if ((ret = read_file( certfile, &x, &siz)) < 0) {
+		gnutls_assert();
+		return ret;
+	}
 
+	ret = read_cert_mem( res, x, siz, type);
+	gnutls_free(x);
+	return ret;
 }
 
 /* Reads a base64 encoded CA file (file contains multiple certificate
@@ -1631,21 +1673,17 @@
 	gnutls_x509_certificate_format type)
 {
 	int siz;
-	char x[MAX_FILE_SIZE];
-	FILE *fd1;
+	char *x;
+	int ret;
 
-	fd1 = fopen(cafile, "rb");
-	if (fd1 == NULL) {
+	if ((ret = read_file( cafile, &x, &siz)) < 0) {
 		gnutls_assert();
-		return GNUTLS_E_FILE_ERROR;
+		return ret;
 	}
 
-	siz = fread(x, 1, sizeof(x)-1, fd1);
-	fclose(fd1);
-
-	x[siz] = 0;
-
-	return read_ca_mem( res, x, siz, type);
+	ret = read_ca_mem( res, x, siz, type);
+	gnutls_free(x);
+	return ret;
 }
 
 
@@ -1656,19 +1694,17 @@
 	gnutls_x509_certificate_format type)
 {
 	int siz;
-	char x[MAX_FILE_SIZE];
-	FILE *fd2;
-
-	fd2 = fopen(keyfile, "rb");
-	if (fd2 == NULL)
-		return GNUTLS_E_FILE_ERROR;
-
-	siz = fread(x, 1, sizeof(x)-1, fd2);
-	fclose(fd2);
+	char *x;
+	int ret;
 
-	x[siz] = 0;
+	if ((ret = read_file( keyfile, &x, &siz)) < 0) {
+		gnutls_assert();
+		return ret;
+	}
 
-	return read_key_mem( res, x, siz, type);
+	ret = read_key_mem( res, x, siz, type);
+	gnutls_free(x);
+	return ret;
 }
 
 /**

--=-YxLKElOogtn7nNzqZUTd--