msvcr71: Add _vscprintf and _vscwprintf.
[wine] / dlls / winhttp / net.c
1 /*
2  * Copyright 2008 Hans Leidekker for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <errno.h>
25
26 #include <sys/types.h>
27 #ifdef HAVE_SYS_SOCKET_H
28 # include <sys/socket.h>
29 #endif
30 #ifdef HAVE_SYS_IOCTL_H
31 # include <sys/ioctl.h>
32 #endif
33 #ifdef HAVE_SYS_FILIO_H
34 # include <sys/filio.h>
35 #endif
36 #ifdef HAVE_POLL_H
37 # include <poll.h>
38 #endif
39 #ifdef HAVE_OPENSSL_SSL_H
40 # include <openssl/ssl.h>
41 #undef FAR
42 #undef DSA
43 #endif
44
45 #include "wine/debug.h"
46 #include "wine/library.h"
47
48 #include "windef.h"
49 #include "winbase.h"
50 #include "winhttp.h"
51 #include "wincrypt.h"
52
53 #include "winhttp_private.h"
54
55 /* to avoid conflicts with the Unix socket headers */
56 #define USE_WS_PREFIX
57 #include "winsock2.h"
58
59 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
60
61 #ifndef HAVE_GETADDRINFO
62
63 /* critical section to protect non-reentrant gethostbyname() */
64 static CRITICAL_SECTION cs_gethostbyname;
65 static CRITICAL_SECTION_DEBUG critsect_debug =
66 {
67     0, 0, &cs_gethostbyname,
68     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
69       0, 0, { (DWORD_PTR)(__FILE__ ": cs_gethostbyname") }
70 };
71 static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 };
72
73 #endif
74
75 #ifdef SONAME_LIBSSL
76
77 #include <openssl/err.h>
78
79 static CRITICAL_SECTION init_ssl_cs;
80 static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
81 {
82     0, 0, &init_ssl_cs,
83     { &init_ssl_cs_debug.ProcessLocksList,
84       &init_ssl_cs_debug.ProcessLocksList },
85     0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") }
86 };
87 static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
88
89 static void *libssl_handle;
90 static void *libcrypto_handle;
91
92 static SSL_METHOD *method;
93 static SSL_CTX *ctx;
94
95 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
96
97 MAKE_FUNCPTR( SSL_library_init );
98 MAKE_FUNCPTR( SSL_load_error_strings );
99 MAKE_FUNCPTR( SSLv23_method );
100 MAKE_FUNCPTR( SSL_CTX_free );
101 MAKE_FUNCPTR( SSL_CTX_new );
102 MAKE_FUNCPTR( SSL_new );
103 MAKE_FUNCPTR( SSL_free );
104 MAKE_FUNCPTR( SSL_set_fd );
105 MAKE_FUNCPTR( SSL_connect );
106 MAKE_FUNCPTR( SSL_shutdown );
107 MAKE_FUNCPTR( SSL_write );
108 MAKE_FUNCPTR( SSL_read );
109 MAKE_FUNCPTR( SSL_get_verify_result );
110 MAKE_FUNCPTR( SSL_get_peer_certificate );
111 MAKE_FUNCPTR( SSL_CTX_set_default_verify_paths );
112
113 MAKE_FUNCPTR( BIO_new_fp );
114 MAKE_FUNCPTR( CRYPTO_num_locks );
115 MAKE_FUNCPTR( CRYPTO_set_id_callback );
116 MAKE_FUNCPTR( CRYPTO_set_locking_callback );
117 MAKE_FUNCPTR( ERR_get_error );
118 MAKE_FUNCPTR( ERR_error_string );
119 MAKE_FUNCPTR( i2d_X509 );
120 #undef MAKE_FUNCPTR
121
122 static CRITICAL_SECTION *ssl_locks;
123
124 static unsigned long ssl_thread_id(void)
125 {
126     return GetCurrentThreadId();
127 }
128
129 static void ssl_lock_callback(int mode, int type, const char *file, int line)
130 {
131     if (mode & CRYPTO_LOCK)
132         EnterCriticalSection( &ssl_locks[type] );
133     else
134         LeaveCriticalSection( &ssl_locks[type] );
135 }
136
137 #endif
138
139 /* translate a unix error code into a winsock error code */
140 static int sock_get_error( int err )
141 {
142 #if !defined(__MINGW32__) && !defined (_MSC_VER)
143     switch (err)
144     {
145         case EINTR:             return WSAEINTR;
146         case EBADF:             return WSAEBADF;
147         case EPERM:
148         case EACCES:            return WSAEACCES;
149         case EFAULT:            return WSAEFAULT;
150         case EINVAL:            return WSAEINVAL;
151         case EMFILE:            return WSAEMFILE;
152         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
153         case EINPROGRESS:       return WSAEINPROGRESS;
154         case EALREADY:          return WSAEALREADY;
155         case ENOTSOCK:          return WSAENOTSOCK;
156         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
157         case EMSGSIZE:          return WSAEMSGSIZE;
158         case EPROTOTYPE:        return WSAEPROTOTYPE;
159         case ENOPROTOOPT:       return WSAENOPROTOOPT;
160         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
161         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
162         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
163         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
164         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
165         case EADDRINUSE:        return WSAEADDRINUSE;
166         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
167         case ENETDOWN:          return WSAENETDOWN;
168         case ENETUNREACH:       return WSAENETUNREACH;
169         case ENETRESET:         return WSAENETRESET;
170         case ECONNABORTED:      return WSAECONNABORTED;
171         case EPIPE:
172         case ECONNRESET:        return WSAECONNRESET;
173         case ENOBUFS:           return WSAENOBUFS;
174         case EISCONN:           return WSAEISCONN;
175         case ENOTCONN:          return WSAENOTCONN;
176         case ESHUTDOWN:         return WSAESHUTDOWN;
177         case ETOOMANYREFS:      return WSAETOOMANYREFS;
178         case ETIMEDOUT:         return WSAETIMEDOUT;
179         case ECONNREFUSED:      return WSAECONNREFUSED;
180         case ELOOP:             return WSAELOOP;
181         case ENAMETOOLONG:      return WSAENAMETOOLONG;
182         case EHOSTDOWN:         return WSAEHOSTDOWN;
183         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
184         case ENOTEMPTY:         return WSAENOTEMPTY;
185 #ifdef EPROCLIM
186         case EPROCLIM:          return WSAEPROCLIM;
187 #endif
188 #ifdef EUSERS
189         case EUSERS:            return WSAEUSERS;
190 #endif
191 #ifdef EDQUOT
192         case EDQUOT:            return WSAEDQUOT;
193 #endif
194 #ifdef ESTALE
195         case ESTALE:            return WSAESTALE;
196 #endif
197 #ifdef EREMOTE
198         case EREMOTE:           return WSAEREMOTE;
199 #endif
200     default: errno = err; perror( "sock_set_error" ); return WSAEFAULT;
201     }
202 #endif
203     return err;
204 }
205
206 BOOL netconn_init( netconn_t *conn, BOOL secure )
207 {
208 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
209     int i;
210 #endif
211
212     conn->socket = -1;
213     if (!secure) return TRUE;
214
215 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
216     EnterCriticalSection( &init_ssl_cs );
217     if (libssl_handle)
218     {
219         LeaveCriticalSection( &init_ssl_cs );
220         return TRUE;
221     }
222     if (!(libssl_handle = wine_dlopen( SONAME_LIBSSL, RTLD_NOW, NULL, 0 )))
223     {
224         ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL);
225         set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
226         LeaveCriticalSection( &init_ssl_cs );
227         return FALSE;
228     }
229     if (!(libcrypto_handle = wine_dlopen( SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0 )))
230     {
231         ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO);
232         set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
233         LeaveCriticalSection( &init_ssl_cs );
234         return FALSE;
235     }
236 #define LOAD_FUNCPTR(x) \
237     if (!(p##x = wine_dlsym( libssl_handle, #x, NULL, 0 ))) \
238     { \
239         ERR("Failed to load symbol %s\n", #x); \
240         set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
241         LeaveCriticalSection( &init_ssl_cs ); \
242         return FALSE; \
243     }
244     LOAD_FUNCPTR( SSL_library_init );
245     LOAD_FUNCPTR( SSL_load_error_strings );
246     LOAD_FUNCPTR( SSLv23_method );
247     LOAD_FUNCPTR( SSL_CTX_free );
248     LOAD_FUNCPTR( SSL_CTX_new );
249     LOAD_FUNCPTR( SSL_new );
250     LOAD_FUNCPTR( SSL_free );
251     LOAD_FUNCPTR( SSL_set_fd );
252     LOAD_FUNCPTR( SSL_connect );
253     LOAD_FUNCPTR( SSL_shutdown );
254     LOAD_FUNCPTR( SSL_write );
255     LOAD_FUNCPTR( SSL_read );
256     LOAD_FUNCPTR( SSL_get_verify_result );
257     LOAD_FUNCPTR( SSL_get_peer_certificate );
258     LOAD_FUNCPTR( SSL_CTX_set_default_verify_paths );
259 #undef LOAD_FUNCPTR
260
261 #define LOAD_FUNCPTR(x) \
262     if (!(p##x = wine_dlsym( libcrypto_handle, #x, NULL, 0 ))) \
263     { \
264         ERR("Failed to load symbol %s\n", #x); \
265         set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
266         LeaveCriticalSection( &init_ssl_cs ); \
267         return FALSE; \
268     }
269     LOAD_FUNCPTR( BIO_new_fp );
270     LOAD_FUNCPTR( CRYPTO_num_locks );
271     LOAD_FUNCPTR( CRYPTO_set_id_callback );
272     LOAD_FUNCPTR( CRYPTO_set_locking_callback );
273     LOAD_FUNCPTR( ERR_get_error );
274     LOAD_FUNCPTR( ERR_error_string );
275     LOAD_FUNCPTR( i2d_X509 );
276 #undef LOAD_FUNCPTR
277
278     pSSL_library_init();
279     pSSL_load_error_strings();
280     pBIO_new_fp( stderr, BIO_NOCLOSE );
281
282     method = pSSLv23_method();
283     ctx = pSSL_CTX_new( method );
284     if (!pSSL_CTX_set_default_verify_paths( ctx ))
285     {
286         ERR("SSL_CTX_set_default_verify_paths failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
287         set_last_error( ERROR_OUTOFMEMORY );
288         LeaveCriticalSection( &init_ssl_cs );
289         return FALSE;
290     }
291
292     pCRYPTO_set_id_callback(ssl_thread_id);
293     ssl_locks = HeapAlloc(GetProcessHeap(), 0,
294             pCRYPTO_num_locks() * sizeof(HANDLE));
295     if (!ssl_locks)
296     {
297         set_last_error( ERROR_OUTOFMEMORY );
298         LeaveCriticalSection( &init_ssl_cs );
299         return FALSE;
300     }
301     for (i = 0; i < pCRYPTO_num_locks(); i++)
302         InitializeCriticalSection( &ssl_locks[i] );
303     pCRYPTO_set_locking_callback(ssl_lock_callback);
304
305     LeaveCriticalSection( &init_ssl_cs );
306 #else
307     WARN("SSL support not compiled in.\n");
308     set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
309     return FALSE;
310 #endif
311     return TRUE;
312 }
313
314 void netconn_unload( void )
315 {
316 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
317     if (libcrypto_handle)
318     {
319         if (ssl_locks)
320         {
321             int i;
322
323             for (i = 0; i < pCRYPTO_num_locks(); i++)
324                 DeleteCriticalSection( &ssl_locks[i] );
325             HeapFree( GetProcessHeap(), 0, ssl_locks );
326         }
327         wine_dlclose( libcrypto_handle, NULL, 0 );
328     }
329     if (libssl_handle)
330     {
331         if (ctx)
332             pSSL_CTX_free( ctx );
333         wine_dlclose( libssl_handle, NULL, 0 );
334     }
335 #endif
336 }
337
338 BOOL netconn_connected( netconn_t *conn )
339 {
340     return (conn->socket != -1);
341 }
342
343 BOOL netconn_create( netconn_t *conn, int domain, int type, int protocol )
344 {
345     if ((conn->socket = socket( domain, type, protocol )) == -1)
346     {
347         WARN("unable to create socket (%s)\n", strerror(errno));
348         set_last_error( sock_get_error( errno ) );
349         return FALSE;
350     }
351     return TRUE;
352 }
353
354 BOOL netconn_close( netconn_t *conn )
355 {
356     int res;
357
358 #ifdef SONAME_LIBSSL
359     if (conn->secure)
360     {
361         heap_free( conn->peek_msg_mem );
362         conn->peek_msg_mem = NULL;
363         conn->peek_msg = NULL;
364         conn->peek_len = 0;
365
366         pSSL_shutdown( conn->ssl_conn );
367         pSSL_free( conn->ssl_conn );
368
369         conn->ssl_conn = NULL;
370         conn->secure = FALSE;
371     }
372 #endif
373     res = closesocket( conn->socket );
374     conn->socket = -1;
375     if (res == -1)
376     {
377         set_last_error( sock_get_error( errno ) );
378         return FALSE;
379     }
380     return TRUE;
381 }
382
383 BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len, int timeout )
384 {
385     BOOL ret = FALSE;
386     int res = 0, state;
387
388     if (timeout > 0)
389     {
390         state = 1;
391         ioctlsocket( conn->socket, FIONBIO, &state );
392     }
393     if (connect( conn->socket, sockaddr, addr_len ) < 0)
394     {
395         res = sock_get_error( errno );
396         if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
397         {
398             struct pollfd pfd;
399
400             pfd.fd = conn->socket;
401             pfd.events = POLLOUT;
402             if (poll( &pfd, 1, timeout ) > 0)
403                 ret = TRUE;
404             else
405                 res = sock_get_error( errno );
406         }
407     }
408     else
409         ret = TRUE;
410     if (timeout > 0)
411     {
412         state = 0;
413         ioctlsocket( conn->socket, FIONBIO, &state );
414     }
415     if (!ret)
416     {
417         WARN("unable to connect to host (%d)\n", res);
418         set_last_error( res );
419     }
420     return ret;
421 }
422
423 BOOL netconn_secure_connect( netconn_t *conn )
424 {
425 #ifdef SONAME_LIBSSL
426     X509 *cert;
427     long res;
428
429     if (!(conn->ssl_conn = pSSL_new( ctx )))
430     {
431         ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
432         set_last_error( ERROR_OUTOFMEMORY );
433         goto fail;
434     }
435     if (!pSSL_set_fd( conn->ssl_conn, conn->socket ))
436     {
437         ERR("SSL_set_fd failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
438         set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
439         goto fail;
440     }
441     if (pSSL_connect( conn->ssl_conn ) <= 0)
442     {
443         ERR("SSL_connect failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
444         set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
445         goto fail;
446     }
447     if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn )))
448     {
449         ERR("No certificate for server: %s\n", pERR_error_string( pERR_get_error(), 0 ));
450         set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
451         goto fail;
452     }
453     if ((res = pSSL_get_verify_result( conn->ssl_conn )) != X509_V_OK)
454     {
455         /* FIXME: we should set an error and return, but we only print an error at the moment */
456         ERR("couldn't verify server certificate (%ld)\n", res);
457     }
458     TRACE("established SSL connection\n");
459     conn->secure = TRUE;
460     return TRUE;
461
462 fail:
463     if (conn->ssl_conn)
464     {
465         pSSL_shutdown( conn->ssl_conn );
466         pSSL_free( conn->ssl_conn );
467         conn->ssl_conn = NULL;
468     }
469 #endif
470     return FALSE;
471 }
472
473 BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int flags, int *sent )
474 {
475     if (!netconn_connected( conn )) return FALSE;
476     if (conn->secure)
477     {
478 #ifdef SONAME_LIBSSL
479         if (flags) FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
480         *sent = pSSL_write( conn->ssl_conn, msg, len );
481         if (*sent < 1 && len) return FALSE;
482         return TRUE;
483 #else
484         return FALSE;
485 #endif
486     }
487     if ((*sent = send( conn->socket, msg, len, flags )) == -1)
488     {
489         set_last_error( sock_get_error( errno ) );
490         return FALSE;
491     }
492     return TRUE;
493 }
494
495 BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd )
496 {
497     *recvd = 0;
498     if (!netconn_connected( conn )) return FALSE;
499     if (!len) return TRUE;
500
501     if (conn->secure)
502     {
503 #ifdef SONAME_LIBSSL
504         if (flags & ~(MSG_PEEK | MSG_WAITALL))
505             FIXME("SSL_read does not support the following flags: %08x\n", flags);
506
507         /* this ugly hack is all for MSG_PEEK */
508         if (flags & MSG_PEEK && !conn->peek_msg)
509         {
510             if (!(conn->peek_msg = conn->peek_msg_mem = heap_alloc( len + 1 ))) return FALSE;
511         }
512         else if (flags & MSG_PEEK && conn->peek_msg)
513         {
514             if (len < conn->peek_len) FIXME("buffer isn't big enough, should we wrap?\n");
515             *recvd = min( len, conn->peek_len );
516             memcpy( buf, conn->peek_msg, *recvd );
517             return TRUE;
518         }
519         else if (conn->peek_msg)
520         {
521             *recvd = min( len, conn->peek_len );
522             memcpy( buf, conn->peek_msg, *recvd );
523             conn->peek_len -= *recvd;
524             conn->peek_msg += *recvd;
525
526             if (conn->peek_len == 0)
527             {
528                 heap_free( conn->peek_msg_mem );
529                 conn->peek_msg_mem = NULL;
530                 conn->peek_msg = NULL;
531             }
532             /* check if we have enough data from the peek buffer */
533             if (!(flags & MSG_WAITALL) || (*recvd == len)) return TRUE;
534         }
535         *recvd += pSSL_read( conn->ssl_conn, (char *)buf + *recvd, len - *recvd );
536         if (flags & MSG_PEEK) /* must copy into buffer */
537         {
538             conn->peek_len = *recvd;
539             if (!*recvd)
540             {
541                 heap_free( conn->peek_msg_mem );
542                 conn->peek_msg_mem = NULL;
543                 conn->peek_msg = NULL;
544             }
545             else memcpy( conn->peek_msg, buf, *recvd );
546         }
547         if (*recvd < 1 && len) return FALSE;
548         return TRUE;
549 #else
550         return FALSE;
551 #endif
552     }
553     if ((*recvd = recv( conn->socket, buf, len, flags )) == -1)
554     {
555         set_last_error( sock_get_error( errno ) );
556         return FALSE;
557     }
558     return TRUE;
559 }
560
561 BOOL netconn_query_data_available( netconn_t *conn, DWORD *available )
562 {
563 #ifdef FIONREAD
564     int ret, unread;
565 #endif
566     *available = 0;
567     if (!netconn_connected( conn )) return FALSE;
568
569     if (conn->secure)
570     {
571 #ifdef SONAME_LIBSSL
572         if (conn->peek_msg) *available = conn->peek_len;
573 #endif
574         return TRUE;
575     }
576 #ifdef FIONREAD
577     if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread ))) *available = unread;
578 #endif
579     return TRUE;
580 }
581
582 BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
583 {
584     struct pollfd pfd;
585     BOOL ret = FALSE;
586     DWORD recvd = 0;
587
588     if (!netconn_connected( conn )) return FALSE;
589
590     if (conn->secure)
591     {
592 #ifdef SONAME_LIBSSL
593         while (recvd < *buflen)
594         {
595             int dummy;
596             if (!netconn_recv( conn, &buffer[recvd], 1, 0, &dummy ))
597             {
598                 set_last_error( ERROR_CONNECTION_ABORTED );
599                 break;
600             }
601             if (buffer[recvd] == '\n')
602             {
603                 ret = TRUE;
604                 break;
605             }
606             if (buffer[recvd] != '\r') recvd++;
607         }
608         if (ret)
609         {
610             buffer[recvd++] = 0;
611             *buflen = recvd;
612             TRACE("received line %s\n", debugstr_a(buffer));
613         }
614         return ret;
615 #else
616         return FALSE;
617 #endif
618     }
619
620     pfd.fd = conn->socket;
621     pfd.events = POLLIN;
622     while (recvd < *buflen)
623     {
624         int timeout, res;
625         struct timeval tv;
626         socklen_t len = sizeof(tv);
627
628         if ((res = getsockopt( conn->socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv, &len ) != -1))
629             timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
630         else
631             timeout = -1;
632         if (poll( &pfd, 1, timeout ) > 0)
633         {
634             if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0)
635             {
636                 if (res == -1) set_last_error( sock_get_error( errno ) );
637                 break;
638             }
639             if (buffer[recvd] == '\n')
640             {
641                 ret = TRUE;
642                 break;
643             }
644             if (buffer[recvd] != '\r') recvd++;
645         }
646         else
647         {
648             set_last_error( ERROR_WINHTTP_TIMEOUT );
649             break;
650         }
651     }
652     if (ret)
653     {
654         buffer[recvd++] = 0;
655         *buflen = recvd;
656         TRACE("received line %s\n", debugstr_a(buffer));
657     }
658     return ret;
659 }
660
661 DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
662 {
663     int res;
664     struct timeval tv;
665
666     /* value is in milliseconds, convert to struct timeval */
667     tv.tv_sec = value / 1000;
668     tv.tv_usec = (value % 1000) * 1000;
669
670     if ((res = setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, sizeof(tv) ) == -1))
671     {
672         WARN("setsockopt failed (%s)\n", strerror( errno ));
673         return sock_get_error( errno );
674     }
675     return ERROR_SUCCESS;
676 }
677
678 BOOL netconn_resolve( WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr *sa, socklen_t *sa_len )
679 {
680     char *hostname;
681 #ifdef HAVE_GETADDRINFO
682     struct addrinfo *res, hints;
683     int ret;
684 #else
685     struct hostent *he;
686     struct sockaddr_in *sin = (struct sockaddr_in *)sa;
687 #endif
688
689     if (!(hostname = strdupWA( hostnameW ))) return FALSE;
690
691 #ifdef HAVE_GETADDRINFO
692     memset( &hints, 0, sizeof(struct addrinfo) );
693     /* Prefer IPv4 to IPv6 addresses, since some web servers do not listen on
694      * their IPv6 addresses even though they have IPv6 addresses in the DNS.
695      */
696     hints.ai_family = AF_INET;
697
698     ret = getaddrinfo( hostname, NULL, &hints, &res );
699     if (ret != 0)
700     {
701         TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(hostnameW), gai_strerror(ret));
702         hints.ai_family = AF_INET6;
703         ret = getaddrinfo( hostname, NULL, &hints, &res );
704         if (ret != 0)
705         {
706             TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret));
707             heap_free( hostname );
708             return FALSE;
709         }
710     }
711     heap_free( hostname );
712     if (*sa_len < res->ai_addrlen)
713     {
714         WARN("address too small\n");
715         freeaddrinfo( res );
716         return FALSE;
717     }
718     *sa_len = res->ai_addrlen;
719     memcpy( sa, res->ai_addr, res->ai_addrlen );
720     /* Copy port */
721     switch (res->ai_family)
722     {
723     case AF_INET:
724         ((struct sockaddr_in *)sa)->sin_port = htons( port );
725         break;
726     case AF_INET6:
727         ((struct sockaddr_in6 *)sa)->sin6_port = htons( port );
728         break;
729     }
730
731     freeaddrinfo( res );
732     return TRUE;
733 #else
734     EnterCriticalSection( &cs_gethostbyname );
735
736     he = gethostbyname( hostname );
737     heap_free( hostname );
738     if (!he)
739     {
740         TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW), h_errno);
741         LeaveCriticalSection( &cs_gethostbyname );
742         return FALSE;
743     }
744     if (*sa_len < sizeof(struct sockaddr_in))
745     {
746         WARN("address too small\n");
747         LeaveCriticalSection( &cs_gethostbyname );
748         return FALSE;
749     }
750     *sa_len = sizeof(struct sockaddr_in);
751     memset( sa, 0, sizeof(struct sockaddr_in) );
752     memcpy( &sin->sin_addr, he->h_addr, he->h_length );
753     sin->sin_family = he->h_addrtype;
754     sin->sin_port = htons( port );
755
756     LeaveCriticalSection( &cs_gethostbyname );
757     return TRUE;
758 #endif
759 }
760
761 const void *netconn_get_certificate( netconn_t *conn )
762 {
763 #ifdef SONAME_LIBSSL
764     X509 *cert;
765     unsigned char *buffer, *p;
766     int len;
767     BOOL malloc = FALSE;
768     const CERT_CONTEXT *ret;
769
770     if (!conn->secure) return NULL;
771
772     if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL;
773     p = NULL;
774     if ((len = pi2d_X509( cert, &p )) < 0) return NULL;
775     /*
776      * SSL 0.9.7 and above malloc the buffer if it is null.
777      * however earlier version do not and so we would need to alloc the buffer.
778      *
779      * see the i2d_X509 man page for more details.
780      */
781     if (!p)
782     {
783         if (!(buffer = heap_alloc( len ))) return NULL;
784         p = buffer;
785         len = pi2d_X509( cert, &p );
786     }
787     else
788     {
789         buffer = p;
790         malloc = TRUE;
791     }
792
793     ret = CertCreateCertificateContext( X509_ASN_ENCODING, buffer, len );
794
795     if (malloc) free( buffer );
796     else heap_free( buffer );
797
798     return ret;
799 #else
800     return NULL;
801 #endif
802 }