blob: 33c62641b0e2edc464558a4c62515bf3d8bb8ffd [file] [log] [blame]
Damien Millere3476ed2006-07-24 14:13:33 +10001/* $OpenBSD: auth-options.c,v 1.39 2006/07/22 20:48:22 stevesk Exp $ */
Damien Millere4340be2000-09-16 13:29:08 +11002/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
Damien Millere4340be2000-09-16 13:29:08 +11006 * 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".
11 */
12
Damien Millerf6d9e222000-06-18 14:50:44 +100013#include "includes.h"
Damien Millerf6d9e222000-06-18 14:50:44 +100014
Damien Miller9f2abc42006-07-10 20:53:08 +100015#include <sys/types.h>
16
Damien Millerbe43ebf2006-07-24 13:51:51 +100017#if defined(HAVE_NETDB_H)
18# include <netdb.h>
19#endif
Damien Miller9f2abc42006-07-10 20:53:08 +100020#include <pwd.h>
Damien Millere3476ed2006-07-24 14:13:33 +100021#include <string.h>
Damien Miller9f2abc42006-07-10 20:53:08 +100022
Damien Millerf6d9e222000-06-18 14:50:44 +100023#include "xmalloc.h"
24#include "match.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000025#include "log.h"
26#include "canohost.h"
Ben Lindstromc7637672001-06-09 00:36:26 +000027#include "channels.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000028#include "auth-options.h"
Damien Miller33804262001-02-04 23:20:18 +110029#include "servconf.h"
Ben Lindstromd71ba572001-09-12 18:03:31 +000030#include "misc.h"
Ben Lindstrom7a2073c2002-03-22 02:30:41 +000031#include "monitor_wrap.h"
Ben Lindstroma574cda2002-05-15 16:16:14 +000032#include "auth.h"
Damien Millerf6d9e222000-06-18 14:50:44 +100033
34/* Flags set authorized_keys flags */
35int no_port_forwarding_flag = 0;
36int no_agent_forwarding_flag = 0;
37int no_x11_forwarding_flag = 0;
38int no_pty_flag = 0;
39
40/* "command=" option. */
41char *forced_command = NULL;
42
43/* "environment=" options. */
44struct envstring *custom_environment = NULL;
45
Damien Millerd27b9472005-12-13 19:29:02 +110046/* "tunnel=" option. */
47int forced_tun_device = -1;
48
Damien Miller33804262001-02-04 23:20:18 +110049extern ServerOptions options;
50
Ben Lindstrom7a2073c2002-03-22 02:30:41 +000051void
Damien Miller874d77b2000-10-14 16:23:11 +110052auth_clear_options(void)
53{
54 no_agent_forwarding_flag = 0;
55 no_port_forwarding_flag = 0;
56 no_pty_flag = 0;
57 no_x11_forwarding_flag = 0;
58 while (custom_environment) {
59 struct envstring *ce = custom_environment;
60 custom_environment = ce->next;
61 xfree(ce->s);
62 xfree(ce);
63 }
64 if (forced_command) {
65 xfree(forced_command);
66 forced_command = NULL;
67 }
Damien Millerd27b9472005-12-13 19:29:02 +110068 forced_tun_device = -1;
Ben Lindstrom7bb8b492001-03-17 00:47:54 +000069 channel_clear_permitted_opens();
Ben Lindstroma574cda2002-05-15 16:16:14 +000070 auth_debug_reset();
Damien Miller874d77b2000-10-14 16:23:11 +110071}
72
Ben Lindstrom226cfa02001-01-22 05:34:40 +000073/*
74 * return 1 if access is granted, 0 if not.
75 * side effect: sets key option flags
76 */
Damien Millerf6d9e222000-06-18 14:50:44 +100077int
Damien Miller33804262001-02-04 23:20:18 +110078auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
Damien Millerf6d9e222000-06-18 14:50:44 +100079{
80 const char *cp;
Ben Lindstrom7bb8b492001-03-17 00:47:54 +000081 int i;
Damien Miller874d77b2000-10-14 16:23:11 +110082
83 /* reset options */
84 auth_clear_options();
85
Ben Lindstrom36d7bd02001-02-10 22:27:19 +000086 if (!opts)
87 return 1;
88
Damien Miller33804262001-02-04 23:20:18 +110089 while (*opts && *opts != ' ' && *opts != '\t') {
Damien Millerf6d9e222000-06-18 14:50:44 +100090 cp = "no-port-forwarding";
Damien Miller33804262001-02-04 23:20:18 +110091 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
Ben Lindstroma574cda2002-05-15 16:16:14 +000092 auth_debug_add("Port forwarding disabled.");
Damien Millerf6d9e222000-06-18 14:50:44 +100093 no_port_forwarding_flag = 1;
Damien Miller33804262001-02-04 23:20:18 +110094 opts += strlen(cp);
Damien Millerf6d9e222000-06-18 14:50:44 +100095 goto next_option;
96 }
97 cp = "no-agent-forwarding";
Damien Miller33804262001-02-04 23:20:18 +110098 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
Ben Lindstroma574cda2002-05-15 16:16:14 +000099 auth_debug_add("Agent forwarding disabled.");
Damien Millerf6d9e222000-06-18 14:50:44 +1000100 no_agent_forwarding_flag = 1;
Damien Miller33804262001-02-04 23:20:18 +1100101 opts += strlen(cp);
Damien Millerf6d9e222000-06-18 14:50:44 +1000102 goto next_option;
103 }
104 cp = "no-X11-forwarding";
Damien Miller33804262001-02-04 23:20:18 +1100105 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
Ben Lindstroma574cda2002-05-15 16:16:14 +0000106 auth_debug_add("X11 forwarding disabled.");
Damien Millerf6d9e222000-06-18 14:50:44 +1000107 no_x11_forwarding_flag = 1;
Damien Miller33804262001-02-04 23:20:18 +1100108 opts += strlen(cp);
Damien Millerf6d9e222000-06-18 14:50:44 +1000109 goto next_option;
110 }
111 cp = "no-pty";
Damien Miller33804262001-02-04 23:20:18 +1100112 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
Ben Lindstroma574cda2002-05-15 16:16:14 +0000113 auth_debug_add("Pty allocation disabled.");
Damien Millerf6d9e222000-06-18 14:50:44 +1000114 no_pty_flag = 1;
Damien Miller33804262001-02-04 23:20:18 +1100115 opts += strlen(cp);
Damien Millerf6d9e222000-06-18 14:50:44 +1000116 goto next_option;
117 }
118 cp = "command=\"";
Damien Miller33804262001-02-04 23:20:18 +1100119 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
Damien Miller33804262001-02-04 23:20:18 +1100120 opts += strlen(cp);
121 forced_command = xmalloc(strlen(opts) + 1);
Damien Millerf6d9e222000-06-18 14:50:44 +1000122 i = 0;
Damien Miller33804262001-02-04 23:20:18 +1100123 while (*opts) {
124 if (*opts == '"')
Damien Millerf6d9e222000-06-18 14:50:44 +1000125 break;
Damien Miller33804262001-02-04 23:20:18 +1100126 if (*opts == '\\' && opts[1] == '"') {
127 opts += 2;
Damien Millerf6d9e222000-06-18 14:50:44 +1000128 forced_command[i++] = '"';
129 continue;
130 }
Damien Miller33804262001-02-04 23:20:18 +1100131 forced_command[i++] = *opts++;
Damien Millerf6d9e222000-06-18 14:50:44 +1000132 }
Damien Miller33804262001-02-04 23:20:18 +1100133 if (!*opts) {
Damien Millerf6d9e222000-06-18 14:50:44 +1000134 debug("%.100s, line %lu: missing end quote",
Ben Lindstrom226cfa02001-01-22 05:34:40 +0000135 file, linenum);
Ben Lindstroma574cda2002-05-15 16:16:14 +0000136 auth_debug_add("%.100s, line %lu: missing end quote",
Ben Lindstrom226cfa02001-01-22 05:34:40 +0000137 file, linenum);
Damien Miller056ddf72001-03-14 10:15:20 +1100138 xfree(forced_command);
139 forced_command = NULL;
140 goto bad_option;
Damien Millerf6d9e222000-06-18 14:50:44 +1000141 }
Damien Miller98299262006-07-24 14:01:43 +1000142 forced_command[i] = '\0';
Ben Lindstroma574cda2002-05-15 16:16:14 +0000143 auth_debug_add("Forced command: %.900s", forced_command);
Damien Miller33804262001-02-04 23:20:18 +1100144 opts++;
Damien Millerf6d9e222000-06-18 14:50:44 +1000145 goto next_option;
146 }
147 cp = "environment=\"";
Ben Lindstrom5d860f02002-08-01 01:28:38 +0000148 if (options.permit_user_env &&
149 strncasecmp(opts, cp, strlen(cp)) == 0) {
Damien Millerf6d9e222000-06-18 14:50:44 +1000150 char *s;
151 struct envstring *new_envstring;
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000152
Damien Miller33804262001-02-04 23:20:18 +1100153 opts += strlen(cp);
154 s = xmalloc(strlen(opts) + 1);
Damien Millerf6d9e222000-06-18 14:50:44 +1000155 i = 0;
Damien Miller33804262001-02-04 23:20:18 +1100156 while (*opts) {
157 if (*opts == '"')
Damien Millerf6d9e222000-06-18 14:50:44 +1000158 break;
Damien Miller33804262001-02-04 23:20:18 +1100159 if (*opts == '\\' && opts[1] == '"') {
160 opts += 2;
Damien Millerf6d9e222000-06-18 14:50:44 +1000161 s[i++] = '"';
162 continue;
163 }
Damien Miller33804262001-02-04 23:20:18 +1100164 s[i++] = *opts++;
Damien Millerf6d9e222000-06-18 14:50:44 +1000165 }
Damien Miller33804262001-02-04 23:20:18 +1100166 if (!*opts) {
Damien Millerf6d9e222000-06-18 14:50:44 +1000167 debug("%.100s, line %lu: missing end quote",
Ben Lindstrom226cfa02001-01-22 05:34:40 +0000168 file, linenum);
Ben Lindstroma574cda2002-05-15 16:16:14 +0000169 auth_debug_add("%.100s, line %lu: missing end quote",
Ben Lindstrom226cfa02001-01-22 05:34:40 +0000170 file, linenum);
Damien Miller056ddf72001-03-14 10:15:20 +1100171 xfree(s);
172 goto bad_option;
Damien Millerf6d9e222000-06-18 14:50:44 +1000173 }
Damien Miller98299262006-07-24 14:01:43 +1000174 s[i] = '\0';
Ben Lindstroma574cda2002-05-15 16:16:14 +0000175 auth_debug_add("Adding to environment: %.900s", s);
Damien Millerf6d9e222000-06-18 14:50:44 +1000176 debug("Adding to environment: %.900s", s);
Damien Miller33804262001-02-04 23:20:18 +1100177 opts++;
Damien Millerf6d9e222000-06-18 14:50:44 +1000178 new_envstring = xmalloc(sizeof(struct envstring));
179 new_envstring->s = s;
180 new_envstring->next = custom_environment;
181 custom_environment = new_envstring;
182 goto next_option;
183 }
184 cp = "from=\"";
Damien Miller33804262001-02-04 23:20:18 +1100185 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
Damien Miller33804262001-02-04 23:20:18 +1100186 const char *remote_ip = get_remote_ipaddr();
187 const char *remote_host = get_canonical_hostname(
Damien Miller3a961dc2003-06-03 10:25:48 +1000188 options.use_dns);
Damien Miller33804262001-02-04 23:20:18 +1100189 char *patterns = xmalloc(strlen(opts) + 1);
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000190
Damien Miller33804262001-02-04 23:20:18 +1100191 opts += strlen(cp);
Damien Millerf6d9e222000-06-18 14:50:44 +1000192 i = 0;
Damien Miller33804262001-02-04 23:20:18 +1100193 while (*opts) {
194 if (*opts == '"')
Damien Millerf6d9e222000-06-18 14:50:44 +1000195 break;
Damien Miller33804262001-02-04 23:20:18 +1100196 if (*opts == '\\' && opts[1] == '"') {
197 opts += 2;
Damien Millerf6d9e222000-06-18 14:50:44 +1000198 patterns[i++] = '"';
199 continue;
200 }
Damien Miller33804262001-02-04 23:20:18 +1100201 patterns[i++] = *opts++;
Damien Millerf6d9e222000-06-18 14:50:44 +1000202 }
Damien Miller33804262001-02-04 23:20:18 +1100203 if (!*opts) {
Damien Millerf6d9e222000-06-18 14:50:44 +1000204 debug("%.100s, line %lu: missing end quote",
Ben Lindstrom226cfa02001-01-22 05:34:40 +0000205 file, linenum);
Ben Lindstroma574cda2002-05-15 16:16:14 +0000206 auth_debug_add("%.100s, line %lu: missing end quote",
Ben Lindstrom226cfa02001-01-22 05:34:40 +0000207 file, linenum);
Damien Miller056ddf72001-03-14 10:15:20 +1100208 xfree(patterns);
209 goto bad_option;
Damien Millerf6d9e222000-06-18 14:50:44 +1000210 }
Damien Miller98299262006-07-24 14:01:43 +1000211 patterns[i] = '\0';
Damien Miller33804262001-02-04 23:20:18 +1100212 opts++;
Ben Lindstromf0c50292001-06-25 05:17:53 +0000213 if (match_host_and_ip(remote_host, remote_ip,
214 patterns) != 1) {
215 xfree(patterns);
Damien Miller996acd22003-04-09 20:59:48 +1000216 logit("Authentication tried for %.100s with "
Damien Miller33804262001-02-04 23:20:18 +1100217 "correct key but not from a permitted "
218 "host (host=%.200s, ip=%.200s).",
219 pw->pw_name, remote_host, remote_ip);
Ben Lindstroma574cda2002-05-15 16:16:14 +0000220 auth_debug_add("Your host '%.200s' is not "
Damien Miller33804262001-02-04 23:20:18 +1100221 "permitted to use this key for login.",
222 remote_host);
Damien Millerf6d9e222000-06-18 14:50:44 +1000223 /* deny access */
224 return 0;
225 }
Ben Lindstromf0c50292001-06-25 05:17:53 +0000226 xfree(patterns);
Damien Millerf6d9e222000-06-18 14:50:44 +1000227 /* Host name matches. */
228 goto next_option;
229 }
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000230 cp = "permitopen=\"";
231 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
Damien Millerf91ee4c2005-03-01 21:24:33 +1100232 char *host, *p;
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000233 u_short port;
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000234 char *patterns = xmalloc(strlen(opts) + 1);
235
236 opts += strlen(cp);
237 i = 0;
238 while (*opts) {
239 if (*opts == '"')
240 break;
241 if (*opts == '\\' && opts[1] == '"') {
242 opts += 2;
243 patterns[i++] = '"';
244 continue;
245 }
246 patterns[i++] = *opts++;
247 }
248 if (!*opts) {
249 debug("%.100s, line %lu: missing end quote",
250 file, linenum);
Damien Millerf91ee4c2005-03-01 21:24:33 +1100251 auth_debug_add("%.100s, line %lu: missing "
252 "end quote", file, linenum);
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000253 xfree(patterns);
254 goto bad_option;
255 }
Damien Miller98299262006-07-24 14:01:43 +1000256 patterns[i] = '\0';
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000257 opts++;
Damien Millerf91ee4c2005-03-01 21:24:33 +1100258 p = patterns;
259 host = hpdelim(&p);
260 if (host == NULL || strlen(host) >= NI_MAXHOST) {
261 debug("%.100s, line %lu: Bad permitopen "
Darren Tucker90b9e022005-03-14 23:08:50 +1100262 "specification <%.100s>", file, linenum,
Damien Millerf91ee4c2005-03-01 21:24:33 +1100263 patterns);
Ben Lindstroma574cda2002-05-15 16:16:14 +0000264 auth_debug_add("%.100s, line %lu: "
Damien Millerf91ee4c2005-03-01 21:24:33 +1100265 "Bad permitopen specification", file,
266 linenum);
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000267 xfree(patterns);
268 goto bad_option;
269 }
Darren Tucker47eede72005-03-14 23:08:12 +1100270 host = cleanhostname(host);
271 if (p == NULL || (port = a2port(p)) == 0) {
Damien Millerf91ee4c2005-03-01 21:24:33 +1100272 debug("%.100s, line %lu: Bad permitopen port "
273 "<%.100s>", file, linenum, p ? p : "");
Ben Lindstroma574cda2002-05-15 16:16:14 +0000274 auth_debug_add("%.100s, line %lu: "
Ben Lindstromd71ba572001-09-12 18:03:31 +0000275 "Bad permitopen port", file, linenum);
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000276 xfree(patterns);
277 goto bad_option;
278 }
Ben Lindstrom2d70f982001-03-19 00:13:46 +0000279 if (options.allow_tcp_forwarding)
Ben Lindstromd71ba572001-09-12 18:03:31 +0000280 channel_add_permitted_opens(host, port);
Ben Lindstrom7bb8b492001-03-17 00:47:54 +0000281 xfree(patterns);
282 goto next_option;
283 }
Damien Millerd27b9472005-12-13 19:29:02 +1100284 cp = "tunnel=\"";
285 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
286 char *tun = NULL;
287 opts += strlen(cp);
288 tun = xmalloc(strlen(opts) + 1);
289 i = 0;
290 while (*opts) {
291 if (*opts == '"')
292 break;
293 tun[i++] = *opts++;
294 }
295 if (!*opts) {
296 debug("%.100s, line %lu: missing end quote",
297 file, linenum);
298 auth_debug_add("%.100s, line %lu: missing end quote",
299 file, linenum);
300 xfree(tun);
301 forced_tun_device = -1;
302 goto bad_option;
303 }
Damien Miller98299262006-07-24 14:01:43 +1000304 tun[i] = '\0';
Damien Millerd27b9472005-12-13 19:29:02 +1100305 forced_tun_device = a2tun(tun, NULL);
306 xfree(tun);
Damien Miller7b58e802005-12-13 19:33:19 +1100307 if (forced_tun_device == SSH_TUNID_ERR) {
Damien Millerd27b9472005-12-13 19:29:02 +1100308 debug("%.100s, line %lu: invalid tun device",
309 file, linenum);
310 auth_debug_add("%.100s, line %lu: invalid tun device",
311 file, linenum);
312 forced_tun_device = -1;
313 goto bad_option;
314 }
315 auth_debug_add("Forced tun device: %d", forced_tun_device);
316 opts++;
317 goto next_option;
318 }
Damien Millerf6d9e222000-06-18 14:50:44 +1000319next_option:
320 /*
321 * Skip the comma, and move to the next option
322 * (or break out if there are no more).
323 */
Damien Miller33804262001-02-04 23:20:18 +1100324 if (!*opts)
Damien Millerf6d9e222000-06-18 14:50:44 +1000325 fatal("Bugs in auth-options.c option processing.");
Damien Miller33804262001-02-04 23:20:18 +1100326 if (*opts == ' ' || *opts == '\t')
Damien Millerf6d9e222000-06-18 14:50:44 +1000327 break; /* End of options. */
Damien Miller33804262001-02-04 23:20:18 +1100328 if (*opts != ',')
Damien Millerf6d9e222000-06-18 14:50:44 +1000329 goto bad_option;
Damien Miller33804262001-02-04 23:20:18 +1100330 opts++;
Damien Millerf6d9e222000-06-18 14:50:44 +1000331 /* Process the next option. */
332 }
Ben Lindstrom7a2073c2002-03-22 02:30:41 +0000333
334 if (!use_privsep)
Ben Lindstroma574cda2002-05-15 16:16:14 +0000335 auth_debug_send();
Ben Lindstrom7a2073c2002-03-22 02:30:41 +0000336
Damien Millerf6d9e222000-06-18 14:50:44 +1000337 /* grant access */
338 return 1;
339
340bad_option:
Damien Miller996acd22003-04-09 20:59:48 +1000341 logit("Bad options in %.100s file, line %lu: %.50s",
Damien Miller33804262001-02-04 23:20:18 +1100342 file, linenum, opts);
Ben Lindstroma574cda2002-05-15 16:16:14 +0000343 auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
Damien Miller33804262001-02-04 23:20:18 +1100344 file, linenum, opts);
Ben Lindstrom7a2073c2002-03-22 02:30:41 +0000345
346 if (!use_privsep)
Ben Lindstroma574cda2002-05-15 16:16:14 +0000347 auth_debug_send();
Ben Lindstrom7a2073c2002-03-22 02:30:41 +0000348
Damien Millerf6d9e222000-06-18 14:50:44 +1000349 /* deny access */
350 return 0;
351}