215 lines
3.9 KiB
C
215 lines
3.9 KiB
C
/*
|
|
* Part of Very Secure FTPd
|
|
* Licence: GPL v2
|
|
* Author: Chris Evans
|
|
* privsock.c
|
|
*
|
|
* This file contains code for a simple message and file descriptor passing
|
|
* API, over a pair of UNIX sockets.
|
|
* The messages are typically travelling across a privilege boundary, with
|
|
* heavy distrust of messages on the side of more privilege.
|
|
*/
|
|
|
|
#include "privsock.h"
|
|
|
|
#include "utility.h"
|
|
#include "defs.h"
|
|
#include "str.h"
|
|
#include "netstr.h"
|
|
#include "sysutil.h"
|
|
#include "sysdeputil.h"
|
|
#include "session.h"
|
|
|
|
void
|
|
priv_sock_init(struct vsf_session* p_sess)
|
|
{
|
|
struct vsf_sysutil_socketpair_retval retval;
|
|
if (p_sess->parent_fd != -1)
|
|
{
|
|
bug("parent_fd active");
|
|
}
|
|
if (p_sess->child_fd != -1)
|
|
{
|
|
bug("child_fd active");
|
|
}
|
|
retval = vsf_sysutil_unix_stream_socketpair();
|
|
p_sess->parent_fd = retval.socket_one;
|
|
p_sess->child_fd = retval.socket_two;
|
|
}
|
|
|
|
void
|
|
priv_sock_close(struct vsf_session* p_sess)
|
|
{
|
|
if (p_sess->parent_fd != -1)
|
|
{
|
|
vsf_sysutil_close(p_sess->parent_fd);
|
|
p_sess->parent_fd = -1;
|
|
}
|
|
if (p_sess->child_fd != -1)
|
|
{
|
|
vsf_sysutil_close(p_sess->child_fd);
|
|
p_sess->child_fd = -1;
|
|
}
|
|
}
|
|
|
|
void
|
|
priv_sock_set_parent_context(struct vsf_session* p_sess)
|
|
{
|
|
if (p_sess->child_fd == -1)
|
|
{
|
|
bug("child_fd not active");
|
|
}
|
|
vsf_sysutil_close(p_sess->child_fd);
|
|
p_sess->child_fd = -1;
|
|
}
|
|
|
|
void
|
|
priv_sock_set_child_context(struct vsf_session* p_sess)
|
|
{
|
|
if (p_sess->parent_fd == -1)
|
|
{
|
|
bug("parent_fd not active");
|
|
}
|
|
vsf_sysutil_close(p_sess->parent_fd);
|
|
p_sess->parent_fd = -1;
|
|
}
|
|
|
|
void
|
|
priv_sock_send_cmd(int fd, char cmd)
|
|
{
|
|
int retval = vsf_sysutil_write_loop(fd, &cmd, sizeof(cmd));
|
|
if (retval != sizeof(cmd))
|
|
{
|
|
die("priv_sock_send_cmd");
|
|
}
|
|
}
|
|
|
|
void
|
|
priv_sock_send_str(int fd, const struct mystr* p_str)
|
|
{
|
|
unsigned int len = str_getlen(p_str);
|
|
priv_sock_send_int(fd, (int) len);
|
|
if (len > 0)
|
|
{
|
|
str_netfd_write(p_str, fd);
|
|
}
|
|
}
|
|
|
|
void
|
|
priv_sock_send_buf(int fd, const char* p_buf, unsigned int len)
|
|
{
|
|
priv_sock_send_int(fd, (int) len);
|
|
if (len > 0)
|
|
{
|
|
if (vsf_sysutil_write_loop(fd, p_buf, len) != (int) len)
|
|
{
|
|
die("priv_sock_send_buf");
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
priv_sock_recv_buf(int fd, char* p_buf, unsigned int len)
|
|
{
|
|
unsigned int recv_len = (unsigned int) priv_sock_get_int(fd);
|
|
if (recv_len > len)
|
|
{
|
|
bug("recv_len bigger than buffer");
|
|
}
|
|
if (recv_len > 0)
|
|
{
|
|
if (vsf_sysutil_read_loop(fd, p_buf, recv_len) != (int) recv_len)
|
|
{
|
|
die("priv_sock_recv_buf");
|
|
}
|
|
}
|
|
}
|
|
|
|
char
|
|
priv_sock_get_result(int fd)
|
|
{
|
|
char res;
|
|
int retval = vsf_sysutil_read_loop(fd, &res, sizeof(res));
|
|
if (retval != sizeof(res))
|
|
{
|
|
die("priv_sock_get_result");
|
|
}
|
|
return res;
|
|
}
|
|
|
|
char
|
|
priv_sock_get_cmd(int fd)
|
|
{
|
|
char res;
|
|
int retval = vsf_sysutil_read_loop(fd, &res, sizeof(res));
|
|
if (retval != sizeof(res))
|
|
{
|
|
die("priv_sock_get_cmd");
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void
|
|
priv_sock_get_str(int fd, struct mystr* p_dest)
|
|
{
|
|
unsigned int len = (unsigned int) priv_sock_get_int(fd);
|
|
if (len > VSFTP_PRIVSOCK_MAXSTR)
|
|
{
|
|
die("priv_sock_get_str: too big");
|
|
}
|
|
str_empty(p_dest);
|
|
if (len > 0)
|
|
{
|
|
int retval = str_netfd_read(p_dest, fd, len);
|
|
if ((unsigned int) retval != len)
|
|
{
|
|
die("priv_sock_get_str: read error");
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
priv_sock_send_result(int fd, char res)
|
|
{
|
|
int retval = vsf_sysutil_write_loop(fd, &res, sizeof(res));
|
|
if (retval != sizeof(res))
|
|
{
|
|
die("priv_sock_send_result");
|
|
}
|
|
}
|
|
|
|
void
|
|
priv_sock_send_fd(int fd, int send_fd)
|
|
{
|
|
vsf_sysutil_send_fd(fd, send_fd);
|
|
}
|
|
|
|
int
|
|
priv_sock_recv_fd(int fd)
|
|
{
|
|
return vsf_sysutil_recv_fd(fd);
|
|
}
|
|
|
|
void
|
|
priv_sock_send_int(int fd, int the_int)
|
|
{
|
|
int retval = vsf_sysutil_write_loop(fd, &the_int, sizeof(the_int));
|
|
if (retval != sizeof(the_int))
|
|
{
|
|
die("priv_sock_send_int");
|
|
}
|
|
}
|
|
|
|
int
|
|
priv_sock_get_int(int fd)
|
|
{
|
|
int the_int;
|
|
int retval = vsf_sysutil_read_loop(fd, &the_int, sizeof(the_int));
|
|
if (retval != sizeof(the_int))
|
|
{
|
|
die("priv_sock_get_int");
|
|
}
|
|
return the_int;
|
|
}
|
|
|