Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / lib / system.c
index db9446e..67edebb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2015 Free Software Foundation, Inc.
+ * Copyright (C) 2010-2012 Free Software Foundation, Inc.
  *
  * Author: Nikos Mavrogiannopoulos
  *
 # include <windows.h>
 # include <wincrypt.h>
 # if defined(__MINGW32__) && !defined(__MINGW64__) && __MINGW32_MAJOR_VERSION <= 3 && __MINGW32_MINOR_VERSION <= 20
-typedef PCCRL_CONTEXT WINAPI(*CertEnumCRLsInStoreFunc) (HCERTSTORE
+typedef PCCRL_CONTEXT WINAPI(*Type_CertEnumCRLsInStore) (HCERTSTORE
                                                         hCertStore,
                                                         PCCRL_CONTEXT
                                                         pPrevCrlContext);
-static CertEnumCRLsInStoreFunc pCertEnumCRLsInStore;
+static Type_CertEnumCRLsInStore Loaded_CertEnumCRLsInStore;
 static HMODULE Crypt32_dll;
 # else
-#  define pCertEnumCRLsInStore CertEnumCRLsInStore
+#  define Loaded_CertEnumCRLsInStore CertEnumCRLsInStore
 # endif
 
 #else /* _WIN32 */
@@ -110,65 +110,50 @@ int system_errno(gnutls_transport_ptr_t ptr)
        return errno;
 }
 
-#ifdef MSG_NOSIGNAL
-ssize_t
-system_writev_nosignal(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
-             int iovec_cnt)
-{
-       struct msghdr hdr;
-
-       memset(&hdr, 0, sizeof(hdr));
-       hdr.msg_iov = (struct iovec *)iovec;
-       hdr.msg_iovlen = iovec_cnt;
-
-       return sendmsg(GNUTLS_POINTER_TO_INT(ptr), &hdr, MSG_NOSIGNAL);
-}
-#endif
-
 ssize_t
 system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
              int iovec_cnt)
 {
        return writev(GNUTLS_POINTER_TO_INT(ptr), (struct iovec *) iovec,
                      iovec_cnt);
+
 }
 #endif
 
-
 ssize_t
 system_read(gnutls_transport_ptr_t ptr, void *data, size_t data_size)
 {
        return recv(GNUTLS_POINTER_TO_INT(ptr), data, data_size, 0);
 }
 
