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