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