new server "sj3proxy".

this server is communicating between unix domain and inet.
This commit is contained in:
iratqq 2008-02-02 13:25:16 +00:00
commit 7e097c2015
16 changed files with 738 additions and 21 deletions

View file

@ -835,8 +835,9 @@ fi
SJ3SYSCONFDIR=$sj3sysconf_dir SJ3SYSCONFDIR=$sj3sysconf_dir
AC_SUBST(SJ3SYSCONFDIR) AC_SUBST(SJ3SYSCONFDIR)
AC_DEFINE_UNQUOTED(SJ3CONFDIR, "$sj3sysconf_dir", [server config dir]) AC_DEFINE_UNQUOTED(SJ3CONFDIR, "$sj3sysconf_dir", [server config dir])
AC_DEFINE_UNQUOTED(RUNCMDFILE, "$sj3sysconf_dir/sj3serv.lua", [server config file]) 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 dnl configure config directory
sj3var_dir=`echo $localstatedir | grep prefix` sj3var_dir=`echo $localstatedir | grep prefix`
@ -855,6 +856,8 @@ fi
SJ3VARDIR="$sj3var_dir" SJ3VARDIR="$sj3var_dir"
AC_SUBST(SJ3VARDIR) AC_SUBST(SJ3VARDIR)
AC_DEFINE_UNQUOTED(CHROOTDIR, "$sj3var_dir/spool/sj3", [chrooted dir]) 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]) AC_DEFINE_UNQUOTED(SOCKETNAME, "$sj3var_dir/run/sj3serv.socket", [socket file])
SJ3DICTDIR="$sj3var_dir/spool/sj3" SJ3DICTDIR="$sj3var_dir/spool/sj3"
@ -894,6 +897,7 @@ AC_CONFIG_FILES([
src/sj3demo/Makefile src/sj3demo/Makefile
src/sj3dic/Makefile src/sj3dic/Makefile
src/sj3mkdic/Makefile src/sj3mkdic/Makefile
src/sj3proxy/Makefile
src/sj3serv/Makefile src/sj3serv/Makefile
src/sj3stat/Makefile src/sj3stat/Makefile
]) ])

View file

@ -66,7 +66,7 @@
#define PORTNAME "sj3" #define PORTNAME "sj3"
#define LOCALHOST "localhost" #define LOCALHOST "localhost"
#define CHROOTFLAG 1 #define CHROOTFLAG 1
#define STRICTAUTHFLAG 1
#define MAINDICTIONARY "sj3main.dic" #define MAINDICTIONARY "sj3main.dic"
#define USERDICTIONARY "private.dic" #define USERDICTIONARY "private.dic"
#define STUDYFILE "study.dat" #define STUDYFILE "study.dat"

View file

@ -17,9 +17,6 @@
#ifndef SJ3LUA_H #ifndef SJ3LUA_H
#define SJ3LUA_H #define SJ3LUA_H
#include <stdio.h>
#include <lua.h>
int sj3lua_check_table(lua_State *); int sj3lua_check_table(lua_State *);
int lua2sj_boolean(lua_State *, char *, int, int, int *); int lua2sj_boolean(lua_State *, char *, int, int, int *);
int lua2sj_integer(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_boolean(lua_State *, char *, int);
void sj2lua_integer(lua_State *, char *, int); void sj2lua_integer(lua_State *, char *, int);
void sj2lua_string(lua_State *, char *, char *); void sj2lua_string(lua_State *, char *, char *);
void set_luafunction(lua_State *, char *, lua_CFunction);
#endif #endif

View file

@ -119,3 +119,11 @@ sj2lua_string(lua_State *lstate, char *name, char *s)
lua_pushstring(lstate, s); lua_pushstring(lstate, s);
lua_settable(lstate, -3); 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);
}

View file

@ -2,5 +2,6 @@ SUBDIRS = \
sj3mkdic \ sj3mkdic \
sj3serv \ sj3serv \
sj3dic \ sj3dic \
sj3proxy \
sj3stat \ sj3stat \
sj3demo sj3demo

