diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj index 5573140daa29..58af537555ce 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj +++ b/contrib/win32/openssh/win32iocompat.vcxproj @@ -328,6 +328,7 @@ + diff --git a/contrib/win32/openssh/win32iocompat.vcxproj.filters b/contrib/win32/openssh/win32iocompat.vcxproj.filters index c727e636bca0..c9ec6cd264ba 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj.filters +++ b/contrib/win32/openssh/win32iocompat.vcxproj.filters @@ -24,6 +24,7 @@ + diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index 2f62fa855478..84b1ec9eb220 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -106,6 +106,77 @@ errno_from_Win32Error(int win32_error) } } +/* return 1 if the file is native a unix socket, 0 otherwise + detail = 1: AF_UNIX + detail = 2: PIPE - this may fail, so treat any value other than 1 and 3 as PIPE + detail = 3: FILE + */ +int fileio_is_afunix_socket(const char* name, int* detail) +{ + wchar_t* name_w = utf8_to_utf16(name); + int ret = 0; + int type; + HANDLE h; + FILE_ATTRIBUTE_TAG_INFO info; + + if (name_w == NULL) + return 0; + + if (detail != NULL) + *detail = 0; + + h = CreateFileW(name_w, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, + NULL); + if (h == INVALID_HANDLE_VALUE) { + ret = 0; + debug("fileio_is_afunix_socket - ERROR: CreateFileW failed, error: 0x%08x", GetLastError()); + goto clean; + } + + if (GetFileInformationByHandleEx(h, FileAttributeTagInfo, &info, sizeof(info)) != FALSE) { + if (info.ReparseTag == IO_REPARSE_TAG_AF_UNIX) { + ret = 1; + if (detail != NULL) + *detail = 1; + goto clean; + } + }else{ + ret = 0; + debug("fileio_is_afunix_socket - ERROR: GetFileInformationByHandleEx failed, error: 0x%08x", GetLastError()); + } + + SetLastError(ERROR_SUCCESS); + type = GetFileType(h); + if(GetLastError() != ERROR_SUCCESS) { + ret = 0; + debug("fileio_is_afunix_socket - ERROR: GetFileType failed, error: 0x%08x", GetLastError()); + goto clean; + } + + if (type == FILE_TYPE_PIPE) { + ret = 0; + if (detail != NULL) + *detail = 2; + goto clean; + } else if (type == FILE_TYPE_DISK) { + ret = 0; + if (detail != NULL) + *detail = 3; + goto clean; + } + +clean: + if (name_w) + free(name_w); + if (h != INVALID_HANDLE_VALUE) + CloseHandle(h); + return ret; +} + struct w32_io* fileio_afunix_socket() { diff --git a/contrib/win32/win32compat/lxss.c b/contrib/win32/win32compat/lxss.c new file mode 100644 index 000000000000..02071ed94b28 --- /dev/null +++ b/contrib/win32/win32compat/lxss.c @@ -0,0 +1,92 @@ + +#include "w32fd.h" +#include "inc\utf.h" +#include "misc_internal.h" +#include "debug.h" + +#include +#include +#include + + +static const NTSTATUS STATUS_SUCCESS = 0; + +#define MAX_EA_INFO_SIZE 64 + +#pragma pack(push, 1) +typedef struct _FILE_FULL_EA_INFORMATION { + ULONG NextEntryOffset; + BYTE Flags; + BYTE EaNameLength; + USHORT EaValueLength; + CHAR EaName[1]; +} FILE_FULL_EA_INFORMATION, * PFILE_FULL_EA_INFORMATION; + +#pragma pack(pop) + +typedef +NTSTATUS +(NTAPI* NtSetEaFileFn)( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID EaBuffer, + IN ULONG EaBufferSize); + +struct ea_keyvalue { + const char* name; + const char* value; + ULONG value_len; +}; + +static void lxss_set_ea_info(wchar_t* path, char* buffer, ULONG length, int reparse){ + IO_STATUS_BLOCK ioStatus; + NTSTATUS r; + HMODULE hmod = GetModuleHandleW(L"ntdll.dll"); + if (hmod == NULL) + return; + NtSetEaFileFn NtSetEaFile = (NtSetEaFileFn)GetProcAddress(hmod, "NtSetEaFile"); + if (NtSetEaFile == NULL) + return; + HANDLE file = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | (reparse ? FILE_FLAG_OPEN_REPARSE_POINT : 0), NULL); + if (file == INVALID_HANDLE_VALUE) + return; + + r = NtSetEaFile(file, &ioStatus, buffer, length); + if (r != STATUS_SUCCESS) + return; + CloseHandle(file); +} + +void lxss_set_perm(wchar_t* path, int reparse, ULONG uid, ULONG gid, ULONG mode){ + struct ea_keyvalue** p; + struct ea_keyvalue* ea[4]; // ** + int count = 0; + struct ea_keyvalue uid_ea = {"$LXUID", (char*)&uid, sizeof(uid)}; + struct ea_keyvalue gid_ea = {"$LXGID", (char*)&gid, sizeof(gid)}; + struct ea_keyvalue mode_ea = {"$LXMOD", (char*)&mode, sizeof(mode)}; + FILE_FULL_EA_INFORMATION* ea_info = NULL; + ea[0] = &uid_ea; + ea[1] = &gid_ea; + ea[2] = &mode_ea; + ea[3] = NULL; + __declspec(align(16)) char buffer[MAX_EA_INFO_SIZE * sizeof(ea) / sizeof(ea[0])]; + char *pb = buffer; + + for (p = ea; *p != NULL; p++) { + ea_info = (FILE_FULL_EA_INFORMATION*)pb; + ea_info->NextEntryOffset = MAX_EA_INFO_SIZE; + ea_info->Flags = 0; + ea_info->EaNameLength = (BYTE)strlen((*p)->name); + ea_info->EaValueLength = (USHORT)(*p)->value_len; + memcpy(ea_info->EaName, (*p)->name, ea_info->EaNameLength); + memcpy(ea_info->EaName + ea_info->EaNameLength, (*p)->value, (*p)->value_len); + pb += MAX_EA_INFO_SIZE; + ++count; + } + // mark last info + if (ea_info) + ea_info->NextEntryOffset = 0; + lxss_set_ea_info(path, buffer, count * MAX_EA_INFO_SIZE, reparse); +} diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index 861ee2d585e4..2743f0a04bdd 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -955,6 +955,8 @@ realpath(const char *inputpath, char * resolved) { wchar_t* temppath_utf16 = NULL; wchar_t* resolved_utf16 = NULL; + DWORD temppath_len = 0; + char* temppath_utf8 = NULL; char path[PATH_MAX] = { 0, }, tempPath[PATH_MAX] = { 0, }, *ret = NULL; int is_win_path = 1; @@ -972,6 +974,25 @@ realpath(const char *inputpath, char * resolved) if (is_bash_test_env() && bash_to_win_path(inputpath, path, _countof(path))) is_win_path = 0; + if (_strnicmp(inputpath, TMP_DIR, strlen(TMP_DIR)) == 0) { + /* if input path is TMP_DIR, replace TMP_DIR with GetTempPath() */ + temppath_utf16 = malloc(sizeof(wchar_t) * MAX_PATH + 1); + temppath_len = GetTempPathW(MAX_PATH, temppath_utf16); + if (temppath_len > 0 && temppath_len < MAX_PATH) + { + temppath_utf8 = utf16_to_utf8(temppath_utf16); + if (temppath_utf8 != NULL) + { + strcpy_s(path, PATH_MAX, temppath_utf8); + strcat_s(path, PATH_MAX, &inputpath[strlen(TMP_DIR)]); + is_win_path = 0; + free(temppath_utf8); + } + } + free(temppath_utf16); + temppath_utf16 = NULL; + } + if (is_win_path) { if (_strnicmp(inputpath, PROGRAM_DATA, strlen(PROGRAM_DATA)) == 0) { strcpy_s(path, PATH_MAX, __progdata); diff --git a/contrib/win32/win32compat/misc_internal.h b/contrib/win32/win32compat/misc_internal.h index 5a43a992e820..a27d01b96aa3 100644 --- a/contrib/win32/win32compat/misc_internal.h +++ b/contrib/win32/win32compat/misc_internal.h @@ -12,6 +12,8 @@ #define NULL_DEVICE "/dev/null" #define NULL_DEVICE_WIN "NUL" +#define TMP_DIR "/tmp/" + #define IsWin7OrLess() (!IsWindows8OrGreater()) #define IS_INVALID_HANDLE(h) ( ((NULL == h) || (INVALID_HANDLE_VALUE == h)) ? 1 : 0 ) diff --git a/contrib/win32/win32compat/socketio.c b/contrib/win32/win32compat/socketio.c index c4eceaea8f71..f49a584ff52a 100644 --- a/contrib/win32/win32compat/socketio.c +++ b/contrib/win32/win32compat/socketio.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "w32fd.h" #include "inc\utf.h" #include "misc_internal.h" @@ -43,6 +44,17 @@ #define INTERNAL_RECV_BUFFER_SIZE 70*1024 //70KB #define errno_from_WSALastError() errno_from_WSAError(WSAGetLastError()) +#define CHECK_NAMEDPIPE(pio, retv) do { \ + errno = 0; \ + if (pio->internal.subtype == SOCKET_SUBTYPE_NAMEDPIPE) { \ + errno = ENOTSUP; \ + debug(__FILE__ ":%d: Named pipes are not supported", __LINE__); \ + return retv; \ + } \ +} while (0) + +void lxss_set_perm(wchar_t* path, int reparse, ULONG uid, ULONG gid, ULONG mode); + /* state info that needs to be persisted for an inprocess acceptEx call*/ struct acceptEx_context { char lpOutputBuf[1024]; @@ -83,6 +95,70 @@ errno_from_WSAError(int wsaerrno) } } +static int +socketio_parse_assuan(const char* path, struct sockaddr_in* addr, char* nonce) +{ + int port; + FILE* fp = fopen(path, "rb"); + if (fp == NULL) { + errno = EINVAL; + error("connect: assuan - ERROR: fopen failed:%d", errno); + return -1; + } + fscanf(fp, "%d", &port); + fgetc(fp); // skip \n + if (fread(nonce, 1, 16, fp) != 16) { + errno = EINVAL; + error("connect: assuan - ERROR: invalid nonce"); + fclose(fp); + return -1; + } + fclose(fp); + addr->sin_family = AF_INET; + addr->sin_port = htons(port); + addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + debug("connect: assuan - parsed: port:%d, nonce:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + port, (unsigned char)nonce[0], (unsigned char)nonce[1], (unsigned char)nonce[2], + (unsigned char)nonce[3], (unsigned char)nonce[4], (unsigned char)nonce[5], + (unsigned char)nonce[6], (unsigned char)nonce[7], (unsigned char)nonce[8], + (unsigned char)nonce[9], (unsigned char)nonce[10], (unsigned char)nonce[11], + (unsigned char)nonce[12], (unsigned char)nonce[13], (unsigned char)nonce[14], + (unsigned char)nonce[15]); + return 0; +} + +static void +socketio_fixup_sun_addr(const struct sockaddr_un* orig, struct sockaddr_un* out) +{ + memcpy(out, orig, sizeof(struct sockaddr_un)); + char* resolved; + size_t resolved_len; + if (strncmp(orig->sun_path, "/nt:", 4) == 0) { + /* this is a special windows path used in forward spec + strip this prefix */ + memcpy(out->sun_path, orig->sun_path + 4, sizeof(out->sun_path) - 4); + memset(out->sun_path + sizeof(out->sun_path) - 4, 0, 4); + } else if (strncmp(orig->sun_path, "\\\\?\\", 4 ) == 0 || + strncmp(orig->sun_path, "\\\\.\\", 4) == 0) { + /* if it starts with \\.\ or \\?\, + leave it as-is (default agent NamedPipe path) */ + return; + } else { + /* resolve the path */ + resolved = resolved_path_utf8(orig->sun_path); + if (resolved) + { + resolved_len = strlen(resolved); + if (resolved_len < sizeof(out->sun_path)) + { + /* replace out->sun_path */ + strcpy_s(out->sun_path, sizeof(out->sun_path), resolved); + } + free(resolved); + } + } +} + /* called before any other calls to socketio_ functions */ int socketio_initialize() @@ -118,7 +194,7 @@ socketio_acceptEx(struct w32_io* pio) } /* create accepting socket */ - context->accept_socket = socket(addr.ss_family, SOCK_STREAM, IPPROTO_TCP); + context->accept_socket = socket(addr.ss_family, SOCK_STREAM, addr.ss_family == AF_UNIX ? 0 : IPPROTO_TCP); if (context->accept_socket == INVALID_SOCKET) { errno = errno_from_WSALastError(); debug3("acceptEx - socket() ERROR:%d, io:%p", WSAGetLastError(), pio); @@ -257,6 +333,7 @@ socketio_socket(int domain, int type, int protocol) int socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval, int optlen) { + CHECK_NAMEDPIPE(pio, -1); if ((optname == SO_KEEPALIVE) || (optname == SO_REUSEADDR) || (optname == TCP_NODELAY) || (optname == IPV6_V6ONLY)) SET_ERRNO_ON_ERROR(setsockopt(pio->sock, level, optname, optval, optlen)); @@ -271,6 +348,7 @@ socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optv int socketio_getsockopt(struct w32_io* pio, int level, int optname, char* optval, int* optlen) { + CHECK_NAMEDPIPE(pio, -1); SET_ERRNO_ON_ERROR(getsockopt(pio->sock, level, optname, optval, optlen)); } @@ -278,6 +356,7 @@ socketio_getsockopt(struct w32_io* pio, int level, int optname, char* optval, in int socketio_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen) { + CHECK_NAMEDPIPE(pio, -1); SET_ERRNO_ON_ERROR(getsockname(pio->sock, name, namelen)); } @@ -285,6 +364,7 @@ socketio_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen) int socketio_getpeername(struct w32_io* pio, struct sockaddr* name, int* namelen) { + CHECK_NAMEDPIPE(pio, -1); SET_ERRNO_ON_ERROR(getpeername(pio->sock, name, namelen)); } @@ -294,6 +374,10 @@ socketio_listen(struct w32_io* pio, int backlog) { struct acceptEx_context* context; + if (pio->internal.subtype == SOCKET_SUBTYPE_UNKNOWN) + pio->internal.subtype = SOCKET_SUBTYPE_GENERIC; + CHECK_NAMEDPIPE(pio, -1); + if (SOCKET_ERROR == listen(pio->sock, backlog)) { errno = errno_from_WSALastError(); debug3("listen - listen() ERROR:%d io:%p", WSAGetLastError(), pio); @@ -355,6 +439,26 @@ socketio_listen(struct w32_io* pio, int backlog) int socketio_bind(struct w32_io* pio, const struct sockaddr *name, int namelen) { + struct sockaddr_un sun_addr; + wchar_t *w_path; + if (pio->internal.subtype == SOCKET_SUBTYPE_UNKNOWN) + pio->internal.subtype = SOCKET_SUBTYPE_GENERIC; + CHECK_NAMEDPIPE(pio, -1); + + if (name->sa_family == AF_UNIX) { + socketio_fixup_sun_addr((const struct sockaddr_un*)name, &sun_addr); + name = (struct sockaddr*)&sun_addr; + namelen = sizeof(struct sockaddr_un); + + w_path = utf8_to_utf16(sun_addr.sun_path); + if (w_path) { + // set Lxss Permission Info + // uid(1000), gid(1000), mode(0700) + lxss_set_perm(w_path, TRUE, 1000, 1000, 0700); + free(w_path); + } + } + SET_ERRNO_ON_ERROR(bind(pio->sock, name, namelen)); } @@ -378,6 +482,10 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) return -1; } + if (pio->internal.subtype == SOCKET_SUBTYPE_NAMEDPIPE) { + return fileio_read(pio->internal.proxy_io, buf, len); + } + /* TODO - ensure socket is in accepted or connected state */ /* /io is initiated and pending */ if (pio->read_details.pending) { @@ -533,6 +641,10 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) return -1; } + if (pio->internal.subtype == SOCKET_SUBTYPE_NAMEDPIPE) { + return fileio_write_wrapper(pio->internal.proxy_io, buf, len); + } + /* TODO - ensure socket is in accepted or connected state */ /* if io is already pending */ if (pio->write_details.pending) { @@ -623,6 +735,8 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) int socketio_shutdown(struct w32_io* pio, int how) { + if (pio->internal.subtype == SOCKET_SUBTYPE_NAMEDPIPE) + return 0; /* named pipe does not support it */ SET_ERRNO_ON_ERROR(shutdown(pio->sock, how)); } @@ -631,6 +745,9 @@ int socketio_close(struct w32_io* pio) { debug4("close - io:%p", pio); + if (pio->internal.subtype == SOCKET_SUBTYPE_NAMEDPIPE) { + fileio_close(pio->internal.proxy_io); + } closesocket(pio->sock); /* wait for pending io to abort */ SleepEx(0, TRUE); @@ -675,6 +792,8 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen) int local_address_len, remote_address_len; errno_t r = 0; + CHECK_NAMEDPIPE(pio, NULL); + debug5("accept - io:%p", pio); /* start io if not already started */ if (pio->read_details.pending == FALSE) { @@ -759,6 +878,7 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen) struct sockaddr_in tmp_addr4; struct sockaddr_in6 tmp_addr6; + struct sockaddr_un tmp_un; SOCKADDR* tmp_addr; size_t tmp_addr_len; DWORD tmp_bytes; @@ -778,6 +898,11 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen) tmp_addr4.sin_port = 0; tmp_addr = (SOCKADDR*)&tmp_addr4; tmp_addr_len = sizeof(tmp_addr4); + } else if (name->sa_family == AF_UNIX) { + ZeroMemory(&tmp_un, sizeof(tmp_un)); + tmp_un.sun_family = AF_UNIX; + tmp_addr = (SOCKADDR*)&tmp_un; + tmp_addr_len = sizeof(tmp_un); } else { errno = ENOTSUP; debug3("connectex - ERROR: unsuppored address family:%d, io:%p", name->sa_family, pio); @@ -832,10 +957,71 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen) return 0; } + /* connect implementation */ int socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen) { + int detail = 0; + struct sockaddr_in synth_addr; + struct sockaddr_un sun_addr; + + if (pio->internal.subtype == SOCKET_SUBTYPE_UNKNOWN) + { + if (name->sa_family == AF_UNIX) + { + if (namelen < sizeof(struct sockaddr_un)) + { + errno = EINVAL; + debug("connect - ERROR: invalid sockaddr_un, io:%p", pio); + return -1; + } + + const struct sockaddr_un* sun = (const struct sockaddr_un*)name; + socketio_fixup_sun_addr(sun, &sun_addr); + name = (const struct sockaddr*)&sun_addr; + namelen = sizeof(sun_addr); + sun = (const struct sockaddr_un*)&sun_addr; + + if (fileio_is_afunix_socket(sun->sun_path, &detail)) { + pio->internal.subtype = SOCKET_SUBTYPE_GENERIC; + debug("connect - AF_UNIX socket, path:%s", sun->sun_path); + } else { + if (detail == 3) { + // parse assuan file + debug("connect - AF_UNIX assuan file, path:%s", sun->sun_path); + if (-1 == socketio_parse_assuan(sun->sun_path, &synth_addr, pio->internal.assuan_nonce)) { + errno = EINVAL; + debug("connect: assuan - ERROR: parse assuan file failed:%d, io:%p", errno, pio); + return -1; + } + pio->internal.subtype = SOCKET_SUBTYPE_ASSUAN; + // replace socket + closesocket(pio->sock); + pio->sock = socket(AF_INET, SOCK_STREAM, 0); + if (pio->sock == INVALID_SOCKET) { + errno = WSAGetLastError(); + debug("connect - ERROR: socket failed:%d, io:%p", WSAGetLastError(), pio); + return -1; + } + name = (const struct sockaddr*)&synth_addr; + namelen = sizeof(synth_addr); + } else { + debug("connect - AF_UNIX named pipe, path:%s", sun->sun_path); + pio->internal.subtype = SOCKET_SUBTYPE_NAMEDPIPE; + pio->internal.proxy_io = fileio_afunix_socket(); + if (pio->internal.proxy_io == NULL) { + errno = ENOMEM; + debug("connect - ERROR: out of memory for named pipe, io:%p", pio); + return -1; + } + return fileio_connect(pio->internal.proxy_io, sun->sun_path); + } + } + } else { + pio->internal.subtype = SOCKET_SUBTYPE_GENERIC; + } + } debug5("connect - io:%p", pio); if (pio->write_details.pending == FALSE) { @@ -892,6 +1078,19 @@ socketio_finish_connect(struct w32_io* pio) ZeroMemory(&pio->write_details, sizeof(pio->write_details)); pio->internal.state = SOCK_READY; + + if (!wsa_error) { + // connected + if (pio->internal.subtype == SOCKET_SUBTYPE_ASSUAN) { + // send assuan nonce + if (-1 == socketio_send(pio, pio->internal.assuan_nonce, sizeof(pio->internal.assuan_nonce), 0)) { + wsa_error = WSAGetLastError(); + debug3("finish_connect - ERROR: send assuan nonce failed:%d, io:%p", wsa_error, pio); + goto done; + } + } + } + return (wsa_error? -1 : 0); } @@ -899,6 +1098,10 @@ socketio_finish_connect(struct w32_io* pio) BOOL socketio_is_io_available(struct w32_io* pio, BOOL rd) { + if (pio->internal.subtype == SOCKET_SUBTYPE_NAMEDPIPE && pio->internal.proxy_io) { + return fileio_is_io_available(pio->internal.proxy_io, rd); + } + if ((pio->internal.state == SOCK_LISTENING) || (pio->internal.state == SOCK_CONNECTING)) { DWORD numBytes = 0; @@ -943,6 +1146,12 @@ void socketio_on_select(struct w32_io* pio, BOOL rd) { enum w32_io_sock_state sock_state = pio->internal.state; + + if (pio->internal.subtype == SOCKET_SUBTYPE_NAMEDPIPE) { + fileio_on_select(pio->internal.proxy_io, rd); + return; + } + debug4("on_select - io:%p type:%d rd:%d", pio, pio->type, rd); /* nothing to do for writes (that includes connect) */ diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index b4c436864dc4..b341bf099499 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -316,17 +316,11 @@ w32_socket(int domain, int type, int protocol) if (min_index == -1) return -1; - if (domain == AF_UNIX && type == SOCK_STREAM) { - pio = fileio_afunix_socket(); - if (pio == NULL) - return -1; - pio->type = NONSOCK_FD; - } else { - pio = socketio_socket(domain, type, protocol); - if (pio == NULL) - return -1; - pio->type = SOCK_FD; - } + pio = socketio_socket(domain, type, protocol); + if (pio == NULL) + return -1; + pio->type = SOCK_FD; + pio->internal.subtype = SOCKET_SUBTYPE_UNKNOWN; fd_table_set(pio, min_index); debug4("socket:%d, socktype:%d, io:%p, fd:%d ", pio->sock, type, pio, min_index); @@ -344,12 +338,6 @@ w32_accept(int fd, struct sockaddr* addr, int* addrlen) if (min_index == -1) return -1; - if (fd_table.w32_ios[fd]->type == NONSOCK_FD) { - errno = ENOTSUP; - verbose("Unix domain server sockets are not supported"); - return -1; - } - pio = socketio_accept(fd_table.w32_ios[fd], addr, addrlen); if (!pio) return -1; @@ -410,12 +398,6 @@ int w32_bind(int fd, const struct sockaddr *name, int namelen) { CHECK_FD(fd); - if (fd_table.w32_ios[fd]->type == NONSOCK_FD) { - errno = ENOTSUP; - verbose("Unix domain server sockets are not supported"); - return -1; - } - CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_bind(fd_table.w32_ios[fd], name, namelen); } @@ -424,12 +406,6 @@ int w32_connect(int fd, const struct sockaddr* name, int namelen) { CHECK_FD(fd); - - if (fd_table.w32_ios[fd]->type == NONSOCK_FD) { - struct sockaddr_un* addr = (struct sockaddr_un*)name; - return fileio_connect(fd_table.w32_ios[fd], addr->sun_path); - } - CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_connect(fd_table.w32_ios[fd], name, namelen); } @@ -438,7 +414,6 @@ int w32_recv(int fd, void *buf, size_t len, int flags) { CHECK_FD(fd); - CHECK_SOCK_IO(fd_table.w32_ios[fd]); return socketio_recv(fd_table.w32_ios[fd], buf, len, flags); } @@ -688,6 +663,9 @@ w32_io_process_fd_flags(struct w32_io* pio, int flags) } pio->fd_flags = flags; + if (pio->type == SOCK_FD && pio->internal.subtype == SOCKET_SUBTYPE_NAMEDPIPE) { + return w32_io_process_fd_flags(pio->internal.proxy_io, flags); + } return 0; } diff --git a/contrib/win32/win32compat/w32fd.h b/contrib/win32/win32compat/w32fd.h index 0f1ee3a08f62..4244c85e0063 100644 --- a/contrib/win32/win32compat/w32fd.h +++ b/contrib/win32/win32compat/w32fd.h @@ -65,10 +65,18 @@ enum w32_io_sock_state { SOCK_READY = 3 /*recv and send can be done*/ }; +enum w32_io_sock_subtype { + SOCKET_SUBTYPE_UNKNOWN = 0, + SOCKET_SUBTYPE_GENERIC = 1, + SOCKET_SUBTYPE_NAMEDPIPE = 2, + SOCKET_SUBTYPE_ASSUAN = 3 +}; + /* * This structure encapsulates the I/O state info needed to map a File Descriptor * to Win32 Handle */ +struct w32_io; struct w32_io { OVERLAPPED read_overlapped; OVERLAPPED write_overlapped; @@ -118,6 +126,11 @@ struct w32_io { struct { enum w32_io_sock_state state; void* context; + + enum w32_io_sock_subtype subtype; + struct w32_io* proxy_io; + char assuan_nonce[16]; + int assuan_nonce_sent; }internal; }; @@ -167,4 +180,5 @@ long fileio_lseek(struct w32_io* pio, unsigned __int64 offset, int origin); FILE* fileio_fdopen(struct w32_io* pio, const char *mode); ssize_t fileio_readlink(const char *path, char *buf, size_t bufsiz); int fileio_symlink(const char *target, const char *linkpath); -int fileio_link(const char *oldpath, const char *newpath); \ No newline at end of file +int fileio_link(const char *oldpath, const char *newpath); +int fileio_is_afunix_socket(const char* name, int* detail);