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