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