1 | /* Copyright 1996 by the Massachusetts Institute of Technology. |
---|
2 | * |
---|
3 | * Permission to use, copy, modify, and distribute this |
---|
4 | * software and its documentation for any purpose and without |
---|
5 | * fee is hereby granted, provided that the above copyright |
---|
6 | * notice appear in all copies and that both that copyright |
---|
7 | * notice and this permission notice appear in supporting |
---|
8 | * documentation, and that the name of M.I.T. not be used in |
---|
9 | * advertising or publicity pertaining to distribution of the |
---|
10 | * software without specific, written prior permission. |
---|
11 | * M.I.T. makes no representations about the suitability of |
---|
12 | * this software for any purpose. It is provided "as is" |
---|
13 | * without express or implied warranty. |
---|
14 | */ |
---|
15 | |
---|
16 | static const char rcsid[] = "$Id: access_off.c,v 1.11 1998-11-06 18:52:16 ghudson Exp $"; |
---|
17 | |
---|
18 | #include <sys/types.h> |
---|
19 | #include <sys/stat.h> |
---|
20 | #include <stdio.h> |
---|
21 | #include <stdlib.h> |
---|
22 | #include <signal.h> |
---|
23 | #include <errno.h> |
---|
24 | #include <string.h> |
---|
25 | #include <unistd.h> |
---|
26 | #include <fcntl.h> |
---|
27 | |
---|
28 | #define PATH_INETD_PID "/var/athena/inetd.pid" |
---|
29 | #define PATH_SSHD_PID "/var/athena/sshd.pid" |
---|
30 | #define PATH_SSHD "/etc/athena/sshd" |
---|
31 | #define PATH_RC_CONF "/etc/athena/rc.conf" |
---|
32 | #define PATH_BOOT_ENVIRON "/var/athena/env.boot" |
---|
33 | #define ENV_FALLBACK { "PATH=/etc/athena", NULL } |
---|
34 | |
---|
35 | static char **get_boot_environment(void); |
---|
36 | |
---|
37 | int main(int argc, char **argv) |
---|
38 | { |
---|
39 | FILE *pidfile, *rcfile; |
---|
40 | int pid, on, running; |
---|
41 | char *progname, buf[1024], **env, *env_fallback[] = ENV_FALLBACK; |
---|
42 | |
---|
43 | progname = strrchr(argv[0], '/'); |
---|
44 | progname = (progname) ? progname + 1 : argv[0]; |
---|
45 | |
---|
46 | /* We're turning access off if this program was invoked as access_off; |
---|
47 | * otherwise we're turning access on. */ |
---|
48 | on = (strcmp(progname, "access_off") != 0); |
---|
49 | |
---|
50 | /* Send SIGUSR1 or SIGUSR2 to the Athena inetd. */ |
---|
51 | pidfile = fopen(PATH_INETD_PID, "r"); |
---|
52 | if (!pidfile) |
---|
53 | { |
---|
54 | fprintf(stderr, "Cannot read %s. Daemon probably not running\n", |
---|
55 | PATH_INETD_PID); |
---|
56 | return 1; |
---|
57 | } |
---|
58 | if (fscanf(pidfile, "%d", &pid) != 1) |
---|
59 | { |
---|
60 | fprintf(stderr, "Error reading %s.\n", PATH_INETD_PID); |
---|
61 | return 1; |
---|
62 | } |
---|
63 | fclose(pidfile); |
---|
64 | if (kill(pid, (on) ? SIGUSR1 : SIGUSR2) < 0) |
---|
65 | { |
---|
66 | if (errno != ESRCH) |
---|
67 | perror("Error killing daemon"); |
---|
68 | return 1; |
---|
69 | } |
---|
70 | |
---|
71 | /* If SSHD is set to "switched" in /etc/athena/rc.conf, then start or stop |
---|
72 | * sshd if it's not already in the state we want. */ |
---|
73 | rcfile = fopen(PATH_RC_CONF, "r"); |
---|
74 | if (!rcfile) |
---|
75 | { |
---|
76 | fprintf(stderr, "Cannot read %s: %s", PATH_RC_CONF, strerror(errno)); |
---|
77 | return 1; |
---|
78 | } |
---|
79 | while (fgets(buf, sizeof(buf), rcfile) != NULL) |
---|
80 | { |
---|
81 | /* Ignore lines which aren't setting SSHD. */ |
---|
82 | if (strncmp(buf, "SSHD=", 5) != 0) |
---|
83 | continue; |
---|
84 | |
---|
85 | /* If SSHD is not set to "switched" then we do nothing. */ |
---|
86 | if (strncmp(buf + 5, "switched", 8) != 0) |
---|
87 | break; |
---|
88 | |
---|
89 | /* Read the sshd pidfile and send a signal 0 to the contained pid |
---|
90 | * to determine if sshd is running. */ |
---|
91 | pidfile = fopen(PATH_SSHD_PID, "r"); |
---|
92 | if (pidfile && fscanf(pidfile, "%d", &pid) == 1 && kill(pid, 0) == 0) |
---|
93 | running = 1; |
---|
94 | else |
---|
95 | running = 0; |
---|
96 | if (pidfile) |
---|
97 | fclose(pidfile); |
---|
98 | |
---|
99 | if (on && !running) |
---|
100 | { |
---|
101 | /* ssh is not running and we'd like it to be running. Start it. */ |
---|
102 | pid = fork(); |
---|
103 | if (pid == -1) |
---|
104 | { |
---|
105 | perror("Error forking to run sshd"); |
---|
106 | return 1; |
---|
107 | } |
---|
108 | else if (pid == 0) |
---|
109 | { |
---|
110 | fclose(rcfile); |
---|
111 | /* Make ruid and saved uid equal to effective uid before exec, |
---|
112 | * or sshd might notice and get confused. Set the environment |
---|
113 | * to the boot-time environment. |
---|
114 | */ |
---|
115 | setuid(geteuid()); |
---|
116 | env = get_boot_environment(); |
---|
117 | if (!env) |
---|
118 | env = env_fallback; |
---|
119 | execle(PATH_SSHD, PATH_SSHD, (char *) NULL, env); |
---|
120 | perror("Error running sshd"); |
---|
121 | } |
---|
122 | } |
---|
123 | else if (!on && running) |
---|
124 | { |
---|
125 | /* ssh is running and we'd like it not to be running. Kill it. |
---|
126 | * We can be sure that we read its pid in this case. */ |
---|
127 | kill(pid, SIGTERM); |
---|
128 | } |
---|
129 | |
---|
130 | break; |
---|
131 | } |
---|
132 | fclose(rcfile); |
---|
133 | |
---|
134 | return 0; |
---|
135 | } |
---|
136 | |
---|
137 | static char **get_boot_environment(void) |
---|
138 | { |
---|
139 | int fd, len, count; |
---|
140 | struct stat st; |
---|
141 | char *buf, *p, *q, **env, **ep; |
---|
142 | |
---|
143 | /* Open and read the stored boot environment. */ |
---|
144 | fd = open(PATH_BOOT_ENVIRON, O_RDONLY); |
---|
145 | if (fd == -1) |
---|
146 | return NULL; |
---|
147 | if (fstat(fd, &st) == -1) |
---|
148 | { |
---|
149 | close(fd); |
---|
150 | return NULL; |
---|
151 | } |
---|
152 | buf = malloc(st.st_size); |
---|
153 | if (!buf) |
---|
154 | { |
---|
155 | close(fd); |
---|
156 | return NULL; |
---|
157 | } |
---|
158 | len = 0; |
---|
159 | while (len < st.st_size) |
---|
160 | { |
---|
161 | count = read(fd, buf + len, st.st_size - len); |
---|
162 | if (count < 0 && errno != EINTR) |
---|
163 | { |
---|
164 | close(fd); |
---|
165 | free(buf); |
---|
166 | return NULL; |
---|
167 | } |
---|
168 | else if (count > 0) |
---|
169 | len += count; |
---|
170 | } |
---|
171 | close(fd); |
---|
172 | |
---|
173 | /* Allocate space for the environment pointers. */ |
---|
174 | count = 0; |
---|
175 | for (p = buf; *p; p++) |
---|
176 | { |
---|
177 | if (*p == '\n') |
---|
178 | count++; |
---|
179 | } |
---|
180 | env = malloc((count + 1) * sizeof(char *)); |
---|
181 | if (!env) |
---|
182 | { |
---|
183 | free(buf); |
---|
184 | return NULL; |
---|
185 | } |
---|
186 | |
---|
187 | /* Set the environment pointers. */ |
---|
188 | ep = env; |
---|
189 | p = buf; |
---|
190 | while ((q = strchr(p, '\n')) != NULL) |
---|
191 | { |
---|
192 | *ep++ = p; |
---|
193 | *q = 0; |
---|
194 | p = q + 1; |
---|
195 | } |
---|
196 | |
---|
197 | /* Terminate the environment list and return it. */ |
---|
198 | *ep = NULL; |
---|
199 | return env; |
---|
200 | } |
---|