1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * privsock.c
6 *
7 * This file contains code for a simple message and file descriptor passing
8 * API, over a pair of UNIX sockets.
9 * The messages are typically travelling across a privilege boundary, with
10 * heavy distrust of messages on the side of more privilege.
11 */
12
13 #include "privsock.h"
14
15 #include "utility.h"
16 #include "defs.h"
17 #include "str.h"
18 #include "netstr.h"
19 #include "sysutil.h"
20 #include "sysdeputil.h"
21 #include "session.h"
22
23 void
priv_sock_init(struct vsf_session * p_sess)24 priv_sock_init(struct vsf_session* p_sess)
25 {
26 struct vsf_sysutil_socketpair_retval retval;
27 if (p_sess->parent_fd != -1)
28 {
29 bug("parent_fd active");
30 }
31 if (p_sess->child_fd != -1)
32 {
33 bug("child_fd active");
34 }
35 retval = vsf_sysutil_unix_stream_socketpair();
36 p_sess->parent_fd = retval.socket_one;
37 p_sess->child_fd = retval.socket_two;
38 }
39
40 void
priv_sock_close(struct vsf_session * p_sess)41 priv_sock_close(struct vsf_session* p_sess)
42 {
43 if (p_sess->parent_fd != -1)
44 {
45 vsf_sysutil_close(p_sess->parent_fd);
46 p_sess->parent_fd = -1;
47 }
48 if (p_sess->child_fd != -1)
49 {
50 vsf_sysutil_close(p_sess->child_fd);
51 p_sess->child_fd = -1;
52 }
53 }
54
55 void
priv_sock_set_parent_context(struct vsf_session * p_sess)56 priv_sock_set_parent_context(struct vsf_session* p_sess)
57 {
58 if (p_sess->child_fd == -1)
59 {
60 bug("child_fd not active");
61 }
62 vsf_sysutil_close(p_sess->child_fd);
63 p_sess->child_fd = -1;
64 }
65
66 void
priv_sock_set_child_context(struct vsf_session * p_sess)67 priv_sock_set_child_context(struct vsf_session* p_sess)
68 {
69 if (p_sess->parent_fd == -1)
70 {
71 bug("parent_fd not active");
72 }
73 vsf_sysutil_close(p_sess->parent_fd);
74 p_sess->parent_fd = -1;
75 }
76
77 void
priv_sock_send_cmd(int fd,char cmd)78 priv_sock_send_cmd(int fd, char cmd)
79 {
80 int retval = vsf_sysutil_write_loop(fd, &cmd, sizeof(cmd));
81 if (retval != sizeof(cmd))
82 {
83 die("priv_sock_send_cmd");
84 }
85 }
86
87 void
priv_sock_send_str(int fd,const struct mystr * p_str)88 priv_sock_send_str(int fd, const struct mystr* p_str)
89 {
90 unsigned int len = str_getlen(p_str);
91 priv_sock_send_int(fd, (int) len);
92 if (len > 0)
93 {
94 str_netfd_write(p_str, fd);
95 }
96 }
97
98 void
priv_sock_send_buf(int fd,const char * p_buf,unsigned int len)99 priv_sock_send_buf(int fd, const char* p_buf, unsigned int len)
100 {
101 priv_sock_send_int(fd, (int) len);
102 if (len > 0)
103 {
104 if (vsf_sysutil_write_loop(fd, p_buf, len) != (int) len)
105 {
106 die("priv_sock_send_buf");
107 }
108 }
109 }
110
111 void
priv_sock_recv_buf(int fd,char * p_buf,unsigned int len)112 priv_sock_recv_buf(int fd, char* p_buf, unsigned int len)
113 {
114 unsigned int recv_len = (unsigned int) priv_sock_get_int(fd);
115 if (recv_len > len)
116 {
117 bug("recv_len bigger than buffer");
118 }
119 if (recv_len > 0)
120 {
121 if (vsf_sysutil_read_loop(fd, p_buf, recv_len) != (int) recv_len)
122 {
123 die("priv_sock_recv_buf");
124 }
125 }
126 }
127
128 char
priv_sock_get_result(int fd)129 priv_sock_get_result(int fd)
130 {
131 char res;
132 int retval = vsf_sysutil_read_loop(fd, &res, sizeof(res));
133 if (retval != sizeof(res))
134 {
135 die("priv_sock_get_result");
136 }
137 return res;
138 }
139
140 char
priv_sock_get_cmd(int fd)141 priv_sock_get_cmd(int fd)
142 {
143 char res;
144 int retval = vsf_sysutil_read_loop(fd, &res, sizeof(res));
145 if (retval != sizeof(res))
146 {
147 die("priv_sock_get_cmd");
148 }
149 return res;
150 }
151
152 void
priv_sock_get_str(int fd,struct mystr * p_dest)153 priv_sock_get_str(int fd, struct mystr* p_dest)
154 {
155 unsigned int len = (unsigned int) priv_sock_get_int(fd);
156 if (len > VSFTP_PRIVSOCK_MAXSTR)
157 {
158 die("priv_sock_get_str: too big");
159 }
160 str_empty(p_dest);
161 if (len > 0)
162 {
163 int retval = str_netfd_read(p_dest, fd, len);
164 if ((unsigned int) retval != len)
165 {
166 die("priv_sock_get_str: read error");
167 }
168 }
169 }
170
171 void
priv_sock_send_result(int fd,char res)172 priv_sock_send_result(int fd, char res)
173 {
174 int retval = vsf_sysutil_write_loop(fd, &res, sizeof(res));
175 if (retval != sizeof(res))
176 {
177 die("priv_sock_send_result");
178 }
179 }
180
181 void
priv_sock_send_fd(int fd,int send_fd)182 priv_sock_send_fd(int fd, int send_fd)
183 {
184 vsf_sysutil_send_fd(fd, send_fd);
185 }
186
187 int
priv_sock_recv_fd(int fd)188 priv_sock_recv_fd(int fd)
189 {
190 return vsf_sysutil_recv_fd(fd);
191 }
192
193 void
priv_sock_send_int(int fd,int the_int)194 priv_sock_send_int(int fd, int the_int)
195 {
196 int retval = vsf_sysutil_write_loop(fd, &the_int, sizeof(the_int));
197 if (retval != sizeof(the_int))
198 {
199 die("priv_sock_send_int");
200 }
201 }
202
203 int
priv_sock_get_int(int fd)204 priv_sock_get_int(int fd)
205 {
206 int the_int;
207 int retval = vsf_sysutil_read_loop(fd, &the_int, sizeof(the_int));
208 if (retval != sizeof(the_int))
209 {
210 die("priv_sock_get_int");
211 }
212 return the_int;
213 }
214
215