privsock.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. #include "privsock.h"
  13. #include "utility.h"
  14. #include "defs.h"
  15. #include "str.h"
  16. #include "netstr.h"
  17. #include "sysutil.h"
  18. #include "sysdeputil.h"
  19. #include "session.h"
  20. void
  21. priv_sock_init(struct vsf_session* p_sess)
  22. {
  23. struct vsf_sysutil_socketpair_retval retval;
  24. if (p_sess->parent_fd != -1)
  25. {
  26. bug("parent_fd active");
  27. }
  28. if (p_sess->child_fd != -1)
  29. {
  30. bug("child_fd active");
  31. }
  32. retval = vsf_sysutil_unix_stream_socketpair();
  33. p_sess->parent_fd = retval.socket_one;
  34. p_sess->child_fd = retval.socket_two;
  35. }
  36. void
  37. priv_sock_close(struct vsf_session* p_sess)
  38. {
  39. if (p_sess->parent_fd != -1)
  40. {
  41. vsf_sysutil_close(p_sess->parent_fd);
  42. p_sess->parent_fd = -1;
  43. }
  44. if (p_sess->child_fd != -1)
  45. {
  46. vsf_sysutil_close(p_sess->child_fd);
  47. p_sess->child_fd = -1;
  48. }
  49. }
  50. void
  51. priv_sock_set_parent_context(struct vsf_session* p_sess)
  52. {
  53. if (p_sess->child_fd == -1)
  54. {
  55. bug("child_fd not active");
  56. }
  57. vsf_sysutil_close(p_sess->child_fd);
  58. p_sess->child_fd = -1;
  59. }
  60. void
  61. priv_sock_set_child_context(struct vsf_session* p_sess)
  62. {
  63. if (p_sess->parent_fd == -1)
  64. {
  65. bug("parent_fd not active");
  66. }
  67. vsf_sysutil_close(p_sess->parent_fd);
  68. p_sess->parent_fd = -1;
  69. }
  70. void
  71. priv_sock_send_cmd(int fd, char cmd)
  72. {
  73. int retval = vsf_sysutil_write_loop(fd, &cmd, sizeof(cmd));
  74. if (retval != sizeof(cmd))
  75. {
  76. die("priv_sock_send_cmd");
  77. }
  78. }
  79. void
  80. priv_sock_send_str(int fd, const struct mystr* p_str)
  81. {
  82. unsigned int len = str_getlen(p_str);
  83. priv_sock_send_int(fd, (int) len);
  84. if (len > 0)
  85. {
  86. str_netfd_write(p_str, fd);
  87. }
  88. }
  89. void
  90. priv_sock_send_buf(int fd, const char* p_buf, unsigned int len)
  91. {
  92. priv_sock_send_int(fd, (int) len);
  93. if (len > 0)
  94. {
  95. if (vsf_sysutil_write_loop(fd, p_buf, len) != (int) len)
  96. {
  97. die("priv_sock_send_buf");
  98. }
  99. }
  100. }
  101. void
  102. priv_sock_recv_buf(int fd, char* p_buf, unsigned int len)
  103. {
  104. unsigned int recv_len = (unsigned int) priv_sock_get_int(fd);
  105. if (recv_len > len)
  106. {
  107. bug("recv_len bigger than buffer");
  108. }
  109. if (recv_len > 0)
  110. {
  111. if (vsf_sysutil_read_loop(fd, p_buf, recv_len) != (int) recv_len)
  112. {
  113. die("priv_sock_recv_buf");
  114. }
  115. }
  116. }
  117. char
  118. priv_sock_get_result(int fd)
  119. {
  120. char res;
  121. int retval = vsf_sysutil_read_loop(fd, &res, sizeof(res));
  122. if (retval != sizeof(res))
  123. {
  124. die("priv_sock_get_result");
  125. }
  126. return res;
  127. }
  128. char
  129. priv_sock_get_cmd(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_cmd");
  136. }
  137. return res;
  138. }
  139. void
  140. priv_sock_get_str(int fd, struct mystr* p_dest)
  141. {
  142. unsigned int len = (unsigned int) priv_sock_get_int(fd);
  143. if (len > VSFTP_PRIVSOCK_MAXSTR)
  144. {
  145. die("priv_sock_get_str: too big");
  146. }
  147. str_empty(p_dest);
  148. if (len > 0)
  149. {
  150. int retval = str_netfd_read(p_dest, fd, len);
  151. if ((unsigned int) retval != len)
  152. {
  153. die("priv_sock_get_str: read error");
  154. }
  155. }
  156. }
  157. void
  158. priv_sock_send_result(int fd, char res)
  159. {
  160. int retval = vsf_sysutil_write_loop(fd, &res, sizeof(res));
  161. if (retval != sizeof(res))
  162. {
  163. die("priv_sock_send_result");
  164. }
  165. }
  166. void
  167. priv_sock_send_fd(int fd, int send_fd)
  168. {
  169. vsf_sysutil_send_fd(fd, send_fd);
  170. }
  171. int
  172. priv_sock_recv_fd(int fd)
  173. {
  174. return vsf_sysutil_recv_fd(fd);
  175. }
  176. void
  177. priv_sock_send_int(int fd, int the_int)
  178. {
  179. int retval = vsf_sysutil_write_loop(fd, &the_int, sizeof(the_int));
  180. if (retval != sizeof(the_int))
  181. {
  182. die("priv_sock_send_int");
  183. }
  184. }
  185. int
  186. priv_sock_get_int(int fd)
  187. {
  188. int the_int;
  189. int retval = vsf_sysutil_read_loop(fd, &the_int, sizeof(the_int));
  190. if (retval != sizeof(the_int))
  191. {
  192. die("priv_sock_get_int");
  193. }
  194. return the_int;
  195. }