new server "sj3proxy".
this server is communicating between unix domain and inet.
This commit is contained in:
parent
d2223576d0
commit
7e097c2015
16 changed files with 738 additions and 21 deletions
|
|
@ -835,8 +835,9 @@ fi
|
|||
|
||||
SJ3SYSCONFDIR=$sj3sysconf_dir
|
||||
AC_SUBST(SJ3SYSCONFDIR)
|
||||
AC_DEFINE_UNQUOTED(SJ3CONFDIR, "$sj3sysconf_dir", [server config dir])
|
||||
AC_DEFINE_UNQUOTED(RUNCMDFILE, "$sj3sysconf_dir/sj3serv.lua", [server config file])
|
||||
AC_DEFINE_UNQUOTED(SJ3CONFDIR, "$sj3sysconf_dir", [server config dir])
|
||||
AC_DEFINE_UNQUOTED(RUNCMDFILE, "$sj3sysconf_dir/sj3serv.lua", [server config file])
|
||||
AC_DEFINE_UNQUOTED(SJ3PROXYCFG, "$sj3sysconf_dir/sj3proxy.lua", [proxy config file])
|
||||
|
||||
dnl configure config directory
|
||||
sj3var_dir=`echo $localstatedir | grep prefix`
|
||||
|
|
@ -855,6 +856,8 @@ fi
|
|||
SJ3VARDIR="$sj3var_dir"
|
||||
AC_SUBST(SJ3VARDIR)
|
||||
AC_DEFINE_UNQUOTED(CHROOTDIR, "$sj3var_dir/spool/sj3", [chrooted dir])
|
||||
AC_DEFINE_UNQUOTED(SOCKDIR, "$sj3var_dir/run", [socket dir])
|
||||
AC_DEFINE_UNQUOTED(SOCKETFILE, "/sj3serv.socket", [socket file])
|
||||
AC_DEFINE_UNQUOTED(SOCKETNAME, "$sj3var_dir/run/sj3serv.socket", [socket file])
|
||||
|
||||
SJ3DICTDIR="$sj3var_dir/spool/sj3"
|
||||
|
|
@ -894,6 +897,7 @@ AC_CONFIG_FILES([
|
|||
src/sj3demo/Makefile
|
||||
src/sj3dic/Makefile
|
||||
src/sj3mkdic/Makefile
|
||||
src/sj3proxy/Makefile
|
||||
src/sj3serv/Makefile
|
||||
src/sj3stat/Makefile
|
||||
])
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@
|
|||
#define PORTNAME "sj3"
|
||||
#define LOCALHOST "localhost"
|
||||
#define CHROOTFLAG 1
|
||||
|
||||
#define STRICTAUTHFLAG 1
|
||||
#define MAINDICTIONARY "sj3main.dic"
|
||||
#define USERDICTIONARY "private.dic"
|
||||
#define STUDYFILE "study.dat"
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@
|
|||
#ifndef SJ3LUA_H
|
||||
#define SJ3LUA_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <lua.h>
|
||||
|
||||
int sj3lua_check_table(lua_State *);
|
||||
int lua2sj_boolean(lua_State *, char *, int, int, int *);
|
||||
int lua2sj_integer(lua_State *, char *, int, int, int *);
|
||||
|
|
@ -27,6 +24,7 @@ char *lua2sj_string(lua_State *, char *, int, char *, char *, size_t);
|
|||
void sj2lua_boolean(lua_State *, char *, int);
|
||||
void sj2lua_integer(lua_State *, char *, int);
|
||||
void sj2lua_string(lua_State *, char *, char *);
|
||||
void set_luafunction(lua_State *, char *, lua_CFunction);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -119,3 +119,11 @@ sj2lua_string(lua_State *lstate, char *name, char *s)
|
|||
lua_pushstring(lstate, s);
|
||||
lua_settable(lstate, -3);
|
||||
}
|
||||
|
||||
void
|
||||
set_luafunction(lua_State *lstate, char *name, lua_CFunction fun)
|
||||
{
|
||||
lua_pushstring(lstate, name);
|
||||
lua_pushcfunction(lstate, fun);
|
||||
lua_settable(lstate, -3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,5 +2,6 @@ SUBDIRS = \
|
|||
sj3mkdic \
|
||||
sj3serv \
|
||||
sj3dic \
|
||||
sj3proxy \
|
||||
sj3stat \
|
||||
sj3demo
|
||||
|
|
|
|||
71
trunk/src/sj3proxy/atomicio.c
Normal file
71
trunk/src/sj3proxy/atomicio.c
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* $OpenBSD: atomicio.c,v 1.9 2007/09/07 14:50:44 tobias Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2006 Damien Miller. All rights reserved.
|
||||
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
|
||||
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "atomicio.h"
|
||||
|
||||
/*
|
||||
* ensure all of data on socket comes through. f==read || f==vwrite
|
||||
*/
|
||||
size_t
|
||||
atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
|
||||
{
|
||||
char *s = _s;
|
||||
size_t pos = 0;
|
||||
ssize_t res;
|
||||
struct pollfd pfd;
|
||||
|
||||
pfd.fd = fd;
|
||||
pfd.events = f == read ? POLLIN : POLLOUT;
|
||||
while (n > pos) {
|
||||
res = (f) (fd, s + pos, n - pos);
|
||||
switch (res) {
|
||||
case -1:
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EAGAIN) {
|
||||
(void)poll(&pfd, 1, -1);
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
case 0:
|
||||
errno = EPIPE;
|
||||
return pos;
|
||||
default:
|
||||
pos += (size_t)res;
|
||||
}
|
||||
}
|
||||
return (pos);
|
||||
}
|
||||
39
trunk/src/sj3proxy/atomicio.h
Normal file
39
trunk/src/sj3proxy/atomicio.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* $OpenBSD: atomicio.h,v 1.2 2007/09/07 14:50:44 tobias Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Damien Miller. All rights reserved.
|
||||
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _ATOMICIO_H
|
||||
#define _ATOMICIO_H
|
||||
|
||||
/*
|
||||
* Ensure all of data on socket comes through. f==read || f==vwrite
|
||||
*/
|
||||
size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
|
||||
|
||||
#define vwrite (ssize_t (*)(int, void *, size_t))write
|
||||
|
||||
#endif /* _ATOMICIO_H */
|
||||
26
trunk/src/sj3proxy/freebsd-sj3proxy.sh.in
Executable file
26
trunk/src/sj3proxy/freebsd-sj3proxy.sh.in
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
|
||||
# PROVIDE: sj3proxy
|
||||
# REQUIRE: DAEMON
|
||||
# BEFORE: LOGIN
|
||||
# KEYWORD: shutdown
|
||||
|
||||
# Define these sj3_* variables in one of these files:
|
||||
# /etc/rc.conf
|
||||
# /etc/rc.conf.local
|
||||
# /etc/rc.conf.d/sj3
|
||||
#
|
||||
# DO NOT CHANGE THESE DEFAULT VALUES HERE
|
||||
#
|
||||
sj3proxy_enable=${sj3proxy_enable:-"NO"} # Enable sj3proxy
|
||||
#sj3_program="%%PREFIX%%/sbin/sj3proxy" # Location of sj3proxy
|
||||
|
||||
. %%RC_SUBR%%
|
||||
|
||||
name="sj3proxy"
|
||||
rcvar=`set_rcvar`
|
||||
command="%%PREFIX%%/sbin/sj3proxy"
|
||||
|
||||
load_rc_config $name
|
||||
run_rc_command "$1"
|
||||
61
trunk/src/sj3proxy/priv.c
Normal file
61
trunk/src/sj3proxy/priv.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Iwata <iwata@quasiquote.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include "sj3proxy.h"
|
||||
|
||||
void
|
||||
set_priv(const char *title)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
if (!chroot_enable)
|
||||
return;
|
||||
|
||||
if ((pw = getpwnam(chuser_name)) == NULL) {
|
||||
fprintf(stderr, "failed to get user \"%s\"\n", chuser_name);
|
||||
fflush(stderr);
|
||||
exit(255);
|
||||
}
|
||||
if (chroot(chroot_dir) != 0) {
|
||||
fprintf(stderr, "can't chroot\n");
|
||||
fflush(stderr);
|
||||
exit(255);
|
||||
}
|
||||
if (chdir("/") != 0) {
|
||||
fprintf(stderr, "can't change directory '/'\n");
|
||||
fflush(stderr);
|
||||
exit(255);
|
||||
}
|
||||
|
||||
if (title != NULL)
|
||||
setproctitle("%s %s", pw->pw_name, title);
|
||||
|
||||
/*
|
||||
* Drop privileges and clear the group access list
|
||||
*/
|
||||
if (setgroups(1, &pw->pw_gid) == -1 ||
|
||||
setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
|
||||
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) {
|
||||
fprintf(stderr, "can't drop privileges\n");
|
||||
fflush(stderr);
|
||||
exit(255);
|
||||
}
|
||||
}
|
||||
424
trunk/src/sj3proxy/sj3proxy.c
Normal file
424
trunk/src/sj3proxy/sj3proxy.c
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Iwata <iwata@quasiquote.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/param.h>
|
||||
#include "sys-queue.h"
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "Const.h"
|
||||
#include "sj3proxy.h"
|
||||
#include "sj3lua.h"
|
||||
#include "atomicio.h"
|
||||
|
||||
int chroot_enable = -1;
|
||||
char address_family_str[256];
|
||||
int address_family = AF_UNSPEC;
|
||||
char chuser_name[BUFSIZ];
|
||||
char chroot_dir[MAXPATHLEN];
|
||||
char socket_file[MAXPATHLEN];
|
||||
char host_name[NI_MAXHOST];
|
||||
char service_name[NI_MAXSERV];
|
||||
|
||||
struct listen_addr {
|
||||
TAILQ_ENTRY(listen_addr) entry;
|
||||
struct sockaddr_storage sa;
|
||||
int fd;
|
||||
} *listen_addrs_ptr;
|
||||
TAILQ_HEAD(listen_addrs, listen_addr) listen_addrs;
|
||||
|
||||
static void
|
||||
close_listen_socks(void)
|
||||
{
|
||||
struct listen_addr *np = listen_addrs_ptr;
|
||||
|
||||
while ((np = TAILQ_FIRST(&listen_addrs)) != NULL) {
|
||||
close(np->fd);
|
||||
TAILQ_REMOVE(&listen_addrs, np, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SIGCHLD handler. This is called whenever a child dies. This will then
|
||||
* reap any zombies left by exited children.
|
||||
*/
|
||||
static void
|
||||
main_sigchld_handler(int sig)
|
||||
{
|
||||
int save_errno = errno;
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
|
||||
(pid < 0 && errno == EINTR))
|
||||
;
|
||||
|
||||
signal(SIGCHLD, main_sigchld_handler);
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
static void
|
||||
readwrite(int inet_fd)
|
||||
{
|
||||
struct sockaddr_un sunix;
|
||||
int sj3_fd;
|
||||
char buf[BUFSIZ];
|
||||
struct pollfd pfd[2];
|
||||
int nfds;
|
||||
ssize_t readlen;
|
||||
|
||||
if (access(socket_file, R_OK | W_OK) == -1) {
|
||||
fprintf(stderr, "Can't find AF_UNIX socket\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset((char *)&sunix, 0, sizeof(sunix));
|
||||
sunix.sun_family = AF_UNIX;
|
||||
strlcpy(sunix.sun_path, socket_file, sizeof(sunix.sun_path));
|
||||
|
||||
if ((sj3_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
fprintf(stderr, "Can't create AF_UNIX socket\n");
|
||||
return;
|
||||
}
|
||||
fcntl(sj3_fd, F_SETFD, 1);
|
||||
if (connect(sj3_fd, (struct sockaddr *)&sunix, SUN_LEN(&sunix)) < 0) {
|
||||
fprintf(stderr, "Can't connect AF_UNIX socket\n");
|
||||
close(sj3_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
pfd[0].fd = inet_fd;
|
||||
pfd[0].events = POLLIN;
|
||||
|
||||
pfd[1].fd = sj3_fd;
|
||||
pfd[1].events = POLLIN;
|
||||
|
||||
for ( ; ; ){
|
||||
if ((nfds = poll(pfd, 2, -1)) < 0) {
|
||||
close(inet_fd);
|
||||
close(sj3_fd);
|
||||
fprintf(stderr, "Polling Error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nfds == 0)
|
||||
return;
|
||||
|
||||
if (pfd[0].revents & POLLIN) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if ((readlen = read(inet_fd, buf, sizeof(buf))) == -1) {
|
||||
close(sj3_fd);
|
||||
return;
|
||||
} else if (readlen == 0) {
|
||||
shutdown(inet_fd, SHUT_RD);
|
||||
return;
|
||||
} else {
|
||||
if (atomicio(vwrite, sj3_fd, buf, readlen) != readlen)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (pfd[1].revents & POLLIN) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if ((readlen = read(sj3_fd, buf, BUFSIZ)) == -1) {
|
||||
close(sj3_fd);
|
||||
return;
|
||||
} else if (readlen == 0) {
|
||||
shutdown(inet_fd, SHUT_WR);
|
||||
return;
|
||||
} else {
|
||||
if (atomicio(vwrite, inet_fd, buf, readlen) != readlen)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
set_server(lua_State *lstate)
|
||||
{
|
||||
if (!sj3lua_check_table(lstate))
|
||||
return 0;
|
||||
lua2sj_string(lstate, "user", 1, SJ3OWNER, chuser_name, sizeof(chuser_name));
|
||||
lua2sj_boolean(lstate, "chroot", 1, CHROOTFLAG, &chroot_enable);
|
||||
lua2sj_string(lstate, "chroot_dir", 1, SOCKDIR, chroot_dir, sizeof(chroot_dir));
|
||||
lua2sj_string(lstate, "socket_file", 1, SOCKETFILE, socket_file, sizeof(socket_file));
|
||||
lua2sj_string(lstate, "host_name", 1, LOCALHOST, host_name, sizeof(host_name));
|
||||
lua2sj_string(lstate, "address_famiy", 1, ADDRESSFAMILY, address_family_str, sizeof(address_family_str));
|
||||
lua2sj_string(lstate, "service_name", 1, PORTNUMBER, service_name, sizeof(service_name));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_server(lua_State *lstate)
|
||||
{
|
||||
sj2lua_string(lstate, "user", chuser_name);
|
||||
sj2lua_boolean(lstate, "chroot", chroot_enable);
|
||||
sj2lua_string(lstate, "chroot_dir", chroot_dir);
|
||||
sj2lua_string(lstate, "socket_file", socket_file);
|
||||
sj2lua_string(lstate, "host_name", host_name);
|
||||
sj2lua_string(lstate, "address_famiy", address_family_str);
|
||||
sj2lua_string(lstate, "service_name", service_name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct sockaddr *sa;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res, *res0;
|
||||
int listen_sock, maxfd;
|
||||
socklen_t fromlen;
|
||||
int inet_fd = -1;
|
||||
int error;
|
||||
u_int8_t salen;
|
||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||
int fdsetsz;
|
||||
int on = 1;
|
||||
fd_set *fdset;
|
||||
struct sockaddr_storage from;
|
||||
int pid;
|
||||
int errflg = 0;
|
||||
int c;
|
||||
int daemon_disable = 0;
|
||||
lua_State *lua_state = NULL;
|
||||
int opt_inet4 = 0, opt_inet6 = 0;
|
||||
|
||||
if ((lua_state = luaL_newstate()) == NULL) {
|
||||
fprintf(stderr, "Can't setup lua");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
luaL_openlibs(lua_state);
|
||||
|
||||
/* sj3.functions */
|
||||
lua_newtable(lua_state);
|
||||
set_luafunction(lua_state, "set_server", set_server);
|
||||
set_luafunction(lua_state, "get_server", get_server);
|
||||
lua_setglobal(lua_state, "sj3proxy");
|
||||
|
||||
if (luaL_dofile(lua_state, SJ3PROXYCFG) != 0) {
|
||||
fprintf(stderr, "%s\n", lua_tostring(lua_state, -1));
|
||||
exit(255);
|
||||
}
|
||||
|
||||
while ((c = getopt(argc, argv, "46d")) != EOF) {
|
||||
switch (c) {
|
||||
case '4':
|
||||
opt_inet4 = 1;
|
||||
break;
|
||||
case '6':
|
||||
opt_inet6 = 1;
|
||||
break;
|
||||
case 'd':
|
||||
daemon_disable = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
errflg++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (errflg || optind < argc) {
|
||||
fprintf(stderr, "Usage: sj3_proxy [-46d]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(address_family_str, "unspec") == 0)
|
||||
address_family = AF_UNSPEC;
|
||||
if (opt_inet4 || strcmp(address_family_str, "inet") == 0)
|
||||
address_family = AF_INET;
|
||||
else if (opt_inet6 || strcmp(address_family_str, "inet6") == 0)
|
||||
address_family = AF_INET6;
|
||||
|
||||
if (!daemon_disable)
|
||||
daemon(0, 1);
|
||||
|
||||
|
||||
TAILQ_INIT(&listen_addrs);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = address_family;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
error = getaddrinfo(host_name, service_name, &hints, &res);
|
||||
if (error) {
|
||||
perror(gai_strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res0 = res;
|
||||
|
||||
for ( ; res; res = res->ai_next) {
|
||||
sa = res->ai_addr;
|
||||
salen = res->ai_addrlen;
|
||||
|
||||
if (res->ai_family != AF_INET && res->ai_family != AF_INET6)
|
||||
continue;
|
||||
|
||||
if (getnameinfo(sa, salen,
|
||||
ntop, sizeof(ntop), strport, sizeof(strport),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||
fprintf(stderr, "getnameinfo failed\n");
|
||||
continue;
|
||||
}
|
||||
/* Create socket for listening. */
|
||||
listen_sock = socket(res->ai_family, res->ai_socktype,
|
||||
res->ai_protocol);
|
||||
if (listen_sock < 0) {
|
||||
/* kernel may not support ipv6 */
|
||||
fprintf(stderr, "socket: %.100s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set socket options.
|
||||
* Allow local port reuse in TIME_WAIT.
|
||||
*/
|
||||
if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
&on, sizeof(on)) == -1)
|
||||
fprintf(stderr, "setsockopt SO_REUSEADDR: %s\n", strerror(errno));
|
||||
|
||||
if (bind(listen_sock, sa, salen) < 0) {
|
||||
fprintf(stderr, "Bind to port %s on %s failed: %.200s.\n",
|
||||
strport, ntop, strerror(errno));
|
||||
close(listen_sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Start listening on the port. */
|
||||
if (listen(listen_sock, 127) < 0) {
|
||||
fprintf(stderr, "listen: %.100s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((listen_addrs_ptr = calloc(1, sizeof(struct listen_addr))) ==
|
||||
NULL) {
|
||||
fprintf(stderr, "setup_listeners calloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memcpy(&listen_addrs_ptr->sa, sa, SA_LEN(sa));
|
||||
listen_addrs_ptr->fd = listen_sock;
|
||||
TAILQ_INSERT_TAIL(&listen_addrs, listen_addrs_ptr, entry);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
|
||||
/* drop privilege */
|
||||
set_priv(NULL);
|
||||
|
||||
/* Arrange SIGCHLD to be caught. */
|
||||
signal(SIGCHLD, main_sigchld_handler);
|
||||
|
||||
/* setup fd set for listen */
|
||||
fdset = NULL;
|
||||
maxfd = 0;
|
||||
TAILQ_FOREACH(listen_addrs_ptr, &listen_addrs, entry) {
|
||||
if (listen_addrs_ptr->fd > maxfd)
|
||||
maxfd = listen_addrs_ptr->fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stay listening for connections until the system crashes or
|
||||
* the daemon is killed with a signal.
|
||||
*/
|
||||
for ( ; ; ) {
|
||||
int ret;
|
||||
|
||||
if (fdset != NULL)
|
||||
free(fdset);
|
||||
fdsetsz = howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask);
|
||||
fdset = (fd_set *)malloc(fdsetsz);
|
||||
memset(fdset, 0, fdsetsz);
|
||||
|
||||
TAILQ_FOREACH(listen_addrs_ptr, &listen_addrs, entry)
|
||||
FD_SET(listen_addrs_ptr->fd, fdset);
|
||||
|
||||
/* Wait in select until there is a connection. */
|
||||
ret = select(maxfd + 1, fdset, NULL, NULL, NULL);
|
||||
if (ret < 0 && errno != EINTR)
|
||||
fprintf(stderr, "select: %.100s\n", strerror(errno));
|
||||
if (ret < 0)
|
||||
continue;
|
||||
TAILQ_FOREACH(listen_addrs_ptr, &listen_addrs, entry) {
|
||||
if (!FD_ISSET(listen_addrs_ptr->fd, fdset))
|
||||
continue;
|
||||
fromlen = sizeof(from);
|
||||
inet_fd = accept(listen_addrs_ptr->fd, (struct sockaddr *)&from,
|
||||
&fromlen);
|
||||
if (inet_fd < 0) {
|
||||
if (errno != EINTR && errno != EWOULDBLOCK)
|
||||
fprintf(stderr, "accept: %.100s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Normal production daemon. Fork, and have
|
||||
* the child process the connection. The
|
||||
* parent continues listening.
|
||||
*/
|
||||
if ((pid = fork()) == 0) {
|
||||
/*
|
||||
* Child. Close the listening and max_startup
|
||||
* sockets. Start using the accepted socket.
|
||||
* Reinitialize logging (since our pid has
|
||||
* changed). We break out of the loop to handle
|
||||
* the connection.
|
||||
*/
|
||||
close_listen_socks();
|
||||
break;
|
||||
}
|
||||
/* Parent. Stay in the loop. */
|
||||
if (pid < 0) {
|
||||
fprintf(stderr, "fork: %.100s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Close the new socket (the child is now taking care of it). */
|
||||
close(inet_fd);
|
||||
}
|
||||
if (TAILQ_EMPTY(&listen_addrs))
|
||||
break;
|
||||
}
|
||||
|
||||
readwrite(inet_fd);
|
||||
|
||||
close(inet_fd);
|
||||
close_listen_socks();
|
||||
|
||||
_exit(0);
|
||||
}
|
||||
36
trunk/src/sj3proxy/sj3proxy.h
Normal file
36
trunk/src/sj3proxy/sj3proxy.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Iwata <iwata@quasiquote.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SJ3PROXY_H
|
||||
#define SJ3PROXY_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
extern int chroot_enable;
|
||||
extern char address_family_str[256];
|
||||
extern int address_family;
|
||||
extern char chuser_name[BUFSIZ];
|
||||
extern char chroot_dir[MAXPATHLEN];
|
||||
extern char socket_file[MAXPATHLEN];
|
||||
extern char host_name[NI_MAXHOST];
|
||||
extern char service_name[NI_MAXSERV];
|
||||
|
||||
void set_priv(const char *);
|
||||
|
||||
#endif
|
||||
|
||||
49
trunk/src/sj3proxy/sj3proxy.lua.example.in
Normal file
49
trunk/src/sj3proxy/sj3proxy.lua.example.in
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
--[[ -- -*- lua -*-
|
||||
Copyright (c) 2004 Iwata <iwata@quasiquote.org>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
--]]
|
||||
|
||||
local prefix = "%%SJ3VARDIR%%"
|
||||
|
||||
sj3proxy.set_server {
|
||||
-- user: String
|
||||
-- run as user name
|
||||
user = "%%SJ3OWNER%%",
|
||||
|
||||
-- chroot: Boolean
|
||||
-- sj3serv is chrooted or not
|
||||
chroot = true,
|
||||
|
||||
-- chroot_dir: String
|
||||
-- chrooted path
|
||||
chroot_dir = prefix .. "/run",
|
||||
|
||||
-- socket_file: String
|
||||
-- unix domain socket file name
|
||||
-- Note: this file is opened after chroot
|
||||
socket_file = "/sj3serv.socket",
|
||||
|
||||
-- address_famiy: String (unspec or inet4 or inet6)
|
||||
-- listening address family
|
||||
address_famiy = "unspec",
|
||||
|
||||
-- listen: String
|
||||
-- listening address
|
||||
listen = "localhost",
|
||||
|
||||
-- port: String
|
||||
-- listening service name
|
||||
port = "3086",
|
||||
}
|
||||
|
||||
|
|
@ -204,13 +204,12 @@ exec_connect()
|
|||
if (getsockname(cur_client->fd, &addr, &len) < 0)
|
||||
perror("getsockname");
|
||||
|
||||
if (addr.sa_family == AF_UNIX) {
|
||||
if (strict_auth_enable) {
|
||||
getpeereid(cur_client->fd, &euid, &egid);
|
||||
if (ugid.uid != euid || ugid.gid != egid) {
|
||||
longjmp(error_ret, SJ3_NotAllowedUser);
|
||||
}
|
||||
}
|
||||
|
||||
cur_cli -> uid = ugid.uid;
|
||||
} else
|
||||
longjmp(error_ret, SJ3_NotAllowedUser);
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ char chuser_name[BUFSIZ];
|
|||
int chroot_enable = -1;
|
||||
char chroot_dir[MAXPATHLEN];
|
||||
|
||||
int strict_auth_enable = -1;
|
||||
|
||||
char log_file[MAXPATHLEN];
|
||||
|
||||
char debug_file[MAXPATHLEN];
|
||||
|
|
@ -115,11 +117,12 @@ set_server(lua_State *lstate)
|
|||
{
|
||||
if (!sj3lua_check_table(lstate))
|
||||
return 0;
|
||||
lua2sj_integer(lstate, "max_client", 1, MAXCLIENTNUM, &max_client);
|
||||
lua2sj_string(lstate, "dict_dir", 1, DICTROOTDIR, dict_dir, sizeof(dict_dir));
|
||||
lua2sj_string(lstate, "user", 1, SJ3OWNER, chuser_name, sizeof(chuser_name));
|
||||
lua2sj_boolean(lstate, "chroot", 1, CHROOTFLAG, &chroot_enable);
|
||||
lua2sj_string(lstate, "chroot_dir", 1, CHROOTDIR, chroot_dir, sizeof(dict_dir));
|
||||
lua2sj_integer(lstate, "max_client", 1, MAXCLIENTNUM, &max_client);
|
||||
lua2sj_string(lstate, "dict_dir", 1, DICTROOTDIR, dict_dir, sizeof(dict_dir));
|
||||
lua2sj_string(lstate, "user", 1, SJ3OWNER, chuser_name, sizeof(chuser_name));
|
||||
lua2sj_boolean(lstate, "chroot", 1, CHROOTFLAG, &chroot_enable);
|
||||
lua2sj_string(lstate, "chroot_dir", 1, CHROOTDIR, chroot_dir, sizeof(dict_dir));
|
||||
lua2sj_boolean(lstate, "strict_auth", 1, STRICTAUTHFLAG, &strict_auth_enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -264,14 +267,6 @@ get_error(lua_State *lstate)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
set_luafunction(lua_State *lstate, char *name, lua_CFunction fun)
|
||||
{
|
||||
lua_pushstring(lstate, name);
|
||||
lua_pushcfunction(lstate, fun);
|
||||
lua_settable(lstate, -3);
|
||||
}
|
||||
|
||||
void
|
||||
read_runcmd()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ extern char pid_file[MAXPATHLEN];
|
|||
extern char chuser_name[BUFSIZ];
|
||||
extern int chroot_enable;
|
||||
extern char chroot_dir[MAXPATHLEN];
|
||||
extern int strict_auth_enable;
|
||||
extern char domain_socket_name[MAXPATHLEN];
|
||||
extern char dict_dir[MAXPATHLEN];
|
||||
extern char dict_file[FILENAME_MAX];
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ sj3.set_server {
|
|||
-- dictionary name
|
||||
-- Note: this directory is opened after chroot
|
||||
dict_dir = "/spool/sj3",
|
||||
|
||||
-- strict_auth: Boolean
|
||||
-- check always peer userid for security.
|
||||
-- Note: if you want to run sj3serv with sj3proxy, set false
|
||||
strict_auth = true,
|
||||
}
|
||||
|
||||
sj3.set_domain {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue