Annotation of src/usr.bin/ssh/auth-options.c, Revision 1.31.4.1
1.3 deraadt 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:
1.1 markus 12: #include "includes.h"
1.31.4.1! brad 13: RCSID("$OpenBSD: auth-options.c,v 1.33 2005/12/08 18:34:11 reyk Exp $");
1.1 markus 14:
15: #include "xmalloc.h"
16: #include "match.h"
1.11 markus 17: #include "log.h"
18: #include "canohost.h"
1.18 markus 19: #include "channels.h"
1.11 markus 20: #include "auth-options.h"
1.12 markus 21: #include "servconf.h"
1.20 stevesk 22: #include "misc.h"
1.22 provos 23: #include "monitor_wrap.h"
1.24 markus 24: #include "auth.h"
1.1 markus 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:
1.31.4.1! brad 38: /* "tunnel=" option. */
! 39: int forced_tun_device = -1;
! 40:
1.12 markus 41: extern ServerOptions options;
42:
1.22 provos 43: void
1.5 markus 44: auth_clear_options(void)
45: {
46: no_agent_forwarding_flag = 0;
47: no_port_forwarding_flag = 0;
48: no_pty_flag = 0;
49: no_x11_forwarding_flag = 0;
50: while (custom_environment) {
51: struct envstring *ce = custom_environment;
52: custom_environment = ce->next;
53: xfree(ce->s);
54: xfree(ce);
55: }
56: if (forced_command) {
57: xfree(forced_command);
58: forced_command = NULL;
59: }
1.31.4.1! brad 60: forced_tun_device = -1;
1.15 markus 61: channel_clear_permitted_opens();
1.24 markus 62: auth_debug_reset();
1.5 markus 63: }
64:
1.10 markus 65: /*
66: * return 1 if access is granted, 0 if not.
67: * side effect: sets key option flags
68: */
1.1 markus 69: int
1.12 markus 70: auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
1.1 markus 71: {
72: const char *cp;
1.15 markus 73: int i;
1.5 markus 74:
75: /* reset options */
76: auth_clear_options();
1.13 markus 77:
78: if (!opts)
79: return 1;
1.5 markus 80:
1.12 markus 81: while (*opts && *opts != ' ' && *opts != '\t') {
1.1 markus 82: cp = "no-port-forwarding";
1.12 markus 83: if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1.24 markus 84: auth_debug_add("Port forwarding disabled.");
1.1 markus 85: no_port_forwarding_flag = 1;
1.12 markus 86: opts += strlen(cp);
1.1 markus 87: goto next_option;
88: }
89: cp = "no-agent-forwarding";
1.12 markus 90: if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1.24 markus 91: auth_debug_add("Agent forwarding disabled.");
1.1 markus 92: no_agent_forwarding_flag = 1;
1.12 markus 93: opts += strlen(cp);
1.1 markus 94: goto next_option;
95: }
96: cp = "no-X11-forwarding";
1.12 markus 97: if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1.24 markus 98: auth_debug_add("X11 forwarding disabled.");
1.1 markus 99: no_x11_forwarding_flag = 1;
1.12 markus 100: opts += strlen(cp);
1.1 markus 101: goto next_option;
102: }
103: cp = "no-pty";
1.12 markus 104: if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1.24 markus 105: auth_debug_add("Pty allocation disabled.");
1.1 markus 106: no_pty_flag = 1;
1.12 markus 107: opts += strlen(cp);
1.1 markus 108: goto next_option;
109: }
110: cp = "command=\"";
1.12 markus 111: if (strncasecmp(opts, cp, strlen(cp)) == 0) {
112: opts += strlen(cp);
113: forced_command = xmalloc(strlen(opts) + 1);
1.1 markus 114: i = 0;
1.12 markus 115: while (*opts) {
116: if (*opts == '"')
1.1 markus 117: break;
1.12 markus 118: if (*opts == '\\' && opts[1] == '"') {
119: opts += 2;
1.1 markus 120: forced_command[i++] = '"';
121: continue;
122: }
1.12 markus 123: forced_command[i++] = *opts++;
1.1 markus 124: }
1.12 markus 125: if (!*opts) {
1.1 markus 126: debug("%.100s, line %lu: missing end quote",
1.10 markus 127: file, linenum);
1.24 markus 128: auth_debug_add("%.100s, line %lu: missing end quote",
1.10 markus 129: file, linenum);
1.14 markus 130: xfree(forced_command);
131: forced_command = NULL;
132: goto bad_option;
1.1 markus 133: }
134: forced_command[i] = 0;
1.24 markus 135: auth_debug_add("Forced command: %.900s", forced_command);
1.12 markus 136: opts++;
1.1 markus 137: goto next_option;
138: }
139: cp = "environment=\"";
1.26 markus 140: if (options.permit_user_env &&
141: strncasecmp(opts, cp, strlen(cp)) == 0) {
1.1 markus 142: char *s;
143: struct envstring *new_envstring;
1.15 markus 144:
1.12 markus 145: opts += strlen(cp);
146: s = xmalloc(strlen(opts) + 1);
1.1 markus 147: i = 0;
1.12 markus 148: while (*opts) {
149: if (*opts == '"')
1.1 markus 150: break;
1.12 markus 151: if (*opts == '\\' && opts[1] == '"') {
152: opts += 2;
1.1 markus 153: s[i++] = '"';
154: continue;
155: }
1.12 markus 156: s[i++] = *opts++;
1.1 markus 157: }
1.12 markus 158: if (!*opts) {
1.1 markus 159: debug("%.100s, line %lu: missing end quote",
1.10 markus 160: file, linenum);
1.24 markus 161: auth_debug_add("%.100s, line %lu: missing end quote",
1.10 markus 162: file, linenum);
1.14 markus 163: xfree(s);
164: goto bad_option;
1.1 markus 165: }
166: s[i] = 0;
1.24 markus 167: auth_debug_add("Adding to environment: %.900s", s);
1.1 markus 168: debug("Adding to environment: %.900s", s);
1.12 markus 169: opts++;
1.1 markus 170: new_envstring = xmalloc(sizeof(struct envstring));
171: new_envstring->s = s;
172: new_envstring->next = custom_environment;
173: custom_environment = new_envstring;
174: goto next_option;
175: }
176: cp = "from=\"";
1.12 markus 177: if (strncasecmp(opts, cp, strlen(cp)) == 0) {
178: const char *remote_ip = get_remote_ipaddr();
179: const char *remote_host = get_canonical_hostname(
1.28 markus 180: options.use_dns);
1.12 markus 181: char *patterns = xmalloc(strlen(opts) + 1);
1.15 markus 182:
1.12 markus 183: opts += strlen(cp);
1.1 markus 184: i = 0;
1.12 markus 185: while (*opts) {
186: if (*opts == '"')
1.1 markus 187: break;
1.12 markus 188: if (*opts == '\\' && opts[1] == '"') {
189: opts += 2;
1.1 markus 190: patterns[i++] = '"';
191: continue;
192: }
1.12 markus 193: patterns[i++] = *opts++;
1.1 markus 194: }
1.12 markus 195: if (!*opts) {
1.1 markus 196: debug("%.100s, line %lu: missing end quote",
1.10 markus 197: file, linenum);
1.24 markus 198: auth_debug_add("%.100s, line %lu: missing end quote",
1.10 markus 199: file, linenum);
1.14 markus 200: xfree(patterns);
201: goto bad_option;
1.1 markus 202: }
203: patterns[i] = 0;
1.12 markus 204: opts++;
1.19 markus 205: if (match_host_and_ip(remote_host, remote_ip,
206: patterns) != 1) {
207: xfree(patterns);
1.27 itojun 208: logit("Authentication tried for %.100s with "
1.12 markus 209: "correct key but not from a permitted "
210: "host (host=%.200s, ip=%.200s).",
211: pw->pw_name, remote_host, remote_ip);
1.24 markus 212: auth_debug_add("Your host '%.200s' is not "
1.12 markus 213: "permitted to use this key for login.",
214: remote_host);
1.1 markus 215: /* deny access */
216: return 0;
217: }
1.19 markus 218: xfree(patterns);
1.1 markus 219: /* Host name matches. */
1.15 markus 220: goto next_option;
221: }
222: cp = "permitopen=\"";
223: if (strncasecmp(opts, cp, strlen(cp)) == 0) {
1.29 djm 224: char *host, *p;
1.15 markus 225: u_short port;
226: char *patterns = xmalloc(strlen(opts) + 1);
227:
228: opts += strlen(cp);
229: i = 0;
230: while (*opts) {
231: if (*opts == '"')
232: break;
233: if (*opts == '\\' && opts[1] == '"') {
234: opts += 2;
235: patterns[i++] = '"';
236: continue;
237: }
238: patterns[i++] = *opts++;
239: }
240: if (!*opts) {
241: debug("%.100s, line %lu: missing end quote",
242: file, linenum);
1.29 djm 243: auth_debug_add("%.100s, line %lu: missing "
244: "end quote", file, linenum);
1.15 markus 245: xfree(patterns);
246: goto bad_option;
247: }
248: patterns[i] = 0;
249: opts++;
1.29 djm 250: p = patterns;
251: host = hpdelim(&p);
252: if (host == NULL || strlen(host) >= NI_MAXHOST) {
253: debug("%.100s, line %lu: Bad permitopen "
1.31 deraadt 254: "specification <%.100s>", file, linenum,
1.29 djm 255: patterns);
1.24 markus 256: auth_debug_add("%.100s, line %lu: "
1.29 djm 257: "Bad permitopen specification", file,
258: linenum);
1.15 markus 259: xfree(patterns);
260: goto bad_option;
261: }
1.30 deraadt 262: host = cleanhostname(host);
263: if (p == NULL || (port = a2port(p)) == 0) {
1.29 djm 264: debug("%.100s, line %lu: Bad permitopen port "
265: "<%.100s>", file, linenum, p ? p : "");
1.24 markus 266: auth_debug_add("%.100s, line %lu: "
1.20 stevesk 267: "Bad permitopen port", file, linenum);
1.15 markus 268: xfree(patterns);
269: goto bad_option;
270: }
1.16 markus 271: if (options.allow_tcp_forwarding)
1.20 stevesk 272: channel_add_permitted_opens(host, port);
1.15 markus 273: xfree(patterns);
1.31.4.1! brad 274: goto next_option;
! 275: }
! 276: cp = "tunnel=\"";
! 277: if (strncasecmp(opts, cp, strlen(cp)) == 0) {
! 278: char *tun = NULL;
! 279: opts += strlen(cp);
! 280: tun = xmalloc(strlen(opts) + 1);
! 281: i = 0;
! 282: while (*opts) {
! 283: if (*opts == '"')
! 284: break;
! 285: tun[i++] = *opts++;
! 286: }
! 287: if (!*opts) {
! 288: debug("%.100s, line %lu: missing end quote",
! 289: file, linenum);
! 290: auth_debug_add("%.100s, line %lu: missing end quote",
! 291: file, linenum);
! 292: xfree(tun);
! 293: forced_tun_device = -1;
! 294: goto bad_option;
! 295: }
! 296: tun[i] = 0;
! 297: forced_tun_device = a2tun(tun, NULL);
! 298: xfree(tun);
! 299: if (forced_tun_device == SSH_TUNID_ERR) {
! 300: debug("%.100s, line %lu: invalid tun device",
! 301: file, linenum);
! 302: auth_debug_add("%.100s, line %lu: invalid tun device",
! 303: file, linenum);
! 304: forced_tun_device = -1;
! 305: goto bad_option;
! 306: }
! 307: auth_debug_add("Forced tun device: %d", forced_tun_device);
! 308: opts++;
1.1 markus 309: goto next_option;
310: }
311: next_option:
312: /*
313: * Skip the comma, and move to the next option
314: * (or break out if there are no more).
315: */
1.12 markus 316: if (!*opts)
1.1 markus 317: fatal("Bugs in auth-options.c option processing.");
1.12 markus 318: if (*opts == ' ' || *opts == '\t')
1.1 markus 319: break; /* End of options. */
1.12 markus 320: if (*opts != ',')
1.1 markus 321: goto bad_option;
1.12 markus 322: opts++;
1.1 markus 323: /* Process the next option. */
324: }
1.22 provos 325:
326: if (!use_privsep)
1.24 markus 327: auth_debug_send();
1.22 provos 328:
1.1 markus 329: /* grant access */
330: return 1;
331:
332: bad_option:
1.27 itojun 333: logit("Bad options in %.100s file, line %lu: %.50s",
1.12 markus 334: file, linenum, opts);
1.24 markus 335: auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
1.12 markus 336: file, linenum, opts);
1.22 provos 337:
338: if (!use_privsep)
1.24 markus 339: auth_debug_send();
1.22 provos 340:
1.1 markus 341: /* deny access */
342: return 0;
343: }