-/**
- * gnutls_system_recv_timeout:
- * @ptr: A gnutls_transport_ptr_t pointer
- * @ms: The number of milliseconds to wait.
- *
- * Wait for data to be received from the provided socket (@ptr) within a
- * timeout period in milliseconds, using select() on the provided @ptr.
- *
- * This function is provided as a helper for constructing custom
- * callbacks for gnutls_transport_set_pull_timeout_function(),
- * which can be used if you rely on socket file descriptors.
+/* Wait for data to be received within a timeout period in milliseconds.
+ * To catch a termination it will also try to receive 0 bytes from the
+ * socket if select reports to proceed.
  *
  * Returns -1 on error, 0 on timeout, positive value if data are available for reading.
- *
- * Since: 3.4.0
- **/
-int gnutls_system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
+ */
+int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
 {
        fd_set rfds;
        struct timeval tv;
        int ret;
        int fd = GNUTLS_POINTER_TO_INT(ptr);
 
+       if (fd < 0 || fd >= FD_SETSIZE) {
+               errno = EINVAL;
+               return -1;
+       }
+
        FD_ZERO(&rfds);
        FD_SET(fd, &rfds);
 
-       tv.tv_sec = ms/1000;
-       tv.tv_usec = (ms % 1000) * 1000;
+       tv.tv_sec = 0;
+       tv.tv_usec = ms * 1000;
+
+       while (tv.tv_usec >= 1000000) {
+               tv.tv_usec -= 1000000;
+               tv.tv_sec++;
+       }
 
        ret = select(fd + 1, &rfds, NULL, NULL, &tv);
        if (ret <= 0)
@@ -297,7 +282,7 @@ mutex_deinit_func gnutls_mutex_deinit = gnutls_system_mutex_deinit;
 mutex_lock_func gnutls_mutex_lock = gnutls_system_mutex_lock;
 mutex_unlock_func gnutls_mutex_unlock = gnutls_system_mutex_unlock;
 
-int gnutls_system_global_init(void)
+int gnutls_system_global_init()
 {
 #ifdef _WIN32
 #if defined(__MINGW32__) && !defined(__MINGW64__) && __MINGW32_MAJOR_VERSION <= 3 && __MINGW32_MINOR_VERSION <= 20
@@ -307,10 +292,10 @@ int gnutls_system_global_init(void)
        if (crypto == NULL)
                return GNUTLS_E_CRYPTO_INIT_FAILED;
 
-       pCertEnumCRLsInStore =
-           (CertEnumCRLsInStoreFunc) GetProcAddress(crypto,
+       Loaded_CertEnumCRLsInStore =
+           (Type_CertEnumCRLsInStore) GetProcAddress(crypto,
                                                      "CertEnumCRLsInStore");
-       if (pCertEnumCRLsInStore == NULL) {
+       if (Loaded_CertEnumCRLsInStore == NULL) {
                FreeLibrary(crypto);
                return GNUTLS_E_CRYPTO_INIT_FAILED;
        }
@@ -321,7 +306,7 @@ int gnutls_system_global_init(void)
        return 0;
 }
 
-void gnutls_system_global_deinit(void)
+void gnutls_system_global_deinit()
 {
 #ifdef _WIN32
 #if defined(__MINGW32__) && !defined(__MINGW64__) && __MINGW32_MAJOR_VERSION <= 3 && __MINGW32_MINOR_VERSION <= 20
@@ -338,7 +323,7 @@ void gnutls_system_global_deinit(void)
  */
 int _gnutls_find_config_path(char *path, size_t max_size)
 {
-       const char *home_dir = getenv("HOME");
+       const char *home_dir = secure_getenv("HOME");
 
        if (home_dir != NULL && home_dir[0] != 0) {
                snprintf(path, max_size, "%s/" CONFIG_PATH, home_dir);
@@ -351,7 +336,7 @@ int _gnutls_find_config_path(char *path, size_t max_size)
                const char *home_path = getenv("HOMEPATH");
 
                if (home_drive != NULL && home_path != NULL) {
-                       snprintf(path, max_size, "%s%s\\" CONFIG_PATH, home_drive, home_path);
+                       snprintf(path, max_size, "%s%s/" CONFIG_PATH, home_drive, home_path);
                } else {
                        path[0] = 0;
                }
@@ -448,7 +433,7 @@ int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags,
                        return GNUTLS_E_FILE_ERROR;
 
                cert = CertEnumCertificatesInStore(store, NULL);
-               crl = pCertEnumCRLsInStore(store, NULL);
+               crl = Loaded_CertEnumCRLsInStore(store, NULL);
 
                while (cert != NULL) {
                        if (cert->dwCertEncodingType == X509_ASN_ENCODING) {
@@ -474,7 +459,7 @@ int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags,
                                                                     tl_flags,
                                                                     tl_vflags);
                        }
-                       crl = pCertEnumCRLsInStore(store, crl);
+                       crl = Loaded_CertEnumCRLsInStore(store, crl);
                }
                CertCloseStore(store, 0);
        }
@@ -588,8 +573,9 @@ gnutls_x509_trust_list_add_system_trust(gnutls_x509_trust_list_t list,
 #if defined(_WIN32)
 #include <winnls.h>
 
+/* Can convert only english */
 int _gnutls_ucs2_to_utf8(const void *data, size_t size,
-                        gnutls_datum_t * output, unsigned be)
+                        gnutls_datum_t * output)
 {
        int ret;
        unsigned i;
@@ -613,24 +599,20 @@ int _gnutls_ucs2_to_utf8(const void *data, size_t size,
                size -= 2;
        }
 
-       src_len = wcslen(data);
-
        src = gnutls_malloc(size+2);
        if (src == NULL)
                return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
        /* convert to LE */
-       if (be) {
-               for (i = 0; i < size; i += 2) {
-                       src[i] = ((uint8_t *) data)[1 + i];
-                       src[1 + i] = ((uint8_t *) data)[i];
-               }
-       } else {
-               memcpy(src, data, size);
+       for (i = 0; i < size; i += 2) {
+               src[i] = ((uint8_t *) data)[1 + i];
+               src[1 + i] = ((uint8_t *) data)[i];
        }
        src[size] = 0;
        src[size+1] = 0;
 
+       src_len = wcslen(src);
+
        ret =
            WideCharToMultiByte(CP_UTF8, flags,
                                (void *) src, src_len, NULL, 0,
@@ -678,7 +660,7 @@ int _gnutls_ucs2_to_utf8(const void *data, size_t size,
 #include <iconv.h>
 
 int _gnutls_ucs2_to_utf8(const void *data, size_t size,
-                        gnutls_datum_t * output, unsigned be)
+                        gnutls_datum_t * output)
 {
        iconv_t conv;
        int ret;
@@ -689,11 +671,7 @@ int _gnutls_ucs2_to_utf8(const void *data, size_t size,
        if (size == 0)
                return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
-       if (be) {
-               conv = iconv_open("UTF-8", "UTF-16BE");
-       } else {
-               conv = iconv_open("UTF-8", "UTF-16LE");
-       }
+       conv = iconv_open("UTF-8", "UTF-16BE");
        if (conv == (iconv_t) - 1)
                return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
@@ -734,7 +712,7 @@ int _gnutls_ucs2_to_utf8(const void *data, size_t size,
 
 /* Can convert only english (ASCII) */
 int _gnutls_ucs2_to_utf8(const void *data, size_t size,
-                        gnutls_datum_t * output, unsigned be)
+                        gnutls_datum_t * output)
 {
        unsigned int i, j;
        char *dst;
@@ -750,10 +728,7 @@ int _gnutls_ucs2_to_utf8(const void *data, size_t size,
        for (i = j = 0; i < size; i += 2, j++) {
                if (src[i] != 0 || !c_isascii(src[i + 1]))
                        return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
-               if (be)
-                       dst[j] = src[i + 1];
-               else
-                       dst[j] = src[i];
+               dst[j] = src[i + 1];
        }
 
        output->data = (void *) dst;