Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F26446729
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
17 KB
Subscribers
None
View Options
diff --git a/src/assuan-socket-connect.c b/src/assuan-socket-connect.c
index 019a41c..457edfe 100644
--- a/src/assuan-socket-connect.c
+++ b/src/assuan-socket-connect.c
@@ -1,349 +1,373 @@
/* assuan-socket-connect.c - Assuan socket based client
* Copyright (C) 2002, 2003, 2004, 2009 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
* SPDX-License-Identifier: LGPL-2.1+
*/
#include <config.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_W32_SYSTEM
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# include <windows.h>
#else
# include <sys/socket.h>
# include <sys/un.h>
# include <netinet/in.h>
# include <arpa/inet.h>
#endif
#include "assuan-defs.h"
#include "debug.h"
/* Hacks for Slowaris. */
#ifndef PF_LOCAL
# ifdef PF_UNIX
# define PF_LOCAL PF_UNIX
# else
# define PF_LOCAL AF_UNIX
# endif
#endif
#ifndef AF_LOCAL
# define AF_LOCAL AF_UNIX
#endif
#ifndef INADDR_NONE
#define INADDR_NONE ((unsigned long)(-1))
#endif /*INADDR_NONE*/
#ifndef SUN_LEN
# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+ strlen ((ptr)->sun_path))
#endif
#undef WITH_IPV6
#if defined (AF_INET6) && defined(PF_INET) \
&& defined (INET6_ADDRSTRLEN) && defined(HAVE_INET_PTON)
# define WITH_IPV6 1
#endif
/* Returns true if STR represents a valid port number in decimal
* notation and no garbage is following. */
static int
parse_portno (const char *str, uint16_t *r_port)
{
unsigned int value;
for (value=0; *str && (*str >= '0' && *str <= '9'); str++)
{
value = value * 10 + (*str - '0');
if (value > 65535)
return 0;
}
if (*str || !value)
return 0;
*r_port = value;
return 1;
}
static gpg_error_t
_assuan_connect_finalize (assuan_context_t ctx, assuan_fd_t fd,
unsigned int flags)
{
gpg_error_t err;
ctx->engine.release = _assuan_client_release;
ctx->engine.readfnc = _assuan_simple_read;
ctx->engine.writefnc = _assuan_simple_write;
ctx->engine.sendfd = NULL;
ctx->engine.receivefd = NULL;
ctx->finish_handler = _assuan_client_finish;
ctx->inbound.fd = fd;
ctx->outbound.fd = fd;
ctx->max_accepts = -1;
ctx->flags.is_socket = 1;
+#ifdef HAVE_W32_SYSTEM
+ ctx->engine.sendfd = w32_fdpass_send;
+#else
if (flags & ASSUAN_SOCKET_CONNECT_FDPASSING)
_assuan_init_uds_io (ctx);
+#endif
/* initial handshake */
{
assuan_response_t response;
int off;
err = _assuan_read_from_server (ctx, &response, &off, 0);
if (err)
TRACE1 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect", ctx,
"can't connect to server: %s\n", gpg_strerror (err));
- else if (response != ASSUAN_RESPONSE_OK)
+ else if (response == ASSUAN_RESPONSE_OK)
+ {
+ const char *line = ctx->inbound.line + off;
+ int pid = ASSUAN_INVALID_PID;
+
+ /* Parse the message: OK ..., process %i */
+ line = strchr (line, ',');
+ if (line)
+ {
+ line = strchr (line + 1, ' ');
+ if (line)
+ {
+ line = strchr (line + 1, ' ');
+ if (line)
+ pid = atoi (line + 1);
+ }
+ }
+ if (pid != ASSUAN_INVALID_PID)
+ ctx->pid = pid;
+ }
+ else
{
char *sname = _assuan_encode_c_string (ctx, ctx->inbound.line);
if (sname)
{
TRACE1 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect", ctx,
"can't connect to server: %s", sname);
_assuan_free (ctx, sname);
}
err = _assuan_error (ctx, GPG_ERR_ASS_CONNECT_FAILED);
}
}
return err;
}
/* Attach an existing connected file descriptor FD to an allocated handle CTX
* and initialize the connection.
*/
gpg_error_t
assuan_socket_connect_fd (assuan_context_t ctx, assuan_fd_t fd,
unsigned int flags)
{
gpg_error_t err;
if (!ctx)
return GPG_ERR_INV_ARG;
if (fd == ASSUAN_INVALID_FD)
return GPG_ERR_INV_ARG;
err = _assuan_connect_finalize (ctx, fd, flags);
if (err)
_assuan_reset (ctx);
return err;
}
/* Make a connection to the Unix domain socket NAME and return a new
* Assuan context in CTX. SERVER_PID is currently not used but may
* become handy in the future. Defined flag bits are:
*
* ASSUAN_SOCKET_CONNECT_FDPASSING
* sendmsg and recvmsg are used.
*
* NAME must either start with a slash and optional with a drive
* prefix ("c:") or use one of these URL schemata:
*
* file://<fname>
*
* This is the same as the default just with an explicit schemata.
*
* assuan://<ipaddr>:<port>
* assuan://[<ip6addr>]:<port>
*
* Connect using TCP to PORT of the server with the numerical
* IPADDR. Note that '[' and ']' are literal characters.
*/
gpg_error_t
assuan_socket_connect (assuan_context_t ctx, const char *name,
pid_t server_pid, unsigned int flags)
{
gpg_error_t err = 0;
assuan_fd_t fd;
#ifdef WITH_IPV6
struct sockaddr_in6 srvr_addr_in6;
#endif
struct sockaddr_un srvr_addr_un;
struct sockaddr_in srvr_addr_in;
struct sockaddr *srvr_addr = NULL;
uint16_t port = 0;
size_t len = 0;
const char *s;
int af = AF_LOCAL;
int pf = PF_LOCAL;
TRACE2 (ctx, ASSUAN_LOG_CTX, "assuan_socket_connect", ctx,
"name=%s, flags=0x%x", name ? name : "(null)", flags);
if (!ctx || !name)
return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
if (!strncmp (name, "file://", 7) && name[7])
name += 7;
else if (!strncmp (name, "assuan://", 9) && name[9])
{
name += 9;
af = AF_INET;
pf = PF_INET;
}
else /* Default. */
{
/* We require that the name starts with a slash if no URL
schemata is used. To make things easier we allow an optional
drive prefix. */
s = name;
if (*s && s[1] == ':')
s += 2;
if (*s != DIRSEP_C && *s != '/')
return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
}
if (af == AF_LOCAL)
{
int redirected;
if (_assuan_sock_set_sockaddr_un (name, (struct sockaddr *)&srvr_addr_un,
&redirected))
return _assuan_error (ctx, gpg_err_code_from_syserror ());
len = SUN_LEN (&srvr_addr_un);
srvr_addr = (struct sockaddr *)&srvr_addr_un;
}
else
{
char *addrstr, *p;
#ifdef HAVE_INET_PTON
void *addrbuf = NULL;
#endif
addrstr = _assuan_malloc (ctx, strlen (name) + 1);
if (!addrstr)
return _assuan_error (ctx, gpg_err_code_from_syserror ());
if (*name == '[')
{
strcpy (addrstr, name+1);
p = strchr (addrstr, ']');
if (!p || p[1] != ':' || !parse_portno (p+2, &port))
err = _assuan_error (ctx, GPG_ERR_BAD_URI);
else
{
*p = 0;
#ifdef WITH_IPV6
af = AF_INET6;
pf = PF_INET6;
memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6);
srvr_addr_in6.sin6_family = af;
srvr_addr_in6.sin6_port = htons (port);
#ifdef HAVE_INET_PTON
addrbuf = &srvr_addr_in6.sin6_addr;
#endif
srvr_addr = (struct sockaddr *)&srvr_addr_in6;
len = sizeof srvr_addr_in6;
#else
err = _assuan_error (ctx, GPG_ERR_EAFNOSUPPORT);
#endif
}
}
else
{
strcpy (addrstr, name);
p = strchr (addrstr, ':');
if (!p || !parse_portno (p+1, &port))
err = _assuan_error (ctx, GPG_ERR_BAD_URI);
else
{
*p = 0;
memset (&srvr_addr_in, 0, sizeof srvr_addr_in);
srvr_addr_in.sin_family = af;
srvr_addr_in.sin_port = htons (port);
#ifdef HAVE_INET_PTON
addrbuf = &srvr_addr_in.sin_addr;
#endif
srvr_addr = (struct sockaddr *)&srvr_addr_in;
len = sizeof srvr_addr_in;
}
}
if (!err)
{
#ifdef HAVE_INET_PTON
switch (inet_pton (af, addrstr, addrbuf))
{
case 1: break;
case 0: err = _assuan_error (ctx, GPG_ERR_BAD_URI); break;
default: err = _assuan_error (ctx, gpg_err_code_from_syserror ());
}
#else /*!HAVE_INET_PTON*/
/* We need to use the old function. If we are here v6
support isn't enabled anyway and thus we can do fine
without. Note that Windows as a compatible inet_pton
function named inetPton, but only since Vista. */
srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr);
if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE)
err = _assuan_error (ctx, GPG_ERR_BAD_URI);
#endif /*!HAVE_INET_PTON*/
}
_assuan_free (ctx, addrstr);
if (err)
return err;
}
fd = _assuan_sock_new (ctx, pf, SOCK_STREAM, 0);
if (fd == ASSUAN_INVALID_FD)
{
err = _assuan_error (ctx, gpg_err_code_from_syserror ());
TRACE1 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect", ctx,
"can't create socket: %s", strerror (errno));
return err;
}
if (_assuan_sock_connect (ctx, fd, srvr_addr, len) == -1)
{
TRACE2 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect", ctx,
"can't connect to `%s': %s\n", name, strerror (errno));
_assuan_close (ctx, fd);
return _assuan_error (ctx, GPG_ERR_ASS_CONNECT_FAILED);
}
err = _assuan_connect_finalize (ctx, fd, flags);
if (err)
_assuan_reset (ctx);
return err;
}
diff --git a/src/assuan-socket-server.c b/src/assuan-socket-server.c
index a8330a8..f5fe038 100644
--- a/src/assuan-socket-server.c
+++ b/src/assuan-socket-server.c
@@ -1,259 +1,263 @@
/* assuan-socket-server.c - Assuan socket based server
* Copyright (C) 2002, 2007, 2009 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
* Assuan is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Assuan is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
* SPDX-License-Identifier: LGPL-2.1+
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_W32_SYSTEM
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# include <windows.h>
# if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
# elif HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
# endif
#else
# include <sys/socket.h>
# include <sys/un.h>
#endif
#ifdef HAVE_SYS_UCRED_H
#include <sys/ucred.h>
#endif
#ifdef HAVE_UCRED_H
#include <ucred.h>
#endif
#include "debug.h"
#include "assuan-defs.h"
static gpg_error_t
accept_connection_bottom (assuan_context_t ctx)
{
assuan_fd_t fd = ctx->connected_fd;
TRACE (ctx, ASSUAN_LOG_SYSIO, "accept_connection_bottom", ctx);
ctx->peercred_valid = 0;
#ifdef SO_PEERCRED
{
#ifdef HAVE_STRUCT_SOCKPEERCRED_PID
struct sockpeercred cr; /* OpenBSD */
#else
struct ucred cr; /* GNU/Linux */
#endif
socklen_t cl = sizeof cr;
if (!getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
{
ctx->peercred_valid = 1;
ctx->peercred.pid = cr.pid;
ctx->peercred.uid = cr.uid;
ctx->peercred.gid = cr.gid;
}
}
#elif defined (LOCAL_PEERPID)
{ /* macOS */
socklen_t len = sizeof (pid_t);
if (!getsockopt (fd, SOL_LOCAL, LOCAL_PEERPID, &ctx->peercred.pid, &len))
{
ctx->peercred_valid = 1;
#if defined (LOCAL_PEERCRED)
{
struct xucred cr;
len = sizeof (struct xucred);
if (!getsockopt (fd, SOL_LOCAL, LOCAL_PEERCRED, &cr, &len))
{
ctx->peercred.uid = cr.cr_uid;
ctx->peercred.gid = cr.cr_gid;
}
}
#endif
}
}
#elif defined (LOCAL_PEEREID)
{ /* NetBSD */
struct unpcbid unp;
socklen_t unpl = sizeof unp;
if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1)
{
ctx->peercred_valid = 1;
ctx->peercred.pid = unp.unp_pid;
ctx->peercred.uid = unp.unp_euid;
ctx->peercred.gid = unp.unp_egid;
}
}
#elif defined (HAVE_GETPEERUCRED)
{ /* Solaris */
ucred_t *ucred = NULL;
if (getpeerucred (fd, &ucred) != -1)
{
ctx->peercred_valid = 1;
ctx->peercred.pid = ucred_getpid (ucred);
ctx->peercred.uid = ucred_geteuid (ucred);
ctx->peercred.gid = ucred_getegid (ucred);
ucred_free (ucred);
}
}
#elif defined(HAVE_GETPEEREID)
{ /* FreeBSD */
if (getpeereid (fd, &ctx->peercred.uid, &ctx->peercred.gid) != -1)
{
ctx->peercred_valid = 1;
ctx->peercred.pid = ASSUAN_INVALID_PID;
}
}
#endif
/* This overrides any already set PID if the function returns
a valid one. */
if (ctx->peercred_valid && ctx->peercred.pid != ASSUAN_INVALID_PID)
ctx->pid = ctx->peercred.pid;
ctx->inbound.fd = fd;
ctx->inbound.eof = 0;
ctx->inbound.linelen = 0;
ctx->inbound.attic.linelen = 0;
ctx->inbound.attic.pending = 0;
ctx->outbound.fd = fd;
ctx->outbound.data.linelen = 0;
ctx->outbound.data.error = 0;
ctx->flags.confidential = 0;
return 0;
}
static gpg_error_t
accept_connection (assuan_context_t ctx)
{
assuan_fd_t fd;
struct sockaddr_un clnt_addr;
socklen_t len = sizeof clnt_addr;
TRACE1 (ctx, ASSUAN_LOG_SYSIO, "accept_connection", ctx,
"listen_fd=0x%x", ctx->listen_fd);
fd = SOCKET2HANDLE(accept (HANDLE2SOCKET(ctx->listen_fd),
(struct sockaddr*)&clnt_addr, &len ));
if (fd == ASSUAN_INVALID_FD)
{
return _assuan_error (ctx, gpg_err_code_from_syserror ());
}
TRACE1 (ctx, ASSUAN_LOG_SYSIO, "accept_connection", ctx,
"fd->0x%x", fd);
if (_assuan_sock_check_nonce (ctx, fd, &ctx->listen_nonce))
{
_assuan_close (ctx, fd);
return _assuan_error (ctx, GPG_ERR_ASS_ACCEPT_FAILED);
}
ctx->connected_fd = fd;
return accept_connection_bottom (ctx);
}
/*
Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing
1 - FD has already been accepted.
*/
gpg_error_t
assuan_init_socket_server (assuan_context_t ctx, assuan_fd_t fd,
unsigned int flags)
{
gpg_error_t rc;
TRACE_BEG2 (ctx, ASSUAN_LOG_CTX, "assuan_init_socket_server", ctx,
"fd=0x%x, flags=0x%x", fd, flags);
ctx->flags.is_socket = 1;
rc = _assuan_register_std_commands (ctx);
if (rc)
return TRACE_ERR (rc);
ctx->engine.release = _assuan_server_release;
ctx->engine.readfnc = _assuan_simple_read;
ctx->engine.writefnc = _assuan_simple_write;
ctx->engine.sendfd = NULL;
ctx->engine.receivefd = NULL;
ctx->flags.is_server = 1;
if (flags & ASSUAN_SOCKET_SERVER_ACCEPTED)
/* We want a second accept to indicate EOF. */
ctx->max_accepts = 1;
else
ctx->max_accepts = -1;
ctx->input_fd = ASSUAN_INVALID_FD;
ctx->output_fd = ASSUAN_INVALID_FD;
ctx->inbound.fd = ASSUAN_INVALID_FD;
ctx->outbound.fd = ASSUAN_INVALID_FD;
if (flags & ASSUAN_SOCKET_SERVER_ACCEPTED)
{
ctx->listen_fd = ASSUAN_INVALID_FD;
ctx->connected_fd = fd;
}
else
{
ctx->listen_fd = fd;
ctx->connected_fd = ASSUAN_INVALID_FD;
}
ctx->accept_handler = ((flags & ASSUAN_SOCKET_SERVER_ACCEPTED)
? accept_connection_bottom
: accept_connection);
ctx->finish_handler = _assuan_server_finish;
+#ifdef HAVE_W32_SYSTEM
+ ctx->engine.receivefd = w32_fdpass_recv;
+#else
if (flags & ASSUAN_SOCKET_SERVER_FDPASSING)
_assuan_init_uds_io (ctx);
+#endif
rc = _assuan_register_std_commands (ctx);
if (rc)
_assuan_reset (ctx);
return TRACE_ERR (rc);
}
/* Save a copy of NONCE in context CTX. This should be used to
register the server's nonce with an context established by
assuan_init_socket_server. */
void
assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce)
{
if (ctx && nonce)
ctx->listen_nonce = *nonce;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jul 17, 1:45 AM (3 h, 1 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
6e/8b/56583d6551840288e96ab20696a6
Attached To
rA Assuan
Event Timeline
Log In to Comment