1 | /* |
---|
2 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
---|
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
---|
4 | * All rights reserved |
---|
5 | * As far as I am concerned, the code I have written for this software |
---|
6 | * can be used freely for any purpose. Any derived versions of this |
---|
7 | * software must be clearly marked as such, and if the derived work is |
---|
8 | * incompatible with the protocol description in the RFC file, it must be |
---|
9 | * called by a name other than "ssh" or "Secure Shell". |
---|
10 | */ |
---|
11 | |
---|
12 | #include "includes.h" |
---|
13 | RCSID("$OpenBSD: auth-options.c,v 1.26 2002/07/30 17:03:55 markus Exp $"); |
---|
14 | |
---|
15 | #include "xmalloc.h" |
---|
16 | #include "match.h" |
---|
17 | #include "log.h" |
---|
18 | #include "canohost.h" |
---|
19 | #include "channels.h" |
---|
20 | #include "auth-options.h" |
---|
21 | #include "servconf.h" |
---|
22 | #include "misc.h" |
---|
23 | #include "monitor_wrap.h" |
---|
24 | #include "auth.h" |
---|
25 | |
---|
26 | /* Flags set authorized_keys flags */ |
---|
27 | int no_port_forwarding_flag = 0; |
---|
28 | int no_agent_forwarding_flag = 0; |
---|
29 | int no_x11_forwarding_flag = 0; |
---|
30 | int no_pty_flag = 0; |
---|
31 | |
---|
32 | /* "command=" option. */ |
---|
33 | char *forced_command = NULL; |
---|
34 | |
---|
35 | /* "environment=" options. */ |
---|
36 | struct envstring *custom_environment = NULL; |
---|
37 | |
---|
38 | extern ServerOptions options; |
---|
39 | |
---|
40 | void |
---|
41 | auth_clear_options(void) |
---|
42 | { |
---|
43 | no_agent_forwarding_flag = 0; |
---|
44 | no_port_forwarding_flag = 0; |
---|
45 | no_pty_flag = 0; |
---|
46 | no_x11_forwarding_flag = 0; |
---|
47 | while (custom_environment) { |
---|
48 | struct envstring *ce = custom_environment; |
---|
49 | custom_environment = ce->next; |
---|
50 | xfree(ce->s); |
---|
51 | xfree(ce); |
---|
52 | } |
---|
53 | if (forced_command) { |
---|
54 | xfree(forced_command); |
---|
55 | forced_command = NULL; |
---|
56 | } |
---|
57 | channel_clear_permitted_opens(); |
---|
58 | auth_debug_reset(); |
---|
59 | } |
---|
60 | |
---|
61 | /* |
---|
62 | * return 1 if access is granted, 0 if not. |
---|
63 | * side effect: sets key option flags |
---|
64 | */ |
---|
65 | int |
---|
66 | auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) |
---|
67 | { |
---|
68 | const char *cp; |
---|
69 | int i; |
---|
70 | |
---|
71 | /* reset options */ |
---|
72 | auth_clear_options(); |
---|
73 | |
---|
74 | if (!opts) |
---|
75 | return 1; |
---|
76 | |
---|
77 | while (*opts && *opts != ' ' && *opts != '\t') { |
---|
78 | cp = "no-port-forwarding"; |
---|
79 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
---|
80 | auth_debug_add("Port forwarding disabled."); |
---|
81 | no_port_forwarding_flag = 1; |
---|
82 | opts += strlen(cp); |
---|
83 | goto next_option; |
---|
84 | } |
---|
85 | cp = "no-agent-forwarding"; |
---|
86 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
---|
87 | auth_debug_add("Agent forwarding disabled."); |
---|
88 | no_agent_forwarding_flag = 1; |
---|
89 | opts += strlen(cp); |
---|
90 | goto next_option; |
---|
91 | } |
---|
92 | cp = "no-X11-forwarding"; |
---|
93 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
---|
94 | auth_debug_add("X11 forwarding disabled."); |
---|
95 | no_x11_forwarding_flag = 1; |
---|
96 | opts += strlen(cp); |
---|
97 | goto next_option; |
---|
98 | } |
---|
99 | cp = "no-pty"; |
---|
100 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
---|
101 | auth_debug_add("Pty allocation disabled."); |
---|
102 | no_pty_flag = 1; |
---|
103 | opts += strlen(cp); |
---|
104 | goto next_option; |
---|
105 | } |
---|
106 | cp = "command=\""; |
---|
107 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
---|
108 | opts += strlen(cp); |
---|
109 | forced_command = xmalloc(strlen(opts) + 1); |
---|
110 | i = 0; |
---|
111 | while (*opts) { |
---|
112 | if (*opts == '"') |
---|
113 | break; |
---|
114 | if (*opts == '\\' && opts[1] == '"') { |
---|
115 | opts += 2; |
---|
116 | forced_command[i++] = '"'; |
---|
117 | continue; |
---|
118 | } |
---|
119 | forced_command[i++] = *opts++; |
---|
120 | } |
---|
121 | if (!*opts) { |
---|
122 | debug("%.100s, line %lu: missing end quote", |
---|
123 | file, linenum); |
---|
124 | auth_debug_add("%.100s, line %lu: missing end quote", |
---|
125 | file, linenum); |
---|
126 | xfree(forced_command); |
---|
127 | forced_command = NULL; |
---|
128 | goto bad_option; |
---|
129 | } |
---|
130 | forced_command[i] = 0; |
---|
131 | auth_debug_add("Forced command: %.900s", forced_command); |
---|
132 | opts++; |
---|
133 | goto next_option; |
---|
134 | } |
---|
135 | cp = "environment=\""; |
---|
136 | if (options.permit_user_env && |
---|
137 | strncasecmp(opts, cp, strlen(cp)) == 0) { |
---|
138 | char *s; |
---|
139 | struct envstring *new_envstring; |
---|
140 | |
---|
141 | opts += strlen(cp); |
---|
142 | s = xmalloc(strlen(opts) + 1); |
---|
143 | i = 0; |
---|
144 | while (*opts) { |
---|
145 | if (*opts == '"') |
---|
146 | break; |
---|
147 | if (*opts == '\\' && opts[1] == '"') { |
---|
148 | opts += 2; |
---|
149 | s[i++] = '"'; |
---|
150 | continue; |
---|
151 | } |
---|
152 | s[i++] = *opts++; |
---|
153 | } |
---|
154 | if (!*opts) { |
---|
155 | debug("%.100s, line %lu: missing end quote", |
---|
156 | file, linenum); |
---|
157 | auth_debug_add("%.100s, line %lu: missing end quote", |
---|
158 | file, linenum); |
---|
159 | xfree(s); |
---|
160 | goto bad_option; |
---|
161 | } |
---|
162 | s[i] = 0; |
---|
163 | auth_debug_add("Adding to environment: %.900s", s); |
---|
164 | debug("Adding to environment: %.900s", s); |
---|
165 | opts++; |
---|
166 | new_envstring = xmalloc(sizeof(struct envstring)); |
---|
167 | new_envstring->s = s; |
---|
168 | new_envstring->next = custom_environment; |
---|
169 | custom_environment = new_envstring; |
---|
170 | goto next_option; |
---|
171 | } |
---|
172 | cp = "from=\""; |
---|
173 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
---|
174 | const char *remote_ip = get_remote_ipaddr(); |
---|
175 | const char *remote_host = get_canonical_hostname( |
---|
176 | options.verify_reverse_mapping); |
---|
177 | char *patterns = xmalloc(strlen(opts) + 1); |
---|
178 | |
---|
179 | opts += strlen(cp); |
---|
180 | i = 0; |
---|
181 | while (*opts) { |
---|
182 | if (*opts == '"') |
---|
183 | break; |
---|
184 | if (*opts == '\\' && opts[1] == '"') { |
---|
185 | opts += 2; |
---|
186 | patterns[i++] = '"'; |
---|
187 | continue; |
---|
188 | } |
---|
189 | patterns[i++] = *opts++; |
---|
190 | } |
---|
191 | if (!*opts) { |
---|
192 | debug("%.100s, line %lu: missing end quote", |
---|
193 | file, linenum); |
---|
194 | auth_debug_add("%.100s, line %lu: missing end quote", |
---|
195 | file, linenum); |
---|
196 | xfree(patterns); |
---|
197 | goto bad_option; |
---|
198 | } |
---|
199 | patterns[i] = 0; |
---|
200 | opts++; |
---|
201 | if (match_host_and_ip(remote_host, remote_ip, |
---|
202 | patterns) != 1) { |
---|
203 | xfree(patterns); |
---|
204 | log("Authentication tried for %.100s with " |
---|
205 | "correct key but not from a permitted " |
---|
206 | "host (host=%.200s, ip=%.200s).", |
---|
207 | pw->pw_name, remote_host, remote_ip); |
---|
208 | auth_debug_add("Your host '%.200s' is not " |
---|
209 | "permitted to use this key for login.", |
---|
210 | remote_host); |
---|
211 | /* deny access */ |
---|
212 | return 0; |
---|
213 | } |
---|
214 | xfree(patterns); |
---|
215 | /* Host name matches. */ |
---|
216 | goto next_option; |
---|
217 | } |
---|
218 | cp = "permitopen=\""; |
---|
219 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
---|
220 | char host[256], sport[6]; |
---|
221 | u_short port; |
---|
222 | char *patterns = xmalloc(strlen(opts) + 1); |
---|
223 | |
---|
224 | opts += strlen(cp); |
---|
225 | i = 0; |
---|
226 | while (*opts) { |
---|
227 | if (*opts == '"') |
---|
228 | break; |
---|
229 | if (*opts == '\\' && opts[1] == '"') { |
---|
230 | opts += 2; |
---|
231 | patterns[i++] = '"'; |
---|
232 | continue; |
---|
233 | } |
---|
234 | patterns[i++] = *opts++; |
---|
235 | } |
---|
236 | if (!*opts) { |
---|
237 | debug("%.100s, line %lu: missing end quote", |
---|
238 | file, linenum); |
---|
239 | auth_debug_add("%.100s, line %lu: missing end quote", |
---|
240 | file, linenum); |
---|
241 | xfree(patterns); |
---|
242 | goto bad_option; |
---|
243 | } |
---|
244 | patterns[i] = 0; |
---|
245 | opts++; |
---|
246 | if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 && |
---|
247 | sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) { |
---|
248 | debug("%.100s, line %lu: Bad permitopen specification " |
---|
249 | "<%.100s>", file, linenum, patterns); |
---|
250 | auth_debug_add("%.100s, line %lu: " |
---|
251 | "Bad permitopen specification", file, linenum); |
---|
252 | xfree(patterns); |
---|
253 | goto bad_option; |
---|
254 | } |
---|
255 | if ((port = a2port(sport)) == 0) { |
---|
256 | debug("%.100s, line %lu: Bad permitopen port <%.100s>", |
---|
257 | file, linenum, sport); |
---|
258 | auth_debug_add("%.100s, line %lu: " |
---|
259 | "Bad permitopen port", file, linenum); |
---|
260 | xfree(patterns); |
---|
261 | goto bad_option; |
---|
262 | } |
---|
263 | if (options.allow_tcp_forwarding) |
---|
264 | channel_add_permitted_opens(host, port); |
---|
265 | xfree(patterns); |
---|
266 | goto next_option; |
---|
267 | } |
---|
268 | next_option: |
---|
269 | /* |
---|
270 | * Skip the comma, and move to the next option |
---|
271 | * (or break out if there are no more). |
---|
272 | */ |
---|
273 | if (!*opts) |
---|
274 | fatal("Bugs in auth-options.c option processing."); |
---|
275 | if (*opts == ' ' || *opts == '\t') |
---|
276 | break; /* End of options. */ |
---|
277 | if (*opts != ',') |
---|
278 | goto bad_option; |
---|
279 | opts++; |
---|
280 | /* Process the next option. */ |
---|
281 | } |
---|
282 | |
---|
283 | if (!use_privsep) |
---|
284 | auth_debug_send(); |
---|
285 | |
---|
286 | /* grant access */ |
---|
287 | return 1; |
---|
288 | |
---|
289 | bad_option: |
---|
290 | log("Bad options in %.100s file, line %lu: %.50s", |
---|
291 | file, linenum, opts); |
---|
292 | auth_debug_add("Bad options in %.100s file, line %lu: %.50s", |
---|
293 | file, linenum, opts); |
---|
294 | |
---|
295 | if (!use_privsep) |
---|
296 | auth_debug_send(); |
---|
297 | |
---|
298 | /* deny access */ |
---|
299 | return 0; |
---|
300 | } |
---|