1 | /* |
---|
2 | * percent_x() takes a string and performs %<char> expansions. It aborts the |
---|
3 | * program when the expansion would overflow the output buffer. The result |
---|
4 | * of %<char> expansion may be passed on to a shell process. For this |
---|
5 | * reason, characters with a special meaning to shells are replaced by |
---|
6 | * underscores. |
---|
7 | * |
---|
8 | * Diagnostics are reported through syslog(3). |
---|
9 | * |
---|
10 | * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. |
---|
11 | */ |
---|
12 | |
---|
13 | #ifndef lint |
---|
14 | static char sccsid[] = "@(#) percent_x.c 1.4 94/12/28 17:42:37"; |
---|
15 | #endif |
---|
16 | |
---|
17 | /* System libraries. */ |
---|
18 | |
---|
19 | #include <stdio.h> |
---|
20 | #include <syslog.h> |
---|
21 | #include <string.h> |
---|
22 | |
---|
23 | extern void exit(); |
---|
24 | |
---|
25 | /* Local stuff. */ |
---|
26 | |
---|
27 | #include "tcpd.h" |
---|
28 | |
---|
29 | /* percent_x - do %<char> expansion, abort if result buffer is too small */ |
---|
30 | |
---|
31 | char *percent_x(result, result_len, string, request) |
---|
32 | char *result; |
---|
33 | int result_len; |
---|
34 | char *string; |
---|
35 | struct request_info *request; |
---|
36 | { |
---|
37 | char *bp = result; |
---|
38 | char *end = result + result_len - 1; /* end of result buffer */ |
---|
39 | char *expansion; |
---|
40 | int expansion_len; |
---|
41 | static char ok_chars[] = "1234567890!@%-_=+:,./\ |
---|
42 | abcdefghijklmnopqrstuvwxyz\ |
---|
43 | ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
---|
44 | char *str = string; |
---|
45 | char *cp; |
---|
46 | int ch; |
---|
47 | |
---|
48 | /* |
---|
49 | * Warning: we may be called from a child process or after pattern |
---|
50 | * matching, so we cannot use clean_exit() or tcpd_jump(). |
---|
51 | */ |
---|
52 | |
---|
53 | while (*str) { |
---|
54 | if (*str == '%' && (ch = str[1]) != 0) { |
---|
55 | str += 2; |
---|
56 | expansion = |
---|
57 | ch == 'a' ? eval_hostaddr(request->client) : |
---|
58 | ch == 'A' ? eval_hostaddr(request->server) : |
---|
59 | ch == 'c' ? eval_client(request) : |
---|
60 | ch == 'd' ? eval_daemon(request) : |
---|
61 | ch == 'h' ? eval_hostinfo(request->client) : |
---|
62 | ch == 'H' ? eval_hostinfo(request->server) : |
---|
63 | ch == 'n' ? eval_hostname(request->client) : |
---|
64 | ch == 'N' ? eval_hostname(request->server) : |
---|
65 | ch == 'p' ? eval_pid(request) : |
---|
66 | ch == 's' ? eval_server(request) : |
---|
67 | ch == 'u' ? eval_user(request) : |
---|
68 | ch == '%' ? "%" : (tcpd_warn("unrecognized %%%c", ch), ""); |
---|
69 | for (cp = expansion; *(cp += strspn(cp, ok_chars)); /* */ ) |
---|
70 | *cp = '_'; |
---|
71 | expansion_len = cp - expansion; |
---|
72 | } else { |
---|
73 | expansion = str++; |
---|
74 | expansion_len = 1; |
---|
75 | } |
---|
76 | if (bp + expansion_len >= end) { |
---|
77 | tcpd_warn("percent_x: expansion too long: %.30s...", result); |
---|
78 | sleep(5); |
---|
79 | exit(0); |
---|
80 | } |
---|
81 | memcpy(bp, expansion, expansion_len); |
---|
82 | bp += expansion_len; |
---|
83 | } |
---|
84 | *bp = 0; |
---|
85 | return (result); |
---|
86 | } |
---|