aboutsummaryrefslogtreecommitdiff
path: root/src/progman.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-11-28 12:09:15 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-11-28 13:15:51 +0200
commit36a53f1875a097fa16bceaf674dc627d916651df (patch)
treeee33a5cf08231f11a3b31e0f16652229d5add561 /src/progman.c
parent69bc6e88c7babf356efbacbdc2230de407c27590 (diff)
downloadpies-36a53f1875a097fa16bceaf674dc627d916651df.tar.gz
pies-36a53f1875a097fa16bceaf674dc627d916651df.tar.bz2
Handle per-tcpmux ACL's. Optionally pass socket data via environment variables.
* src/inetd-bi.c (tcpmux): Consult the component's ACL before deciding whether to handle the connection. * src/pies.c (str_to_socket_type): Rewrite using strtotok. (socket_type_to_str): New function (str_to_cf): New flags: sockenv and resolve. Use strtotok. (main): Log_tag defaults to program instance name. * src/pies.h: Include socket-related headers. (CF_SOCKENV, CF_RESOLVE): New flags. (pies_sockaddr_storage): New union. (check_acl): New proto. (progman_run_comp): Change signature. (socket_type_to_str): New proto. * src/progman.c (struct prog): New members sa_storage, sa_len. (prog_sockenv): New function. (progman_run_comp): Call prog_sockenv. Initialize sa_storage and sa_len of the created struct prog. (prog_start): Call prog_sockenv. Do not close 2 if logging to stderr. (check_acl): Remove static. (_prog_accept): Use union pies_sockaddr_storage. Pass socket address in pinst->v.p.sa_storage and pinst->v.p.sa_len. (sockenv_hint, envsize): New variables. (add_env): New function. (env_setup): Remove. (environ_setup): New function. * src/socket.c: Remove unnecessary includes.
Diffstat (limited to 'src/progman.c')
-rw-r--r--src/progman.c264
1 files changed, 215 insertions, 49 deletions
diff --git a/src/progman.c b/src/progman.c
index 4743507..fa4e377 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -57,6 +57,8 @@ struct prog
size_t num_instances; /* Number of running instances */
/* If comp->type == pies_comp_inetd && status == status_enabled */
struct prog *listener;
+ union pies_sockaddr_storage sa_storage;
+ size_t sa_len;
} p;
struct
@@ -507,19 +509,101 @@ open_redirector (struct prog *master, int stream)
}
}
-extern char **environ;
+
+extern char **environ; /* Environment */
+static size_t envsize; /* Size of environ. If it is not 0, then we
+ have allocated space for the environ. */
+
+#define ENV_PROTO "PROTO"
+#define ENV_SOCKTYPE "SOCKTYPE"
+#define ENV_LOCALIP "LOCALIP"
+#define ENV_LOCALPORT "LOCALPORT"
+#define ENV_LOCALHOST "LOCALHOST"
+#define ENV_REMOTEIP "REMOTEIP"
+#define ENV_REMOTEPORT "REMOTEPORT"
+#define ENV_REMOTEHOST "REMOTEHOST"
+
+static char *sockenv_hint[] = {
+ "-" ENV_PROTO,
+ "-" ENV_SOCKTYPE,
+ "-" ENV_LOCALIP,
+ "-" ENV_LOCALPORT,
+ "-" ENV_LOCALHOST,
+ "-" ENV_REMOTEIP,
+ "-" ENV_REMOTEPORT,
+ "-" ENV_REMOTEHOST,
+ NULL
+};
-static char *
-find_env (const char *name, int val)
+#define DEBUG_ENVIRON(l) \
+ do \
+ if (debug_level >= (l)) \
+ { \
+ int i; \
+ logmsg_printf (LOG_DEBUG, "environment: "); \
+ for (i = 0; environ[i]; i++) \
+ logmsg_printf (LOG_DEBUG, "%s ", environ[i]); \
+ logmsg_printf (LOG_DEBUG, "\n"); \
+ } \
+ while (0)
+
+static void
+add_env (const char *name, const char *value)
{
- int nlen = strcspn (name, "+=");
- int i;
+ size_t i;
+ size_t namelen = strlen (name);
+ char *p;
for (i = 0; environ[i]; i++)
{
- size_t elen = strcspn (environ[i], "=");
- if (elen == nlen && memcmp (name, environ[i], nlen) == 0)
- return val ? environ[i] + elen + 1 : environ[i];
+ if (!strncmp (environ[i], name, namelen) && environ[i][namelen] == '=')
+ break;
+ }
+
+ if (environ[i] == NULL)
+ {
+ if (envsize == 0)
+ {
+ char **new_env;
+
+ envsize = i + 4;
+ new_env = xcalloc (envsize, sizeof new_env[0]);
+ for (i = 0; new_env[i] = environ[i]; i++)
+ ;
+ environ = new_env;
+ }
+ else if (i == envsize)
+ {
+ envsize += 4;
+ environ = xrealloc (environ,
+ envsize * sizeof environ[0]);
+ }
+ environ[i+1] = NULL;
+ }
+
+ if (!value)
+ value = "";
+ p = xmalloc (namelen + 1 + strlen (value) + 1);
+ strcpy (p, name);
+ p[namelen] = '=';
+ strcpy (p + namelen + 1, value);
+ environ[i] = p;
+}
+
+static char *
+find_env (const char *name, int val)
+{
+ if (environ)
+ {
+ int nlen = strcspn (name, "+=");
+ int i;
+
+ for (i = 0; environ[i]; i++)
+ {
+ size_t elen = strcspn (environ[i], "=");
+ if (elen == nlen && memcmp (name, environ[i], nlen) == 0)
+ return val ? environ[i] + elen + 1 : environ[i];
+ }
}
return NULL;
}
@@ -580,20 +664,20 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b)
return res;
}
-static char **
-env_setup (char **env)
+static void
+environ_setup (char **hint)
{
char **old_env = environ;
char **new_env;
- int count, i, n;
+ size_t count, i, n;
- if (!env)
- return old_env;
+ if (!hint)
+ return;
- if (strcmp (env[0], "-") == 0)
+ if (strcmp (hint[0], "-") == 0)
{
old_env = NULL;
- env++;
+ hint++;
}
/* Count new environment size */
@@ -602,10 +686,10 @@ env_setup (char **env)
for (i = 0; old_env[i]; i++)
count++;
- for (i = 0; env[i]; i++)
+ for (i = 0; hint[i]; i++)
count++;
- /* Allocate the new environment. */
+ /* Allocate new environment. */
new_env = xcalloc (count + 1, sizeof new_env[0]);
/* Populate the environment. */
@@ -614,41 +698,122 @@ env_setup (char **env)
if (old_env)
for (i = 0; old_env[i]; i++)
{
- if (!locate_unset (env, old_env[i]))
+ if (!locate_unset (hint, old_env[i]))
new_env[n++] = old_env[i];
}
- for (i = 0; env[i]; i++)
+ for (i = 0; hint[i]; i++)
{
char *p;
- if (env[i][0] == '-')
+ if (hint[i][0] == '-')
{
/* Skip unset directives. */
continue;
}
- if ((p = strchr (env[i], '=')))
+ if ((p = strchr (hint[i], '=')))
{
- if (p == env[i])
+ if (p == hint[i])
continue; /* Ignore erroneous entry */
if (p[-1] == '+')
- new_env[n++] = env_concat (env[i], p - env[i] - 1,
- find_env(env[i], 1), p + 1);
+ new_env[n++] = env_concat (hint[i], p - hint[i] - 1,
+ find_env(hint[i], 1), p + 1);
else if (p[1] == '+')
- new_env[n++] = env_concat (env[i], p - env[i],
- p + 2, find_env(env[i], 1));
+ new_env[n++] = env_concat (hint[i], p - hint[i],
+ p + 2, find_env(hint[i], 1));
else
- new_env[n++] = env[i];
+ new_env[n++] = hint[i];
}
else
{
- p = find_env (env[i], 0);
+ p = find_env (hint[i], 0);
if (p)
new_env[n++] = p;
}
}
new_env[n] = NULL;
- return new_env;
+
+ if (envsize)
+ free (environ);
+
+ environ = new_env;
+ envsize = count + 1;
+}
+
+/* Pass socket information in environment variables. */
+void
+prog_sockenv (struct prog *prog)
+{
+ char buf[INT_BUFSIZE_BOUND (uintmax_t)];
+ char *p;
+ struct hostent *host;
+ union pies_sockaddr_storage sa_server;
+ socklen_t len = sizeof (sa_server);
+ union pies_sockaddr_storage *sa_client = &prog->v.p.sa_storage;
+ socklen_t cltlen = prog->v.p.sa_len;
+ const char *proto = NULL;
+
+ if (!(prog->v.p.comp->flags & CF_SOCKENV))
+ return;
+
+ if (socket_type_to_str (prog->v.p.comp->socket_type, &proto))
+ proto = umaxtostr (prog->v.p.comp->socket_type, buf);
+ add_env (ENV_SOCKTYPE, proto);
+
+ if (prog->v.p.comp->socket_url)
+ proto = prog->v.p.comp->socket_url->proto_s;
+ else if (prog->v.p.listener)
+ proto = prog->v.p.listener->v.p.comp->socket_url->proto_s;
+ else if (ISCF_TCPMUX (prog->v.p.comp->flags))
+ proto = "TCP";
+
+ add_env (ENV_PROTO, proto);
+
+ if (getsockname (prog->v.p.socket,
+ (struct sockaddr *) &sa_server, &len) < 0)
+ logmsg (LOG_WARNING, "getsockname(): %s", strerror (errno));
+ else if (sa_server.s.sa_family == AF_INET)
+ {
+ p = inet_ntoa (sa_server.s_in.sin_addr);
+ if (p)
+ add_env (ENV_LOCALIP, p);
+
+ p = umaxtostr (ntohs (sa_server.s_in.sin_port), buf);
+ add_env (ENV_LOCALPORT, p);
+
+ if (prog->v.p.comp->flags & CF_RESOLVE)
+ {
+ if ((host = gethostbyaddr ((char *) &sa_server.s_in.sin_addr,
+ sizeof (sa_server.s_in.sin_addr),
+ AF_INET)) == NULL)
+ logmsg (LOG_WARNING, "gethostbyaddr: %s", strerror (errno));
+ else
+ add_env (ENV_LOCALHOST, host->h_name);
+ }
+ }
+
+ if (cltlen > 0 && sa_client->s.sa_family == AF_INET)
+ {
+ p = inet_ntoa (sa_client->s_in.sin_addr);
+ if (p)
+ add_env (ENV_REMOTEIP, p);
+
+ p = umaxtostr (ntohs (sa_client->s_in.sin_port), buf);
+ add_env (ENV_REMOTEPORT, p);
+
+ if (prog->v.p.comp->flags & CF_RESOLVE)
+ {
+ if ((host = gethostbyaddr ((char *) &sa_client->s_in.sin_addr,
+ sizeof (sa_client->s_in.sin_addr),
+ AF_INET)) == NULL)
+ logmsg (LOG_WARNING, "gethostbyaddr: %s",
+ strerror (errno));
+ else
+ add_env (ENV_REMOTEHOST, host->h_name);
+ }
+ }
+ /* FIXME: $REMOTEINFO ? */
+ DEBUG_ENVIRON (4);
}
static int
@@ -744,15 +909,10 @@ prog_start_prologue (struct prog *prog)
prog->tag, prog->v.p.comp->dir, strerror (errno));
}
- environ = env_setup (prog->v.p.comp->env);
- if (debug_level >= 4)
- {
- int i;
- logmsg_printf (LOG_DEBUG, "environment: ");
- for (i = 0; environ[i]; i++)
- logmsg_printf (LOG_DEBUG, "%s ", environ[i]);
- logmsg_printf (LOG_DEBUG, "\n");
- }
+ environ_setup (prog->v.p.comp->env ?
+ prog->v.p.comp->env :
+ ((prog->v.p.comp->flags & CF_SOCKENV) ? sockenv_hint : NULL));
+ DEBUG_ENVIRON (4);
pies_priv_setup (&prog->v.p.comp->privs);
if (prog->v.p.comp->umask)
@@ -796,11 +956,15 @@ prog_execute (struct prog *prog)
}
void
-progman_run_comp (struct component *comp, int fd)
+progman_run_comp (struct component *comp, int fd,
+ union pies_sockaddr_storage *sa, socklen_t salen)
{
struct prog *prog = register_prog0 (comp, -1);
prog->v.p.socket = fd;
+ prog->v.p.sa_storage = *sa;
+ prog->v.p.sa_len = salen;
prog_start_prologue (prog);
+ prog_sockenv (prog);
prog_execute (prog);
}
@@ -899,6 +1063,8 @@ prog_start (struct prog *prog)
case pies_comp_accept:
case pies_comp_inetd:
+ prog_sockenv (prog);
+
dup2 (prog->v.p.socket, 0);
dup2 (prog->v.p.socket, 1);
close (prog->v.p.socket);
@@ -908,8 +1074,11 @@ prog_start (struct prog *prog)
if (redir[RETR_ERR] == -1)
{
- close (2);
- open ("/dev/null", O_WRONLY);
+ if (!DIAG_OUTPUT (DIAG_TO_STDERR))
+ {
+ close (2);
+ open ("/dev/null", O_WRONLY);
+ }
}
else if (redir[RETR_ERR] != 1)
{
@@ -954,8 +1123,8 @@ prog_start (struct prog *prog)
}
}
-static int
-check_acl (pies_acl_t acl, struct sockaddr *s, int salen)
+int
+check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen)
{
struct acl_input input;
int rc;
@@ -985,11 +1154,7 @@ _prog_accept (struct prog *p)
{
int fd;
struct prog *pinst;
- union
- {
- struct sockaddr s_in;
- struct sockaddr s_un;
- } addr;
+ union pies_sockaddr_storage addr;
socklen_t addrlen = sizeof addr;
fd = accept (p->v.p.socket, (struct sockaddr*) &addr, &addrlen);
@@ -1035,6 +1200,8 @@ _prog_accept (struct prog *p)
pinst = register_prog0 (p->v.p.comp, -1);
pinst->v.p.socket = fd;
pinst->v.p.listener = p;
+ pinst->v.p.sa_storage = addr;
+ pinst->v.p.sa_len = addrlen;
prog_start (pinst);
close (fd);
pinst->v.p.socket = -1;
@@ -1869,7 +2036,6 @@ run_command (struct action *act, struct prog *prog, unsigned retcode,
else
setenv ("PIES_STATUS", umaxtostr (STATUS_CODE (retcode), buf), 1);
- /* FIXME: see above */
close_fds (NULL);
argv[0] = "/bin/sh";

Return to:

Send suggestions and report system problems to the System administrator.