2 * Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 * This file is part of Assuan.
6 * Assuan is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * Assuan is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #ifdef HAVE_W32_SYSTEM
24 #define WIN32_LEAN_AND_MEAN
29 #include <sys/types.h>
30 #include <sys/socket.h>
37 #include "assuan-defs.h"
39 /* Hacks for Slowaris. */
42 # define PF_LOCAL PF_UNIX
44 # define PF_LOCAL AF_UNIX
48 # define AF_LOCAL AF_UNIX
51 #ifdef HAVE_W32_SYSTEM
59 #ifdef HAVE_W32_SYSTEM
61 _assuan_sock_wsa2errno (int err
)
69 case ERROR_BROKEN_PIPE
:
71 case WSANOTINITIALISED
:
79 /* W32: Fill BUFFER with LENGTH bytes of random. Returns -1 on
80 failure, 0 on success. Sets errno on failure. */
82 get_nonce (char *buffer
, size_t nbytes
)
87 if (!CryptAcquireContext (&prov
, NULL
, NULL
, PROV_RSA_FULL
,
88 (CRYPT_VERIFYCONTEXT
|CRYPT_SILENT
)) )
92 if (!CryptGenRandom (prov
, nbytes
, buffer
))
96 CryptReleaseContext (prov
, 0);
102 /* W32: The buffer for NONCE needs to be at least 16 bytes. Returns 0 on
103 success and sets errno on failure. */
105 read_port_and_nonce (const char *fname
, unsigned short *port
, char *nonce
)
112 fp
= fopen (fname
, "rb");
115 nread
= fread (buffer
, 1, sizeof buffer
- 1, fp
);
123 aval
= atoi (buffer
);
124 if (aval
< 1 || aval
> 65535)
129 *port
= (unsigned int)aval
;
130 for (p
=buffer
; nread
&& *p
!= '\n'; p
++, nread
--)
132 if (*p
!= '\n' || nread
!= 17)
138 memcpy (nonce
, p
, 16);
141 #endif /*HAVE_W32_SYSTEM*/
146 _assuan_close (assuan_fd_t fd
)
148 #ifdef HAVE_W32_SYSTEM
149 int rc
= closesocket (HANDLE2SOCKET(fd
));
151 errno
= _assuan_sock_wsa2errno (WSAGetLastError ());
152 if (rc
&& WSAGetLastError () == WSAENOTSOCK
)
154 rc
= CloseHandle (fd
);
166 /* Return a new socket. Note that under W32 we consider a socket the
167 same as an System Handle; all functions using such a handle know
168 about this dual use and act accordingly. */
170 _assuan_sock_new (int domain
, int type
, int proto
)
172 #ifdef HAVE_W32_SYSTEM
174 if (domain
== AF_UNIX
|| domain
== AF_LOCAL
)
176 res
= SOCKET2HANDLE(socket (domain
, type
, proto
));
177 if (res
== ASSUAN_INVALID_FD
)
178 errno
= _assuan_sock_wsa2errno (WSAGetLastError ());
181 return socket (domain
, type
, proto
);
187 _assuan_sock_connect (assuan_fd_t sockfd
, struct sockaddr
*addr
, int addrlen
)
189 #ifdef HAVE_W32_SYSTEM
190 if (addr
->sa_family
== AF_LOCAL
|| addr
->sa_family
== AF_UNIX
)
192 struct sockaddr_in myaddr
;
193 struct sockaddr_un
*unaddr
;
198 unaddr
= (struct sockaddr_un
*)addr
;
199 if (read_port_and_nonce (unaddr
->sun_path
, &port
, nonce
))
202 myaddr
.sin_family
= AF_INET
;
203 myaddr
.sin_port
= htons (port
);
204 myaddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
206 /* Set return values. */
207 unaddr
->sun_family
= myaddr
.sin_family
;
208 unaddr
->sun_port
= myaddr
.sin_port
;
209 unaddr
->sun_addr
.s_addr
= myaddr
.sin_addr
.s_addr
;
211 ret
= connect (HANDLE2SOCKET(sockfd
),
212 (struct sockaddr
*)&myaddr
, sizeof myaddr
);
215 /* Send the nonce. */
216 ret
= _assuan_io_write (sockfd
, nonce
, 16);
217 if (ret
>= 0 && ret
!= 16)
228 res
= connect (HANDLE2SOCKET (sockfd
), addr
, addrlen
);
230 errno
= _assuan_sock_wsa2errno (WSAGetLastError ());
234 return connect (sockfd
, addr
, addrlen
);
240 _assuan_sock_bind (assuan_fd_t sockfd
, struct sockaddr
*addr
, int addrlen
)
242 #ifdef HAVE_W32_SYSTEM
243 if (addr
->sa_family
== AF_LOCAL
|| addr
->sa_family
== AF_UNIX
)
245 struct sockaddr_in myaddr
;
246 struct sockaddr_un
*unaddr
;
249 int len
= sizeof myaddr
;
253 if (get_nonce (nonce
, 16))
256 unaddr
= (struct sockaddr_un
*)addr
;
259 myaddr
.sin_family
= AF_INET
;
260 myaddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
262 filefd
= open (unaddr
->sun_path
,
263 (O_WRONLY
|O_CREAT
|O_EXCL
|O_BINARY
),
264 (S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
));
268 errno
= WSAEADDRINUSE
;
271 fp
= fdopen (filefd
, "wb");
280 rc
= bind (HANDLE2SOCKET (sockfd
), (struct sockaddr
*)&myaddr
, len
);
282 rc
= getsockname (HANDLE2SOCKET (sockfd
),
283 (struct sockaddr
*)&myaddr
, &len
);
288 remove (unaddr
->sun_path
);
292 fprintf (fp
, "%d\n", ntohs (myaddr
.sin_port
));
293 fwrite (nonce
, 16, 1, fp
);
300 int res
= bind (HANDLE2SOCKET(sockfd
), addr
, addrlen
);
302 errno
= _assuan_sock_wsa2errno (WSAGetLastError ());
306 return bind (sockfd
, addr
, addrlen
);
312 _assuan_sock_get_nonce (struct sockaddr
*addr
, int addrlen
,
313 assuan_sock_nonce_t
*nonce
)
315 #ifdef HAVE_W32_SYSTEM
316 if (addr
->sa_family
== AF_LOCAL
|| addr
->sa_family
== AF_UNIX
)
318 struct sockaddr_un
*unaddr
;
321 if (sizeof nonce
->nonce
!= 16)
327 unaddr
= (struct sockaddr_un
*)addr
;
328 if (read_port_and_nonce (unaddr
->sun_path
, &port
, nonce
->nonce
))
333 nonce
->length
= 42; /* Arbitrary valuie to detect unitialized nonce. */
334 nonce
->nonce
[0] = 42;
346 _assuan_sock_check_nonce (assuan_fd_t fd
, assuan_sock_nonce_t
*nonce
)
348 #ifdef HAVE_W32_SYSTEM
353 if (sizeof nonce
->nonce
!= 16)
359 if (nonce
->length
== 42 && nonce
->nonce
[0] == 42)
360 return 0; /* Not a Unix domain socket. */
362 if (nonce
->length
!= 16)
372 n
= _assuan_io_read (SOCKET2HANDLE(fd
), p
, nleft
);
373 if (n
< 0 && errno
== EINTR
)
375 else if (n
< 0 && errno
== EAGAIN
)
390 if (memcmp (buffer
, nonce
->nonce
, 16))
405 assuan_sock_close (assuan_fd_t fd
)
407 return _assuan_close (fd
);
411 assuan_sock_new (int domain
, int type
, int proto
)
413 return _assuan_sock_new (domain
, type
, proto
);
417 assuan_sock_connect (assuan_fd_t sockfd
, struct sockaddr
*addr
, int addrlen
)
419 return _assuan_sock_connect (sockfd
, addr
, addrlen
);
423 assuan_sock_bind (assuan_fd_t sockfd
, struct sockaddr
*addr
, int addrlen
)
425 return _assuan_sock_bind (sockfd
, addr
, addrlen
);
429 assuan_sock_get_nonce (struct sockaddr
*addr
, int addrlen
,
430 assuan_sock_nonce_t
*nonce
)
432 return _assuan_sock_get_nonce (addr
, addrlen
, nonce
);
436 assuan_sock_check_nonce (assuan_fd_t fd
, assuan_sock_nonce_t
*nonce
)
438 return _assuan_sock_check_nonce (fd
, nonce
);