version/tests: Fix a copy-paste mistake.
[wine] / dlls / wininet / netconnection.c
1 /*
2  * Wininet - networking layer. Uses unix sockets or OpenSSL.
3  *
4  * Copyright 2002 TransGaming Technologies Inc.
5  *
6  * David Hammerton
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but 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.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <sys/types.h>
27 #ifdef HAVE_POLL_H
28 #include <poll.h>
29 #endif
30 #ifdef HAVE_SYS_POLL_H
31 # include <sys/poll.h>
32 #endif
33 #ifdef HAVE_SYS_TIME_H
34 # include <sys/time.h>
35 #endif
36 #ifdef HAVE_SYS_SOCKET_H
37 # include <sys/socket.h>
38 #endif
39 #ifdef HAVE_SYS_FILIO_H
40 # include <sys/filio.h>
41 #endif
42 #ifdef HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif
45 #ifdef HAVE_SYS_IOCTL_H
46 # include <sys/ioctl.h>
47 #endif
48 #include <time.h>
49 #ifdef HAVE_NETDB_H
50 # include <netdb.h>
51 #endif
52 #ifdef HAVE_NETINET_IN_H
53 # include <netinet/in.h>
54 #endif
55 #ifdef HAVE_OPENSSL_SSL_H
56 # include <openssl/ssl.h>
57 #undef FAR
58 #undef DSA
59 #endif
60
61 #include <stdarg.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <stdio.h>
65 #include <errno.h>
66
67 #include "wine/library.h"
68 #include "windef.h"
69 #include "winbase.h"
70 #include "wininet.h"
71 #include "winerror.h"
72 #include "wincrypt.h"
73
74 #include "wine/debug.h"
75 #include "internet.h"
76
77 /* To avoid conflicts with the Unix socket headers. we only need it for
78  * the error codes anyway. */
79 #define USE_WS_PREFIX
80 #include "winsock2.h"
81
82 #define RESPONSE_TIMEOUT        30            /* FROM internet.c */
83
84
85 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
86
87 /* FIXME!!!!!!
88  *    This should use winsock - To use winsock the functions will have to change a bit
89  *        as they are designed for unix sockets.
90  *    SSL stuff should use crypt32.dll
91  */
92
93 #ifdef SONAME_LIBSSL
94
95 #include <openssl/err.h>
96
97 static void *OpenSSL_ssl_handle;
98 static void *OpenSSL_crypto_handle;
99
100 static SSL_METHOD *meth;
101 static SSL_CTX *ctx;
102
103 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
104
105 /* OpenSSL functions that we use */
106 MAKE_FUNCPTR(SSL_library_init);
107 MAKE_FUNCPTR(SSL_load_error_strings);
108 MAKE_FUNCPTR(SSLv23_method);
109 MAKE_FUNCPTR(SSL_CTX_new);
110 MAKE_FUNCPTR(SSL_new);
111 MAKE_FUNCPTR(SSL_free);
112 MAKE_FUNCPTR(SSL_set_fd);
113 MAKE_FUNCPTR(SSL_connect);
114 MAKE_FUNCPTR(SSL_shutdown);
115 MAKE_FUNCPTR(SSL_write);
116 MAKE_FUNCPTR(SSL_read);
117 MAKE_FUNCPTR(SSL_get_verify_result);
118 MAKE_FUNCPTR(SSL_get_peer_certificate);
119 MAKE_FUNCPTR(SSL_CTX_get_timeout);
120 MAKE_FUNCPTR(SSL_CTX_set_timeout);
121 MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths);
122 MAKE_FUNCPTR(i2d_X509);
123
124 /* OpenSSL's libcrypto functions that we use */
125 MAKE_FUNCPTR(BIO_new_fp);
126 MAKE_FUNCPTR(ERR_get_error);
127 MAKE_FUNCPTR(ERR_error_string);
128 #undef MAKE_FUNCPTR
129
130 #endif
131
132 BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
133 {
134     connection->useSSL = FALSE;
135     connection->socketFD = -1;
136     if (useSSL)
137     {
138 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
139         TRACE("using SSL connection\n");
140         if (OpenSSL_ssl_handle) /* already initialized everything */
141             return TRUE;
142         OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0);
143         if (!OpenSSL_ssl_handle)
144         {
145             ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
146                 SONAME_LIBSSL);
147             INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
148             return FALSE;
149         }
150         OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
151         if (!OpenSSL_crypto_handle)
152         {
153             ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
154                 SONAME_LIBCRYPTO);
155             INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
156             return FALSE;
157         }
158
159         /* mmm nice ugly macroness */
160 #define DYNSSL(x) \
161     p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \
162     if (!p##x) \
163     { \
164         ERR("failed to load symbol %s\n", #x); \
165         INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); \
166         return FALSE; \
167     }
168
169         DYNSSL(SSL_library_init);
170         DYNSSL(SSL_load_error_strings);
171         DYNSSL(SSLv23_method);
172         DYNSSL(SSL_CTX_new);
173         DYNSSL(SSL_new);
174         DYNSSL(SSL_free);
175         DYNSSL(SSL_set_fd);
176         DYNSSL(SSL_connect);
177         DYNSSL(SSL_shutdown);
178         DYNSSL(SSL_write);
179         DYNSSL(SSL_read);
180         DYNSSL(SSL_get_verify_result);
181         DYNSSL(SSL_get_peer_certificate);
182         DYNSSL(SSL_CTX_get_timeout);
183         DYNSSL(SSL_CTX_set_timeout);
184         DYNSSL(SSL_CTX_set_default_verify_paths);
185         DYNSSL(i2d_X509);
186 #undef DYNSSL
187
188 #define DYNCRYPTO(x) \
189     p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \
190     if (!p##x) \
191     { \
192         ERR("failed to load symbol %s\n", #x); \
193         INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); \
194         return FALSE; \
195     }
196         DYNCRYPTO(BIO_new_fp);
197         DYNCRYPTO(ERR_get_error);
198         DYNCRYPTO(ERR_error_string);
199 #undef DYNCRYPTO
200
201         pSSL_library_init();
202         pSSL_load_error_strings();
203         pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
204
205         meth = pSSLv23_method();
206         connection->peek_msg = NULL;
207         connection->peek_msg_mem = NULL;
208 #else
209         FIXME("can't use SSL, not compiled in.\n");
210         INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
211         return FALSE;
212 #endif
213     }
214     return TRUE;
215 }
216
217 BOOL NETCON_connected(WININET_NETCONNECTION *connection)
218 {
219     if (connection->socketFD == -1)
220         return FALSE;
221     else
222         return TRUE;
223 }
224
225 /* translate a unix error code into a winsock one */
226 static int sock_get_error( int err )
227 {
228 #if !defined(__MINGW32__) && !defined (_MSC_VER)
229     switch (err)
230     {
231         case EINTR:             return WSAEINTR;
232         case EBADF:             return WSAEBADF;
233         case EPERM:
234         case EACCES:            return WSAEACCES;
235         case EFAULT:            return WSAEFAULT;
236         case EINVAL:            return WSAEINVAL;
237         case EMFILE:            return WSAEMFILE;
238         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
239         case EINPROGRESS:       return WSAEINPROGRESS;
240         case EALREADY:          return WSAEALREADY;
241         case ENOTSOCK:          return WSAENOTSOCK;
242         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
243         case EMSGSIZE:          return WSAEMSGSIZE;
244         case EPROTOTYPE:        return WSAEPROTOTYPE;
245         case ENOPROTOOPT:       return WSAENOPROTOOPT;
246         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
247         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
248         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
249         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
250         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
251         case EADDRINUSE:        return WSAEADDRINUSE;
252         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
253         case ENETDOWN:          return WSAENETDOWN;
254         case ENETUNREACH:       return WSAENETUNREACH;
255         case ENETRESET:         return WSAENETRESET;
256         case ECONNABORTED:      return WSAECONNABORTED;
257         case EPIPE:
258         case ECONNRESET:        return WSAECONNRESET;
259         case ENOBUFS:           return WSAENOBUFS;
260         case EISCONN:           return WSAEISCONN;
261         case ENOTCONN:          return WSAENOTCONN;
262         case ESHUTDOWN:         return WSAESHUTDOWN;
263         case ETOOMANYREFS:      return WSAETOOMANYREFS;
264         case ETIMEDOUT:         return WSAETIMEDOUT;
265         case ECONNREFUSED:      return WSAECONNREFUSED;
266         case ELOOP:             return WSAELOOP;
267         case ENAMETOOLONG:      return WSAENAMETOOLONG;
268         case EHOSTDOWN:         return WSAEHOSTDOWN;
269         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
270         case ENOTEMPTY:         return WSAENOTEMPTY;
271 #ifdef EPROCLIM
272         case EPROCLIM:          return WSAEPROCLIM;
273 #endif
274 #ifdef EUSERS
275         case EUSERS:            return WSAEUSERS;
276 #endif
277 #ifdef EDQUOT
278         case EDQUOT:            return WSAEDQUOT;
279 #endif
280 #ifdef ESTALE
281         case ESTALE:            return WSAESTALE;
282 #endif
283 #ifdef EREMOTE
284         case EREMOTE:           return WSAEREMOTE;
285 #endif
286     default: errno=err; perror("sock_set_error"); return WSAEFAULT;
287     }
288 #endif
289     return err;
290 }
291
292 /******************************************************************************
293  * NETCON_create
294  * Basically calls 'socket()'
295  */
296 BOOL NETCON_create(WININET_NETCONNECTION *connection, int domain,
297               int type, int protocol)
298 {
299 #ifdef SONAME_LIBSSL
300     if (connection->useSSL)
301         return FALSE;
302 #endif
303
304     connection->socketFD = socket(domain, type, protocol);
305     if (connection->socketFD == -1)
306     {
307         INTERNET_SetLastError(sock_get_error(errno));
308         return FALSE;
309     }
310     return TRUE;
311 }
312
313 /******************************************************************************
314  * NETCON_close
315  * Basically calls 'close()' unless we should use SSL
316  */
317 BOOL NETCON_close(WININET_NETCONNECTION *connection)
318 {
319     int result;
320
321     if (!NETCON_connected(connection)) return FALSE;
322
323 #ifdef SONAME_LIBSSL
324     if (connection->useSSL)
325     {
326         HeapFree(GetProcessHeap(),0,connection->peek_msg_mem);
327         connection->peek_msg = NULL;
328         connection->peek_msg_mem = NULL;
329         connection->peek_len = 0;
330
331         pSSL_shutdown(connection->ssl_s);
332         pSSL_free(connection->ssl_s);
333         connection->ssl_s = NULL;
334
335         connection->useSSL = FALSE;
336     }
337 #endif
338
339     result = closesocket(connection->socketFD);
340     connection->socketFD = -1;
341
342     if (result == -1)
343     {
344         INTERNET_SetLastError(sock_get_error(errno));
345         return FALSE;
346     }
347     return TRUE;
348 }
349 #ifdef SONAME_LIBSSL
350 static BOOL check_hostname(X509 *cert, char *hostname)
351 {
352     /* FIXME: implement */
353     return TRUE;
354 }
355 #endif
356 /******************************************************************************
357  * NETCON_secure_connect
358  * Initiates a secure connection over an existing plaintext connection.
359  */
360 BOOL NETCON_secure_connect(WININET_NETCONNECTION *connection, LPCWSTR hostname)
361 {
362 #ifdef SONAME_LIBSSL
363     long verify_res;
364     X509 *cert;
365     int len;
366     char *hostname_unix;
367
368     /* can't connect if we are already connected */
369     if (connection->useSSL)
370     {
371         ERR("already connected\n");
372         return FALSE;
373     }
374
375     ctx = pSSL_CTX_new(meth);
376     if (!pSSL_CTX_set_default_verify_paths(ctx))
377     {
378         ERR("SSL_CTX_set_default_verify_paths failed: %s\n",
379             pERR_error_string(pERR_get_error(), 0));
380         INTERNET_SetLastError(ERROR_OUTOFMEMORY);
381         return FALSE;
382     }
383     connection->ssl_s = pSSL_new(ctx);
384     if (!connection->ssl_s)
385     {
386         ERR("SSL_new failed: %s\n",
387             pERR_error_string(pERR_get_error(), 0));
388         INTERNET_SetLastError(ERROR_OUTOFMEMORY);
389         goto fail;
390     }
391
392     if (!pSSL_set_fd(connection->ssl_s, connection->socketFD))
393     {
394         ERR("SSL_set_fd failed: %s\n",
395             pERR_error_string(pERR_get_error(), 0));
396         INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
397         goto fail;
398     }
399
400     if (pSSL_connect(connection->ssl_s) <= 0)
401     {
402         ERR("SSL_connect failed: %s\n",
403             pERR_error_string(pERR_get_error(), 0));
404         INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR);
405         goto fail;
406     }
407     cert = pSSL_get_peer_certificate(connection->ssl_s);
408     if (!cert)
409     {
410         ERR("no certificate for server %s\n", debugstr_w(hostname));
411         /* FIXME: is this the best error? */
412         INTERNET_SetLastError(ERROR_INTERNET_INVALID_CA);
413         goto fail;
414     }
415     verify_res = pSSL_get_verify_result(connection->ssl_s);
416     if (verify_res != X509_V_OK)
417     {
418         ERR("couldn't verify the security of the connection, %ld\n", verify_res);
419         /* FIXME: we should set an error and return, but we only warn at
420          * the moment */
421     }
422
423     len = WideCharToMultiByte(CP_UNIXCP, 0, hostname, -1, NULL, 0, NULL, NULL);
424     hostname_unix = HeapAlloc(GetProcessHeap(), 0, len);
425     if (!hostname_unix)
426     {
427         INTERNET_SetLastError(ERROR_OUTOFMEMORY);
428         goto fail;
429     }
430     WideCharToMultiByte(CP_UNIXCP, 0, hostname, -1, hostname_unix, len, NULL, NULL);
431
432     if (!check_hostname(cert, hostname_unix))
433     {
434         HeapFree(GetProcessHeap(), 0, hostname_unix);
435         INTERNET_SetLastError(ERROR_INTERNET_SEC_CERT_CN_INVALID);
436         goto fail;
437     }
438
439     HeapFree(GetProcessHeap(), 0, hostname_unix);
440     connection->useSSL = TRUE;
441     return TRUE;
442
443 fail:
444     if (connection->ssl_s)
445     {
446         pSSL_shutdown(connection->ssl_s);
447         pSSL_free(connection->ssl_s);
448         connection->ssl_s = NULL;
449     }
450 #endif
451     return FALSE;
452 }
453
454 /******************************************************************************
455  * NETCON_connect
456  * Connects to the specified address.
457  */
458 BOOL NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
459                     unsigned int addrlen)
460 {
461     int result;
462
463     if (!NETCON_connected(connection)) return FALSE;
464
465     result = connect(connection->socketFD, serv_addr, addrlen);
466     if (result == -1)
467     {
468         WARN("Unable to connect to host (%s)\n", strerror(errno));
469         INTERNET_SetLastError(sock_get_error(errno));
470
471         closesocket(connection->socketFD);
472         connection->socketFD = -1;
473         return FALSE;
474     }
475
476     return TRUE;
477 }
478
479 /******************************************************************************
480  * NETCON_send
481  * Basically calls 'send()' unless we should use SSL
482  * number of chars send is put in *sent
483  */
484 BOOL NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
485                 int *sent /* out */)
486 {
487     if (!NETCON_connected(connection)) return FALSE;
488     if (!connection->useSSL)
489     {
490         *sent = send(connection->socketFD, msg, len, flags);
491         if (*sent == -1)
492         {
493             INTERNET_SetLastError(sock_get_error(errno));
494             return FALSE;
495         }
496         return TRUE;
497     }
498     else
499     {
500 #ifdef SONAME_LIBSSL
501         if (flags)
502             FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
503         *sent = pSSL_write(connection->ssl_s, msg, len);
504         if (*sent < 1 && len)
505             return FALSE;
506         return TRUE;
507 #else
508         return FALSE;
509 #endif
510     }
511 }
512
513 /******************************************************************************
514  * NETCON_recv
515  * Basically calls 'recv()' unless we should use SSL
516  * number of chars received is put in *recvd
517  */
518 BOOL NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
519                 int *recvd /* out */)
520 {
521     *recvd = 0;
522     if (!NETCON_connected(connection)) return FALSE;
523     if (!len)
524         return TRUE;
525     if (!connection->useSSL)
526     {
527         *recvd = recv(connection->socketFD, buf, len, flags);
528         if (*recvd == -1)
529         {
530             INTERNET_SetLastError(sock_get_error(errno));
531             return FALSE;
532         }
533         return TRUE;
534     }
535     else
536     {
537 #ifdef SONAME_LIBSSL
538         if (flags & ~(MSG_PEEK|MSG_WAITALL))
539             FIXME("SSL_read does not support the following flag: %08x\n", flags);
540
541         /* this ugly hack is all for MSG_PEEK. eww gross */
542         if (flags & MSG_PEEK && !connection->peek_msg)
543         {
544             connection->peek_msg = connection->peek_msg_mem = HeapAlloc(GetProcessHeap(), 0, (sizeof(char) * len) + 1);
545         }
546         else if (flags & MSG_PEEK && connection->peek_msg)
547         {
548             if (len < connection->peek_len)
549                 FIXME("buffer isn't big enough. Do the expect us to wrap?\n");
550             *recvd = min(len, connection->peek_len);
551             memcpy(buf, connection->peek_msg, *recvd);
552             return TRUE;
553         }
554         else if (connection->peek_msg)
555         {
556             *recvd = min(len, connection->peek_len);
557             memcpy(buf, connection->peek_msg, *recvd);
558             connection->peek_len -= *recvd;
559             connection->peek_msg += *recvd;
560             if (connection->peek_len == 0)
561             {
562                 HeapFree(GetProcessHeap(), 0, connection->peek_msg_mem);
563                 connection->peek_msg_mem = NULL;
564                 connection->peek_msg = NULL;
565             }
566             /* check if we got enough data from the peek buffer */
567             if (!(flags & MSG_WAITALL) || (*recvd == len))
568                 return TRUE;
569             /* otherwise, fall through */
570         }
571         *recvd += pSSL_read(connection->ssl_s, (char*)buf + *recvd, len - *recvd);
572         if (flags & MSG_PEEK) /* must copy stuff into buffer */
573         {
574             connection->peek_len = *recvd;
575             if (!*recvd)
576             {
577                 HeapFree(GetProcessHeap(), 0, connection->peek_msg_mem);
578                 connection->peek_msg_mem = NULL;
579                 connection->peek_msg = NULL;
580             }
581             else
582                 memcpy(connection->peek_msg, buf, *recvd);
583         }
584         if (*recvd < 1 && len)
585             return FALSE;
586         return TRUE;
587 #else
588         return FALSE;
589 #endif
590     }
591 }
592
593 /******************************************************************************
594  * NETCON_query_data_available
595  * Returns the number of bytes of peeked data plus the number of bytes of
596  * queued, but unread data.
597  */
598 BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available)
599 {
600     *available = 0;
601     if (!NETCON_connected(connection))
602         return FALSE;
603
604 #ifdef SONAME_LIBSSL
605     if (connection->peek_msg) *available = connection->peek_len;
606 #endif
607
608 #ifdef FIONREAD
609     if (!connection->useSSL)
610     {
611         int unread;
612         int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread);
613         if (!retval)
614         {
615             TRACE("%d bytes of queued, but unread data\n", unread);
616             *available += unread;
617         }
618     }
619 #endif
620     return TRUE;
621 }
622
623 /******************************************************************************
624  * NETCON_getNextLine
625  */
626 BOOL NETCON_getNextLine(WININET_NETCONNECTION *connection, LPSTR lpszBuffer, LPDWORD dwBuffer)
627 {
628
629     TRACE("\n");
630
631     if (!NETCON_connected(connection)) return FALSE;
632
633     if (!connection->useSSL)
634     {
635         struct pollfd pfd;
636         DWORD nRecv = 0;
637         int ret;
638
639         pfd.fd = connection->socketFD;
640         pfd.events = POLLIN;
641
642         while (nRecv < *dwBuffer)
643         {
644             if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0)
645             {
646                 if ((ret = recv(connection->socketFD, &lpszBuffer[nRecv], 1, 0)) <= 0)
647                 {
648                     if (ret == -1) INTERNET_SetLastError(sock_get_error(errno));
649                     break;
650                 }
651
652                 if (lpszBuffer[nRecv] == '\n')
653                 {
654                     lpszBuffer[nRecv++] = '\0';
655                     *dwBuffer = nRecv;
656                     TRACE(":%u %s\n", nRecv, lpszBuffer);
657                     return TRUE;
658                 }
659                 if (lpszBuffer[nRecv] != '\r')
660                     nRecv++;
661             }
662             else
663             {
664                 INTERNET_SetLastError(ERROR_INTERNET_TIMEOUT);
665                 break;
666             }
667         }
668     }
669     else
670     {
671 #ifdef SONAME_LIBSSL
672         long prev_timeout;
673         DWORD nRecv = 0;
674         BOOL success = TRUE;
675
676         prev_timeout = pSSL_CTX_get_timeout(ctx);
677         pSSL_CTX_set_timeout(ctx, RESPONSE_TIMEOUT);
678
679         while (nRecv < *dwBuffer)
680         {
681             int recv = 1;
682             if (!NETCON_recv(connection, &lpszBuffer[nRecv], 1, 0, &recv))
683             {
684                 INTERNET_SetLastError(ERROR_CONNECTION_ABORTED);
685                 success = FALSE;
686             }
687
688             if (lpszBuffer[nRecv] == '\n')
689             {
690                 success = TRUE;
691                 break;
692             }
693             if (lpszBuffer[nRecv] != '\r')
694                 nRecv++;
695         }
696
697         pSSL_CTX_set_timeout(ctx, prev_timeout);
698         if (success)
699         {
700             lpszBuffer[nRecv++] = '\0';
701             *dwBuffer = nRecv;
702             TRACE("_SSL:%u %s\n", nRecv, lpszBuffer);
703             return TRUE;
704         }
705 #endif
706     }
707     return FALSE;
708 }
709
710
711 LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection)
712 {
713 #ifdef SONAME_LIBSSL
714     X509* cert;
715     unsigned char* buffer,*p;
716     INT len;
717     BOOL malloced = FALSE;
718     LPCVOID r = NULL;
719
720     if (!connection->useSSL)
721         return NULL;
722
723     cert = pSSL_get_peer_certificate(connection->ssl_s);
724     p = NULL;
725     len = pi2d_X509(cert,&p);
726     /*
727      * SSL 0.9.7 and above malloc the buffer if it is null. 
728      * however earlier version do not and so we would need to alloc the buffer.
729      *
730      * see the i2d_X509 man page for more details.
731      */
732     if (!p)
733     {
734         buffer = HeapAlloc(GetProcessHeap(),0,len);
735         p = buffer;
736         len = pi2d_X509(cert,&p);
737     }
738     else
739     {
740         buffer = p;
741         malloced = TRUE;
742     }
743
744     r = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);
745
746     if (malloced)
747         free(buffer);
748     else
749         HeapFree(GetProcessHeap(),0,buffer);
750
751     return r;
752 #else
753     return NULL;
754 #endif
755 }
756
757 DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value)
758 {
759     int result;
760     struct timeval tv;
761
762     /* FIXME: we should probably store the timeout in the connection to set
763      * when we do connect */
764     if (!NETCON_connected(connection))
765         return ERROR_SUCCESS;
766
767     /* value is in milliseconds, convert to struct timeval */
768     tv.tv_sec = value / 1000;
769     tv.tv_usec = (value % 1000) * 1000;
770
771     result = setsockopt(connection->socketFD, SOL_SOCKET,
772                         send ? SO_SNDTIMEO : SO_RCVTIMEO, &tv,
773                         sizeof(tv));
774
775     if (result == -1)
776     {
777         WARN("setsockopt failed (%s)\n", strerror(errno));
778         return sock_get_error(errno);
779     }
780
781     return ERROR_SUCCESS;
782 }