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