no need to check for DTLS
[gnutls.git] / lib / system.c
blob82572ba971ca4d98a1be2b93359dac100bc5ac65
1 /*
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/>
23 #include <system.h>
24 #include <gnutls_int.h>
25 #include <gnutls_errors.h>
27 #include <errno.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
31 #ifdef _WIN32
32 # include <windows.h>
33 # include <Wincrypt.h>
35 #else
36 # ifdef HAVE_PTHREAD_LOCKS
37 # include <pthread.h>
38 # endif
40 # if defined(HAVE_GETPWUID_R)
41 # include <pwd.h>
42 # endif
43 #endif
45 /* We need to disable gnulib's replacement wrappers to get native
46 Windows interfaces. */
47 #undef recv
48 #undef send
49 #undef select
51 /* System specific function wrappers.
54 /* wrappers for write() and writev()
56 #ifdef _WIN32
58 int
59 system_errno (gnutls_transport_ptr p)
61 int tmperr = WSAGetLastError ();
62 int ret = 0;
63 switch (tmperr)
65 case WSAEWOULDBLOCK:
66 ret = EAGAIN;
67 break;
68 case NO_ERROR:
69 ret = 0;
70 break;
71 case WSAEINTR:
72 ret = EINTR;
73 break;
74 case WSAEMSGSIZE:
75 ret = EMSGSIZE;
76 break;
77 default:
78 ret = EIO;
79 break;
81 WSASetLastError (tmperr);
83 return ret;
86 ssize_t
87 system_write (gnutls_transport_ptr ptr, const void *data, size_t data_size)
89 return send (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
91 #else /* POSIX */
92 int
93 system_errno (gnutls_transport_ptr_t ptr)
95 #if defined(_AIX) || defined(AIX)
96 if (errno == 0) errno = EAGAIN;
97 #endif
99 return errno;
102 ssize_t
103 system_writev (gnutls_transport_ptr_t ptr, const giovec_t * iovec,
104 int iovec_cnt)
106 return writev (GNUTLS_POINTER_TO_INT (ptr), (struct iovec *) iovec,
107 iovec_cnt);
110 #endif
112 ssize_t
113 system_read (gnutls_transport_ptr_t ptr, void *data, size_t data_size)
115 return recv (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
118 /* Wait for data to be received within a timeout period in milliseconds.
119 * To catch a termination it will also try to receive 0 bytes from the
120 * socket if select reports to proceed.
122 * Returns -1 on error, 0 on timeout, positive value if data are available for reading.
124 int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
126 fd_set rfds;
127 struct timeval tv;
128 int ret, ret2;
129 int fd = GNUTLS_POINTER_TO_INT(ptr);
131 FD_ZERO(&rfds);
132 FD_SET(fd, &rfds);
134 tv.tv_sec = 0;
135 tv.tv_usec = ms * 1000;
137 while(tv.tv_usec >= 1000000)
139 tv.tv_usec -= 1000000;
140 tv.tv_sec++;
143 ret = select(fd+1, &rfds, NULL, NULL, &tv);
144 if (ret <= 0)
145 return ret;
147 ret2 = recv(fd, NULL, 0, MSG_PEEK);
148 if (ret2 == -1)
149 return ret2;
151 return ret;
154 /* Thread stuff */
156 #ifdef HAVE_WIN32_LOCKS
159 /* FIXME: win32 locks are untested */
160 static int
161 gnutls_system_mutex_init (void **priv)
163 CRITICAL_SECTION *lock = malloc (sizeof (CRITICAL_SECTION));
165 if (lock == NULL)
166 return GNUTLS_E_MEMORY_ERROR;
168 InitializeCriticalSection (lock);
170 *priv = lock;
172 return 0;
175 static int
176 gnutls_system_mutex_deinit (void **priv)
178 DeleteCriticalSection ((CRITICAL_SECTION *) * priv);
179 free (*priv);
181 return 0;
184 static int
185 gnutls_system_mutex_lock (void **priv)
187 EnterCriticalSection ((CRITICAL_SECTION *) * priv);
188 return 0;
191 static int
192 gnutls_system_mutex_unlock (void **priv)
194 LeaveCriticalSection ((CRITICAL_SECTION *) * priv);
195 return 0;
198 #endif /* WIN32_LOCKS */
200 #ifdef HAVE_PTHREAD_LOCKS
202 static int
203 gnutls_system_mutex_init (void **priv)
205 pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t));
206 int ret;
208 if (lock == NULL)
209 return GNUTLS_E_MEMORY_ERROR;
211 ret = pthread_mutex_init (lock, NULL);
212 if (ret)
214 free (lock);
215 gnutls_assert ();
216 return GNUTLS_E_LOCKING_ERROR;
219 *priv = lock;
221 return 0;
224 static int
225 gnutls_system_mutex_deinit (void **priv)
227 pthread_mutex_destroy ((pthread_mutex_t *) * priv);
228 free (*priv);
229 return 0;
232 static int
233 gnutls_system_mutex_lock (void **priv)
235 if (pthread_mutex_lock ((pthread_mutex_t *) * priv))
237 gnutls_assert ();
238 return GNUTLS_E_LOCKING_ERROR;
241 return 0;
244 static int
245 gnutls_system_mutex_unlock (void **priv)
247 if (pthread_mutex_unlock ((pthread_mutex_t *) * priv))
249 gnutls_assert ();
250 return GNUTLS_E_LOCKING_ERROR;
253 return 0;
256 #endif /* PTHREAD_LOCKS */
258 #ifdef HAVE_NO_LOCKS
260 static int
261 gnutls_system_mutex_init (void **priv)
263 return 0;
266 static int
267 gnutls_system_mutex_deinit (void **priv)
269 return 0;
272 static int
273 gnutls_system_mutex_lock (void **priv)
275 return 0;
278 static int
279 gnutls_system_mutex_unlock (void **priv)
281 return 0;
284 #endif /* NO_LOCKS */
286 gnutls_time_func gnutls_time = time;
287 mutex_init_func gnutls_mutex_init = gnutls_system_mutex_init;
288 mutex_deinit_func gnutls_mutex_deinit = gnutls_system_mutex_deinit;
289 mutex_lock_func gnutls_mutex_lock = gnutls_system_mutex_lock;
290 mutex_unlock_func gnutls_mutex_unlock = gnutls_system_mutex_unlock;
292 #define CONFIG_PATH ".gnutls"
294 /* Returns a path to store user-specific configuration
295 * data.
297 int _gnutls_find_config_path(char* path, size_t max_size)
299 char tmp_home_dir[1024];
300 const char *home_dir = getenv ("HOME");
302 #ifdef _WIN32
303 if (home_dir == NULL || home_dir[0] == '\0')
305 const char *home_drive = getenv ("HOMEDRIVE");
306 const char *home_path = getenv ("HOMEPATH");
308 if (home_drive != NULL && home_path != NULL)
310 snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s%s", home_drive, home_path);
312 else
314 tmp_home_dir[0] = 0;
317 home_dir = tmp_home_dir;
319 #elif defined(HAVE_GETPWUID_R)
320 if (home_dir == NULL || home_dir[0] == '\0')
322 struct passwd *pwd;
323 struct passwd _pwd;
324 char buf[1024];
326 getpwuid_r(getuid(), &_pwd, buf, sizeof(buf), &pwd);
327 if (pwd != NULL)
329 snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s", pwd->pw_dir);
331 else
333 tmp_home_dir[0] = 0;
336 home_dir = tmp_home_dir;
338 #else
339 if (home_dir == NULL || home_dir[0] == '\0')
341 tmp_home_dir[0] = 0;
342 home_dir = tmp_home_dir;
344 #endif
346 if (home_dir == NULL || home_dir[0] == 0)
347 path[0] = 0;
348 else
349 snprintf(path, max_size, "%s/"CONFIG_PATH, home_dir);
351 return 0;
355 * gnutls_x509_trust_list_add_system_trust:
356 * @list: The structure of the list
357 * @tl_flags: GNUTLS_TL_*
358 * @tl_vflags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL
360 * This function adds the system's default trusted certificate
361 * authorities to the trusted list. Note that on unsupported system
362 * this function returns %GNUTLS_E_UNIMPLEMENTED_FEATURE.
364 * Returns: The number of added elements or a negative error code on error.
366 * Since: 3.1
369 gnutls_x509_trust_list_add_system_trust(gnutls_x509_trust_list_t list,
370 unsigned int tl_flags, unsigned int tl_vflags)
372 #if !defined(DEFAULT_TRUST_STORE_PKCS11) && !defined(DEFAULT_TRUST_STORE_FILE) && !defined(_WIN32)
373 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
374 #else
375 int ret, r = 0;
376 const char* crl_file =
377 # ifdef DEFAULT_CRL_FILE
378 DEFAULT_CRL_FILE;
379 # else
380 NULL;
381 # endif
383 # ifdef _WIN32
384 unsigned int i;
386 for (i=0;i<2;i++)
388 HCERTSTORE store;
389 const CERT_CONTEXT *cert;
390 const CRL_CONTEXT *crl;
391 gnutls_datum_t data;
393 if (i==0) store = CertOpenSystemStore(0, "ROOT");
394 else store = CertOpenSystemStore(0, "CA");
396 if (store == NULL) return GNUTLS_E_FILE_ERROR;
398 cert = CertEnumCertificatesInStore(store, NULL);
399 crl = CertEnumCRLsInStore(store, NULL);
401 while(cert != NULL)
403 if (cert->dwCertEncodingType == X509_ASN_ENCODING)
405 data.data = cert->pbCertEncoded;
406 data.size = cert->cbCertEncoded;
407 if (gnutls_x509_trust_list_add_trust_mem(list, &data, NULL, GNUTLS_X509_FMT_DER, tl_flags, tl_vflags) > 0)
408 r++;
410 cert = CertEnumCertificatesInStore(store, cert);
413 while(crl != NULL)
415 if (crl->dwCertEncodingType == X509_ASN_ENCODING)
417 data.data = crl->pbCrlEncoded;
418 data.size = crl->cbCrlEncoded;
419 gnutls_x509_trust_list_add_trust_mem(list, NULL, &data, GNUTLS_X509_FMT_DER, tl_flags, tl_vflags);
421 crl = CertEnumCRLsInStore(store, crl);
423 CertCloseStore(store, 0);
425 # endif
427 # if defined(ENABLE_PKCS11) && defined(DEFAULT_TRUST_STORE_PKCS11)
428 ret = gnutls_x509_trust_list_add_trust_file(list, DEFAULT_TRUST_STORE_PKCS11, crl_file,
429 GNUTLS_X509_FMT_DER, tl_flags, tl_vflags);
430 if (ret > 0)
431 r += ret;
432 # endif
434 # ifdef DEFAULT_TRUST_STORE_FILE
435 ret = gnutls_x509_trust_list_add_trust_file(list, DEFAULT_TRUST_STORE_FILE, crl_file,
436 GNUTLS_X509_FMT_PEM, tl_flags, tl_vflags);
437 if (ret > 0)
438 r += ret;
439 # endif
440 #endif
442 return r;