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
;
486 char* dst
= NULL
, *pdst
;
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 /* Note that dstlen has enough size for every possible input characters.
496 * (remember the in UTF-16 the characters in data are at most size/2,
497 * and we allocate 4 bytes per character).
499 pdst
= dst
= gnutls_malloc(dstlen
+1);
502 ret
= gnutls_assert_val(GNUTLS_E_MEMORY_ERROR
);
507 ret
= iconv(conv
, &src
, &size
, &pdst
, &dstlen
);
510 ret
= gnutls_assert_val(GNUTLS_E_PARSING_ERROR
);
514 output
->data
= (void*)dst
;
515 output
->size
= orig
-dstlen
;
516 output
->data
[output
->size
] = 0;
529 #elif defined(_WIN32)
532 /* Can convert only english */
533 int _gnutls_ucs2_to_utf8(const void* data
, size_t size
, gnutls_datum_t
*output
)
537 int len
= 0, src_len
;
543 src
= gnutls_malloc(size
);
545 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR
);
548 for (i
=0;i
<size
;i
+=2)
550 src
[i
] = ((char*)data
)[1+i
];
551 src
[1+i
] = ((char*)data
)[i
];
554 ret
= WideCharToMultiByte(CP_UTF8
, MB_ERR_INVALID_CHARS
, (void*)src
, src_len
,
555 NULL
, 0, NULL
, NULL
);
558 ret
= gnutls_assert_val(GNUTLS_E_PARSING_ERROR
);
563 dst
= gnutls_malloc(len
);
566 ret
= gnutls_assert_val(GNUTLS_E_MEMORY_ERROR
);
570 ret
= WideCharToMultiByte(CP_UTF8
, MB_ERR_INVALID_CHARS
, (void*)src
, src_len
,
571 dst
, len
, NULL
, NULL
);
574 ret
= gnutls_assert_val(GNUTLS_E_PARSING_ERROR
);
593 /* Can convert only english (ASCII) */
594 int _gnutls_ucs2_to_utf8(const void* data
, size_t size
, gnutls_datum_t
*output
)
598 const char *src
= data
;
600 if (size
== 0 || size
% 2 != 0)
601 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
603 dst
= gnutls_malloc(size
+1);
605 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR
);
607 for (i
=j
=0;i
<size
;i
+=2,j
++)
609 if (src
[i
] != 0 || !isascii(src
[i
+1]))
610 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR
);
614 output
->data
= (void*)dst
;
616 output
->data
[output
->size
] = 0;