summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-07-25 15:47:19 +0200
committerGitLab <gitlab@gitlab.com>2016-07-26 16:26:14 +0000
commit38b4dd48760be6a13ea059a54a43a826cfe46cfc (patch)
treeb4bbf3ed19eefae2231fc91afb88571c98ef08bb
parentef861381871a77719aac292d7ac3ee6a961b53cc (diff)
downloadgnutls-38b4dd48760be6a13ea059a54a43a826cfe46cfc.tar.gz
split system.c to various files under system/
-rw-r--r--lib/Makefile.am6
-rw-r--r--lib/system.c725
-rw-r--r--lib/system/certs.c313
-rw-r--r--lib/system/iconv.c212
-rw-r--r--lib/system/inet_ntop.c (renamed from lib/inet_ntop.c)0
-rw-r--r--lib/system/sockets.c188
-rw-r--r--lib/system/threads.c168
-rw-r--r--lib/system/vasprintf.c (renamed from lib/vasprintf.c)0
8 files changed, 890 insertions, 722 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 6eaf9b86e2..94a4d3c92d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -71,8 +71,10 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c \
priority.c hash_int.c cipher_int.c session.c db.c x509_b64.c \
extensions.c auth.c sslv2_compat.c datum.c session_pack.c mpi.c \
pk.c cert.c global.c constate.c anon_cred.c pkix_asn1_tab.c gnutls_asn1_tab.c \
- mem.c fingerprint.c vasprintf.c vasprintf.h tls-sig.c ecc.c alert.c privkey_raw.c \
- system.c system/fastopen.c inet_ntop.c str.c state.c x509.c file.c supplemental.c \
+ mem.c fingerprint.c tls-sig.c ecc.c alert.c privkey_raw.c \
+ system/certs.c system/threads.c system/fastopen.c system/sockets.c \
+ system/inet_ntop.c system/iconv.c system/vasprintf.c vasprintf.h system.c \
+ str.c state.c x509.c file.c supplemental.c \
random.c crypto-api.c privkey.c pcert.c pubkey.c locks.c dtls.c \
system_override.c crypto-backend.c verify-tofu.c pin.c tpm.c fips.c \
safe-memfuncs.c inet_pton.c atfork.c atfork.h randomart.c \
diff --git a/lib/system.c b/lib/system.c
index d1e1171da6..5ddd355904 100644
--- a/lib/system.c
+++ b/lib/system.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2010-2015 Free Software Foundation, Inc.
+ * Copyright (C) 2010-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2015-2016 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -30,306 +31,21 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <c-ctype.h>
+#include <time.h>
#ifdef _WIN32
# 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
- hCertStore,
- PCCRL_CONTEXT
- pPrevCrlContext);
-static CertEnumCRLsInStoreFunc pCertEnumCRLsInStore;
-static HMODULE Crypt32_dll;
-# else
-# define pCertEnumCRLsInStore CertEnumCRLsInStore
-# endif
-
-#else /* !_WIN32 */
-
-# include <poll.h>
-
-# ifdef HAVE_PTHREAD_LOCKS
-# include <pthread.h>
-# endif
-
-# if defined(HAVE_GETPWUID_R)
-# include <pwd.h>
-# endif
#endif
-/* System specific function wrappers.
+/* System specific function wrappers for certificate stores.
*/
-
-#ifdef _WIN32
-/* Do not use the gnulib functions for sending and receiving data.
- * Using them makes gnutls only working with gnulib applications.
- */
-#undef send
-#undef recv
-#undef select
-
-int system_errno(gnutls_transport_ptr p)
-{
- int tmperr = WSAGetLastError();
- int ret = 0;
- switch (tmperr) {
- case WSAEWOULDBLOCK:
- ret = EAGAIN;
- break;
- case NO_ERROR:
- ret = 0;
- break;
- case WSAEINTR:
- ret = EINTR;
- break;
- case WSAEMSGSIZE:
- ret = EMSGSIZE;
- break;
- default:
- ret = EIO;
- break;
- }
- WSASetLastError(tmperr);
-
- return ret;
-}
-
-ssize_t
-system_write(gnutls_transport_ptr ptr, const void *data, size_t data_size)
-{
- return send(GNUTLS_POINTER_TO_INT(ptr), data, data_size, 0);
-}
-#else /* POSIX */
-int system_errno(gnutls_transport_ptr_t ptr)
-{
-#if defined(_AIX) || defined(AIX)
- if (errno == 0)
- errno = EAGAIN;
-#endif
-
- return errno;
-}
-
-static ssize_t
-_system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
- int iovec_cnt, int flags)
-{
- 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, flags);
-}
-
-#ifdef MSG_NOSIGNAL
-ssize_t
-system_writev_nosignal(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
- int iovec_cnt)
-{
- return _system_writev(ptr, iovec, iovec_cnt, MSG_NOSIGNAL);
-}
-
-#endif
-
-ssize_t
-system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
- int iovec_cnt)
-{
- return _system_writev(ptr, iovec, iovec_cnt, 0);
-}
-
-#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.
- *
- * 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 ret;
- int fd = GNUTLS_POINTER_TO_INT(ptr);
-#ifndef _WIN32
- int timeo;
- struct pollfd pfd;
-
- pfd.fd = fd;
- pfd.events = POLLIN;
- pfd.revents = 0;
-
- if (ms == GNUTLS_INDEFINITE_TIMEOUT)
- timeo = -1;
- else
- timeo = ms;
- do {
- ret = poll(&pfd, 1, timeo);
- } while(ret == -1 && errno == EINTR);
-#else
- fd_set rfds;
- struct timeval _tv, *tv = NULL;
-
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
-
- if (ms != GNUTLS_INDEFINITE_TIMEOUT) {
- _tv.tv_sec = ms/1000;
- _tv.tv_usec = (ms % 1000) * 1000;
- tv = &_tv;
- }
-
- ret = select(fd + 1, &rfds, NULL, NULL, tv);
-#endif
- if (ret <= 0)
- return ret;
-
- return ret;
-}
-
-/* Thread stuff */
-
-#ifdef HAVE_WIN32_LOCKS
-static int gnutls_system_mutex_init(void **priv)
-{
- CRITICAL_SECTION *lock = malloc(sizeof(CRITICAL_SECTION));
-
- if (lock == NULL)
- return GNUTLS_E_MEMORY_ERROR;
-
- InitializeCriticalSection(lock);
-
- *priv = lock;
-
- return 0;
-}
-
-static int gnutls_system_mutex_deinit(void **priv)
-{
- DeleteCriticalSection((CRITICAL_SECTION *) * priv);
- free(*priv);
-
- return 0;
-}
-
-static int gnutls_system_mutex_lock(void **priv)
-{
- EnterCriticalSection((CRITICAL_SECTION *) * priv);
- return 0;
-}
-
-static int gnutls_system_mutex_unlock(void **priv)
-{
- LeaveCriticalSection((CRITICAL_SECTION *) * priv);
- return 0;
-}
-
-#endif /* WIN32_LOCKS */
-
-#ifdef HAVE_PTHREAD_LOCKS
-
-static int gnutls_system_mutex_init(void **priv)
-{
- pthread_mutex_t *lock = malloc(sizeof(pthread_mutex_t));
- int ret;
-
- if (lock == NULL)
- return GNUTLS_E_MEMORY_ERROR;
-
- ret = pthread_mutex_init(lock, NULL);
- if (ret) {
- free(lock);
- gnutls_assert();
- return GNUTLS_E_LOCKING_ERROR;
- }
-
- *priv = lock;
-
- return 0;
-}
-
-static int gnutls_system_mutex_deinit(void **priv)
-{
- pthread_mutex_destroy((pthread_mutex_t *) * priv);
- free(*priv);
- return 0;
-}
-
-static int gnutls_system_mutex_lock(void **priv)
-{
- if (pthread_mutex_lock((pthread_mutex_t *) * priv)) {
- gnutls_assert();
- return GNUTLS_E_LOCKING_ERROR;
- }
-
- return 0;
-}
-
-static int gnutls_system_mutex_unlock(void **priv)
-{
- if (pthread_mutex_unlock((pthread_mutex_t *) * priv)) {
- gnutls_assert();
- return GNUTLS_E_LOCKING_ERROR;
- }
-
- return 0;
-}
-
-#endif /* PTHREAD_LOCKS */
-
-#ifdef HAVE_NO_LOCKS
-
-static int gnutls_system_mutex_init(void **priv)
-{
- return 0;
-}
-
-static int gnutls_system_mutex_deinit(void **priv)
-{
- return 0;
-}
-
-static int gnutls_system_mutex_lock(void **priv)
-{
- return 0;
-}
-
-static int gnutls_system_mutex_unlock(void **priv)
-{
- return 0;
-}
-
-#endif /* NO_LOCKS */
-
gnutls_time_func gnutls_time;
-mutex_init_func gnutls_mutex_init = gnutls_system_mutex_init;
-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)
{
#ifdef _WIN32
#if defined(__MINGW32__) && !defined(__MINGW64__) && __MINGW32_MAJOR_VERSION <= 3 && __MINGW32_MINOR_VERSION <= 20
+ /* used in system/certs.c */
HMODULE crypto;
crypto = LoadLibraryA("Crypt32.dll");
@@ -362,434 +78,3 @@ void gnutls_system_global_deinit(void)
}
-#define CONFIG_PATH ".gnutls"
-
-/* Returns a path to store user-specific configuration
- * data.
- */
-int _gnutls_find_config_path(char *path, size_t max_size)
-{
- const char *home_dir = secure_getenv("HOME");
-
- if (home_dir != NULL && home_dir[0] != 0) {
- snprintf(path, max_size, "%s/" CONFIG_PATH, home_dir);
- return 0;
- }
-
-#ifdef _WIN32
- if (home_dir == NULL || home_dir[0] == '\0') {
- const char *home_drive = getenv("HOMEDRIVE");
- 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);
- } else {
- path[0] = 0;
- }
- }
-#elif defined(HAVE_GETPWUID_R)
- if (home_dir == NULL || home_dir[0] == '\0') {
- struct passwd *pwd;
- struct passwd _pwd;
- int ret;
- char tmp[512];
-
- ret = getpwuid_r(getuid(), &_pwd, tmp, sizeof(tmp), &pwd);
- if (ret == 0 && pwd != NULL) {
- snprintf(path, max_size, "%s/" CONFIG_PATH, pwd->pw_dir);
- } else {
- path[0] = 0;
- }
- }
-#else
- if (home_dir == NULL || home_dir[0] == '\0') {
- path[0] = 0;
- }
-#endif
-
- return 0;
-}
-
-#if defined(DEFAULT_TRUST_STORE_FILE) || (defined(DEFAULT_TRUST_STORE_PKCS11) && defined(ENABLE_PKCS11))
-static
-int
-add_system_trust(gnutls_x509_trust_list_t list,
- unsigned int tl_flags, unsigned int tl_vflags)
-{
- int ret, r = 0;
- const char *crl_file =
-#ifdef DEFAULT_CRL_FILE
- DEFAULT_CRL_FILE;
-#else
- NULL;
-#endif
-
-#if defined(ENABLE_PKCS11) && defined(DEFAULT_TRUST_STORE_PKCS11)
- ret =
- gnutls_x509_trust_list_add_trust_file(list,
- DEFAULT_TRUST_STORE_PKCS11,
- crl_file,
- GNUTLS_X509_FMT_DER,
- tl_flags, tl_vflags);
- if (ret > 0)
- r += ret;
-#endif
-
-#ifdef DEFAULT_TRUST_STORE_FILE
- ret =
- gnutls_x509_trust_list_add_trust_file(list,
- DEFAULT_TRUST_STORE_FILE,
- crl_file,
- GNUTLS_X509_FMT_PEM,
- tl_flags, tl_vflags);
- if (ret > 0)
- r += ret;
-#endif
-
-#ifdef DEFAULT_BLACKLIST_FILE
- ret = gnutls_x509_trust_list_remove_trust_file(list, DEFAULT_BLACKLIST_FILE, GNUTLS_X509_FMT_PEM);
- if (ret < 0) {
- _gnutls_debug_log("Could not load blacklist file '%s'\n", DEFAULT_BLACKLIST_FILE);
- }
-#endif
-
- return r;
-}
-#elif defined(_WIN32)
-static
-int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags,
- unsigned int tl_vflags)
-{
- unsigned int i;
- int r = 0;
-
- for (i = 0; i < 2; i++) {
- HCERTSTORE store;
- const CERT_CONTEXT *cert;
- const CRL_CONTEXT *crl;
- gnutls_datum_t data;
-
- if (i == 0)
- store = CertOpenSystemStore(0, "ROOT");
- else
- store = CertOpenSystemStore(0, "CA");
-
- if (store == NULL)
- return GNUTLS_E_FILE_ERROR;
-
- cert = CertEnumCertificatesInStore(store, NULL);
- crl = pCertEnumCRLsInStore(store, NULL);
-
- while (cert != NULL) {
- if (cert->dwCertEncodingType == X509_ASN_ENCODING) {
- data.data = cert->pbCertEncoded;
- data.size = cert->cbCertEncoded;
- if (gnutls_x509_trust_list_add_trust_mem
- (list, &data, NULL,
- GNUTLS_X509_FMT_DER, tl_flags,
- tl_vflags) > 0)
- r++;
- }
- cert = CertEnumCertificatesInStore(store, cert);
- }
-
- while (crl != NULL) {
- if (crl->dwCertEncodingType == X509_ASN_ENCODING) {
- data.data = crl->pbCrlEncoded;
- data.size = crl->cbCrlEncoded;
- gnutls_x509_trust_list_add_trust_mem(list,
- NULL,
- &data,
- GNUTLS_X509_FMT_DER,
- tl_flags,
- tl_vflags);
- }
- crl = pCertEnumCRLsInStore(store, crl);
- }
- CertCloseStore(store, 0);
- }
-
-#ifdef DEFAULT_BLACKLIST_FILE
- ret = gnutls_x509_trust_list_remove_trust_file(list, DEFAULT_BLACKLIST_FILE, GNUTLS_X509_FMT_PEM);
- if (ret < 0) {
- _gnutls_debug_log("Could not load blacklist file '%s'\n", DEFAULT_BLACKLIST_FILE);
- }
-#endif
-
- return r;
-}
-#elif defined(ANDROID) || defined(__ANDROID__) || defined(DEFAULT_TRUST_STORE_DIR)
-
-# include <dirent.h>
-# include <unistd.h>
-
-# if defined(ANDROID) || defined(__ANDROID__)
-# define DEFAULT_TRUST_STORE_DIR "/system/etc/security/cacerts/"
-
-static int load_revoked_certs(gnutls_x509_trust_list_t list, unsigned type)
-{
- DIR *dirp;
- struct dirent *d;
- int ret;
- int r = 0;
- char path[GNUTLS_PATH_MAX];
-
- dirp = opendir("/data/misc/keychain/cacerts-removed/");
- if (dirp != NULL) {
- do {
- d = readdir(dirp);
- if (d != NULL && d->d_type == DT_REG) {
- snprintf(path, sizeof(path),
- "/data/misc/keychain/cacerts-removed/%s",
- d->d_name);
-
- ret =
- gnutls_x509_trust_list_remove_trust_file
- (list, path, type);
- if (ret >= 0)
- r += ret;
- }
- }
- while (d != NULL);
- closedir(dirp);
- }
-
- return r;
-}
-# endif
-
-
-/* This works on android 4.x
- */
-static
-int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags,
- unsigned int tl_vflags)
-{
- int r = 0, ret;
-
- ret = gnutls_x509_trust_list_add_trust_dir(list, DEFAULT_TRUST_STORE_DIR,
- NULL, GNUTLS_X509_FMT_PEM, tl_flags, tl_vflags);
- if (ret >= 0)
- r += ret;
-
-# if defined(ANDROID) || defined(__ANDROID__)
- ret = load_revoked_certs(list, GNUTLS_X509_FMT_DER);
- if (ret >= 0)
- r -= ret;
-
- ret = gnutls_x509_trust_list_add_trust_dir(list, "/data/misc/keychain/cacerts-added/",
- NULL, GNUTLS_X509_FMT_DER, tl_flags, tl_vflags);
- if (ret >= 0)
- r += ret;
-# endif
-
- return r;
-}
-#else
-
-#define add_system_trust(x,y,z) GNUTLS_E_UNIMPLEMENTED_FEATURE
-
-#endif
-
-/**
- * gnutls_x509_trust_list_add_system_trust:
- * @list: The structure of the list
- * @tl_flags: GNUTLS_TL_*
- * @tl_vflags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL
- *
- * This function adds the system's default trusted certificate
- * authorities to the trusted list. Note that on unsupported systems
- * this function returns %GNUTLS_E_UNIMPLEMENTED_FEATURE.
- *
- * This function implies the flag %GNUTLS_TL_NO_DUPLICATES.
- *
- * Returns: The number of added elements or a negative error code on error.
- *
- * Since: 3.1
- **/
-int
-gnutls_x509_trust_list_add_system_trust(gnutls_x509_trust_list_t list,
- unsigned int tl_flags,
- unsigned int tl_vflags)
-{
- return add_system_trust(list, tl_flags|GNUTLS_TL_NO_DUPLICATES, tl_vflags);
-}
-
-#if defined(_WIN32)
-#include <winnls.h>
-
-int _gnutls_ucs2_to_utf8(const void *data, size_t size,
- gnutls_datum_t * output, unsigned be)
-{
- int ret;
- unsigned i;
- int len = 0, src_len;
- char *dst = NULL;
- char *src = NULL;
- static unsigned flags = 0;
- static int checked = 0;
-
- if (checked == 0) {
- /* Not all windows versions support MB_ERR_INVALID_CHARS */
- ret =
- WideCharToMultiByte(CP_UTF8, MB_ERR_INVALID_CHARS,
- L"hello", -1, NULL, 0, NULL, NULL);
- if (ret > 0)
- flags = MB_ERR_INVALID_CHARS;
- checked = 1;
- }
-
- if (((uint8_t *) data)[size] == 0 && ((uint8_t *) data)[size+1] == 0) {
- 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);
- }
- src[size] = 0;
- src[size+1] = 0;
-
- ret =
- WideCharToMultiByte(CP_UTF8, flags,
- (void *) src, src_len, NULL, 0,
- NULL, NULL);
- if (ret == 0) {
- _gnutls_debug_log("WideCharToMultiByte: %d\n", (int)GetLastError());
- ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- goto fail;
- }
-
- len = ret + 1;
- dst = gnutls_malloc(len);
- if (dst == NULL) {
- ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- goto fail;
- }
- dst[0] = 0;
-
- ret =
- WideCharToMultiByte(CP_UTF8, flags,
- (void *) src, src_len, dst, len-1, NULL,
- NULL);
- if (ret == 0) {
- ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- goto fail;
- }
- dst[len - 1] = 0;
-
- output->data = dst;
- output->size = ret;
-
- ret = 0;
- goto cleanup;
-
- fail:
- gnutls_free(dst);
-
- cleanup:
- gnutls_free(src);
- return ret;
-}
-
-#elif defined(HAVE_ICONV) || defined(HAVE_LIBICONV)
-
-#include <iconv.h>
-
-int _gnutls_ucs2_to_utf8(const void *data, size_t size,
- gnutls_datum_t * output, unsigned be)
-{
- iconv_t conv;
- int ret;
- size_t orig, dstlen = size * 2;
- char *src = (void *) data;
- char *dst = NULL, *pdst;
-
- 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");
- }
- if (conv == (iconv_t) - 1)
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-
- /* Note that dstlen has enough size for every possible input characters.
- * (remember the in UTF-16 the characters in data are at most size/2,
- * and we allocate 4 bytes per character).
- */
- pdst = dst = gnutls_malloc(dstlen + 1);
- if (dst == NULL) {
- ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- goto fail;
- }
-
- orig = dstlen;
- ret = iconv(conv, &src, &size, &pdst, &dstlen);
- if (ret == -1) {
- ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- goto fail;
- }
-
- output->data = (void *) dst;
- output->size = orig - dstlen;
- output->data[output->size] = 0;
-
- ret = 0;
- goto cleanup;
-
- fail:
- gnutls_free(dst);
-
- cleanup:
- iconv_close(conv);
-
- return ret;
-}
-
-#else
-
-/* Can convert only english (ASCII) */
-int _gnutls_ucs2_to_utf8(const void *data, size_t size,
- gnutls_datum_t * output, unsigned be)
-{
- unsigned int i, j;
- char *dst;
- const char *src = data;
-
- if (size == 0 || size % 2 != 0)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-
- dst = gnutls_malloc(size + 1);
- if (dst == NULL)
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-
- 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];
- }
-
- output->data = (void *) dst;
- output->size = j;
- output->data[output->size] = 0;
-
- return 0;
-}
-#endif
diff --git a/lib/system/certs.c b/lib/system/certs.c
new file mode 100644
index 0000000000..c7ca3547ea
--- /dev/null
+++ b/lib/system/certs.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2010-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+#include <system.h>
+#include "gnutls_int.h"
+#include "errors.h"
+
+#include <sys/socket.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <c-ctype.h>
+
+#ifdef _WIN32
+# 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
+ hCertStore,
+ PCCRL_CONTEXT
+ pPrevCrlContext);
+static CertEnumCRLsInStoreFunc pCertEnumCRLsInStore;
+static HMODULE Crypt32_dll;
+# else
+# define pCertEnumCRLsInStore CertEnumCRLsInStore
+# endif
+
+#else /* !_WIN32 */
+
+# include <poll.h>
+
+# if defined(HAVE_GETPWUID_R)
+# include <pwd.h>
+# endif
+#endif
+
+/* System specific function wrappers for certificate stores.
+ */
+
+#define CONFIG_PATH ".gnutls"
+
+/* Returns a path to store user-specific configuration
+ * data.
+ */
+int _gnutls_find_config_path(char *path, size_t max_size)
+{
+ const char *home_dir = secure_getenv("HOME");
+
+ if (home_dir != NULL && home_dir[0] != 0) {
+ snprintf(path, max_size, "%s/" CONFIG_PATH, home_dir);
+ return 0;
+ }
+
+#ifdef _WIN32
+ if (home_dir == NULL || home_dir[0] == '\0') {
+ const char *home_drive = getenv("HOMEDRIVE");
+ 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);
+ } else {
+ path[0] = 0;
+ }
+ }
+#elif defined(HAVE_GETPWUID_R)
+ if (home_dir == NULL || home_dir[0] == '\0') {
+ struct passwd *pwd;
+ struct passwd _pwd;
+ int ret;
+ char tmp[512];
+
+ ret = getpwuid_r(getuid(), &_pwd, tmp, sizeof(tmp), &pwd);
+ if (ret == 0 && pwd != NULL) {
+ snprintf(path, max_size, "%s/" CONFIG_PATH, pwd->pw_dir);
+ } else {
+ path[0] = 0;
+ }
+ }
+#else
+ if (home_dir == NULL || home_dir[0] == '\0') {
+ path[0] = 0;
+ }
+#endif
+
+ return 0;
+}
+
+#if defined(DEFAULT_TRUST_STORE_FILE) || (defined(DEFAULT_TRUST_STORE_PKCS11) && defined(ENABLE_PKCS11))
+static
+int
+add_system_trust(gnutls_x509_trust_list_t list,
+ unsigned int tl_flags, unsigned int tl_vflags)
+{
+ int ret, r = 0;
+ const char *crl_file =
+#ifdef DEFAULT_CRL_FILE
+ DEFAULT_CRL_FILE;
+#else
+ NULL;
+#endif
+
+#if defined(ENABLE_PKCS11) && defined(DEFAULT_TRUST_STORE_PKCS11)
+ ret =
+ gnutls_x509_trust_list_add_trust_file(list,
+ DEFAULT_TRUST_STORE_PKCS11,
+ crl_file,
+ GNUTLS_X509_FMT_DER,
+ tl_flags, tl_vflags);
+ if (ret > 0)
+ r += ret;
+#endif
+
+#ifdef DEFAULT_TRUST_STORE_FILE
+ ret =
+ gnutls_x509_trust_list_add_trust_file(list,
+ DEFAULT_TRUST_STORE_FILE,
+ crl_file,
+ GNUTLS_X509_FMT_PEM,
+ tl_flags, tl_vflags);
+ if (ret > 0)
+ r += ret;
+#endif
+
+#ifdef DEFAULT_BLACKLIST_FILE
+ ret = gnutls_x509_trust_list_remove_trust_file(list, DEFAULT_BLACKLIST_FILE, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ _gnutls_debug_log("Could not load blacklist file '%s'\n", DEFAULT_BLACKLIST_FILE);
+ }
+#endif
+
+ return r;
+}
+#elif defined(_WIN32)
+static
+int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags,
+ unsigned int tl_vflags)
+{
+ unsigned int i;
+ int r = 0;
+
+ for (i = 0; i < 2; i++) {
+ HCERTSTORE store;
+ const CERT_CONTEXT *cert;
+ const CRL_CONTEXT *crl;
+ gnutls_datum_t data;
+
+ if (i == 0)
+ store = CertOpenSystemStore(0, "ROOT");
+ else
+ store = CertOpenSystemStore(0, "CA");
+
+ if (store == NULL)
+ return GNUTLS_E_FILE_ERROR;
+
+ cert = CertEnumCertificatesInStore(store, NULL);
+ crl = pCertEnumCRLsInStore(store, NULL);
+
+ while (cert != NULL) {
+ if (cert->dwCertEncodingType == X509_ASN_ENCODING) {
+ data.data = cert->pbCertEncoded;
+ data.size = cert->cbCertEncoded;
+ if (gnutls_x509_trust_list_add_trust_mem
+ (list, &data, NULL,
+ GNUTLS_X509_FMT_DER, tl_flags,
+ tl_vflags) > 0)
+ r++;
+ }
+ cert = CertEnumCertificatesInStore(store, cert);
+ }
+
+ while (crl != NULL) {
+ if (crl->dwCertEncodingType == X509_ASN_ENCODING) {
+ data.data = crl->pbCrlEncoded;
+ data.size = crl->cbCrlEncoded;
+ gnutls_x509_trust_list_add_trust_mem(list,
+ NULL,
+ &data,
+ GNUTLS_X509_FMT_DER,
+ tl_flags,
+ tl_vflags);
+ }
+ crl = pCertEnumCRLsInStore(store, crl);
+ }
+ CertCloseStore(store, 0);
+ }
+
+#ifdef DEFAULT_BLACKLIST_FILE
+ ret = gnutls_x509_trust_list_remove_trust_file(list, DEFAULT_BLACKLIST_FILE, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ _gnutls_debug_log("Could not load blacklist file '%s'\n", DEFAULT_BLACKLIST_FILE);
+ }
+#endif
+
+ return r;
+}
+#elif defined(ANDROID) || defined(__ANDROID__) || defined(DEFAULT_TRUST_STORE_DIR)
+
+# include <dirent.h>
+# include <unistd.h>
+
+# if defined(ANDROID) || defined(__ANDROID__)
+# define DEFAULT_TRUST_STORE_DIR "/system/etc/security/cacerts/"
+
+static int load_revoked_certs(gnutls_x509_trust_list_t list, unsigned type)
+{
+ DIR *dirp;
+ struct dirent *d;
+ int ret;
+ int r = 0;
+ char path[GNUTLS_PATH_MAX];
+
+ dirp = opendir("/data/misc/keychain/cacerts-removed/");
+ if (dirp != NULL) {
+ do {
+ d = readdir(dirp);
+ if (d != NULL && d->d_type == DT_REG) {
+ snprintf(path, sizeof(path),
+ "/data/misc/keychain/cacerts-removed/%s",
+ d->d_name);
+
+ ret =
+ gnutls_x509_trust_list_remove_trust_file
+ (list, path, type);
+ if (ret >= 0)
+ r += ret;
+ }
+ }
+ while (d != NULL);
+ closedir(dirp);
+ }
+
+ return r;
+}
+# endif
+
+
+/* This works on android 4.x
+ */
+static
+int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags,
+ unsigned int tl_vflags)
+{
+ int r = 0, ret;
+
+ ret = gnutls_x509_trust_list_add_trust_dir(list, DEFAULT_TRUST_STORE_DIR,
+ NULL, GNUTLS_X509_FMT_PEM, tl_flags, tl_vflags);
+ if (ret >= 0)
+ r += ret;
+
+# if defined(ANDROID) || defined(__ANDROID__)
+ ret = load_revoked_certs(list, GNUTLS_X509_FMT_DER);
+ if (ret >= 0)
+ r -= ret;
+
+ ret = gnutls_x509_trust_list_add_trust_dir(list, "/data/misc/keychain/cacerts-added/",
+ NULL, GNUTLS_X509_FMT_DER, tl_flags, tl_vflags);
+ if (ret >= 0)
+ r += ret;
+# endif
+
+ return r;
+}
+#else
+
+#define add_system_trust(x,y,z) GNUTLS_E_UNIMPLEMENTED_FEATURE
+
+#endif
+
+/**
+ * gnutls_x509_trust_list_add_system_trust:
+ * @list: The structure of the list
+ * @tl_flags: GNUTLS_TL_*
+ * @tl_vflags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL
+ *
+ * This function adds the system's default trusted certificate
+ * authorities to the trusted list. Note that on unsupported systems
+ * this function returns %GNUTLS_E_UNIMPLEMENTED_FEATURE.
+ *
+ * This function implies the flag %GNUTLS_TL_NO_DUPLICATES.
+ *
+ * Returns: The number of added elements or a negative error code on error.
+ *
+ * Since: 3.1
+ **/
+int
+gnutls_x509_trust_list_add_system_trust(gnutls_x509_trust_list_t list,
+ unsigned int tl_flags,
+ unsigned int tl_vflags)
+{
+ return add_system_trust(list, tl_flags|GNUTLS_TL_NO_DUPLICATES, tl_vflags);
+}
+
diff --git a/lib/system/iconv.c b/lib/system/iconv.c
new file mode 100644
index 0000000000..c0e4480d1f
--- /dev/null
+++ b/lib/system/iconv.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2010-2016 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+#include <system.h>
+#include "gnutls_int.h"
+#include "errors.h"
+
+#include <sys/socket.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <c-ctype.h>
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <winnls.h>
+
+int _gnutls_ucs2_to_utf8(const void *data, size_t size,
+ gnutls_datum_t * output, unsigned be)
+{
+ int ret;
+ unsigned i;
+ int len = 0, src_len;
+ char *dst = NULL;
+ char *src = NULL;
+ static unsigned flags = 0;
+ static int checked = 0;
+
+ if (checked == 0) {
+ /* Not all windows versions support MB_ERR_INVALID_CHARS */
+ ret =
+ WideCharToMultiByte(CP_UTF8, MB_ERR_INVALID_CHARS,
+ L"hello", -1, NULL, 0, NULL, NULL);
+ if (ret > 0)
+ flags = MB_ERR_INVALID_CHARS;
+ checked = 1;
+ }
+
+ if (((uint8_t *) data)[size] == 0 && ((uint8_t *) data)[size+1] == 0) {
+ 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);
+ }
+ src[size] = 0;
+ src[size+1] = 0;
+
+ ret =
+ WideCharToMultiByte(CP_UTF8, flags,
+ (void *) src, src_len, NULL, 0,
+ NULL, NULL);
+ if (ret == 0) {
+ _gnutls_debug_log("WideCharToMultiByte: %d\n", (int)GetLastError());
+ ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+ goto fail;
+ }
+
+ len = ret + 1;
+ dst = gnutls_malloc(len);
+ if (dst == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ goto fail;
+ }
+ dst[0] = 0;
+
+ ret =
+ WideCharToMultiByte(CP_UTF8, flags,
+ (void *) src, src_len, dst, len-1, NULL,
+ NULL);
+ if (ret == 0) {
+ ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+ goto fail;
+ }
+ dst[len - 1] = 0;
+
+ output->data = dst;
+ output->size = ret;
+
+ ret = 0;
+ goto cleanup;
+
+ fail:
+ gnutls_free(dst);
+
+ cleanup:
+ gnutls_free(src);
+ return ret;
+}
+
+#elif defined(HAVE_ICONV) || defined(HAVE_LIBICONV)
+
+#include <iconv.h>
+
+int _gnutls_ucs2_to_utf8(const void *data, size_t size,
+ gnutls_datum_t * output, unsigned be)
+{
+ iconv_t conv;
+ int ret;
+ size_t orig, dstlen = size * 2;
+ char *src = (void *) data;
+ char *dst = NULL, *pdst;
+
+ 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");
+ }
+ if (conv == (iconv_t) - 1)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ /* Note that dstlen has enough size for every possible input characters.
+ * (remember the in UTF-16 the characters in data are at most size/2,
+ * and we allocate 4 bytes per character).
+ */
+ pdst = dst = gnutls_malloc(dstlen + 1);
+ if (dst == NULL) {
+ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ goto fail;
+ }
+
+ orig = dstlen;
+ ret = iconv(conv, &src, &size, &pdst, &dstlen);
+ if (ret == -1) {
+ ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+ goto fail;
+ }
+
+ output->data = (void *) dst;
+ output->size = orig - dstlen;
+ output->data[output->size] = 0;
+
+ ret = 0;
+ goto cleanup;
+
+ fail:
+ gnutls_free(dst);
+
+ cleanup:
+ iconv_close(conv);
+
+ return ret;
+}
+
+#else
+
+/* Can convert only english (ASCII) */
+int _gnutls_ucs2_to_utf8(const void *data, size_t size,
+ gnutls_datum_t * output, unsigned be)
+{
+ unsigned int i, j;
+ char *dst;
+ const char *src = data;
+
+ if (size == 0 || size % 2 != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ dst = gnutls_malloc(size + 1);
+ if (dst == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ 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];
+ }
+
+ output->data = (void *) dst;
+ output->size = j;
+ output->data[output->size] = 0;
+
+ return 0;
+}
+#endif
diff --git a/lib/inet_ntop.c b/lib/system/inet_ntop.c
index 2ed11ba308..2ed11ba308 100644
--- a/lib/inet_ntop.c
+++ b/lib/system/inet_ntop.c
diff --git a/lib/system/sockets.c b/lib/system/sockets.c
new file mode 100644
index 0000000000..f399fc93a9
--- /dev/null
+++ b/lib/system/sockets.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2010-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+#include <system.h>
+#include "gnutls_int.h"
+#include "errors.h"
+
+#include <sys/socket.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <c-ctype.h>
+
+#ifdef _WIN32
+# include <windows.h>
+#else /* !_WIN32 */
+# include <poll.h>
+#endif
+
+/* System specific socket function wrappers.
+ */
+
+#ifdef _WIN32
+/* Do not use the gnulib functions for sending and receiving data.
+ * Using them makes gnutls only working with gnulib applications.
+ */
+#undef send
+#undef recv
+#undef select
+
+int system_errno(gnutls_transport_ptr p)
+{
+ int tmperr = WSAGetLastError();
+ int ret = 0;
+ switch (tmperr) {
+ case WSAEWOULDBLOCK:
+ ret = EAGAIN;
+ break;
+ case NO_ERROR:
+ ret = 0;
+ break;
+ case WSAEINTR:
+ ret = EINTR;
+ break;
+ case WSAEMSGSIZE:
+ ret = EMSGSIZE;
+ break;
+ default:
+ ret = EIO;
+ break;
+ }
+ WSASetLastError(tmperr);
+
+ return ret;
+}
+
+ssize_t
+system_write(gnutls_transport_ptr ptr, const void *data, size_t data_size)
+{
+ return send(GNUTLS_POINTER_TO_INT(ptr), data, data_size, 0);
+}
+#else /* POSIX */
+int system_errno(gnutls_transport_ptr_t ptr)
+{
+#if defined(_AIX) || defined(AIX)
+ if (errno == 0)
+ errno = EAGAIN;
+#endif
+
+ return errno;
+}
+
+static ssize_t
+_system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
+ int iovec_cnt, int flags)
+{
+ 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, flags);
+}
+
+#ifdef MSG_NOSIGNAL
+ssize_t
+system_writev_nosignal(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
+ int iovec_cnt)
+{
+ return _system_writev(ptr, iovec, iovec_cnt, MSG_NOSIGNAL);
+}
+
+#endif
+
+ssize_t
+system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
+ int iovec_cnt)
+{
+ return _system_writev(ptr, iovec, iovec_cnt, 0);
+}
+
+#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.
+ *
+ * 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 ret;
+ int fd = GNUTLS_POINTER_TO_INT(ptr);
+#ifndef _WIN32
+ int timeo;
+ struct pollfd pfd;
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ if (ms == GNUTLS_INDEFINITE_TIMEOUT)
+ timeo = -1;
+ else
+ timeo = ms;
+ do {
+ ret = poll(&pfd, 1, timeo);
+ } while(ret == -1 && errno == EINTR);
+#else
+ fd_set rfds;
+ struct timeval _tv, *tv = NULL;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ if (ms != GNUTLS_INDEFINITE_TIMEOUT) {
+ _tv.tv_sec = ms/1000;
+ _tv.tv_usec = (ms % 1000) * 1000;
+ tv = &_tv;
+ }
+
+ ret = select(fd + 1, &rfds, NULL, NULL, tv);
+#endif
+ if (ret <= 0)
+ return ret;
+
+ return ret;
+}
+
diff --git a/lib/system/threads.c b/lib/system/threads.c
new file mode 100644
index 0000000000..a9a2fa44a9
--- /dev/null
+++ b/lib/system/threads.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2010-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+#include <system.h>
+#include "gnutls_int.h"
+#include "errors.h"
+
+#include <sys/socket.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <c-ctype.h>
+
+#ifdef _WIN32
+# include <windows.h>
+# include <wincrypt.h>
+
+#else /* !_WIN32 */
+
+# ifdef HAVE_PTHREAD_LOCKS
+# include <pthread.h>
+# endif
+
+#endif
+
+/* System specific lock function wrappers.
+ */
+
+/* Thread stuff */
+
+#ifdef HAVE_WIN32_LOCKS
+static int gnutls_system_mutex_init(void **priv)
+{
+ CRITICAL_SECTION *lock = malloc(sizeof(CRITICAL_SECTION));
+
+ if (lock == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ InitializeCriticalSection(lock);
+
+ *priv = lock;
+
+ return 0;
+}
+
+static int gnutls_system_mutex_deinit(void **priv)
+{
+ DeleteCriticalSection((CRITICAL_SECTION *) * priv);
+ free(*priv);
+
+ return 0;
+}
+
+static int gnutls_system_mutex_lock(void **priv)
+{
+ EnterCriticalSection((CRITICAL_SECTION *) * priv);
+ return 0;
+}
+
+static int gnutls_system_mutex_unlock(void **priv)
+{
+ LeaveCriticalSection((CRITICAL_SECTION *) * priv);
+ return 0;
+}
+
+#endif /* WIN32_LOCKS */
+
+#ifdef HAVE_PTHREAD_LOCKS
+
+static int gnutls_system_mutex_init(void **priv)
+{
+ pthread_mutex_t *lock = malloc(sizeof(pthread_mutex_t));
+ int ret;
+
+ if (lock == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ ret = pthread_mutex_init(lock, NULL);
+ if (ret) {
+ free(lock);
+ gnutls_assert();
+ return GNUTLS_E_LOCKING_ERROR;
+ }
+
+ *priv = lock;
+
+ return 0;
+}
+
+static int gnutls_system_mutex_deinit(void **priv)
+{
+ pthread_mutex_destroy((pthread_mutex_t *) * priv);
+ free(*priv);
+ return 0;
+}
+
+static int gnutls_system_mutex_lock(void **priv)
+{
+ if (pthread_mutex_lock((pthread_mutex_t *) * priv)) {
+ gnutls_assert();
+ return GNUTLS_E_LOCKING_ERROR;
+ }
+
+ return 0;
+}
+
+static int gnutls_system_mutex_unlock(void **priv)
+{
+ if (pthread_mutex_unlock((pthread_mutex_t *) * priv)) {
+ gnutls_assert();
+ return GNUTLS_E_LOCKING_ERROR;
+ }
+
+ return 0;
+}
+
+#endif /* PTHREAD_LOCKS */
+
+#ifdef HAVE_NO_LOCKS
+
+static int gnutls_system_mutex_init(void **priv)
+{
+ return 0;
+}
+
+static int gnutls_system_mutex_deinit(void **priv)
+{
+ return 0;
+}
+
+static int gnutls_system_mutex_lock(void **priv)
+{
+ return 0;
+}
+
+static int gnutls_system_mutex_unlock(void **priv)
+{
+ return 0;
+}
+
+#endif /* NO_LOCKS */
+
+mutex_init_func gnutls_mutex_init = gnutls_system_mutex_init;
+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;
+
diff --git a/lib/vasprintf.c b/lib/system/vasprintf.c
index 8362942a20..8362942a20 100644
--- a/lib/vasprintf.c
+++ b/lib/system/vasprintf.c