File: env_chk.c

package info (click to toggle)
ccstools 1.7.2-20100401-3
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 984 kB
  • ctags: 1,080
  • sloc: ansic: 20,286; sh: 890; makefile: 80
file content (108 lines) | stat: -rw-r--r-- 2,164 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
 * env_chk.c
 *
 * An example program for execute_handler .
 *
 * Copyright (C) 2005-2009  NTT DATA CORPORATION
 *
 * Version: 1.7.0   2009/09/03
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

static void unescape(unsigned char *dest)
{
	unsigned char *src = dest;
	unsigned char c;
	unsigned char d;
	unsigned char e;
	while (1) {
		c = *src++;
		if (!c)
			break;
		if (c != '\\') {
			*dest++ = c;
			continue;
		}
		c = *src++;
		if (c == '\\') {
			*dest++ = c;
			continue;
		}
		if (c < '0' || c > '3')
			break;
		d = *src++;
		if (d < '0' || d > '7')
			break;
		e = *src++;
		if (e < '0' || e > '7')
			break;
		*dest++ = ((c - '0') << 6) + ((d - '0') << 3) + (e - '0');
	}
	*dest = '\0';
}

int main(int raw_argc, char *raw_argv[])
{
	int i;
	int argc;
	int envc;
	char *filename;
	char **argv;
	char **envp;
	{ /* Check that I'm an execute handler process.  */
		int fd = open("/proc/ccs/.execute_handler", 0);
		close(fd);
		if (fd == EOF) {
			fprintf(stderr, "FATAL: I'm not execute_handler.\n");
			return 1;
		}
	}
	if (raw_argc < 7)
		return 1;
	filename = raw_argv[4];
	argc = atoi(raw_argv[5]);
	envc = atoi(raw_argv[6]);
	if (raw_argc != argc + envc + 7)
		return 1;
	for (i = 5; i < argc + 5; i++)
		raw_argv[i] = raw_argv[i + 2];
	raw_argv[argc + 5] = NULL;
	for (i = argc + 6; i < argc + envc + 6; i++)
		raw_argv[i] = raw_argv[i + 1];
	raw_argv[argc + envc + 6] = NULL;
	argv = raw_argv + 5;
	envp = raw_argv + argc + 6;
	/*
	 * "/usr/sbin/sshd" executes "/usr/sbin/sshd -R".
	 * So, don't check environment variables.
	 */
	unescape(raw_argv[2]);
	if (argc == 2 && !strcmp(argv[1], "-R") &&
	    !strcmp(raw_argv[2], filename)) {
		execve(filename, argv, envp);
		return 1;
	}
	/*
	 * Check environment variables passed to execve() request
	 * and execute the program if it has "CERBERUS=sftp" environment.
	 */
	for (i = 0; i < envc; i++) {
		if (strcmp(envp[i], "CERBERUS=sftp"))
			continue;
		while (i < envc) {
			envp[i] = envp[i + 1];
			i++;
		}
		execve(filename, argv, envp);
		break;
	}
	return 1;
}