View 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);
}

View 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 */

View 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
View 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);
}
}

View 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);
}

View 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

View 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",
}

View file

@ -204,13 +204,12 @@ exec_connect()
if (getsockname(cur_client->fd, &addr, &len) < 0) if (getsockname(cur_client->fd, &addr, &len) < 0)
perror("getsockname"); perror("getsockname");
if (addr.sa_family == AF_UNIX) { if (strict_auth_enable) {
getpeereid(cur_client->fd, &euid, &egid); getpeereid(cur_client->fd, &euid, &egid);
if (ugid.uid != euid || ugid.gid != egid) { if (ugid.uid != euid || ugid.gid != egid) {
longjmp(error_ret, SJ3_NotAllowedUser); longjmp(error_ret, SJ3_NotAllowedUser);
} }
} }
cur_cli -> uid = ugid.uid; cur_cli -> uid = ugid.uid;
} else } else
longjmp(error_ret, SJ3_NotAllowedUser); longjmp(error_ret, SJ3_NotAllowedUser);

View file

@ -80,6 +80,8 @@ char chuser_name[BUFSIZ];
int chroot_enable = -1; int chroot_enable = -1;
char chroot_dir[MAXPATHLEN]; char chroot_dir[MAXPATHLEN];
int strict_auth_enable = -1;
char log_file[MAXPATHLEN]; char log_file[MAXPATHLEN];
char debug_file[MAXPATHLEN]; char debug_file[MAXPATHLEN];
@ -115,11 +117,12 @@ set_server(lua_State *lstate)
{ {
if (!sj3lua_check_table(lstate)) if (!sj3lua_check_table(lstate))
return 0; return 0;
lua2sj_integer(lstate, "max_client", 1, MAXCLIENTNUM, &max_client); lua2sj_integer(lstate, "max_client", 1, MAXCLIENTNUM, &max_client);
lua2sj_string(lstate, "dict_dir", 1, DICTROOTDIR, dict_dir, sizeof(dict_dir)); lua2sj_string(lstate, "dict_dir", 1, DICTROOTDIR, dict_dir, sizeof(dict_dir));
lua2sj_string(lstate, "user", 1, SJ3OWNER, chuser_name, sizeof(chuser_name)); lua2sj_string(lstate, "user", 1, SJ3OWNER, chuser_name, sizeof(chuser_name));
lua2sj_boolean(lstate, "chroot", 1, CHROOTFLAG, &chroot_enable); lua2sj_boolean(lstate, "chroot", 1, CHROOTFLAG, &chroot_enable);
lua2sj_string(lstate, "chroot_dir", 1, CHROOTDIR, chroot_dir, sizeof(dict_dir)); lua2sj_string(lstate, "chroot_dir", 1, CHROOTDIR, chroot_dir, sizeof(dict_dir));
lua2sj_boolean(lstate, "strict_auth", 1, STRICTAUTHFLAG, &strict_auth_enable);
return 0; return 0;
} }
@ -264,14 +267,6 @@ get_error(lua_State *lstate)
return 0; 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 void
read_runcmd() read_runcmd()
{ {

View file

@ -118,6 +118,7 @@ extern char pid_file[MAXPATHLEN];
extern char chuser_name[BUFSIZ]; extern char chuser_name[BUFSIZ];
extern int chroot_enable; extern int chroot_enable;
extern char chroot_dir[MAXPATHLEN]; extern char chroot_dir[MAXPATHLEN];
extern int strict_auth_enable;
extern char domain_socket_name[MAXPATHLEN]; extern char domain_socket_name[MAXPATHLEN];
extern char dict_dir[MAXPATHLEN]; extern char dict_dir[MAXPATHLEN];
extern char dict_file[FILENAME_MAX]; extern char dict_file[FILENAME_MAX];

View file

@ -37,6 +37,11 @@ sj3.set_server {
-- dictionary name -- dictionary name
-- Note: this directory is opened after chroot -- Note: this directory is opened after chroot
dict_dir = "/spool/sj3", 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 { sj3.set_domain {