1 /* assuan-pipe-server.c - Assuan server working over a pipe
2  * Copyright (C) 2001, 2002, 2009 Free Software Foundation, Inc.
3  *
4  * This file is part of Assuan.
5  *
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.
10  *
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.
15  *
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/>.
18  * SPDX-License-Identifier: LGPL-2.1+
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #ifdef HAVE_SYS_TYPES_H
28 # include <sys/types.h>
29 #endif
30 #ifdef HAVE_SYS_STAT_H
31 # include <sys/stat.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
36 #ifdef HAVE_W32_SYSTEM
37 # ifdef HAVE_WINSOCK2_H
38 #  include <winsock2.h>
39 # endif
40 # include <windows.h>
41 #ifdef HAVE_FCNTL_H
42 # include <fcntl.h>
43 #endif
44 #endif
45 
46 #include "assuan-defs.h"
47 #include "debug.h"
48 
49 /* Returns true if atoi(S) denotes a valid socket. */
50 #ifndef HAVE_W32_SYSTEM
51 static int
is_valid_socket(const char * s)52 is_valid_socket (const char *s)
53 {
54   struct stat buf;
55 
56   if ( fstat (atoi (s), &buf ) )
57     return 0;
58   return S_ISSOCK (buf.st_mode);
59 }
60 #endif /*!HAVE_W32_SYSTEM*/
61 
62 
63 /* This actually is a int file descriptor (and not assuan_fd_t) as
64    _get_osfhandle is called on W32 systems.  */
65 gpg_error_t
assuan_init_pipe_server(assuan_context_t ctx,assuan_fd_t filedes[2])66 assuan_init_pipe_server (assuan_context_t ctx, assuan_fd_t filedes[2])
67 {
68   const char *s;
69   unsigned long ul;
70   gpg_error_t rc;
71   assuan_fd_t infd = ASSUAN_INVALID_FD;
72   assuan_fd_t outfd = ASSUAN_INVALID_FD;
73   int is_usd = 0;
74   TRACE_BEG (ctx, ASSUAN_LOG_CTX, "assuan_init_pipe_server", ctx);
75   if (filedes)
76     {
77       TRACE_LOG2 ("fd[0]=0x%x, fd[1]=0x%x", filedes[0], filedes[1]);
78     }
79 
80   rc = _assuan_register_std_commands (ctx);
81   if (rc)
82     return TRACE_ERR (rc);
83 
84 #ifdef HAVE_W32_SYSTEM
85   infd  = filedes[0];
86   outfd = filedes[1];
87 #else
88   s = getenv ("_assuan_connection_fd");
89   if (s && *s && is_valid_socket (s))
90     {
91       /* Well, we are called with an bi-directional file descriptor.
92 	 Prepare for using sendmsg/recvmsg.  In this case we ignore
93 	 the passed file descriptors. */
94       infd = atoi (s);
95       outfd = atoi (s);
96       is_usd = 1;
97 
98     }
99   else if (filedes && filedes[0] != ASSUAN_INVALID_FD
100 	   && filedes[1] != ASSUAN_INVALID_FD )
101     {
102       /* Standard pipe server. */
103       infd = filedes[0];
104       outfd = filedes[1];
105     }
106   else
107     {
108       rc = _assuan_error (ctx, GPG_ERR_ASS_SERVER_START);
109       return TRACE_ERR (rc);
110     }
111 #endif
112 
113   ctx->is_server = 1;
114   ctx->engine.release = _assuan_server_release;
115   ctx->engine.readfnc = _assuan_simple_read;
116   ctx->engine.writefnc = _assuan_simple_write;
117   ctx->engine.sendfd = NULL;
118   ctx->engine.receivefd = NULL;
119   ctx->max_accepts = 1;
120 
121   s = getenv ("_assuan_pipe_connect_pid");
122   if (s && (ul=strtoul (s, NULL, 10)) && ul)
123     ctx->pid = (pid_t)ul;
124   else
125     ctx->pid = (pid_t)-1;
126   ctx->accept_handler = NULL;
127   ctx->finish_handler = _assuan_server_finish;
128   ctx->inbound.fd = infd;
129   ctx->outbound.fd = outfd;
130 
131   if (is_usd)
132     _assuan_init_uds_io (ctx);
133 
134   return TRACE_SUC();
135 }
136