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" 13545d5ecaSDag-Erling Smørgrav RCSID("$OpenBSD: auth-options.c,v 1.24 2002/05/13 20:44:58 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" 23545d5ecaSDag-Erling Smørgrav #include "bufaux.h" 24ae1f160dSDag-Erling Smørgrav #include "misc.h" 25545d5ecaSDag-Erling Smørgrav #include "monitor_wrap.h" 26545d5ecaSDag-Erling Smørgrav #include "auth.h" 27b66f2d16SKris Kennaway 28b66f2d16SKris Kennaway /* Flags set authorized_keys flags */ 29b66f2d16SKris Kennaway int no_port_forwarding_flag = 0; 30b66f2d16SKris Kennaway int no_agent_forwarding_flag = 0; 31b66f2d16SKris Kennaway int no_x11_forwarding_flag = 0; 32b66f2d16SKris Kennaway int no_pty_flag = 0; 33b66f2d16SKris Kennaway 34b66f2d16SKris Kennaway /* "command=" option. */ 35b66f2d16SKris Kennaway char *forced_command = NULL; 36b66f2d16SKris Kennaway 37b66f2d16SKris Kennaway /* "environment=" options. */ 38b66f2d16SKris Kennaway struct envstring *custom_environment = NULL; 39b66f2d16SKris Kennaway 401e8db6e2SBrian Feldman extern ServerOptions options; 411e8db6e2SBrian Feldman 425b9b2fafSBrian Feldman void 435b9b2fafSBrian Feldman auth_clear_options(void) 445b9b2fafSBrian Feldman { 455b9b2fafSBrian Feldman no_agent_forwarding_flag = 0; 465b9b2fafSBrian Feldman no_port_forwarding_flag = 0; 475b9b2fafSBrian Feldman no_pty_flag = 0; 485b9b2fafSBrian Feldman no_x11_forwarding_flag = 0; 495b9b2fafSBrian Feldman while (custom_environment) { 505b9b2fafSBrian Feldman struct envstring *ce = custom_environment; 515b9b2fafSBrian Feldman custom_environment = ce->next; 525b9b2fafSBrian Feldman xfree(ce->s); 535b9b2fafSBrian Feldman xfree(ce); 545b9b2fafSBrian Feldman } 555b9b2fafSBrian Feldman if (forced_command) { 565b9b2fafSBrian Feldman xfree(forced_command); 575b9b2fafSBrian Feldman forced_command = NULL; 585b9b2fafSBrian Feldman } 591e8db6e2SBrian Feldman channel_clear_permitted_opens(); 60545d5ecaSDag-Erling Smørgrav auth_debug_reset(); 615b9b2fafSBrian Feldman } 625b9b2fafSBrian Feldman 631e8db6e2SBrian Feldman /* 641e8db6e2SBrian Feldman * return 1 if access is granted, 0 if not. 651e8db6e2SBrian Feldman * side effect: sets key option flags 661e8db6e2SBrian Feldman */ 67b66f2d16SKris Kennaway int 681e8db6e2SBrian Feldman auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) 69b66f2d16SKris Kennaway { 70b66f2d16SKris Kennaway const char *cp; 711e8db6e2SBrian Feldman int i; 725b9b2fafSBrian Feldman 735b9b2fafSBrian Feldman /* reset options */ 745b9b2fafSBrian Feldman auth_clear_options(); 755b9b2fafSBrian Feldman 761e8db6e2SBrian Feldman if (!opts) 771e8db6e2SBrian Feldman return 1; 781e8db6e2SBrian Feldman 791e8db6e2SBrian Feldman while (*opts && *opts != ' ' && *opts != '\t') { 80b66f2d16SKris Kennaway cp = "no-port-forwarding"; 811e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 82545d5ecaSDag-Erling Smørgrav auth_debug_add("Port forwarding disabled."); 83b66f2d16SKris Kennaway no_port_forwarding_flag = 1; 841e8db6e2SBrian Feldman opts += strlen(cp); 85b66f2d16SKris Kennaway goto next_option; 86b66f2d16SKris Kennaway } 87b66f2d16SKris Kennaway cp = "no-agent-forwarding"; 881e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 89545d5ecaSDag-Erling Smørgrav auth_debug_add("Agent forwarding disabled."); 90b66f2d16SKris Kennaway no_agent_forwarding_flag = 1; 911e8db6e2SBrian Feldman opts += strlen(cp); 92b66f2d16SKris Kennaway goto next_option; 93b66f2d16SKris Kennaway } 94b66f2d16SKris Kennaway cp = "no-X11-forwarding"; 951e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 96545d5ecaSDag-Erling Smørgrav auth_debug_add("X11 forwarding disabled."); 97b66f2d16SKris Kennaway no_x11_forwarding_flag = 1; 981e8db6e2SBrian Feldman opts += strlen(cp); 99b66f2d16SKris Kennaway goto next_option; 100b66f2d16SKris Kennaway } 101b66f2d16SKris Kennaway cp = "no-pty"; 1021e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 103545d5ecaSDag-Erling Smørgrav auth_debug_add("Pty allocation disabled."); 104b66f2d16SKris Kennaway no_pty_flag = 1; 1051e8db6e2SBrian Feldman opts += strlen(cp); 106b66f2d16SKris Kennaway goto next_option; 107b66f2d16SKris Kennaway } 108b66f2d16SKris Kennaway cp = "command=\""; 1091e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 1101e8db6e2SBrian Feldman opts += strlen(cp); 1111e8db6e2SBrian Feldman forced_command = xmalloc(strlen(opts) + 1); 112b66f2d16SKris Kennaway i = 0; 1131e8db6e2SBrian Feldman while (*opts) { 1141e8db6e2SBrian Feldman if (*opts == '"') 115b66f2d16SKris Kennaway break; 1161e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 1171e8db6e2SBrian Feldman opts += 2; 118b66f2d16SKris Kennaway forced_command[i++] = '"'; 119b66f2d16SKris Kennaway continue; 120b66f2d16SKris Kennaway } 1211e8db6e2SBrian Feldman forced_command[i++] = *opts++; 122b66f2d16SKris Kennaway } 1231e8db6e2SBrian Feldman if (!*opts) { 124b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 1251e8db6e2SBrian Feldman file, linenum); 126545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing end quote", 1271e8db6e2SBrian Feldman file, linenum); 1281e8db6e2SBrian Feldman xfree(forced_command); 1291e8db6e2SBrian Feldman forced_command = NULL; 1301e8db6e2SBrian Feldman goto bad_option; 131b66f2d16SKris Kennaway } 132b66f2d16SKris Kennaway forced_command[i] = 0; 133545d5ecaSDag-Erling Smørgrav auth_debug_add("Forced command: %.900s", forced_command); 1341e8db6e2SBrian Feldman opts++; 135b66f2d16SKris Kennaway goto next_option; 136b66f2d16SKris Kennaway } 137b66f2d16SKris Kennaway cp = "environment=\""; 1381e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 139b66f2d16SKris Kennaway char *s; 140b66f2d16SKris Kennaway struct envstring *new_envstring; 1411e8db6e2SBrian Feldman 1421e8db6e2SBrian Feldman opts += strlen(cp); 1431e8db6e2SBrian Feldman s = xmalloc(strlen(opts) + 1); 144b66f2d16SKris Kennaway i = 0; 1451e8db6e2SBrian Feldman while (*opts) { 1461e8db6e2SBrian Feldman if (*opts == '"') 147b66f2d16SKris Kennaway break; 1481e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 1491e8db6e2SBrian Feldman opts += 2; 150b66f2d16SKris Kennaway s[i++] = '"'; 151b66f2d16SKris Kennaway continue; 152b66f2d16SKris Kennaway } 1531e8db6e2SBrian Feldman s[i++] = *opts++; 154b66f2d16SKris Kennaway } 1551e8db6e2SBrian Feldman if (!*opts) { 156b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 1571e8db6e2SBrian Feldman file, linenum); 158545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing end quote", 1591e8db6e2SBrian Feldman file, linenum); 1601e8db6e2SBrian Feldman xfree(s); 1611e8db6e2SBrian Feldman goto bad_option; 162b66f2d16SKris Kennaway } 163b66f2d16SKris Kennaway s[i] = 0; 164545d5ecaSDag-Erling Smørgrav auth_debug_add("Adding to environment: %.900s", s); 165b66f2d16SKris Kennaway debug("Adding to environment: %.900s", s); 1661e8db6e2SBrian Feldman opts++; 167b66f2d16SKris Kennaway new_envstring = xmalloc(sizeof(struct envstring)); 168b66f2d16SKris Kennaway new_envstring->s = s; 169b66f2d16SKris Kennaway new_envstring->next = custom_environment; 170b66f2d16SKris Kennaway custom_environment = new_envstring; 171b66f2d16SKris Kennaway goto next_option; 172b66f2d16SKris Kennaway } 173b66f2d16SKris Kennaway cp = "from=\""; 1741e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 1751e8db6e2SBrian Feldman const char *remote_ip = get_remote_ipaddr(); 1761e8db6e2SBrian Feldman const char *remote_host = get_canonical_hostname( 177ae1f160dSDag-Erling Smørgrav options.verify_reverse_mapping); 1781e8db6e2SBrian Feldman char *patterns = xmalloc(strlen(opts) + 1); 1791e8db6e2SBrian Feldman 1801e8db6e2SBrian Feldman opts += strlen(cp); 181b66f2d16SKris Kennaway i = 0; 1821e8db6e2SBrian Feldman while (*opts) { 1831e8db6e2SBrian Feldman if (*opts == '"') 184b66f2d16SKris Kennaway break; 1851e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 1861e8db6e2SBrian Feldman opts += 2; 187b66f2d16SKris Kennaway patterns[i++] = '"'; 188b66f2d16SKris Kennaway continue; 189b66f2d16SKris Kennaway } 1901e8db6e2SBrian Feldman patterns[i++] = *opts++; 191b66f2d16SKris Kennaway } 1921e8db6e2SBrian Feldman if (!*opts) { 193b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 1941e8db6e2SBrian Feldman file, linenum); 195545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing end quote", 1961e8db6e2SBrian Feldman file, linenum); 1971e8db6e2SBrian Feldman xfree(patterns); 1981e8db6e2SBrian Feldman goto bad_option; 199b66f2d16SKris Kennaway } 200b66f2d16SKris Kennaway patterns[i] = 0; 2011e8db6e2SBrian Feldman opts++; 202ae1f160dSDag-Erling Smørgrav if (match_host_and_ip(remote_host, remote_ip, 203ae1f160dSDag-Erling Smørgrav patterns) != 1) { 204b66f2d16SKris Kennaway xfree(patterns); 2051e8db6e2SBrian Feldman log("Authentication tried for %.100s with " 2061e8db6e2SBrian Feldman "correct key but not from a permitted " 2071e8db6e2SBrian Feldman "host (host=%.200s, ip=%.200s).", 2081e8db6e2SBrian Feldman pw->pw_name, remote_host, remote_ip); 209545d5ecaSDag-Erling Smørgrav auth_debug_add("Your host '%.200s' is not " 2101e8db6e2SBrian Feldman "permitted to use this key for login.", 2111e8db6e2SBrian Feldman remote_host); 212b66f2d16SKris Kennaway /* deny access */ 213b66f2d16SKris Kennaway return 0; 214b66f2d16SKris Kennaway } 215ae1f160dSDag-Erling Smørgrav xfree(patterns); 216b66f2d16SKris Kennaway /* Host name matches. */ 217b66f2d16SKris Kennaway goto next_option; 218b66f2d16SKris Kennaway } 2191e8db6e2SBrian Feldman cp = "permitopen=\""; 2201e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 221ae1f160dSDag-Erling Smørgrav char host[256], sport[6]; 2221e8db6e2SBrian Feldman u_short port; 2231e8db6e2SBrian Feldman char *patterns = xmalloc(strlen(opts) + 1); 2241e8db6e2SBrian Feldman 2251e8db6e2SBrian Feldman opts += strlen(cp); 2261e8db6e2SBrian Feldman i = 0; 2271e8db6e2SBrian Feldman while (*opts) { 2281e8db6e2SBrian Feldman if (*opts == '"') 2291e8db6e2SBrian Feldman break; 2301e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 2311e8db6e2SBrian Feldman opts += 2; 2321e8db6e2SBrian Feldman patterns[i++] = '"'; 2331e8db6e2SBrian Feldman continue; 2341e8db6e2SBrian Feldman } 2351e8db6e2SBrian Feldman patterns[i++] = *opts++; 2361e8db6e2SBrian Feldman } 2371e8db6e2SBrian Feldman if (!*opts) { 2381e8db6e2SBrian Feldman debug("%.100s, line %lu: missing end quote", 2391e8db6e2SBrian Feldman file, linenum); 240545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing end quote", 2411e8db6e2SBrian Feldman file, linenum); 2421e8db6e2SBrian Feldman xfree(patterns); 2431e8db6e2SBrian Feldman goto bad_option; 2441e8db6e2SBrian Feldman } 2451e8db6e2SBrian Feldman patterns[i] = 0; 2461e8db6e2SBrian Feldman opts++; 247ae1f160dSDag-Erling Smørgrav if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 && 248ae1f160dSDag-Erling Smørgrav sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) { 249ae1f160dSDag-Erling Smørgrav debug("%.100s, line %lu: Bad permitopen specification " 250ae1f160dSDag-Erling Smørgrav "<%.100s>", file, linenum, patterns); 251545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: " 252ae1f160dSDag-Erling Smørgrav "Bad permitopen specification", file, linenum); 2531e8db6e2SBrian Feldman xfree(patterns); 2541e8db6e2SBrian Feldman goto bad_option; 2551e8db6e2SBrian Feldman } 256ae1f160dSDag-Erling Smørgrav if ((port = a2port(sport)) == 0) { 257ae1f160dSDag-Erling Smørgrav debug("%.100s, line %lu: Bad permitopen port <%.100s>", 258ae1f160dSDag-Erling Smørgrav file, linenum, sport); 259545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: " 260ae1f160dSDag-Erling Smørgrav "Bad permitopen port", file, linenum); 2611e8db6e2SBrian Feldman xfree(patterns); 2621e8db6e2SBrian Feldman goto bad_option; 2631e8db6e2SBrian Feldman } 2641e8db6e2SBrian Feldman if (options.allow_tcp_forwarding) 265ae1f160dSDag-Erling Smørgrav channel_add_permitted_opens(host, port); 2661e8db6e2SBrian Feldman xfree(patterns); 2671e8db6e2SBrian Feldman goto next_option; 2681e8db6e2SBrian Feldman } 269b66f2d16SKris Kennaway next_option: 270b66f2d16SKris Kennaway /* 271b66f2d16SKris Kennaway * Skip the comma, and move to the next option 272b66f2d16SKris Kennaway * (or break out if there are no more). 273b66f2d16SKris Kennaway */ 2741e8db6e2SBrian Feldman if (!*opts) 275b66f2d16SKris Kennaway fatal("Bugs in auth-options.c option processing."); 2761e8db6e2SBrian Feldman if (*opts == ' ' || *opts == '\t') 277b66f2d16SKris Kennaway break; /* End of options. */ 2781e8db6e2SBrian Feldman if (*opts != ',') 279b66f2d16SKris Kennaway goto bad_option; 2801e8db6e2SBrian Feldman opts++; 281b66f2d16SKris Kennaway /* Process the next option. */ 282b66f2d16SKris Kennaway } 283545d5ecaSDag-Erling Smørgrav 284545d5ecaSDag-Erling Smørgrav if (!use_privsep) 285545d5ecaSDag-Erling Smørgrav auth_debug_send(); 286545d5ecaSDag-Erling Smørgrav 287b66f2d16SKris Kennaway /* grant access */ 288b66f2d16SKris Kennaway return 1; 289b66f2d16SKris Kennaway 290b66f2d16SKris Kennaway bad_option: 291b66f2d16SKris Kennaway log("Bad options in %.100s file, line %lu: %.50s", 2921e8db6e2SBrian Feldman file, linenum, opts); 293545d5ecaSDag-Erling Smørgrav auth_debug_add("Bad options in %.100s file, line %lu: %.50s", 2941e8db6e2SBrian Feldman file, linenum, opts); 295545d5ecaSDag-Erling Smørgrav 296545d5ecaSDag-Erling Smørgrav if (!use_privsep) 297545d5ecaSDag-Erling Smørgrav auth_debug_send(); 298545d5ecaSDag-Erling Smørgrav 299b66f2d16SKris Kennaway /* deny access */ 300b66f2d16SKris Kennaway return 0; 301b66f2d16SKris Kennaway } 302