1b66f2d16SKris Kennaway /* 2b66f2d16SKris Kennaway * Author: Tatu Ylonen <ylo@cs.hut.fi> 3b66f2d16SKris Kennaway * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4b66f2d16SKris Kennaway * All rights reserved 5b66f2d16SKris Kennaway * As far as I am concerned, the code I have written for this software 6b66f2d16SKris Kennaway * can be used freely for any purpose. Any derived versions of this 7b66f2d16SKris Kennaway * software must be clearly marked as such, and if the derived work is 8b66f2d16SKris Kennaway * incompatible with the protocol description in the RFC file, it must be 9b66f2d16SKris Kennaway * called by a name other than "ssh" or "Secure Shell". 10b66f2d16SKris Kennaway */ 11b66f2d16SKris Kennaway 12b66f2d16SKris Kennaway #include "includes.h" 131e8db6e2SBrian Feldman RCSID("$OpenBSD: auth-options.c,v 1.16 2001/03/18 12:07:52 markus Exp $"); 14b66f2d16SKris Kennaway 15b66f2d16SKris Kennaway #include "packet.h" 16b66f2d16SKris Kennaway #include "xmalloc.h" 17b66f2d16SKris Kennaway #include "match.h" 181e8db6e2SBrian Feldman #include "log.h" 191e8db6e2SBrian Feldman #include "canohost.h" 201e8db6e2SBrian Feldman #include "channels.h" 211e8db6e2SBrian Feldman #include "auth-options.h" 221e8db6e2SBrian Feldman #include "servconf.h" 23b66f2d16SKris Kennaway 24b66f2d16SKris Kennaway /* Flags set authorized_keys flags */ 25b66f2d16SKris Kennaway int no_port_forwarding_flag = 0; 26b66f2d16SKris Kennaway int no_agent_forwarding_flag = 0; 27b66f2d16SKris Kennaway int no_x11_forwarding_flag = 0; 28b66f2d16SKris Kennaway int no_pty_flag = 0; 29b66f2d16SKris Kennaway 30b66f2d16SKris Kennaway /* "command=" option. */ 31b66f2d16SKris Kennaway char *forced_command = NULL; 32b66f2d16SKris Kennaway 33b66f2d16SKris Kennaway /* "environment=" options. */ 34b66f2d16SKris Kennaway struct envstring *custom_environment = NULL; 35b66f2d16SKris Kennaway 361e8db6e2SBrian Feldman extern ServerOptions options; 371e8db6e2SBrian Feldman 385b9b2fafSBrian Feldman void 395b9b2fafSBrian Feldman auth_clear_options(void) 405b9b2fafSBrian Feldman { 415b9b2fafSBrian Feldman no_agent_forwarding_flag = 0; 425b9b2fafSBrian Feldman no_port_forwarding_flag = 0; 435b9b2fafSBrian Feldman no_pty_flag = 0; 445b9b2fafSBrian Feldman no_x11_forwarding_flag = 0; 455b9b2fafSBrian Feldman while (custom_environment) { 465b9b2fafSBrian Feldman struct envstring *ce = custom_environment; 475b9b2fafSBrian Feldman custom_environment = ce->next; 485b9b2fafSBrian Feldman xfree(ce->s); 495b9b2fafSBrian Feldman xfree(ce); 505b9b2fafSBrian Feldman } 515b9b2fafSBrian Feldman if (forced_command) { 525b9b2fafSBrian Feldman xfree(forced_command); 535b9b2fafSBrian Feldman forced_command = NULL; 545b9b2fafSBrian Feldman } 551e8db6e2SBrian Feldman channel_clear_permitted_opens(); 565b9b2fafSBrian Feldman } 575b9b2fafSBrian Feldman 581e8db6e2SBrian Feldman /* 591e8db6e2SBrian Feldman * return 1 if access is granted, 0 if not. 601e8db6e2SBrian Feldman * side effect: sets key option flags 611e8db6e2SBrian Feldman */ 62b66f2d16SKris Kennaway int 631e8db6e2SBrian Feldman auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) 64b66f2d16SKris Kennaway { 65b66f2d16SKris Kennaway const char *cp; 661e8db6e2SBrian Feldman int i; 675b9b2fafSBrian Feldman 685b9b2fafSBrian Feldman /* reset options */ 695b9b2fafSBrian Feldman auth_clear_options(); 705b9b2fafSBrian Feldman 711e8db6e2SBrian Feldman if (!opts) 721e8db6e2SBrian Feldman return 1; 731e8db6e2SBrian Feldman 741e8db6e2SBrian Feldman while (*opts && *opts != ' ' && *opts != '\t') { 75b66f2d16SKris Kennaway cp = "no-port-forwarding"; 761e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 77b66f2d16SKris Kennaway packet_send_debug("Port forwarding disabled."); 78b66f2d16SKris Kennaway no_port_forwarding_flag = 1; 791e8db6e2SBrian Feldman opts += strlen(cp); 80b66f2d16SKris Kennaway goto next_option; 81b66f2d16SKris Kennaway } 82b66f2d16SKris Kennaway cp = "no-agent-forwarding"; 831e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 84b66f2d16SKris Kennaway packet_send_debug("Agent forwarding disabled."); 85b66f2d16SKris Kennaway no_agent_forwarding_flag = 1; 861e8db6e2SBrian Feldman opts += strlen(cp); 87b66f2d16SKris Kennaway goto next_option; 88b66f2d16SKris Kennaway } 89b66f2d16SKris Kennaway cp = "no-X11-forwarding"; 901e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 91b66f2d16SKris Kennaway packet_send_debug("X11 forwarding disabled."); 92b66f2d16SKris Kennaway no_x11_forwarding_flag = 1; 931e8db6e2SBrian Feldman opts += strlen(cp); 94b66f2d16SKris Kennaway goto next_option; 95b66f2d16SKris Kennaway } 96b66f2d16SKris Kennaway cp = "no-pty"; 971e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 98b66f2d16SKris Kennaway packet_send_debug("Pty allocation disabled."); 99b66f2d16SKris Kennaway no_pty_flag = 1; 1001e8db6e2SBrian Feldman opts += strlen(cp); 101b66f2d16SKris Kennaway goto next_option; 102b66f2d16SKris Kennaway } 103b66f2d16SKris Kennaway cp = "command=\""; 1041e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 1051e8db6e2SBrian Feldman opts += strlen(cp); 1061e8db6e2SBrian Feldman forced_command = xmalloc(strlen(opts) + 1); 107b66f2d16SKris Kennaway i = 0; 1081e8db6e2SBrian Feldman while (*opts) { 1091e8db6e2SBrian Feldman if (*opts == '"') 110b66f2d16SKris Kennaway break; 1111e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 1121e8db6e2SBrian Feldman opts += 2; 113b66f2d16SKris Kennaway forced_command[i++] = '"'; 114b66f2d16SKris Kennaway continue; 115b66f2d16SKris Kennaway } 1161e8db6e2SBrian Feldman forced_command[i++] = *opts++; 117b66f2d16SKris Kennaway } 1181e8db6e2SBrian Feldman if (!*opts) { 119b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 1201e8db6e2SBrian Feldman file, linenum); 121b66f2d16SKris Kennaway packet_send_debug("%.100s, line %lu: missing end quote", 1221e8db6e2SBrian Feldman file, linenum); 1231e8db6e2SBrian Feldman xfree(forced_command); 1241e8db6e2SBrian Feldman forced_command = NULL; 1251e8db6e2SBrian Feldman goto bad_option; 126b66f2d16SKris Kennaway } 127b66f2d16SKris Kennaway forced_command[i] = 0; 128b66f2d16SKris Kennaway packet_send_debug("Forced command: %.900s", forced_command); 1291e8db6e2SBrian Feldman opts++; 130b66f2d16SKris Kennaway goto next_option; 131b66f2d16SKris Kennaway } 132b66f2d16SKris Kennaway cp = "environment=\""; 1331e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 134b66f2d16SKris Kennaway char *s; 135b66f2d16SKris Kennaway struct envstring *new_envstring; 1361e8db6e2SBrian Feldman 1371e8db6e2SBrian Feldman opts += strlen(cp); 1381e8db6e2SBrian Feldman s = xmalloc(strlen(opts) + 1); 139b66f2d16SKris Kennaway i = 0; 1401e8db6e2SBrian Feldman while (*opts) { 1411e8db6e2SBrian Feldman if (*opts == '"') 142b66f2d16SKris Kennaway break; 1431e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 1441e8db6e2SBrian Feldman opts += 2; 145b66f2d16SKris Kennaway s[i++] = '"'; 146b66f2d16SKris Kennaway continue; 147b66f2d16SKris Kennaway } 1481e8db6e2SBrian Feldman s[i++] = *opts++; 149b66f2d16SKris Kennaway } 1501e8db6e2SBrian Feldman if (!*opts) { 151b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 1521e8db6e2SBrian Feldman file, linenum); 153b66f2d16SKris Kennaway packet_send_debug("%.100s, line %lu: missing end quote", 1541e8db6e2SBrian Feldman file, linenum); 1551e8db6e2SBrian Feldman xfree(s); 1561e8db6e2SBrian Feldman goto bad_option; 157b66f2d16SKris Kennaway } 158b66f2d16SKris Kennaway s[i] = 0; 159b66f2d16SKris Kennaway packet_send_debug("Adding to environment: %.900s", s); 160b66f2d16SKris Kennaway debug("Adding to environment: %.900s", s); 1611e8db6e2SBrian Feldman opts++; 162b66f2d16SKris Kennaway new_envstring = xmalloc(sizeof(struct envstring)); 163b66f2d16SKris Kennaway new_envstring->s = s; 164b66f2d16SKris Kennaway new_envstring->next = custom_environment; 165b66f2d16SKris Kennaway custom_environment = new_envstring; 166b66f2d16SKris Kennaway goto next_option; 167b66f2d16SKris Kennaway } 168b66f2d16SKris Kennaway cp = "from=\""; 1691e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 170b66f2d16SKris Kennaway int mname, mip; 1711e8db6e2SBrian Feldman const char *remote_ip = get_remote_ipaddr(); 1721e8db6e2SBrian Feldman const char *remote_host = get_canonical_hostname( 1731e8db6e2SBrian Feldman options.reverse_mapping_check); 1741e8db6e2SBrian Feldman char *patterns = xmalloc(strlen(opts) + 1); 1751e8db6e2SBrian Feldman 1761e8db6e2SBrian Feldman opts += strlen(cp); 177b66f2d16SKris Kennaway i = 0; 1781e8db6e2SBrian Feldman while (*opts) { 1791e8db6e2SBrian Feldman if (*opts == '"') 180b66f2d16SKris Kennaway break; 1811e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 1821e8db6e2SBrian Feldman opts += 2; 183b66f2d16SKris Kennaway patterns[i++] = '"'; 184b66f2d16SKris Kennaway continue; 185b66f2d16SKris Kennaway } 1861e8db6e2SBrian Feldman patterns[i++] = *opts++; 187b66f2d16SKris Kennaway } 1881e8db6e2SBrian Feldman if (!*opts) { 189b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 1901e8db6e2SBrian Feldman file, linenum); 191b66f2d16SKris Kennaway packet_send_debug("%.100s, line %lu: missing end quote", 1921e8db6e2SBrian Feldman file, linenum); 1931e8db6e2SBrian Feldman xfree(patterns); 1941e8db6e2SBrian Feldman goto bad_option; 195b66f2d16SKris Kennaway } 196b66f2d16SKris Kennaway patterns[i] = 0; 1971e8db6e2SBrian Feldman opts++; 198b66f2d16SKris Kennaway /* 199b66f2d16SKris Kennaway * Deny access if we get a negative 200b66f2d16SKris Kennaway * match for the hostname or the ip 201b66f2d16SKris Kennaway * or if we get not match at all 202b66f2d16SKris Kennaway */ 2031e8db6e2SBrian Feldman mname = match_hostname(remote_host, patterns, 2041e8db6e2SBrian Feldman strlen(patterns)); 2051e8db6e2SBrian Feldman mip = match_hostname(remote_ip, patterns, 2061e8db6e2SBrian Feldman strlen(patterns)); 207b66f2d16SKris Kennaway xfree(patterns); 208b66f2d16SKris Kennaway if (mname == -1 || mip == -1 || 209b66f2d16SKris Kennaway (mname != 1 && mip != 1)) { 2101e8db6e2SBrian Feldman log("Authentication tried for %.100s with " 2111e8db6e2SBrian Feldman "correct key but not from a permitted " 2121e8db6e2SBrian Feldman "host (host=%.200s, ip=%.200s).", 2131e8db6e2SBrian Feldman pw->pw_name, remote_host, remote_ip); 2141e8db6e2SBrian Feldman packet_send_debug("Your host '%.200s' is not " 2151e8db6e2SBrian Feldman "permitted to use this key for login.", 2161e8db6e2SBrian Feldman remote_host); 217b66f2d16SKris Kennaway /* deny access */ 218b66f2d16SKris Kennaway return 0; 219b66f2d16SKris Kennaway } 220b66f2d16SKris Kennaway /* Host name matches. */ 221b66f2d16SKris Kennaway goto next_option; 222b66f2d16SKris Kennaway } 2231e8db6e2SBrian Feldman cp = "permitopen=\""; 2241e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 2251e8db6e2SBrian Feldman u_short port; 2261e8db6e2SBrian Feldman char *c, *ep; 2271e8db6e2SBrian Feldman char *patterns = xmalloc(strlen(opts) + 1); 2281e8db6e2SBrian Feldman 2291e8db6e2SBrian Feldman opts += strlen(cp); 2301e8db6e2SBrian Feldman i = 0; 2311e8db6e2SBrian Feldman while (*opts) { 2321e8db6e2SBrian Feldman if (*opts == '"') 2331e8db6e2SBrian Feldman break; 2341e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 2351e8db6e2SBrian Feldman opts += 2; 2361e8db6e2SBrian Feldman patterns[i++] = '"'; 2371e8db6e2SBrian Feldman continue; 2381e8db6e2SBrian Feldman } 2391e8db6e2SBrian Feldman patterns[i++] = *opts++; 2401e8db6e2SBrian Feldman } 2411e8db6e2SBrian Feldman if (!*opts) { 2421e8db6e2SBrian Feldman debug("%.100s, line %lu: missing end quote", 2431e8db6e2SBrian Feldman file, linenum); 2441e8db6e2SBrian Feldman packet_send_debug("%.100s, line %lu: missing end quote", 2451e8db6e2SBrian Feldman file, linenum); 2461e8db6e2SBrian Feldman xfree(patterns); 2471e8db6e2SBrian Feldman goto bad_option; 2481e8db6e2SBrian Feldman } 2491e8db6e2SBrian Feldman patterns[i] = 0; 2501e8db6e2SBrian Feldman opts++; 2511e8db6e2SBrian Feldman c = strchr(patterns, ':'); 2521e8db6e2SBrian Feldman if (c == NULL) { 2531e8db6e2SBrian Feldman debug("%.100s, line %lu: permitopen: missing colon <%.100s>", 2541e8db6e2SBrian Feldman file, linenum, patterns); 2551e8db6e2SBrian Feldman packet_send_debug("%.100s, line %lu: missing colon", 2561e8db6e2SBrian Feldman file, linenum); 2571e8db6e2SBrian Feldman xfree(patterns); 2581e8db6e2SBrian Feldman goto bad_option; 2591e8db6e2SBrian Feldman } 2601e8db6e2SBrian Feldman *c = 0; 2611e8db6e2SBrian Feldman c++; 2621e8db6e2SBrian Feldman port = strtol(c, &ep, 0); 2631e8db6e2SBrian Feldman if (c == ep) { 2641e8db6e2SBrian Feldman debug("%.100s, line %lu: permitopen: missing port <%.100s>", 2651e8db6e2SBrian Feldman file, linenum, patterns); 2661e8db6e2SBrian Feldman packet_send_debug("%.100s, line %lu: missing port", 2671e8db6e2SBrian Feldman file, linenum); 2681e8db6e2SBrian Feldman xfree(patterns); 2691e8db6e2SBrian Feldman goto bad_option; 2701e8db6e2SBrian Feldman } 2711e8db6e2SBrian Feldman if (options.allow_tcp_forwarding) 2721e8db6e2SBrian Feldman channel_add_permitted_opens(patterns, port); 2731e8db6e2SBrian Feldman xfree(patterns); 2741e8db6e2SBrian Feldman goto next_option; 2751e8db6e2SBrian Feldman } 276b66f2d16SKris Kennaway next_option: 277b66f2d16SKris Kennaway /* 278b66f2d16SKris Kennaway * Skip the comma, and move to the next option 279b66f2d16SKris Kennaway * (or break out if there are no more). 280b66f2d16SKris Kennaway */ 2811e8db6e2SBrian Feldman if (!*opts) 282b66f2d16SKris Kennaway fatal("Bugs in auth-options.c option processing."); 2831e8db6e2SBrian Feldman if (*opts == ' ' || *opts == '\t') 284b66f2d16SKris Kennaway break; /* End of options. */ 2851e8db6e2SBrian Feldman if (*opts != ',') 286b66f2d16SKris Kennaway goto bad_option; 2871e8db6e2SBrian Feldman opts++; 288b66f2d16SKris Kennaway /* Process the next option. */ 289b66f2d16SKris Kennaway } 290b66f2d16SKris Kennaway /* grant access */ 291b66f2d16SKris Kennaway return 1; 292b66f2d16SKris Kennaway 293b66f2d16SKris Kennaway bad_option: 294b66f2d16SKris Kennaway log("Bad options in %.100s file, line %lu: %.50s", 2951e8db6e2SBrian Feldman file, linenum, opts); 296b66f2d16SKris Kennaway packet_send_debug("Bad options in %.100s file, line %lu: %.50s", 2971e8db6e2SBrian Feldman file, linenum, opts); 298b66f2d16SKris Kennaway /* deny access */ 299b66f2d16SKris Kennaway return 0; 300b66f2d16SKris Kennaway } 301