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