If a client hello is received immediately after a completed handshake delete the...
[gnutls.git] / lib / system.c
blob679bb0a9679ba486317694fd84b6527b4cf4c336
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 default:
74 ret = EIO;
75 break;
77 WSASetLastError (tmperr);
79 return ret;
82 ssize_t
83 system_write (gnutls_transport_ptr ptr, const void *data, size_t data_size)
85 return send (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
87 #else /* POSIX */
88 int
89 system_errno (gnutls_transport_ptr_t ptr)
91 #if defined(_AIX) || defined(AIX)
92 if (errno == 0) errno = EAGAIN;
93 #endif
95 return errno;
98 ssize_t
99 system_writev (gnutls_transport_ptr_t ptr, const giovec_t * iovec,
100 int iovec_cnt)
102 return writev (GNUTLS_POINTER_TO_INT (ptr), (struct iovec *) iovec,
103 iovec_cnt);
106 #endif
108 ssize_t
109 system_read (gnutls_transport_ptr_t ptr, void *data, size_t data_size)
111 return recv (GNUTLS_POINTER_TO_INT (ptr), data, data_size, 0);
114 /* Wait for data to be received within a timeout period in milliseconds.
115 * To catch a termination it will also try to receive 0 bytes from the
116 * socket if select reports to proceed.
118 * Returns -1 on error, 0 on timeout, positive value if data are available for reading.
120 int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
122 fd_set rfds;
123 struct timeval tv;
124 int ret, ret2;
125 int fd = GNUTLS_POINTER_TO_INT(ptr);
127 FD_ZERO(&rfds);
128 FD_SET(fd, &rfds);
130 tv.tv_sec = 0;
131 tv.tv_usec = ms * 1000;
133 while(tv.tv_usec >= 1000000)
135 tv.tv_usec -= 1000000;
136 tv.tv_sec++;
139 ret = select(fd+1, &rfds, NULL, NULL, &tv);
140 if (ret <= 0)
141 return ret;
143 ret2 = recv(fd, NULL, 0, MSG_PEEK);
144 if (ret2 == -1)
145 return ret2;
147 return ret;
150 /* Thread stuff */
152 #ifdef HAVE_WIN32_LOCKS
155 /* FIXME: win32 locks are untested */
156 static int
157 gnutls_system_mutex_init (void **priv)
159 CRITICAL_SECTION *lock = malloc (sizeof (CRITICAL_SECTION));
161 if (lock == NULL)
162 return GNUTLS_E_MEMORY_ERROR;
164 InitializeCriticalSection (lock);
166 *priv = lock;
168 return 0;
171 static int
172 gnutls_system_mutex_deinit (void **priv)
174 DeleteCriticalSection ((CRITICAL_SECTION *) * priv);
175 free (*priv);
177 return 0;
180 static int
181 gnutls_system_mutex_lock (void **priv)
183 EnterCriticalSection ((CRITICAL_SECTION *) * priv);
184 return 0;
187 static int
188 gnutls_system_mutex_unlock (void **priv)
190 LeaveCriticalSection ((CRITICAL_SECTION *) * priv);
191 return 0;
194 #endif /* WIN32_LOCKS */
196 #ifdef HAVE_PTHREAD_LOCKS
198 static int
199 gnutls_system_mutex_init (void **priv)
201 pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t));
202 int ret;
204 if (lock == NULL)
205 return GNUTLS_E_MEMORY_ERROR;
207 ret = pthread_mutex_init (lock, NULL);
208 if (ret)
210 free (lock);
211 gnutls_assert ();
212 return GNUTLS_E_LOCKING_ERROR;
215 *priv = lock;
217 return 0;
220 static int
221 gnutls_system_mutex_deinit (void **priv)
223 pthread_mutex_destroy ((pthread_mutex_t *) * priv);
224 free (*priv);
225 return 0;
228 static int
229 gnutls_system_mutex_lock (void **priv)
231 if (pthread_mutex_lock ((pthread_mutex_t *) * priv))
233 gnutls_assert ();
234 return GNUTLS_E_LOCKING_ERROR;
237 return 0;
240 static int
241 gnutls_system_mutex_unlock (void **priv)
243 if (pthread_mutex_unlock ((pthread_mutex_t *) * priv))
245 gnutls_assert ();
246 return GNUTLS_E_LOCKING_ERROR;
249 return 0;
252 #endif /* PTHREAD_LOCKS */
254 #ifdef HAVE_NO_LOCKS
256 static int
257 gnutls_system_mutex_init (void **priv)
259 return 0;
262 static int
263 gnutls_system_mutex_deinit (void **priv)
265 return 0;
268 static int
269 gnutls_system_mutex_lock (void **priv)
271 return 0;
274 static int
275 gnutls_system_mutex_unlock (void **priv)
277 return 0;
280 #endif /* NO_LOCKS */
282 gnutls_time_func gnutls_time = time;
283 mutex_init_func gnutls_mutex_init = gnutls_system_mutex_init;
284 mutex_deinit_func gnutls_mutex_deinit = gnutls_system_mutex_deinit;
285 mutex_lock_func gnutls_mutex_lock = gnutls_system_mutex_lock;
286 mutex_unlock_func gnutls_mutex_unlock = gnutls_system_mutex_unlock;
288 #define CONFIG_PATH ".gnutls"
290 /* Returns a path to store user-specific configuration
291 * data.
293 int _gnutls_find_config_path(char* path, size_t max_size)
295 char tmp_home_dir[1024];
296 const char *home_dir = getenv ("HOME");
298 #ifdef _WIN32
299 if (home_dir == NULL || home_dir[0] == '\0')
301 const char *home_drive = getenv ("HOMEDRIVE");
302 const char *home_path = getenv ("HOMEPATH");
304 if (home_drive != NULL && home_path != NULL)
306 snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s%s", home_drive, home_path);
308 else
310 tmp_home_dir[0] = 0;
313 home_dir = tmp_home_dir;
315 #elif defined(HAVE_GETPWUID_R)
316 if (home_dir == NULL || home_dir[0] == '\0')
318 struct passwd *pwd;
319 struct passwd _pwd;
320 char buf[1024];
322 getpwuid_r(getuid(), &_pwd, buf, sizeof(buf), &pwd);
323 if (pwd != NULL)
325 snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s", pwd->pw_dir);
327 else
329 tmp_home_dir[0] = 0;
332 home_dir = tmp_home_dir;
334 #else
335 if (home_dir == NULL || home_dir[0] == '\0')
337 tmp_home_dir[0] = 0;
338 home_dir = tmp_home_dir;
340 #endif
342 if (home_dir == NULL || home_dir[0] == 0)
343 path[0] = 0;
344 else
345 snprintf(path, max_size, "%s/"CONFIG_PATH, home_dir);
347 return 0;