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