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