1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17/*
18 * Part of Very Secure FTPd
19 * Licence: GPL v2
20 * Author: Chris Evans
21 * privsock.c
22 *
23 * This file contains code for a simple message and file descriptor passing
24 * API, over a pair of UNIX sockets.
25 * The messages are typically travelling across a privilege boundary, with
26 * heavy distrust of messages on the side of more privilege.
27 */
28
29#include "privsock.h"
30
31#include "utility.h"
32#include "defs.h"
33#include "str.h"
34#include "netstr.h"
35#include "sysutil.h"
36#include "sysdeputil.h"
37#include "session.h"
38
39void
40priv_sock_init(struct vsf_session* p_sess)
41{
42  const struct vsf_sysutil_socketpair_retval retval =
43    vsf_sysutil_unix_stream_socketpair();
44  p_sess->parent_fd = retval.socket_one;
45  p_sess->child_fd = retval.socket_two;
46}
47
48void
49priv_sock_send_cmd(int fd, char cmd)
50{
51  int retval = vsf_sysutil_write_loop(fd, &cmd, sizeof(cmd));
52  if (retval != sizeof(cmd))
53  {
54    die("priv_sock_send_cmd");
55  }
56}
57
58void
59priv_sock_send_str(int fd, const struct mystr* p_str)
60{
61  unsigned int len = str_getlen(p_str);
62  priv_sock_send_int(fd, (int) len);
63  if (len > 0)
64  {
65    str_netfd_write(p_str, fd);
66  }
67}
68
69char
70priv_sock_get_result(int fd)
71{
72  char res;
73  int retval = vsf_sysutil_read_loop(fd, &res, sizeof(res));
74  if (retval != sizeof(res))
75  {
76    die("priv_sock_get_result");
77  }
78  return res;
79}
80
81char
82priv_sock_get_cmd(int fd)
83{
84  char res;
85  int retval = vsf_sysutil_read_loop(fd, &res, sizeof(res));
86  if (retval != sizeof(res))
87  {
88    die("priv_sock_get_cmd");
89  }
90  return res;
91}
92
93void
94priv_sock_get_str(int fd, struct mystr* p_dest)
95{
96  unsigned int len = (unsigned int) priv_sock_get_int(fd);
97  if (len > VSFTP_PRIVSOCK_MAXSTR)
98  {
99    die("priv_sock_get_str: too big");
100  }
101  str_empty(p_dest);
102  if (len > 0)
103  {
104    int retval = str_netfd_read(p_dest, fd, len);
105    if ((unsigned int) retval != len)
106    {
107      die("priv_sock_get_str: read error");
108    }
109  }
110}
111
112void
113priv_sock_send_result(int fd, char res)
114{
115  int retval = vsf_sysutil_write_loop(fd, &res, sizeof(res));
116  if (retval != sizeof(res))
117  {
118    die("priv_sock_send_result");
119  }
120}
121
122void
123priv_sock_send_fd(int fd, int send_fd)
124{
125  vsf_sysutil_send_fd(fd, send_fd);
126}
127
128int
129priv_sock_recv_fd(int fd)
130{
131  return vsf_sysutil_recv_fd(fd);
132}
133
134void
135priv_sock_send_int(int fd, int the_int)
136{
137  int retval = vsf_sysutil_write_loop(fd, &the_int, sizeof(the_int));
138  if (retval != sizeof(the_int))
139  {
140    die("priv_sock_send_int");
141  }
142}
143
144int
145priv_sock_get_int(int fd)
146{
147  int the_int;
148  int retval = vsf_sysutil_read_loop(fd, &the_int, sizeof(the_int));
149  if (retval != sizeof(the_int))
150  {
151    die("priv_sock_get_int");
152  }
153  return the_int;
154}
155
156