[11716] | 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 | } |
---|