~ubuntu-branches/debian/sid/rlinetd/sid

« back to all changes in this revision

Viewing changes to src/bytecode.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Luberda
  • Date: 2010-03-20 18:03:45 UTC
  • mfrom: (2.3.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100320180345-x1srfbe2tg00ezsf
Tags: 0.7-1
* New upstream version.
* Recommend rsyslog instead of sysklogd (closes: #526922).
* update-inetd:
  + add support for enabling, disabling and removing entries;
  + use ucf for managing generated files;
  + ignore ucf files in rlinetd.conf;
  + make appropriate changes in  postinst and postrm scripts.
* Set debhelper compat level to 7
* Standards-Version: 3.8.4 (no changes). 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <errno.h>
 
2
#include <fcntl.h>
 
3
#include <grp.h>
 
4
#include <stdio.h>
 
5
#include <stdlib.h>
 
6
#include <string.h>
 
7
#include <sysexits.h>
 
8
#include <syslog.h>
 
9
#include <sys/socket.h>
 
10
#include <sys/time.h>
 
11
#include <time.h>
 
12
#include <sys/types.h>
 
13
#include <sys/resource.h>
 
14
#include <sys/wait.h>
 
15
#include <unistd.h>
 
16
#include <netinet/in.h>
 
17
#include <arpa/inet.h>
 
18
 
 
19
#include "config.h"
 
20
 
 
21
#ifdef HAVE_CAPABILITIES
 
22
#include <sys/capability.h>
 
23
#endif
 
24
 
 
25
#ifdef HAVE_TCP_WRAPPERS
 
26
#include <tcpd.h>
 
27
#endif
 
28
 
 
29
#include "buffer.h"
 
30
#include "bytecode.h"
 
31
#include "db.h"
 
32
#include "error.h"
 
33
#include "rlinetd.h"
 
34
#include "signals.h"
 
35
#include "stack.h"
 
36
#ifdef BYTECODE_DEBUG
 
37
#include "assemble.h"
 
38
#endif
 
39
 
 
40
/* we avoid the more tedious sanity checks by assuming that since
 
41
         we wrote the opcodes, they're going to be what we accept. dodgy. */
 
42
 
 
43
#define rl_fail1(a) \
 
44
        rl_warn("%s(%d) failed %s", (a), *op, strerror(errno))
 
45
 
 
46
#define RL_MIN(a, b) ((a) < (b) ? (a) : (b))
 
47
 
 
48
int allow_severity = LOG_INFO;
 
49
int deny_severity = LOG_WARNING;
 
50
 
 
51
#ifdef BYTECODE_DEBUG
 
52
static char * bytecode2string(rl_opcode_t op);
 
53
static char * bytecodeargs2string(rl_opcode_t* op);
 
54
#endif
 
55
 
 
56
void run_bytecode(rl_opcode_t *op, struct rl_instance *inst) {
 
57
        if(!op)
 
58
                return;
 
59
        if(rl_debug > 1)
 
60
                fprintf(stderr, "sched(%d)\n", getpid());
 
61
        do {
 
62
                if(rl_debug > 1)
 
63
#ifdef BYTECODE_DEBUG
 
64
                        fprintf(stderr, "%d: op %d: %s (%s)\n", getpid(), *op, bytecode2string(*op), bytecodeargs2string(op));
 
65
#else           
 
66
                        fprintf(stderr, "op %d\n", *op);
 
67
#endif                  
 
68
                switch(*op) {
 
69
                        struct argvtab *argv;
 
70
                        struct logtab *log;
 
71
                        int i, j, k;
 
72
#ifdef HAVE_TCP_WRAPPERS
 
73
                        struct request_info *request;
 
74
#endif                  
 
75
                        char *str;
 
76
                        gid_t gid;
 
77
                        struct semaphore *sem;
 
78
                        struct buftab *bt;
 
79
                        
 
80
                        case OP_EXEC:
 
81
                                closelog();
 
82
                                fcntl(inst->sock, F_SETFD, 0);
 
83
                                fcntl(inst->sock, F_SETFL, 0);
 
84
                                j = *++op;
 
85
                                argv = argvtab_get(*++op);
 
86
                                argv_build(inst, argv);
 
87
                                str = (j != -1) ? stringtab_get(j) : argv->argv[0];
 
88
                                pid_t ssid = -1;
 
89
                                while ((ssid = setsid() < 0) && errno == EAGAIN)
 
90
                                        ;
 
91
                                if (ssid < 0)
 
92
                                {
 
93
                                        rl_warn("setsid()) for %s: %s", str, strerror(errno));
 
94
                                        exit(EX_DATAERR);
 
95
                                }
 
96
                                for(i = 0; i < 3; i++)
 
97
                                        if(inst->sock != i)
 
98
                                                dup2(inst->sock, i);
 
99
                                if(inst->sock >= 3)
 
100
                                        close(inst->sock);
 
101
                                if(execv(str, argv->argv)) {
 
102
                                        rl_warn("execv(%s): %s", str, strerror(errno));
 
103
                                        exit(EX_DATAERR);
 
104
                                }
 
105
                                break;
 
106
                        case OP_FISH:
 
107
                                rl_warn("Fish!");
 
108
                                break;
 
109
                        case OP_SUID:
 
110
                                if (rl_debug > 1)
 
111
                                        fprintf(stderr, "++setuid: %d\n", *(op + 1));
 
112
                                if(setuid(*++op))
 
113
                                        rl_fail1("setuid");
 
114
                                break;
 
115
                        case OP_SGID:
 
116
                                if (rl_debug > 1)
 
117
                                        fprintf(stderr, "++setgid: %d\n", *(op + 1));
 
118
                                if(setgid(*++op))
 
119
                                        rl_fail1("setgid");
 
120
                                break;
 
121
                        case OP_NICE:
 
122
                                if (rl_debug > 1)
 
123
                                        fprintf(stderr, "++nice: %d\n", *(op + 1));
 
124
                                if(setpriority(PRIO_PROCESS, 0, *++op))
 
125
                                        rl_fail1("setpriority");
 
126
                                break;
 
127
                        case OP_RLIMIT:
 
128
                                j = *++op;
 
129
                                k = *++op;
 
130
                                
 
131
                                if(setrlimit(j, rlimittab_get(k)))
 
132
                                        rl_fail1("setrlimit");
 
133
                                break;
 
134
                        case OP_CHROOT:
 
135
                                argv = argvtab_get(*++op);
 
136
                                string_build(inst, argv);
 
137
                                if(chroot(argv->str))
 
138
                                        rl_fatal(EX_SOFTWARE, _("ABORT - chroot(\"%s\"): %s"), argv->str, strerror(errno));
 
139
                                if(chdir("/"))
 
140
                                        rl_fatal(EX_SOFTWARE, _("ABORT - chdir(\"/\"): %s"), strerror(errno));
 
141
                                break;
 
142
                        case OP_LOG:
 
143
                                log = logtab_get(*++op);
 
144
                                argv = argvtab_get(log->argv);
 
145
                                if(log->fd < 0) {
 
146
                                        string_build(inst, argv);
 
147
                                        syslog(LOG_INFO, argv->str);
 
148
                                } else {
 
149
                                        iov_build(inst, argv);
 
150
                                        if(writev(log->fd, argv->iov, argv->argc) < 0)
 
151
                                                rl_warn("writev() log: %s", strerror(errno));
 
152
                                }
 
153
                                break;
 
154
                        case OP_ACCEPT:
 
155
                                i = *++op;
 
156
 
 
157
                                if(inst->sin)
 
158
                                        free(inst->sin);
 
159
                                inst->sin = NULL;
 
160
                                inst->sinlen = i;
 
161
                                if(i) {
 
162
                                        inst->sin = (struct sockaddr *)malloc(i);
 
163
                                        if (!inst->sin)
 
164
                                                rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory"));
 
165
                                }
 
166
                                if((inst->sock = accept(inst->sock, inst->sin, &inst->sinlen)) < 0) {
 
167
                                        rl_warn("accept(): %s", strerror(errno));
 
168
                                        return;
 
169
                                }
 
170
                                fcntl(inst->sock, F_SETFL, O_NDELAY);   /* boggle */
 
171
                                if(fcntl(inst->sock, F_SETFD, 0) == -1) {
 
172
                                        rl_warn("fcntl(%d, F_SETFD, 0): %s", inst->sock, strerror(errno));
 
173
                                }
 
174
                                break;
 
175
                        case OP_FORK:
 
176
                                k = *++op;
 
177
                                i = *++op;
 
178
                                rls_block();
 
179
                                switch(j = fork()) {
 
180
                                        case -1:
 
181
                                                rl_warn(_("fork() failed - %s"), strerror(errno));
 
182
                                                break;
 
183
                                        case 0:
 
184
                                                rls_unblock();
 
185
                                                all_unhook();
 
186
                                                rlstk_push(&inst->stk, 0);
 
187
                                                run_bytecode(++op, inst);
 
188
                                                exit(rlstk_pop(&inst->stk));
 
189
                                                break;
 
190
                                        default:
 
191
                                                inst->start = time(NULL);
 
192
                                                pidtab_add(j, i, inst);
 
193
                                                rls_unblock();
 
194
                                                return run_bytecode(oplisttab_get(k), inst);
 
195
                                }
 
196
                                break;
 
197
                        case OP_WRAP:
 
198
                                str = stringtab_get(*++op);
 
199
                                k = *++op;
 
200
#ifdef HAVE_TCP_WRAPPERS
 
201
                                request = (struct request_info *)malloc(sizeof(struct request_info));
 
202
                                if (request == NULL)
 
203
                                        rl_fatal(EX_SOFTWARE, _("ABORT - Can't allocate memory (OP: %d)"), *op);
 
204
 
 
205
                                request_init(request, RQ_FILE, inst->sock,
 
206
                                                RQ_CLIENT_SIN, inst->sin,
 
207
                                                RQ_DAEMON, str,
 
208
                                                0);
 
209
                                /* undocumented tcp wrappers magic -
 
210
                                 * does DNS lookup and possibly other stuff */
 
211
                                fromhost(request);
 
212
 
 
213
                                if(!hosts_access(request)) {
 
214
                                        char host_ip[100];
 
215
                                        struct loglist l;
 
216
 
 
217
                                        /* get address of client */
 
218
                                        l.type = LOG_SOURCE_IP;
 
219
                                        l.arg = host_ip;
 
220
                                        l.len = sizeof(l.arg);
 
221
                                        loglist_build( inst, &l );
 
222
 
 
223
                                        rl_warn(_("access for service %s from host %s denied by TCP wrappers"), str, host_ip);
 
224
                                        free( request );
 
225
                                        run_bytecode(oplisttab_get(k), inst);
 
226
                                }
 
227
#endif
 
228
                                break;
 
229
                        case OP_SETCAP:
 
230
#ifdef HAVE_CAPABILITIES
 
231
                                if(cap_set_proc(captab_get(*++op)))
 
232
                                        rl_warn("cap_set_proc(): %s",   strerror(errno));
 
233
#endif                          
 
234
                                break;
 
235
                        case OP_INITGR:
 
236
                                str = stringtab_get(*++op);
 
237
                                gid = (gid_t)*++op;
 
238
                                if (rl_debug > 1)
 
239
                                        fprintf(stderr, "++initgr: %s, %d\n", str, gid);
 
240
                                if(initgroups(str, gid))
 
241
                                        rl_warn("initgroups(%s, %d): %s", str, gid, strerror(errno));
 
242
                                break;
 
243
                        case OP_BRANCH:
 
244
                                j = *++op;
 
245
                                op += j;
 
246
                                break;
 
247
                        case OP_CLOSE:
 
248
                                if((inst->sock != -1) && close(inst->sock))
 
249
                                        rl_warn("close(%d): %s", inst->sock, strerror(errno));
 
250
                                inst->sock = -1;
 
251
                                return;
 
252
                        case OP_BUFCOPY:
 
253
                                rlstk_push(&inst->stk, rlbuf_copy(inst->sock, inst->buf, rlstk_pop(&inst->stk)));
 
254
                                break;
 
255
                        case OP_ZERO:
 
256
                                rlstk_push(&inst->stk, 0);
 
257
                                break;
 
258
                        case OP_RET:
 
259
                                return;
 
260
                        case OP_EXIT:
 
261
                                exit(0);
 
262
                                return;
 
263
                        case OP_ECHO:
 
264
                                argv = argvtab_get(*++op);
 
265
                                
 
266
                                iov_build(inst, argv);
 
267
                                if(writev(inst->sock, argv->iov, argv->argc) < 0)
 
268
                                        rl_warn("writev(): %s", strerror(errno));
 
269
                                break;
 
270
                        case OP_UP:
 
271
                                sem = semaphore_get(*++op);
 
272
                                if(sem->count-- == sem->limit)
 
273
                                        run_bytecode(oplisttab_get(sem->under), inst);
 
274
                                break;
 
275
                        case OP_DOWN:
 
276
                                sem = semaphore_get(*++op);
 
277
                                if(++sem->count == sem->limit)
 
278
                                        run_bytecode(oplisttab_get(sem->match), inst);
 
279
                                break;
 
280
                        case OP_FROG:
 
281
                                rl_warn("Frog!");
 
282
                                break;
 
283
                        case OP_LSET:
 
284
                                listeners_set(*++op);
 
285
                                break;
 
286
                        case OP_LCLR:
 
287
                                listeners_clear(*++op);
 
288
                                break;
 
289
                        case OP_BUFINIT:
 
290
                                rlbuf_init(&inst->buf, *++op);
 
291
                                break;
 
292
                        case OP_BUFREAD:
 
293
                                rlstk_push(&inst->stk, rlbuf_read(inst->sock, inst->buf));
 
294
                                break;
 
295
                        case OP_BUFWRITE:
 
296
                                rlstk_push(&inst->stk, rlbuf_write(inst->sock, inst->buf));
 
297
                                break;
 
298
                        case OP_RHOOK:
 
299
                                ++op;
 
300
                                read_hook(inst->sock, op + 1 + *op, inst);
 
301
                                return;
 
302
                        case OP_RUNHOOK:
 
303
                                read_unhook(inst->sock);
 
304
                                break;
 
305
                        case OP_WHOOK:
 
306
                                ++op;
 
307
                                write_hook(inst->sock, op + 1 + *op, inst);
 
308
                                return;
 
309
                        case OP_WUNHOOK:
 
310
                                write_unhook(inst->sock);
 
311
                                break;
 
312
                        case OP_BZ:
 
313
                                j = *++op;
 
314
 
 
315
                                if(!rlstk_pop(&inst->stk))
 
316
                                        op += j;
 
317
                                break;
 
318
                        case OP_JUMP:
 
319
                                j = *++op;
 
320
 
 
321
                                return run_bytecode(oplisttab_get(j), inst);
 
322
                        case OP_BZNEG:
 
323
                                j = *++op;
 
324
 
 
325
                                if(rlstk_pop(&inst->stk) <= 0)
 
326
                                        op += j;
 
327
                                break;
 
328
                        case OP_ADD:
 
329
                                j = rlstk_peek(&inst->stk, 1);
 
330
 
 
331
                                rlstk_poke(&inst->stk, 0, rlstk_pop(&inst->stk) + j);
 
332
                                break;
 
333
                        case OP_SUB:
 
334
                                j = rlstk_peek(&inst->stk, 1);
 
335
 
 
336
                                rlstk_poke(&inst->stk, 0, j - rlstk_pop(&inst->stk));
 
337
                                break;
 
338
                        case OP_DUP:
 
339
                                rlstk_push(&inst->stk, rlstk_peek(&inst->stk, 0));
 
340
                                break;
 
341
                        case OP_POP:
 
342
                                rlstk_pop(&inst->stk);
 
343
                                break;
 
344
                        case OP_BUFCLONE:
 
345
                                bt = buftab_get(*++op);
 
346
 
 
347
                                rlbuf_init(&inst->buf, 0);
 
348
                                inst->buf->data = bt->addr;
 
349
                                inst->buf->size = inst->buf->head = bt->len;
 
350
                                break;
 
351
                        case OP_BUFFREE:
 
352
                                inst->buf->data = NULL;
 
353
                                inst->buf->size = 0;
 
354
                                break;
 
355
                        default:
 
356
                                                                                                                                /* should never happen */
 
357
                                rl_fatal(EX_SOFTWARE, _("ABORT - Unknown opcode (%d)"), *op);
 
358
                                break;
 
359
                }
 
360
        } while(op++);
 
361
}
 
362
 
 
363
#ifdef BYTECODE_DEBUG
 
364
static char * bytecode2string(rl_opcode_t op)
 
365
{
 
366
        switch(op) {
 
367
        
 
368
                case OP_EXEC    : return "OP_EXEC";
 
369
                case OP_FISH    : return "OP_FISH";
 
370
                case OP_SUID    : return "OP_SUID";
 
371
                case OP_SGID    : return "OP_SGID";
 
372
                case OP_NICE    : return "OP_NICE";
 
373
                case OP_RLIMIT  : return "OP_RLIMIT";
 
374
                case OP_LOG     : return "OP_LOG";
 
375
                case OP_CHROOT  : return "OP_CHROOT";
 
376
                case OP_ACCEPT  : return "OP_ACCEPT";
 
377
                case OP_FORK    : return "OP_FORK";
 
378
                case OP_WRAP    : return "OP_WRAP";
 
379
                case OP_SETCAP  : return "OP_SETCAP";
 
380
                case OP_INITGR  : return "OP_INITGR";
 
381
                case OP_BRANCH  : return "OP_BRANCH";
 
382
                case OP_CLOSE   : return "OP_CLOSE";
 
383
                case OP_BUFCOPY : return "OP_BUFCOPY";
 
384
                case OP_ZERO    : return "OP_ZERO";
 
385
                case OP_RET     : return "OP_RET";
 
386
                case OP_EXIT    : return "OP_EXIT";
 
387
                case OP_ECHO    : return "OP_ECHO";
 
388
                case OP_UP      : return "OP_UP";
 
389
                case OP_DOWN    : return "OP_DOWN";
 
390
                case OP_FROG    : return "OP_FROG";
 
391
                case OP_LSET    : return "OP_LSET";
 
392
                case OP_LCLR    : return "OP_LCLR";
 
393
                case OP_BUFINIT : return "OP_BUFINIT";
 
394
                case OP_BUFREAD : return "OP_BUFREAD";
 
395
                case OP_BUFWRITE: return "OP_BUFWRITE";
 
396
                case OP_RHOOK   : return "OP_RHOOK";
 
397
                case OP_RUNHOOK : return "OP_RUNHOOK";
 
398
                case OP_WHOOK   : return "OP_WHOOK";
 
399
                case OP_WUNHOOK : return "OP_WUNHOOK";
 
400
                case OP_BZ      : return "OP_BZ";
 
401
                case OP_JUMP    : return "OP_JUMP";
 
402
                case OP_BZNEG   : return "OP_BZNEG";
 
403
                case OP_ADD     : return "OP_ADD";
 
404
                case OP_SUB     : return "OP_SUB";
 
405
                case OP_DUP     : return "OP_DUP";
 
406
                case OP_POP     : return "OP_POP";
 
407
                case OP_BUFCLONE: return "OP_BUFCLONE";
 
408
                case OP_BUFFREE : return "OP_BUFFREE";
 
409
                default         : return "UNKNOWN";
 
410
        }
 
411
}
 
412
static char *
 
413
bytecodeargs2string (rl_opcode_t * op)
 
414
{
 
415
  int nargs;
 
416
 
 
417
  switch (*op)
 
418
  {
 
419
    case OP_ACCEPT:
 
420
    case OP_BRANCH:
 
421
    case OP_BUFCLONE:
 
422
    case OP_BUFCOPY:
 
423
    case OP_BUFINIT:
 
424
    case OP_BZNEG:
 
425
    case OP_BZ:
 
426
    case OP_CHROOT:
 
427
    case OP_DOWN:
 
428
    case OP_ECHO:
 
429
    case OP_JUMP:
 
430
    case OP_LCLR:
 
431
    case OP_LOG:
 
432
    case OP_LSET:
 
433
    case OP_NICE:
 
434
    case OP_RHOOK:
 
435
    case OP_SETCAP:
 
436
    case OP_SGID:
 
437
    case OP_SUID:
 
438
    case OP_UP:
 
439
    case OP_WHOOK:
 
440
      nargs = 1;
 
441
      break;
 
442
 
 
443
    case OP_EXEC:
 
444
    case OP_FORK:
 
445
    case OP_INITGR:
 
446
    case OP_RLIMIT:
 
447
    case OP_WRAP:
 
448
      nargs = 2;
 
449
      break;
 
450
    default:
 
451
      nargs = 0;
 
452
      break;
 
453
  }
 
454
 
 
455
  static char buf[128];
 
456
  int i;
 
457
        buf[0] = 0;
 
458
 
 
459
  for (i = 0; i < nargs; ++i)
 
460
  {
 
461
      sprintf (buf + strlen (buf), "%s%d", i ? ", " : "", *(op + i + 1));
 
462
  }
 
463
  return buf;
 
464
 
 
465
};
 
466
 
 
467
#endif
 
468
 
 
469
/* vim: set ts=2: */