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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/* vi: set sw=4 ts=4: */
/*
* Fake identd server.
*
* Copyright (C) 2007 Denis Vlasenko
*
* Licensed under GPL version 2, see file LICENSE in this tarball for details.
*/
#include <syslog.h>
#include "busybox.h"
#include "isrv.h"
enum { TIMEOUT = 20 };
typedef struct identd_buf_t {
int pos;
int fd_flag;
char buf[64 - 2*sizeof(int)];
} identd_buf_t;
static const char *bogouser = "nobody";
static int new_peer(isrv_state_t *state, int fd)
{
int peer;
identd_buf_t *buf = xzalloc(sizeof(*buf));
peer = isrv_register_peer(state, buf);
if (peer < 0)
return 0; /* failure */
if (isrv_register_fd(state, peer, fd) < 0)
return peer; /* failure, unregister peer */
buf->fd_flag = fcntl(fd, F_GETFL, 0) | O_NONBLOCK;
isrv_want_rd(state, fd);
return 0;
}
static int do_rd(int fd, void **paramp)
{
identd_buf_t *buf = *paramp;
char *cur, *p;
int retval = 0; /* session is ok (so far) */
int sz;
cur = buf->buf + buf->pos;
if (buf->fd_flag & O_NONBLOCK)
fcntl(fd, F_SETFL, buf->fd_flag);
sz = safe_read(fd, cur, sizeof(buf->buf) - buf->pos);
if (sz < 0) {
if (errno != EAGAIN)
goto term; /* terminate this session if !EAGAIN */
goto ok;
}
buf->pos += sz;
buf->buf[buf->pos] = '\0';
p = strpbrk(cur, "\r\n");
if (p)
*p = '\0';
if (!p && sz && buf->pos <= sizeof(buf->buf))
goto ok;
/* Terminate session. If we are in server mode, then
* fd is still in nonblocking mode - we never block here */
fdprintf(fd, "%s : USERID : UNIX : %s\r\n", buf->buf, bogouser);
term:
free(buf);
retval = 1; /* terminate */
ok:
if (buf->fd_flag & O_NONBLOCK)
fcntl(fd, F_SETFL, buf->fd_flag & ~O_NONBLOCK);
return retval;
}
static int do_timeout(void **paramp)
{
return 1; /* terminate session */
}
static void inetd_mode(void)
{
identd_buf_t *buf = xzalloc(sizeof(*buf));
/* We do NOT want nonblocking I/O here! */
buf->fd_flag = fcntl(0, F_GETFL, 0);
do
alarm(TIMEOUT);
while (do_rd(0, (void*)&buf) == 0) /* repeat */;
}
int fakeidentd_main(int argc, char **argv)
{
enum {
OPT_foreground = 0x1,
OPT_inetd = 0x2,
OPT_inetdwait = 0x4,
OPT_nodeamon = 0x7,
OPT_bindaddr = 0x8,
};
const char *bind_address = NULL;
unsigned opt;
int fd;
opt = getopt32(argc, argv, "fiwb:", &bind_address);
if (optind < argc)
bogouser = argv[optind];
/* Daemonize if no -f or -i or -w */
bb_sanitize_stdio(!(opt & OPT_nodeamon));
if (!(opt & OPT_nodeamon)) {
openlog(applet_name, 0, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
}
if (opt & OPT_inetd) {
inetd_mode();
return 0;
}
/* Ignore closed connections when writing */
signal(SIGPIPE, SIG_IGN);
if (opt & OPT_inetdwait) {
fd = 0;
} else {
fd = create_and_bind_stream_or_die(bind_address,
bb_lookup_port("identd", "tcp", 113));
xlisten(fd, 5);
}
isrv_run(fd, new_peer, do_rd, /*do_wr:*/ NULL, do_timeout,
TIMEOUT, (opt & OPT_inetdwait) ? TIMEOUT : 0);
return 0;
}
|