2 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
24 #include <gnutls_int.h>
25 #include <gnutls_errors.h>
29 #include <sys/types.h>
34 # include <wincrypt.h>
35 # if defined(__MINGW32__) && !defined(__MINGW64__) && __MINGW32_MAJOR_VERSION <= 3 && __MINGW32_MINOR_VERSION <= 20
36 typedef PCCRL_CONTEXT WINAPI (*Type_CertEnumCRLsInStore) (HCERTSTORE hCertStore, PCCRL_CONTEXT pPrevCrlContext);
37 static Type_CertEnumCRLsInStore Loaded_CertEnumCRLsInStore;
38 static HMODULE Crypt32_dll;
40 # define Loaded_CertEnumCRLsInStore CertEnumCRLsInStore
43 # ifdef HAVE_PTHREAD_LOCKS
47 # if defined(HAVE_GETPWUID_R)
52 /* We need to disable gnulib's replacement wrappers to get native
53 Windows interfaces. */
58 /* System specific function wrappers.
63 system_errno (gnutls_transport_ptr p)
65 int tmperr = WSAGetLastError ();
85 WSASetLastError (tmperr);
91 system_write (gnutls_transport_ptr ptr, const void *data, size_t data_size)
93 return send (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
97 system_errno (gnutls_transport_ptr_t ptr)
99 #if defined(_AIX) || defined(AIX)
100 if (errno == 0) errno = EAGAIN;
107 system_writev (gnutls_transport_ptr_t ptr, const giovec_t * iovec,
110 return writev (GNUTLS_POINTER_TO_INT (ptr), (struct iovec *) iovec,
117 system_read (gnutls_transport_ptr_t ptr, void *data, size_t data_size)
119 return recv (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
122 /* Wait for data to be received within a timeout period in milliseconds.
123 * To catch a termination it will also try to receive 0 bytes from the
124 * socket if select reports to proceed.
126 * Returns -1 on error, 0 on timeout, positive value if data are available for reading.
128 int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
133 int fd = GNUTLS_POINTER_TO_INT(ptr);
139 tv.tv_usec = ms * 1000;
141 while(tv.tv_usec >= 1000000)
143 tv.tv_usec -= 1000000;
147 ret = select(fd+1, &rfds, NULL, NULL, &tv);
156 #ifdef HAVE_WIN32_LOCKS
158 gnutls_system_mutex_init (void **priv)
160 CRITICAL_SECTION *lock = malloc (sizeof (CRITICAL_SECTION));
163 return GNUTLS_E_MEMORY_ERROR;
165 InitializeCriticalSection (lock);
173 gnutls_system_mutex_deinit (void **priv)
175 DeleteCriticalSection ((CRITICAL_SECTION *) * priv);
182 gnutls_system_mutex_lock (void **priv)
184 EnterCriticalSection ((CRITICAL_SECTION *) * priv);
189 gnutls_system_mutex_unlock (void **priv)
191 LeaveCriticalSection ((CRITICAL_SECTION *) * priv);
195 #endif /* WIN32_LOCKS */
197 #ifdef HAVE_PTHREAD_LOCKS
200 gnutls_system_mutex_init (void **priv)
202 pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t));
206 return GNUTLS_E_MEMORY_ERROR;
208 ret = pthread_mutex_init (lock, NULL);
213 return GNUTLS_E_LOCKING_ERROR;
222 gnutls_system_mutex_deinit (void **priv)
224 pthread_mutex_destroy ((pthread_mutex_t *) * priv);
230 gnutls_system_mutex_lock (void **priv)
232 if (pthread_mutex_lock ((pthread_mutex_t *) * priv))
235 return GNUTLS_E_LOCKING_ERROR;
242 gnutls_system_mutex_unlock (void **priv)
244 if (pthread_mutex_unlock ((pthread_mutex_t *) * priv))
247 return GNUTLS_E_LOCKING_ERROR;
253 #endif /* PTHREAD_LOCKS */
258 gnutls_system_mutex_init (void **priv)
264 gnutls_system_mutex_deinit (void **priv)
270 gnutls_system_mutex_lock (void **priv)
276 gnutls_system_mutex_unlock (void **priv)
281 #endif /* NO_LOCKS */
283 gnutls_time_func gnutls_time = time;
284 mutex_init_func gnutls_mutex_init = gnutls_system_mutex_init;
285 mutex_deinit_func gnutls_mutex_deinit = gnutls_system_mutex_deinit;
286 mutex_lock_func gnutls_mutex_lock = gnutls_system_mutex_lock;
287 mutex_unlock_func gnutls_mutex_unlock = gnutls_system_mutex_unlock;
290 gnutls_system_global_init ()
293 # if defined(__MINGW32__) && !defined(__MINGW64__) && __MINGW32_MAJOR_VERSION <= 3 && __MINGW32_MINOR_VERSION <= 20
295 crypto = LoadLibraryA ("Crypt32.dll");
298 return GNUTLS_E_CRYPTO_INIT_FAILED;
300 Loaded_CertEnumCRLsInStore = (Type_CertEnumCRLsInStore) GetProcAddress (crypto, "CertEnumCRLsInStore");
301 if (Loaded_CertEnumCRLsInStore == NULL)
303 FreeLibrary (crypto);
304 return GNUTLS_E_CRYPTO_INIT_FAILED;
307 Crypt32_dll = crypto;
314 gnutls_system_global_deinit ()
317 # if defined(__MINGW32__) && !defined(__MINGW64__) && __MINGW32_MAJOR_VERSION <= 3 && __MINGW32_MINOR_VERSION <= 20
318 FreeLibrary (Crypt32_dll);
324 #define CONFIG_PATH ".gnutls"
326 /* Returns a path to store user-specific configuration
329 int _gnutls_find_config_path(char* path, size_t max_size)
331 char tmp_home_dir[1024];
332 const char *home_dir = getenv ("HOME");
335 if (home_dir == NULL || home_dir[0] == '\0')
337 const char *home_drive = getenv ("HOMEDRIVE");
338 const char *home_path = getenv ("HOMEPATH");
340 if (home_drive != NULL && home_path != NULL)
342 snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s%s", home_drive, home_path);
349 home_dir = tmp_home_dir;
351 #elif defined(HAVE_GETPWUID_R)
352 if (home_dir == NULL || home_dir[0] == '\0')
358 getpwuid_r(getuid(), &_pwd, buf, sizeof(buf), &pwd);
361 snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s", pwd->pw_dir);
368 home_dir = tmp_home_dir;
371 if (home_dir == NULL || home_dir[0] == '\0')
374 home_dir = tmp_home_dir;
378 if (home_dir == NULL || home_dir[0] == 0)
381 snprintf(path, max_size, "%s/"CONFIG_PATH, home_dir);
387 * gnutls_x509_trust_list_add_system_trust:
388 * @list: The structure of the list
389 * @tl_flags: GNUTLS_TL_*
390 * @tl_vflags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL
392 * This function adds the system's default trusted certificate
393 * authorities to the trusted list. Note that on unsupported system
394 * this function returns %GNUTLS_E_UNIMPLEMENTED_FEATURE.
396 * Returns: The number of added elements or a negative error code on error.
401 gnutls_x509_trust_list_add_system_trust(gnutls_x509_trust_list_t list,
402 unsigned int tl_flags, unsigned int tl_vflags)
404 #if !defined(DEFAULT_TRUST_STORE_PKCS11) && !defined(DEFAULT_TRUST_STORE_FILE) && !defined(_WIN32)
405 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
408 const char* crl_file =
409 # ifdef DEFAULT_CRL_FILE
421 const CERT_CONTEXT *cert;
422 const CRL_CONTEXT *crl;
425 if (i==0) store = CertOpenSystemStore(0, "ROOT");
426 else store = CertOpenSystemStore(0, "CA");
428 if (store == NULL) return GNUTLS_E_FILE_ERROR;
430 cert = CertEnumCertificatesInStore(store, NULL);
431 crl = Loaded_CertEnumCRLsInStore(store, NULL);
435 if (cert->dwCertEncodingType == X509_ASN_ENCODING)
437 data.data = cert->pbCertEncoded;
438 data.size = cert->cbCertEncoded;
439 if (gnutls_x509_trust_list_add_trust_mem(list, &data, NULL, GNUTLS_X509_FMT_DER, tl_flags, tl_vflags) > 0)
442 cert = CertEnumCertificatesInStore(store, cert);
447 if (crl->dwCertEncodingType == X509_ASN_ENCODING)
449 data.data = crl->pbCrlEncoded;
450 data.size = crl->cbCrlEncoded;
451 gnutls_x509_trust_list_add_trust_mem(list, NULL, &data, GNUTLS_X509_FMT_DER, tl_flags, tl_vflags);
453 crl = Loaded_CertEnumCRLsInStore(store, crl);
455 CertCloseStore(store, 0);
459 # if defined(ENABLE_PKCS11) && defined(DEFAULT_TRUST_STORE_PKCS11)
460 ret = gnutls_x509_trust_list_add_trust_file(list, DEFAULT_TRUST_STORE_PKCS11, crl_file,
461 GNUTLS_X509_FMT_DER, tl_flags, tl_vflags);
466 # ifdef DEFAULT_TRUST_STORE_FILE
467 ret = gnutls_x509_trust_list_add_trust_file(list, DEFAULT_TRUST_STORE_FILE, crl_file,
468 GNUTLS_X509_FMT_PEM, tl_flags, tl_vflags);
476 #if defined(HAVE_ICONV)
480 int _gnutls_ucs2_to_utf8(const void* data, size_t size, gnutls_datum_t *output)
484 size_t orig, dstlen = size*2;
485 char* src = (void*)data;
489 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
491 conv = iconv_open("UTF-8", "UTF-16BE");
492 if (conv == (iconv_t)-1)
493 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
495 pdst = dst = gnutls_malloc(dstlen+1);
498 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
503 ret = iconv(conv, &src, &size, &pdst, &dstlen);
506 ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
511 output->data = (void*)dst;
512 output->size = orig-dstlen;
513 output->data[output->size] = 0;
522 #elif defined(_WIN32)
525 /* Can convert only english */
526 int _gnutls_ucs2_to_utf8(const void* data, size_t size, gnutls_datum_t *output)
530 int len = 0, src_len;
536 src = gnutls_malloc(size);
538 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
541 for (i=0;i<size;i+=2)
543 src[i] = ((char*)data)[1+i];
544 src[1+i] = ((char*)data)[i];
547 ret = WideCharToMultiByte(CP_UTF8, MB_ERR_INVALID_CHARS, (void*)src, src_len,
548 NULL, 0, NULL, NULL);
551 ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
556 dst = gnutls_malloc(len);
559 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
563 ret = WideCharToMultiByte(CP_UTF8, MB_ERR_INVALID_CHARS, (void*)src, src_len,
564 dst, len, NULL, NULL);
567 ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
586 /* Can convert only english (ASCII) */
587 int _gnutls_ucs2_to_utf8(const void* data, size_t size, gnutls_datum_t *output)
591 const char *src = data;
593 if (size == 0 || size % 2 != 0)
594 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
596 dst = gnutls_malloc(size+1);
598 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
600 for (i=j=0;i<size;i+=2,j++)
602 if (src[i] != 0 || !isascii(src[i+1]))
603 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
607 output->data = (void*)dst;
609 output->data[output->size] = 0;