- (djm) OpenBSD CVS Sync
[openssh-git.git] / auth-options.c
blobca5e1c931499934b9eec24b4cceaeae693912e5f
1 /* $OpenBSD: auth-options.c,v 1.40 2006/08/03 03:34:41 deraadt Exp $ */
2 /*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
13 #include "includes.h"
15 #include <sys/types.h>
17 #include <netdb.h>
18 #include <pwd.h>
19 #include <string.h>
20 #include <stdio.h>
21 #include <stdarg.h>
23 #include "xmalloc.h"
24 #include "match.h"
25 #include "log.h"
26 #include "canohost.h"
27 #include "buffer.h"
28 #include "channels.h"
29 #include "auth-options.h"
30 #include "servconf.h"
31 #include "misc.h"
32 #include "key.h"
33 #include "hostfile.h"
34 #include "auth.h"
35 #ifdef GSSAPI
36 #include "ssh-gss.h"
37 #endif
38 #include "monitor_wrap.h"
40 /* Flags set authorized_keys flags */
41 int no_port_forwarding_flag = 0;
42 int no_agent_forwarding_flag = 0;
43 int no_x11_forwarding_flag = 0;
44 int no_pty_flag = 0;
46 /* "command=" option. */
47 char *forced_command = NULL;
49 /* "environment=" options. */
50 struct envstring *custom_environment = NULL;
52 /* "tunnel=" option. */
53 int forced_tun_device = -1;
55 extern ServerOptions options;
57 void
58 auth_clear_options(void)
60 no_agent_forwarding_flag = 0;
61 no_port_forwarding_flag = 0;
62 no_pty_flag = 0;
63 no_x11_forwarding_flag = 0;
64 while (custom_environment) {
65 struct envstring *ce = custom_environment;
66 custom_environment = ce->next;
67 xfree(ce->s);
68 xfree(ce);
70 if (forced_command) {
71 xfree(forced_command);
72 forced_command = NULL;
74 forced_tun_device = -1;
75 channel_clear_permitted_opens();
76 auth_debug_reset();
80 * return 1 if access is granted, 0 if not.
81 * side effect: sets key option flags
83 int
84 auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
86 const char *cp;
87 int i;
89 /* reset options */
90 auth_clear_options();
92 if (!opts)
93 return 1;
95 while (*opts && *opts != ' ' && *opts != '\t') {
96 cp = "no-port-forwarding";
97 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
98 auth_debug_add("Port forwarding disabled.");
99 no_port_forwarding_flag = 1;
100 opts += strlen(cp);
101 goto next_option;
103 cp = "no-agent-forwarding";
104 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
105 auth_debug_add("Agent forwarding disabled.");
106 no_agent_forwarding_flag = 1;
107 opts += strlen(cp);
108 goto next_option;
110 cp = "no-X11-forwarding";
111 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
112 auth_debug_add("X11 forwarding disabled.");
113 no_x11_forwarding_flag = 1;
114 opts += strlen(cp);
115 goto next_option;
117 cp = "no-pty";
118 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
119 auth_debug_add("Pty allocation disabled.");
120 no_pty_flag = 1;
121 opts += strlen(cp);
122 goto next_option;
124 cp = "command=\"";
125 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
126 opts += strlen(cp);
127 forced_command = xmalloc(strlen(opts) + 1);
128 i = 0;
129 while (*opts) {
130 if (*opts == '"')
131 break;
132 if (*opts == '\\' && opts[1] == '"') {
133 opts += 2;
134 forced_command[i++] = '"';
135 continue;
137 forced_command[i++] = *opts++;
139 if (!*opts) {
140 debug("%.100s, line %lu: missing end quote",
141 file, linenum);
142 auth_debug_add("%.100s, line %lu: missing end quote",
143 file, linenum);
144 xfree(forced_command);
145 forced_command = NULL;
146 goto bad_option;
148 forced_command[i] = '\0';
149 auth_debug_add("Forced command: %.900s", forced_command);
150 opts++;
151 goto next_option;
153 cp = "environment=\"";
154 if (options.permit_user_env &&
155 strncasecmp(opts, cp, strlen(cp)) == 0) {
156 char *s;
157 struct envstring *new_envstring;
159 opts += strlen(cp);
160 s = xmalloc(strlen(opts) + 1);
161 i = 0;
162 while (*opts) {
163 if (*opts == '"')
164 break;
165 if (*opts == '\\' && opts[1] == '"') {
166 opts += 2;
167 s[i++] = '"';
168 continue;
170 s[i++] = *opts++;
172 if (!*opts) {
173 debug("%.100s, line %lu: missing end quote",
174 file, linenum);
175 auth_debug_add("%.100s, line %lu: missing end quote",
176 file, linenum);
177 xfree(s);
178 goto bad_option;
180 s[i] = '\0';
181 auth_debug_add("Adding to environment: %.900s", s);
182 debug("Adding to environment: %.900s", s);
183 opts++;
184 new_envstring = xmalloc(sizeof(struct envstring));
185 new_envstring->s = s;
186 new_envstring->next = custom_environment;
187 custom_environment = new_envstring;
188 goto next_option;
190 cp = "from=\"";
191 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
192 const char *remote_ip = get_remote_ipaddr();
193 const char *remote_host = get_canonical_hostname(
194 options.use_dns);
195 char *patterns = xmalloc(strlen(opts) + 1);
197 opts += strlen(cp);
198 i = 0;
199 while (*opts) {
200 if (*opts == '"')
201 break;
202 if (*opts == '\\' && opts[1] == '"') {
203 opts += 2;
204 patterns[i++] = '"';
205 continue;
207 patterns[i++] = *opts++;
209 if (!*opts) {
210 debug("%.100s, line %lu: missing end quote",
211 file, linenum);
212 auth_debug_add("%.100s, line %lu: missing end quote",
213 file, linenum);
214 xfree(patterns);
215 goto bad_option;
217 patterns[i] = '\0';
218 opts++;
219 if (match_host_and_ip(remote_host, remote_ip,
220 patterns) != 1) {
221 xfree(patterns);
222 logit("Authentication tried for %.100s with "
223 "correct key but not from a permitted "
224 "host (host=%.200s, ip=%.200s).",
225 pw->pw_name, remote_host, remote_ip);
226 auth_debug_add("Your host '%.200s' is not "
227 "permitted to use this key for login.",
228 remote_host);
229 /* deny access */
230 return 0;
232 xfree(patterns);
233 /* Host name matches. */
234 goto next_option;
236 cp = "permitopen=\"";
237 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
238 char *host, *p;
239 u_short port;
240 char *patterns = xmalloc(strlen(opts) + 1);
242 opts += strlen(cp);
243 i = 0;
244 while (*opts) {
245 if (*opts == '"')
246 break;
247 if (*opts == '\\' && opts[1] == '"') {
248 opts += 2;
249 patterns[i++] = '"';
250 continue;
252 patterns[i++] = *opts++;
254 if (!*opts) {
255 debug("%.100s, line %lu: missing end quote",
256 file, linenum);
257 auth_debug_add("%.100s, line %lu: missing "
258 "end quote", file, linenum);
259 xfree(patterns);
260 goto bad_option;
262 patterns[i] = '\0';
263 opts++;
264 p = patterns;
265 host = hpdelim(&p);
266 if (host == NULL || strlen(host) >= NI_MAXHOST) {
267 debug("%.100s, line %lu: Bad permitopen "
268 "specification <%.100s>", file, linenum,
269 patterns);
270 auth_debug_add("%.100s, line %lu: "
271 "Bad permitopen specification", file,
272 linenum);
273 xfree(patterns);
274 goto bad_option;
276 host = cleanhostname(host);
277 if (p == NULL || (port = a2port(p)) == 0) {
278 debug("%.100s, line %lu: Bad permitopen port "
279 "<%.100s>", file, linenum, p ? p : "");
280 auth_debug_add("%.100s, line %lu: "
281 "Bad permitopen port", file, linenum);
282 xfree(patterns);
283 goto bad_option;
285 if (options.allow_tcp_forwarding)
286 channel_add_permitted_opens(host, port);
287 xfree(patterns);
288 goto next_option;
290 cp = "tunnel=\"";
291 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
292 char *tun = NULL;
293 opts += strlen(cp);
294 tun = xmalloc(strlen(opts) + 1);
295 i = 0;
296 while (*opts) {
297 if (*opts == '"')
298 break;
299 tun[i++] = *opts++;
301 if (!*opts) {
302 debug("%.100s, line %lu: missing end quote",
303 file, linenum);
304 auth_debug_add("%.100s, line %lu: missing end quote",
305 file, linenum);
306 xfree(tun);
307 forced_tun_device = -1;
308 goto bad_option;
310 tun[i] = '\0';
311 forced_tun_device = a2tun(tun, NULL);
312 xfree(tun);
313 if (forced_tun_device == SSH_TUNID_ERR) {
314 debug("%.100s, line %lu: invalid tun device",
315 file, linenum);
316 auth_debug_add("%.100s, line %lu: invalid tun device",
317 file, linenum);
318 forced_tun_device = -1;
319 goto bad_option;
321 auth_debug_add("Forced tun device: %d", forced_tun_device);
322 opts++;
323 goto next_option;
325 next_option:
327 * Skip the comma, and move to the next option
328 * (or break out if there are no more).
330 if (!*opts)
331 fatal("Bugs in auth-options.c option processing.");
332 if (*opts == ' ' || *opts == '\t')
333 break; /* End of options. */
334 if (*opts != ',')
335 goto bad_option;
336 opts++;
337 /* Process the next option. */
340 if (!use_privsep)
341 auth_debug_send();
343 /* grant access */
344 return 1;
346 bad_option:
347 logit("Bad options in %.100s file, line %lu: %.50s",
348 file, linenum, opts);
349 auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
350 file, linenum, opts);
352 if (!use_privsep)
353 auth_debug_send();
355 /* deny access */
356 return 0;