Added function to sort the provided certificate chain prior to verification.
[gnutls.git] / lib / system.c
blobd2ef259e108bbfb6857274d6b329843df95e3fa4
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>
34 #else
35 # ifdef HAVE_PTHREAD_LOCKS
36 # include <pthread.h>
37 # endif
39 # if defined(HAVE_GETPWUID_R)
40 # include <pwd.h>
41 # endif
42 #endif
44 /* We need to disable gnulib's replacement wrappers to get native
45 Windows interfaces. */
46 #undef recv
47 #undef send
48 #undef select
50 /* System specific function wrappers.
53 /* wrappers for write() and writev()
55 #ifdef _WIN32
57 int
58 system_errno (gnutls_transport_ptr p)
60 int tmperr = WSAGetLastError ();
61 int ret = 0;
62 switch (tmperr)
64 case WSAEWOULDBLOCK:
65 ret = EAGAIN;
66 break;
67 case NO_ERROR:
68 ret = 0;
69 break;
70 case WSAEINTR:
71 ret = EINTR;
72 break;
73 case WSAEMSGSIZE:
74 ret = EMSGSIZE;
75 break;
76 default:
77 ret = EIO;
78 break;
80 WSASetLastError (tmperr);
82 return ret;
85 ssize_t
86 system_write (gnutls_transport_ptr ptr, const void *data, size_t data_size)
88 return send (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
90 #else /* POSIX */
91 int
92 system_errno (gnutls_transport_ptr_t ptr)
94 #if defined(_AIX) || defined(AIX)
95 if (errno == 0) errno = EAGAIN;
96 #endif
98 return errno;
101 ssize_t
102 system_writev (gnutls_transport_ptr_t ptr, const giovec_t * iovec,
103 int iovec_cnt)
105 return writev (GNUTLS_POINTER_TO_INT (ptr), (struct iovec *) iovec,
106 iovec_cnt);
109 #endif
111 ssize_t
112 system_read (gnutls_transport_ptr_t ptr, void *data, size_t data_size)
114 return recv (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
117 /* Wait for data to be received within a timeout period in milliseconds.
118 * To catch a termination it will also try to receive 0 bytes from the
119 * socket if select reports to proceed.
121 * Returns -1 on error, 0 on timeout, positive value if data are available for reading.
123 int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
125 fd_set rfds;
126 struct timeval tv;
127 int ret, ret2;
128 int fd = GNUTLS_POINTER_TO_INT(ptr);
130 FD_ZERO(&rfds);
131 FD_SET(fd, &rfds);
133 tv.tv_sec = 0;
134 tv.tv_usec = ms * 1000;
136 while(tv.tv_usec >= 1000000)
138 tv.tv_usec -= 1000000;
139 tv.tv_sec++;
142 ret = select(fd+1, &rfds, NULL, NULL, &tv);
143 if (ret <= 0)
144 return ret;
146 ret2 = recv(fd, NULL, 0, MSG_PEEK);
147 if (ret2 == -1)
148 return ret2;
150 return ret;
153 /* Thread stuff */
155 #ifdef HAVE_WIN32_LOCKS
158 /* FIXME: win32 locks are untested */
159 static int
160 gnutls_system_mutex_init (void **priv)
162 CRITICAL_SECTION *lock = malloc (sizeof (CRITICAL_SECTION));
164 if (lock == NULL)
165 return GNUTLS_E_MEMORY_ERROR;
167 InitializeCriticalSection (lock);
169 *priv = lock;
171 return 0;
174 static int
175 gnutls_system_mutex_deinit (void **priv)
177 DeleteCriticalSection ((CRITICAL_SECTION *) * priv);
178 free (*priv);
180 return 0;
183 static int
184 gnutls_system_mutex_lock (void **priv)
186 EnterCriticalSection ((CRITICAL_SECTION *) * priv);
187 return 0;
190 static int
191 gnutls_system_mutex_unlock (void **priv)
193 LeaveCriticalSection ((CRITICAL_SECTION *) * priv);
194 return 0;
197 #endif /* WIN32_LOCKS */
199 #ifdef HAVE_PTHREAD_LOCKS
201 static int
202 gnutls_system_mutex_init (void **priv)
204 pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t));
205 int ret;
207 if (lock == NULL)
208 return GNUTLS_E_MEMORY_ERROR;
210 ret = pthread_mutex_init (lock, NULL);
211 if (ret)
213 free (lock);
214 gnutls_assert ();
215 return GNUTLS_E_LOCKING_ERROR;
218 *priv = lock;
220 return 0;
223 static int
224 gnutls_system_mutex_deinit (void **priv)
226 pthread_mutex_destroy ((pthread_mutex_t *) * priv);
227 free (*priv);
228 return 0;
231 static int
232 gnutls_system_mutex_lock (void **priv)
234 if (pthread_mutex_lock ((pthread_mutex_t *) * priv))
236 gnutls_assert ();
237 return GNUTLS_E_LOCKING_ERROR;
240 return 0;
243 static int
244 gnutls_system_mutex_unlock (void **priv)
246 if (pthread_mutex_unlock ((pthread_mutex_t *) * priv))
248 gnutls_assert ();
249 return GNUTLS_E_LOCKING_ERROR;
252 return 0;
255 #endif /* PTHREAD_LOCKS */
257 #ifdef HAVE_NO_LOCKS
259 static int
260 gnutls_system_mutex_init (void **priv)
262 return 0;
265 static int
266 gnutls_system_mutex_deinit (void **priv)
268 return 0;
271 static int
272 gnutls_system_mutex_lock (void **priv)
274 return 0;
277 static int
278 gnutls_system_mutex_unlock (void **priv)
280 return 0;
283 #endif /* NO_LOCKS */
285 gnutls_time_func gnutls_time = time;
286 mutex_init_func gnutls_mutex_init = gnutls_system_mutex_init;
287 mutex_deinit_func gnutls_mutex_deinit = gnutls_system_mutex_deinit;
288 mutex_lock_func gnutls_mutex_lock = gnutls_system_mutex_lock;
289 mutex_unlock_func gnutls_mutex_unlock = gnutls_system_mutex_unlock;
291 #define CONFIG_PATH ".gnutls"
293 /* Returns a path to store user-specific configuration
294 * data.
296 int _gnutls_find_config_path(char* path, size_t max_size)
298 char tmp_home_dir[1024];
299 const char *home_dir = getenv ("HOME");
301 #ifdef _WIN32
302 if (home_dir == NULL || home_dir[0] == '\0')
304 const char *home_drive = getenv ("HOMEDRIVE");
305 const char *home_path = getenv ("HOMEPATH");
307 if (home_drive != NULL && home_path != NULL)
309 snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s%s", home_drive, home_path);
311 else
313 tmp_home_dir[0] = 0;
316 home_dir = tmp_home_dir;
318 #elif defined(HAVE_GETPWUID_R)
319 if (home_dir == NULL || home_dir[0] == '\0')
321 struct passwd *pwd;
322 struct passwd _pwd;
323 char buf[1024];
325 getpwuid_r(getuid(), &_pwd, buf, sizeof(buf), &pwd);
326 if (pwd != NULL)
328 snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s", pwd->pw_dir);
330 else
332 tmp_home_dir[0] = 0;
335 home_dir = tmp_home_dir;
337 #else
338 if (home_dir == NULL || home_dir[0] == '\0')
340 tmp_home_dir[0] = 0;
341 home_dir = tmp_home_dir;
343 #endif
345 if (home_dir == NULL || home_dir[0] == 0)
346 path[0] = 0;
347 else
348 snprintf(path, max_size, "%s/"CONFIG_PATH, home_dir);
350 return 0;