wininet: Store hostname for secure connection in its SSL context.
[wine/multimedia.git] / dlls / wininet / netconnection.c
blob6650359df8fc22b1eb9139e081c0fd5f94905fc2
1 /*
2 * Wininet - networking layer. Uses unix sockets or OpenSSL.
4 * Copyright 2002 TransGaming Technologies Inc.
6 * David Hammerton
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.
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.
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
23 #include "config.h"
24 #include "wine/port.h"
26 #if defined(__MINGW32__) || defined (_MSC_VER)
27 #include <ws2tcpip.h>
28 #endif
30 #include <sys/types.h>
31 #ifdef HAVE_POLL_H
32 #include <poll.h>
33 #endif
34 #ifdef HAVE_SYS_POLL_H
35 # include <sys/poll.h>
36 #endif
37 #ifdef HAVE_SYS_TIME_H
38 # include <sys/time.h>
39 #endif
40 #ifdef HAVE_SYS_SOCKET_H
41 # include <sys/socket.h>
42 #endif
43 #ifdef HAVE_SYS_FILIO_H
44 # include <sys/filio.h>
45 #endif
46 #ifdef HAVE_UNISTD_H
47 # include <unistd.h>
48 #endif
49 #ifdef HAVE_SYS_IOCTL_H
50 # include <sys/ioctl.h>
51 #endif
52 #include <time.h>
53 #ifdef HAVE_NETDB_H
54 # include <netdb.h>
55 #endif
56 #ifdef HAVE_NETINET_IN_H
57 # include <netinet/in.h>
58 #endif
59 #ifdef HAVE_OPENSSL_SSL_H
60 # include <openssl/ssl.h>
61 #undef FAR
62 #undef DSA
63 #endif
65 #include <stdarg.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <stdio.h>
69 #include <errno.h>
71 #include "wine/library.h"
72 #include "windef.h"
73 #include "winbase.h"
74 #include "wininet.h"
75 #include "winerror.h"
76 #include "wincrypt.h"
78 #include "wine/debug.h"
79 #include "internet.h"
81 /* To avoid conflicts with the Unix socket headers. we only need it for
82 * the error codes anyway. */
83 #define USE_WS_PREFIX
84 #include "winsock2.h"
86 #define RESPONSE_TIMEOUT 30 /* FROM internet.c */
89 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
91 /* FIXME!!!!!!
92 * This should use winsock - To use winsock the functions will have to change a bit
93 * as they are designed for unix sockets.
94 * SSL stuff should use crypt32.dll
97 #ifdef SONAME_LIBSSL
99 #include <openssl/err.h>
101 static CRITICAL_SECTION init_ssl_cs;
102 static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
104 0, 0, &init_ssl_cs,
105 { &init_ssl_cs_debug.ProcessLocksList,
106 &init_ssl_cs_debug.ProcessLocksList },
107 0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") }
109 static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
111 static void *OpenSSL_ssl_handle;
112 static void *OpenSSL_crypto_handle;
114 static SSL_METHOD *meth;
115 static SSL_CTX *ctx;
116 static int hostname_idx;
118 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
120 /* OpenSSL functions that we use */
121 MAKE_FUNCPTR(SSL_library_init);
122 MAKE_FUNCPTR(SSL_load_error_strings);
123 MAKE_FUNCPTR(SSLv23_method);
124 MAKE_FUNCPTR(SSL_CTX_free);
125 MAKE_FUNCPTR(SSL_CTX_new);
126 MAKE_FUNCPTR(SSL_new);
127 MAKE_FUNCPTR(SSL_free);
128 MAKE_FUNCPTR(SSL_set_fd);
129 MAKE_FUNCPTR(SSL_connect);
130 MAKE_FUNCPTR(SSL_shutdown);
131 MAKE_FUNCPTR(SSL_write);
132 MAKE_FUNCPTR(SSL_read);
133 MAKE_FUNCPTR(SSL_pending);
134 MAKE_FUNCPTR(SSL_get_ex_new_index);
135 MAKE_FUNCPTR(SSL_set_ex_data);
136 MAKE_FUNCPTR(SSL_get_verify_result);
137 MAKE_FUNCPTR(SSL_get_peer_certificate);
138 MAKE_FUNCPTR(SSL_CTX_get_timeout);
139 MAKE_FUNCPTR(SSL_CTX_set_timeout);
140 MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths);
142 /* OpenSSL's libcrypto functions that we use */
143 MAKE_FUNCPTR(BIO_new_fp);
144 MAKE_FUNCPTR(CRYPTO_num_locks);
145 MAKE_FUNCPTR(CRYPTO_set_id_callback);
146 MAKE_FUNCPTR(CRYPTO_set_locking_callback);
147 MAKE_FUNCPTR(ERR_free_strings);
148 MAKE_FUNCPTR(ERR_get_error);
149 MAKE_FUNCPTR(ERR_error_string);
150 MAKE_FUNCPTR(i2d_X509);
151 #undef MAKE_FUNCPTR
153 static CRITICAL_SECTION *ssl_locks;
155 static unsigned long ssl_thread_id(void)
157 return GetCurrentThreadId();
160 static void ssl_lock_callback(int mode, int type, const char *file, int line)
162 if (mode & CRYPTO_LOCK)
163 EnterCriticalSection(&ssl_locks[type]);
164 else
165 LeaveCriticalSection(&ssl_locks[type]);
168 #endif
170 DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
172 connection->useSSL = FALSE;
173 connection->socketFD = -1;
174 if (useSSL)
176 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
177 int i;
179 TRACE("using SSL connection\n");
180 EnterCriticalSection(&init_ssl_cs);
181 if (OpenSSL_ssl_handle) /* already initialized everything */
183 LeaveCriticalSection(&init_ssl_cs);
184 return ERROR_SUCCESS;
186 OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0);
187 if (!OpenSSL_ssl_handle)
189 ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
190 SONAME_LIBSSL);
191 LeaveCriticalSection(&init_ssl_cs);
192 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
194 OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
195 if (!OpenSSL_crypto_handle)
197 ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
198 SONAME_LIBCRYPTO);
199 LeaveCriticalSection(&init_ssl_cs);
200 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
203 /* mmm nice ugly macroness */
204 #define DYNSSL(x) \
205 p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \
206 if (!p##x) \
208 ERR("failed to load symbol %s\n", #x); \
209 LeaveCriticalSection(&init_ssl_cs); \
210 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
213 DYNSSL(SSL_library_init);
214 DYNSSL(SSL_load_error_strings);
215 DYNSSL(SSLv23_method);
216 DYNSSL(SSL_CTX_free);
217 DYNSSL(SSL_CTX_new);
218 DYNSSL(SSL_new);
219 DYNSSL(SSL_free);
220 DYNSSL(SSL_set_fd);
221 DYNSSL(SSL_connect);
222 DYNSSL(SSL_shutdown);
223 DYNSSL(SSL_write);
224 DYNSSL(SSL_read);
225 DYNSSL(SSL_pending);
226 DYNSSL(SSL_get_ex_new_index);
227 DYNSSL(SSL_set_ex_data);
228 DYNSSL(SSL_get_verify_result);
229 DYNSSL(SSL_get_peer_certificate);
230 DYNSSL(SSL_CTX_get_timeout);
231 DYNSSL(SSL_CTX_set_timeout);
232 DYNSSL(SSL_CTX_set_default_verify_paths);
233 #undef DYNSSL
235 #define DYNCRYPTO(x) \
236 p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \
237 if (!p##x) \
239 ERR("failed to load symbol %s\n", #x); \
240 LeaveCriticalSection(&init_ssl_cs); \
241 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
243 DYNCRYPTO(BIO_new_fp);
244 DYNCRYPTO(CRYPTO_num_locks);
245 DYNCRYPTO(CRYPTO_set_id_callback);
246 DYNCRYPTO(CRYPTO_set_locking_callback);
247 DYNCRYPTO(ERR_free_strings);
248 DYNCRYPTO(ERR_get_error);
249 DYNCRYPTO(ERR_error_string);
250 DYNCRYPTO(i2d_X509);
251 #undef DYNCRYPTO
253 pSSL_library_init();
254 pSSL_load_error_strings();
255 pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
257 meth = pSSLv23_method();
258 ctx = pSSL_CTX_new(meth);
259 if (!pSSL_CTX_set_default_verify_paths(ctx))
261 ERR("SSL_CTX_set_default_verify_paths failed: %s\n",
262 pERR_error_string(pERR_get_error(), 0));
263 LeaveCriticalSection(&init_ssl_cs);
264 return ERROR_OUTOFMEMORY;
266 hostname_idx = pSSL_get_ex_new_index(0, (void *)"hostname index",
267 NULL, NULL, NULL);
269 pCRYPTO_set_id_callback(ssl_thread_id);
270 ssl_locks = HeapAlloc(GetProcessHeap(), 0,
271 pCRYPTO_num_locks() * sizeof(CRITICAL_SECTION));
272 if (!ssl_locks)
274 LeaveCriticalSection(&init_ssl_cs);
275 return ERROR_OUTOFMEMORY;
277 for (i = 0; i < pCRYPTO_num_locks(); i++)
278 InitializeCriticalSection(&ssl_locks[i]);
279 pCRYPTO_set_locking_callback(ssl_lock_callback);
280 LeaveCriticalSection(&init_ssl_cs);
281 #else
282 FIXME("can't use SSL, not compiled in.\n");
283 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
284 #endif
286 return ERROR_SUCCESS;
289 void NETCON_unload(void)
291 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
292 if (OpenSSL_crypto_handle)
294 pERR_free_strings();
295 wine_dlclose(OpenSSL_crypto_handle, NULL, 0);
297 if (OpenSSL_ssl_handle)
299 if (ctx)
300 pSSL_CTX_free(ctx);
301 wine_dlclose(OpenSSL_ssl_handle, NULL, 0);
303 if (ssl_locks)
305 int i;
306 for (i = 0; i < pCRYPTO_num_locks(); i++) DeleteCriticalSection(&ssl_locks[i]);
307 HeapFree(GetProcessHeap(), 0, ssl_locks);
309 #endif
312 BOOL NETCON_connected(WININET_NETCONNECTION *connection)
314 if (connection->socketFD == -1)
315 return FALSE;
316 else
317 return TRUE;
320 /* translate a unix error code into a winsock one */
321 int sock_get_error( int err )
323 #if !defined(__MINGW32__) && !defined (_MSC_VER)
324 switch (err)
326 case EINTR: return WSAEINTR;
327 case EBADF: return WSAEBADF;
328 case EPERM:
329 case EACCES: return WSAEACCES;
330 case EFAULT: return WSAEFAULT;
331 case EINVAL: return WSAEINVAL;
332 case EMFILE: return WSAEMFILE;
333 case EWOULDBLOCK: return WSAEWOULDBLOCK;
334 case EINPROGRESS: return WSAEINPROGRESS;
335 case EALREADY: return WSAEALREADY;
336 case ENOTSOCK: return WSAENOTSOCK;
337 case EDESTADDRREQ: return WSAEDESTADDRREQ;
338 case EMSGSIZE: return WSAEMSGSIZE;
339 case EPROTOTYPE: return WSAEPROTOTYPE;
340 case ENOPROTOOPT: return WSAENOPROTOOPT;
341 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
342 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
343 case EOPNOTSUPP: return WSAEOPNOTSUPP;
344 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
345 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
346 case EADDRINUSE: return WSAEADDRINUSE;
347 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
348 case ENETDOWN: return WSAENETDOWN;
349 case ENETUNREACH: return WSAENETUNREACH;
350 case ENETRESET: return WSAENETRESET;
351 case ECONNABORTED: return WSAECONNABORTED;
352 case EPIPE:
353 case ECONNRESET: return WSAECONNRESET;
354 case ENOBUFS: return WSAENOBUFS;
355 case EISCONN: return WSAEISCONN;
356 case ENOTCONN: return WSAENOTCONN;
357 case ESHUTDOWN: return WSAESHUTDOWN;
358 case ETOOMANYREFS: return WSAETOOMANYREFS;
359 case ETIMEDOUT: return WSAETIMEDOUT;
360 case ECONNREFUSED: return WSAECONNREFUSED;
361 case ELOOP: return WSAELOOP;
362 case ENAMETOOLONG: return WSAENAMETOOLONG;
363 case EHOSTDOWN: return WSAEHOSTDOWN;
364 case EHOSTUNREACH: return WSAEHOSTUNREACH;
365 case ENOTEMPTY: return WSAENOTEMPTY;
366 #ifdef EPROCLIM
367 case EPROCLIM: return WSAEPROCLIM;
368 #endif
369 #ifdef EUSERS
370 case EUSERS: return WSAEUSERS;
371 #endif
372 #ifdef EDQUOT
373 case EDQUOT: return WSAEDQUOT;
374 #endif
375 #ifdef ESTALE
376 case ESTALE: return WSAESTALE;
377 #endif
378 #ifdef EREMOTE
379 case EREMOTE: return WSAEREMOTE;
380 #endif
381 default: errno=err; perror("sock_set_error"); return WSAEFAULT;
383 #endif
384 return err;
387 /******************************************************************************
388 * NETCON_create
389 * Basically calls 'socket()'
391 DWORD NETCON_create(WININET_NETCONNECTION *connection, int domain,
392 int type, int protocol)
394 #ifdef SONAME_LIBSSL
395 if (connection->useSSL)
396 return ERROR_NOT_SUPPORTED;
397 #endif
399 connection->socketFD = socket(domain, type, protocol);
400 if (connection->socketFD == -1)
401 return sock_get_error(errno);
403 return ERROR_SUCCESS;
406 /******************************************************************************
407 * NETCON_close
408 * Basically calls 'close()' unless we should use SSL
410 DWORD NETCON_close(WININET_NETCONNECTION *connection)
412 int result;
414 if (!NETCON_connected(connection)) return ERROR_SUCCESS;
416 #ifdef SONAME_LIBSSL
417 if (connection->useSSL)
419 pSSL_shutdown(connection->ssl_s);
420 pSSL_free(connection->ssl_s);
421 connection->ssl_s = NULL;
423 connection->useSSL = FALSE;
425 #endif
427 result = closesocket(connection->socketFD);
428 connection->socketFD = -1;
430 if (result == -1)
431 return sock_get_error(errno);
432 return ERROR_SUCCESS;
434 #ifdef SONAME_LIBSSL
435 static BOOL check_hostname(X509 *cert, LPCWSTR hostname)
437 /* FIXME: implement */
438 return TRUE;
440 #endif
441 /******************************************************************************
442 * NETCON_secure_connect
443 * Initiates a secure connection over an existing plaintext connection.
445 DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
447 DWORD res = ERROR_NOT_SUPPORTED;
448 #ifdef SONAME_LIBSSL
449 long verify_res;
450 X509 *cert;
452 /* can't connect if we are already connected */
453 if (connection->useSSL)
455 ERR("already connected\n");
456 return ERROR_INTERNET_CANNOT_CONNECT;
459 connection->ssl_s = pSSL_new(ctx);
460 if (!connection->ssl_s)
462 ERR("SSL_new failed: %s\n",
463 pERR_error_string(pERR_get_error(), 0));
464 res = ERROR_OUTOFMEMORY;
465 goto fail;
468 if (!pSSL_set_fd(connection->ssl_s, connection->socketFD))
470 ERR("SSL_set_fd failed: %s\n",
471 pERR_error_string(pERR_get_error(), 0));
472 res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
473 goto fail;
476 if (pSSL_connect(connection->ssl_s) <= 0)
478 ERR("SSL_connect failed: %s\n",
479 pERR_error_string(pERR_get_error(), 0));
480 res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
481 goto fail;
483 pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname);
484 cert = pSSL_get_peer_certificate(connection->ssl_s);
485 if (!cert)
487 ERR("no certificate for server %s\n", debugstr_w(hostname));
488 /* FIXME: is this the best error? */
489 res = ERROR_INTERNET_INVALID_CA;
490 goto fail;
492 verify_res = pSSL_get_verify_result(connection->ssl_s);
493 if (verify_res != X509_V_OK)
495 ERR("couldn't verify the security of the connection, %ld\n", verify_res);
496 /* FIXME: we should set an error and return, but we only warn at
497 * the moment */
500 if (!check_hostname(cert, hostname))
502 res = ERROR_INTERNET_SEC_CERT_CN_INVALID;
503 goto fail;
506 connection->useSSL = TRUE;
507 return ERROR_SUCCESS;
509 fail:
510 if (connection->ssl_s)
512 pSSL_shutdown(connection->ssl_s);
513 pSSL_free(connection->ssl_s);
514 connection->ssl_s = NULL;
516 #endif
517 return res;
520 /******************************************************************************
521 * NETCON_connect
522 * Connects to the specified address.
524 DWORD NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
525 unsigned int addrlen)
527 int result;
529 result = connect(connection->socketFD, serv_addr, addrlen);
530 if (result == -1)
532 WARN("Unable to connect to host (%s)\n", strerror(errno));
534 closesocket(connection->socketFD);
535 connection->socketFD = -1;
536 return sock_get_error(errno);
539 return ERROR_SUCCESS;
542 /******************************************************************************
543 * NETCON_send
544 * Basically calls 'send()' unless we should use SSL
545 * number of chars send is put in *sent
547 DWORD NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
548 int *sent /* out */)
550 if (!NETCON_connected(connection)) return ERROR_INTERNET_CONNECTION_ABORTED;
551 if (!connection->useSSL)
553 *sent = send(connection->socketFD, msg, len, flags);
554 if (*sent == -1)
555 return sock_get_error(errno);
556 return ERROR_SUCCESS;
558 else
560 #ifdef SONAME_LIBSSL
561 if (flags)
562 FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
563 *sent = pSSL_write(connection->ssl_s, msg, len);
564 if (*sent < 1 && len)
565 return ERROR_INTERNET_CONNECTION_ABORTED;
566 return ERROR_SUCCESS;
567 #else
568 return ERROR_NOT_SUPPORTED;
569 #endif
573 /******************************************************************************
574 * NETCON_recv
575 * Basically calls 'recv()' unless we should use SSL
576 * number of chars received is put in *recvd
578 DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
579 int *recvd /* out */)
581 *recvd = 0;
582 if (!NETCON_connected(connection)) return ERROR_INTERNET_CONNECTION_ABORTED;
583 if (!len)
584 return ERROR_SUCCESS;
585 if (!connection->useSSL)
587 *recvd = recv(connection->socketFD, buf, len, flags);
588 return *recvd == -1 ? sock_get_error(errno) : ERROR_SUCCESS;
590 else
592 #ifdef SONAME_LIBSSL
593 *recvd = pSSL_read(connection->ssl_s, buf, len);
594 return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
595 #else
596 return ERROR_NOT_SUPPORTED;
597 #endif
601 /******************************************************************************
602 * NETCON_query_data_available
603 * Returns the number of bytes of peeked data plus the number of bytes of
604 * queued, but unread data.
606 BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available)
608 *available = 0;
609 if (!NETCON_connected(connection))
610 return FALSE;
612 if (!connection->useSSL)
614 #ifdef FIONREAD
615 int unread;
616 int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread);
617 if (!retval)
619 TRACE("%d bytes of queued, but unread data\n", unread);
620 *available += unread;
622 #endif
624 else
626 #ifdef SONAME_LIBSSL
627 *available = pSSL_pending(connection->ssl_s);
628 #endif
630 return TRUE;
633 LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection)
635 #ifdef SONAME_LIBSSL
636 X509* cert;
637 unsigned char* buffer,*p;
638 INT len;
639 BOOL malloced = FALSE;
640 LPCVOID r = NULL;
642 if (!connection->useSSL)
643 return NULL;
645 cert = pSSL_get_peer_certificate(connection->ssl_s);
646 p = NULL;
647 len = pi2d_X509(cert,&p);
649 * SSL 0.9.7 and above malloc the buffer if it is null.
650 * however earlier version do not and so we would need to alloc the buffer.
652 * see the i2d_X509 man page for more details.
654 if (!p)
656 buffer = HeapAlloc(GetProcessHeap(),0,len);
657 p = buffer;
658 len = pi2d_X509(cert,&p);
660 else
662 buffer = p;
663 malloced = TRUE;
666 r = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);
668 if (malloced)
669 free(buffer);
670 else
671 HeapFree(GetProcessHeap(),0,buffer);
673 return r;
674 #else
675 return NULL;
676 #endif
679 DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value)
681 int result;
682 struct timeval tv;
684 /* FIXME: we should probably store the timeout in the connection to set
685 * when we do connect */
686 if (!NETCON_connected(connection))
687 return ERROR_SUCCESS;
689 /* value is in milliseconds, convert to struct timeval */
690 tv.tv_sec = value / 1000;
691 tv.tv_usec = (value % 1000) * 1000;
693 result = setsockopt(connection->socketFD, SOL_SOCKET,
694 send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv,
695 sizeof(tv));
697 if (result == -1)
699 WARN("setsockopt failed (%s)\n", strerror(errno));
700 return sock_get_error(errno);
703 return ERROR_SUCCESS;