File: relay-filter.c

package info (click to toggle)
ucspi-proxy 0.99-8
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 380 kB
  • sloc: ansic: 1,957; makefile: 46
file content (121 lines) | stat: -rw-r--r-- 2,792 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <sysdeps.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <bglibs/msg.h>
#include <bglibs/sig.h>
#include "ucspi-proxy.h"

static unsigned relay_rerun_delay;
static const char* client_ip;
static char** relay_command;

static void run_relay_ctrl(void)
{
  /* Run relay-ctrl-allow to allow the client's IP to relay */
  const pid_t p = fork();
  switch (p) {
  case -1:
    error1sys("Could not fork");
    return;
  case 0:
    execvp(relay_command[0], relay_command);
    exit(1);
  }
}

static void catch_child(int ignored)
{
  waitpid(-1, 0, WNOHANG);
  ignored = 0;
}

static void catch_alarm(int ignored)
{
  if (relay_command == 0)
    return;
  /* Run the relay-ctrl process, and then set it up to re-run */
  if (opt_verbose)
    msg2("Running ", relay_command[0]);
  run_relay_ctrl();
  alarm(relay_rerun_delay);
  ignored = 0;
}

void relay_init(int argc, char* argv[])
{
  char* tmp;
  client_ip = getenv("TCPREMOTEIP");
  if (argc >= 1) {
    relay_command = argv;
    if ((tmp = getenv("PROXY_RELAY_INTERVAL")) != 0) {
      relay_rerun_delay = strtoul(tmp, &tmp, 10);
      if (*tmp != 0)
	usage("Delay parameter is not a positive number");
    }
    if (relay_rerun_delay == 0)
      relay_rerun_delay = 300;
  }
}

static void setenvb(const char* name, const char* value, size_t len)
{
  char* s;
  size_t nlen = strlen(name);
  if ((s = malloc(len + nlen + 2)) == 0)
    die_oom(111);
  memcpy(s, name, nlen);
  s[nlen++] = '=';
  memcpy(s + nlen, value, len);
  s[nlen + len] = 0;
  if (putenv(s) != 0)
    die_oom(111);
}

/* Export the username through $USER and $DOMAIN */
static void export_client(const char* username)
{
  const char* at;
  if ((at = strrchr(username, '@')) == 0) {
    setenvb("USER", username, strlen(username));
    setenvb("DOMAIN", 0, 0);
  }
  else {
    setenvb("USER", username, at - username);
    ++at;
    setenvb("DOMAIN", at, strlen(at));
  }
}

void accept_client(const char* username)
{
  if (opt_verbose) {
    if (username)
      msg5("Accepted relay client ", client_ip, ", username '", username, "'");
    else
      msg3("Accepted relay client ", client_ip, ", username unknown");
  }
  if (username)
    export_client(username);
  
  /* Turn off all further filtering, as this IP has already authenticated */
  set_filter(CLIENT_IN, (filter_fn)write_server, 0);
  set_filter(SERVER_FD, (filter_fn)write_client, 0);

  sig_child_catch(catch_child);
  sig_alarm_catch(catch_alarm);
  catch_alarm(0);
}

void deny_client(const char* username)
{
  if (opt_verbose) {
    if (username)
      msg5("Failed login from ", client_ip, ", username '", username, "'");
    else
      msg3("Failed login from ", client_ip, ", username unknown");
  }
}