1*e4a9863fSDag-Erling Smørgrav /* $OpenBSD: auth-options.c,v 1.59 2013/07/12 00:19:58 djm Exp $ */ 2b66f2d16SKris Kennaway /* 3b66f2d16SKris Kennaway * Author: Tatu Ylonen <ylo@cs.hut.fi> 4b66f2d16SKris Kennaway * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5b66f2d16SKris Kennaway * All rights reserved 6b66f2d16SKris Kennaway * As far as I am concerned, the code I have written for this software 7b66f2d16SKris Kennaway * can be used freely for any purpose. Any derived versions of this 8b66f2d16SKris Kennaway * software must be clearly marked as such, and if the derived work is 9b66f2d16SKris Kennaway * incompatible with the protocol description in the RFC file, it must be 10b66f2d16SKris Kennaway * called by a name other than "ssh" or "Secure Shell". 11b66f2d16SKris Kennaway */ 12b66f2d16SKris Kennaway 13b66f2d16SKris Kennaway #include "includes.h" 14761efaa7SDag-Erling Smørgrav 15761efaa7SDag-Erling Smørgrav #include <sys/types.h> 16761efaa7SDag-Erling Smørgrav 17761efaa7SDag-Erling Smørgrav #include <netdb.h> 18761efaa7SDag-Erling Smørgrav #include <pwd.h> 19761efaa7SDag-Erling Smørgrav #include <string.h> 20761efaa7SDag-Erling Smørgrav #include <stdio.h> 21761efaa7SDag-Erling Smørgrav #include <stdarg.h> 22b66f2d16SKris Kennaway 23d4af9e69SDag-Erling Smørgrav #include "openbsd-compat/sys-queue.h" 24b66f2d16SKris Kennaway #include "xmalloc.h" 25b66f2d16SKris Kennaway #include "match.h" 261e8db6e2SBrian Feldman #include "log.h" 271e8db6e2SBrian Feldman #include "canohost.h" 28761efaa7SDag-Erling Smørgrav #include "buffer.h" 291e8db6e2SBrian Feldman #include "channels.h" 301e8db6e2SBrian Feldman #include "servconf.h" 31ae1f160dSDag-Erling Smørgrav #include "misc.h" 32761efaa7SDag-Erling Smørgrav #include "key.h" 33e2f6069cSDag-Erling Smørgrav #include "auth-options.h" 34761efaa7SDag-Erling Smørgrav #include "hostfile.h" 35545d5ecaSDag-Erling Smørgrav #include "auth.h" 36761efaa7SDag-Erling Smørgrav #ifdef GSSAPI 37761efaa7SDag-Erling Smørgrav #include "ssh-gss.h" 38761efaa7SDag-Erling Smørgrav #endif 39761efaa7SDag-Erling Smørgrav #include "monitor_wrap.h" 40b66f2d16SKris Kennaway 41b66f2d16SKris Kennaway /* Flags set authorized_keys flags */ 42b66f2d16SKris Kennaway int no_port_forwarding_flag = 0; 43b66f2d16SKris Kennaway int no_agent_forwarding_flag = 0; 44b66f2d16SKris Kennaway int no_x11_forwarding_flag = 0; 45b66f2d16SKris Kennaway int no_pty_flag = 0; 46d4af9e69SDag-Erling Smørgrav int no_user_rc = 0; 47b15c8340SDag-Erling Smørgrav int key_is_cert_authority = 0; 48b66f2d16SKris Kennaway 49b66f2d16SKris Kennaway /* "command=" option. */ 50b66f2d16SKris Kennaway char *forced_command = NULL; 51b66f2d16SKris Kennaway 52b66f2d16SKris Kennaway /* "environment=" options. */ 53b66f2d16SKris Kennaway struct envstring *custom_environment = NULL; 54b66f2d16SKris Kennaway 55021d409fSDag-Erling Smørgrav /* "tunnel=" option. */ 56021d409fSDag-Erling Smørgrav int forced_tun_device = -1; 57021d409fSDag-Erling Smørgrav 58e2f6069cSDag-Erling Smørgrav /* "principals=" option. */ 59e2f6069cSDag-Erling Smørgrav char *authorized_principals = NULL; 60e2f6069cSDag-Erling Smørgrav 611e8db6e2SBrian Feldman extern ServerOptions options; 621e8db6e2SBrian Feldman 635b9b2fafSBrian Feldman void 645b9b2fafSBrian Feldman auth_clear_options(void) 655b9b2fafSBrian Feldman { 665b9b2fafSBrian Feldman no_agent_forwarding_flag = 0; 675b9b2fafSBrian Feldman no_port_forwarding_flag = 0; 685b9b2fafSBrian Feldman no_pty_flag = 0; 695b9b2fafSBrian Feldman no_x11_forwarding_flag = 0; 70d4af9e69SDag-Erling Smørgrav no_user_rc = 0; 71b15c8340SDag-Erling Smørgrav key_is_cert_authority = 0; 725b9b2fafSBrian Feldman while (custom_environment) { 735b9b2fafSBrian Feldman struct envstring *ce = custom_environment; 745b9b2fafSBrian Feldman custom_environment = ce->next; 75*e4a9863fSDag-Erling Smørgrav free(ce->s); 76*e4a9863fSDag-Erling Smørgrav free(ce); 775b9b2fafSBrian Feldman } 785b9b2fafSBrian Feldman if (forced_command) { 79*e4a9863fSDag-Erling Smørgrav free(forced_command); 805b9b2fafSBrian Feldman forced_command = NULL; 815b9b2fafSBrian Feldman } 82e2f6069cSDag-Erling Smørgrav if (authorized_principals) { 83*e4a9863fSDag-Erling Smørgrav free(authorized_principals); 84e2f6069cSDag-Erling Smørgrav authorized_principals = NULL; 85e2f6069cSDag-Erling Smørgrav } 86021d409fSDag-Erling Smørgrav forced_tun_device = -1; 871e8db6e2SBrian Feldman channel_clear_permitted_opens(); 885b9b2fafSBrian Feldman } 895b9b2fafSBrian Feldman 901e8db6e2SBrian Feldman /* 911e8db6e2SBrian Feldman * return 1 if access is granted, 0 if not. 921e8db6e2SBrian Feldman * side effect: sets key option flags 931e8db6e2SBrian Feldman */ 94b66f2d16SKris Kennaway int 951e8db6e2SBrian Feldman auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) 96b66f2d16SKris Kennaway { 97b66f2d16SKris Kennaway const char *cp; 981e8db6e2SBrian Feldman int i; 995b9b2fafSBrian Feldman 1005b9b2fafSBrian Feldman /* reset options */ 1015b9b2fafSBrian Feldman auth_clear_options(); 1025b9b2fafSBrian Feldman 1031e8db6e2SBrian Feldman if (!opts) 1041e8db6e2SBrian Feldman return 1; 1051e8db6e2SBrian Feldman 1061e8db6e2SBrian Feldman while (*opts && *opts != ' ' && *opts != '\t') { 107b15c8340SDag-Erling Smørgrav cp = "cert-authority"; 108b15c8340SDag-Erling Smørgrav if (strncasecmp(opts, cp, strlen(cp)) == 0) { 109b15c8340SDag-Erling Smørgrav key_is_cert_authority = 1; 110b15c8340SDag-Erling Smørgrav opts += strlen(cp); 111b15c8340SDag-Erling Smørgrav goto next_option; 112b15c8340SDag-Erling Smørgrav } 113b66f2d16SKris Kennaway cp = "no-port-forwarding"; 1141e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 115545d5ecaSDag-Erling Smørgrav auth_debug_add("Port forwarding disabled."); 116b66f2d16SKris Kennaway no_port_forwarding_flag = 1; 1171e8db6e2SBrian Feldman opts += strlen(cp); 118b66f2d16SKris Kennaway goto next_option; 119b66f2d16SKris Kennaway } 120b66f2d16SKris Kennaway cp = "no-agent-forwarding"; 1211e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 122545d5ecaSDag-Erling Smørgrav auth_debug_add("Agent forwarding disabled."); 123b66f2d16SKris Kennaway no_agent_forwarding_flag = 1; 1241e8db6e2SBrian Feldman opts += strlen(cp); 125b66f2d16SKris Kennaway goto next_option; 126b66f2d16SKris Kennaway } 127b66f2d16SKris Kennaway cp = "no-X11-forwarding"; 1281e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 129545d5ecaSDag-Erling Smørgrav auth_debug_add("X11 forwarding disabled."); 130b66f2d16SKris Kennaway no_x11_forwarding_flag = 1; 1311e8db6e2SBrian Feldman opts += strlen(cp); 132b66f2d16SKris Kennaway goto next_option; 133b66f2d16SKris Kennaway } 134b66f2d16SKris Kennaway cp = "no-pty"; 1351e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 136545d5ecaSDag-Erling Smørgrav auth_debug_add("Pty allocation disabled."); 137b66f2d16SKris Kennaway no_pty_flag = 1; 1381e8db6e2SBrian Feldman opts += strlen(cp); 139b66f2d16SKris Kennaway goto next_option; 140b66f2d16SKris Kennaway } 141d4af9e69SDag-Erling Smørgrav cp = "no-user-rc"; 142d4af9e69SDag-Erling Smørgrav if (strncasecmp(opts, cp, strlen(cp)) == 0) { 143d4af9e69SDag-Erling Smørgrav auth_debug_add("User rc file execution disabled."); 144d4af9e69SDag-Erling Smørgrav no_user_rc = 1; 145d4af9e69SDag-Erling Smørgrav opts += strlen(cp); 146d4af9e69SDag-Erling Smørgrav goto next_option; 147d4af9e69SDag-Erling Smørgrav } 148b66f2d16SKris Kennaway cp = "command=\""; 1491e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 1501e8db6e2SBrian Feldman opts += strlen(cp); 151e2f6069cSDag-Erling Smørgrav if (forced_command != NULL) 152*e4a9863fSDag-Erling Smørgrav free(forced_command); 1531e8db6e2SBrian Feldman forced_command = xmalloc(strlen(opts) + 1); 154b66f2d16SKris Kennaway i = 0; 1551e8db6e2SBrian Feldman while (*opts) { 1561e8db6e2SBrian Feldman if (*opts == '"') 157b66f2d16SKris Kennaway break; 1581e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 1591e8db6e2SBrian Feldman opts += 2; 160b66f2d16SKris Kennaway forced_command[i++] = '"'; 161b66f2d16SKris Kennaway continue; 162b66f2d16SKris Kennaway } 1631e8db6e2SBrian Feldman forced_command[i++] = *opts++; 164b66f2d16SKris Kennaway } 1651e8db6e2SBrian Feldman if (!*opts) { 166b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 1671e8db6e2SBrian Feldman file, linenum); 168545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing end quote", 1691e8db6e2SBrian Feldman file, linenum); 170*e4a9863fSDag-Erling Smørgrav free(forced_command); 1711e8db6e2SBrian Feldman forced_command = NULL; 1721e8db6e2SBrian Feldman goto bad_option; 173b66f2d16SKris Kennaway } 174761efaa7SDag-Erling Smørgrav forced_command[i] = '\0'; 1754a421b63SDag-Erling Smørgrav auth_debug_add("Forced command."); 1761e8db6e2SBrian Feldman opts++; 177b66f2d16SKris Kennaway goto next_option; 178b66f2d16SKris Kennaway } 179e2f6069cSDag-Erling Smørgrav cp = "principals=\""; 180e2f6069cSDag-Erling Smørgrav if (strncasecmp(opts, cp, strlen(cp)) == 0) { 181e2f6069cSDag-Erling Smørgrav opts += strlen(cp); 182e2f6069cSDag-Erling Smørgrav if (authorized_principals != NULL) 183*e4a9863fSDag-Erling Smørgrav free(authorized_principals); 184e2f6069cSDag-Erling Smørgrav authorized_principals = xmalloc(strlen(opts) + 1); 185e2f6069cSDag-Erling Smørgrav i = 0; 186e2f6069cSDag-Erling Smørgrav while (*opts) { 187e2f6069cSDag-Erling Smørgrav if (*opts == '"') 188e2f6069cSDag-Erling Smørgrav break; 189e2f6069cSDag-Erling Smørgrav if (*opts == '\\' && opts[1] == '"') { 190e2f6069cSDag-Erling Smørgrav opts += 2; 191e2f6069cSDag-Erling Smørgrav authorized_principals[i++] = '"'; 192e2f6069cSDag-Erling Smørgrav continue; 193e2f6069cSDag-Erling Smørgrav } 194e2f6069cSDag-Erling Smørgrav authorized_principals[i++] = *opts++; 195e2f6069cSDag-Erling Smørgrav } 196e2f6069cSDag-Erling Smørgrav if (!*opts) { 197e2f6069cSDag-Erling Smørgrav debug("%.100s, line %lu: missing end quote", 198e2f6069cSDag-Erling Smørgrav file, linenum); 199e2f6069cSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing end quote", 200e2f6069cSDag-Erling Smørgrav file, linenum); 201*e4a9863fSDag-Erling Smørgrav free(authorized_principals); 202e2f6069cSDag-Erling Smørgrav authorized_principals = NULL; 203e2f6069cSDag-Erling Smørgrav goto bad_option; 204e2f6069cSDag-Erling Smørgrav } 205e2f6069cSDag-Erling Smørgrav authorized_principals[i] = '\0'; 206e2f6069cSDag-Erling Smørgrav auth_debug_add("principals: %.900s", 207e2f6069cSDag-Erling Smørgrav authorized_principals); 208e2f6069cSDag-Erling Smørgrav opts++; 209e2f6069cSDag-Erling Smørgrav goto next_option; 210e2f6069cSDag-Erling Smørgrav } 211b66f2d16SKris Kennaway cp = "environment=\""; 2124b17dab0SDag-Erling Smørgrav if (options.permit_user_env && 2134b17dab0SDag-Erling Smørgrav strncasecmp(opts, cp, strlen(cp)) == 0) { 214b66f2d16SKris Kennaway char *s; 215b66f2d16SKris Kennaway struct envstring *new_envstring; 2161e8db6e2SBrian Feldman 2171e8db6e2SBrian Feldman opts += strlen(cp); 2181e8db6e2SBrian Feldman s = xmalloc(strlen(opts) + 1); 219b66f2d16SKris Kennaway i = 0; 2201e8db6e2SBrian Feldman while (*opts) { 2211e8db6e2SBrian Feldman if (*opts == '"') 222b66f2d16SKris Kennaway break; 2231e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 2241e8db6e2SBrian Feldman opts += 2; 225b66f2d16SKris Kennaway s[i++] = '"'; 226b66f2d16SKris Kennaway continue; 227b66f2d16SKris Kennaway } 2281e8db6e2SBrian Feldman s[i++] = *opts++; 229b66f2d16SKris Kennaway } 2301e8db6e2SBrian Feldman if (!*opts) { 231b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 2321e8db6e2SBrian Feldman file, linenum); 233545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing end quote", 2341e8db6e2SBrian Feldman file, linenum); 235*e4a9863fSDag-Erling Smørgrav free(s); 2361e8db6e2SBrian Feldman goto bad_option; 237b66f2d16SKris Kennaway } 238761efaa7SDag-Erling Smørgrav s[i] = '\0'; 239545d5ecaSDag-Erling Smørgrav auth_debug_add("Adding to environment: %.900s", s); 240b66f2d16SKris Kennaway debug("Adding to environment: %.900s", s); 2411e8db6e2SBrian Feldman opts++; 242b66f2d16SKris Kennaway new_envstring = xmalloc(sizeof(struct envstring)); 243b66f2d16SKris Kennaway new_envstring->s = s; 244b66f2d16SKris Kennaway new_envstring->next = custom_environment; 245b66f2d16SKris Kennaway custom_environment = new_envstring; 246b66f2d16SKris Kennaway goto next_option; 247b66f2d16SKris Kennaway } 248b66f2d16SKris Kennaway cp = "from=\""; 2491e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 2501e8db6e2SBrian Feldman const char *remote_ip = get_remote_ipaddr(); 2511e8db6e2SBrian Feldman const char *remote_host = get_canonical_hostname( 252d95e11bfSDag-Erling Smørgrav options.use_dns); 2531e8db6e2SBrian Feldman char *patterns = xmalloc(strlen(opts) + 1); 2541e8db6e2SBrian Feldman 2551e8db6e2SBrian Feldman opts += strlen(cp); 256b66f2d16SKris Kennaway i = 0; 2571e8db6e2SBrian Feldman while (*opts) { 2581e8db6e2SBrian Feldman if (*opts == '"') 259b66f2d16SKris Kennaway break; 2601e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 2611e8db6e2SBrian Feldman opts += 2; 262b66f2d16SKris Kennaway patterns[i++] = '"'; 263b66f2d16SKris Kennaway continue; 264b66f2d16SKris Kennaway } 2651e8db6e2SBrian Feldman patterns[i++] = *opts++; 266b66f2d16SKris Kennaway } 2671e8db6e2SBrian Feldman if (!*opts) { 268b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 2691e8db6e2SBrian Feldman file, linenum); 270545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing end quote", 2711e8db6e2SBrian Feldman file, linenum); 272*e4a9863fSDag-Erling Smørgrav free(patterns); 2731e8db6e2SBrian Feldman goto bad_option; 274b66f2d16SKris Kennaway } 275761efaa7SDag-Erling Smørgrav patterns[i] = '\0'; 2761e8db6e2SBrian Feldman opts++; 277d4af9e69SDag-Erling Smørgrav switch (match_host_and_ip(remote_host, remote_ip, 278d4af9e69SDag-Erling Smørgrav patterns)) { 279d4af9e69SDag-Erling Smørgrav case 1: 280*e4a9863fSDag-Erling Smørgrav free(patterns); 281d4af9e69SDag-Erling Smørgrav /* Host name matches. */ 282d4af9e69SDag-Erling Smørgrav goto next_option; 283d4af9e69SDag-Erling Smørgrav case -1: 284d4af9e69SDag-Erling Smørgrav debug("%.100s, line %lu: invalid criteria", 285d4af9e69SDag-Erling Smørgrav file, linenum); 286d4af9e69SDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: " 287d4af9e69SDag-Erling Smørgrav "invalid criteria", file, linenum); 288d4af9e69SDag-Erling Smørgrav /* FALLTHROUGH */ 289d4af9e69SDag-Erling Smørgrav case 0: 290*e4a9863fSDag-Erling Smørgrav free(patterns); 291d95e11bfSDag-Erling Smørgrav logit("Authentication tried for %.100s with " 2921e8db6e2SBrian Feldman "correct key but not from a permitted " 2931e8db6e2SBrian Feldman "host (host=%.200s, ip=%.200s).", 2941e8db6e2SBrian Feldman pw->pw_name, remote_host, remote_ip); 295545d5ecaSDag-Erling Smørgrav auth_debug_add("Your host '%.200s' is not " 2961e8db6e2SBrian Feldman "permitted to use this key for login.", 2971e8db6e2SBrian Feldman remote_host); 298d4af9e69SDag-Erling Smørgrav break; 299d4af9e69SDag-Erling Smørgrav } 300b66f2d16SKris Kennaway /* deny access */ 301b66f2d16SKris Kennaway return 0; 302b66f2d16SKris Kennaway } 3031e8db6e2SBrian Feldman cp = "permitopen=\""; 3041e8db6e2SBrian Feldman if (strncasecmp(opts, cp, strlen(cp)) == 0) { 3055e8dbd04SDag-Erling Smørgrav char *host, *p; 306cce7d346SDag-Erling Smørgrav int port; 3071e8db6e2SBrian Feldman char *patterns = xmalloc(strlen(opts) + 1); 3081e8db6e2SBrian Feldman 3091e8db6e2SBrian Feldman opts += strlen(cp); 3101e8db6e2SBrian Feldman i = 0; 3111e8db6e2SBrian Feldman while (*opts) { 3121e8db6e2SBrian Feldman if (*opts == '"') 3131e8db6e2SBrian Feldman break; 3141e8db6e2SBrian Feldman if (*opts == '\\' && opts[1] == '"') { 3151e8db6e2SBrian Feldman opts += 2; 3161e8db6e2SBrian Feldman patterns[i++] = '"'; 3171e8db6e2SBrian Feldman continue; 3181e8db6e2SBrian Feldman } 3191e8db6e2SBrian Feldman patterns[i++] = *opts++; 3201e8db6e2SBrian Feldman } 3211e8db6e2SBrian Feldman if (!*opts) { 3221e8db6e2SBrian Feldman debug("%.100s, line %lu: missing end quote", 3231e8db6e2SBrian Feldman file, linenum); 3245e8dbd04SDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing " 3255e8dbd04SDag-Erling Smørgrav "end quote", file, linenum); 326*e4a9863fSDag-Erling Smørgrav free(patterns); 3271e8db6e2SBrian Feldman goto bad_option; 3281e8db6e2SBrian Feldman } 329761efaa7SDag-Erling Smørgrav patterns[i] = '\0'; 3301e8db6e2SBrian Feldman opts++; 3315e8dbd04SDag-Erling Smørgrav p = patterns; 3325e8dbd04SDag-Erling Smørgrav host = hpdelim(&p); 3335e8dbd04SDag-Erling Smørgrav if (host == NULL || strlen(host) >= NI_MAXHOST) { 3345e8dbd04SDag-Erling Smørgrav debug("%.100s, line %lu: Bad permitopen " 3355e8dbd04SDag-Erling Smørgrav "specification <%.100s>", file, linenum, 3365e8dbd04SDag-Erling Smørgrav patterns); 337545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: " 3385e8dbd04SDag-Erling Smørgrav "Bad permitopen specification", file, 3395e8dbd04SDag-Erling Smørgrav linenum); 340*e4a9863fSDag-Erling Smørgrav free(patterns); 3411e8db6e2SBrian Feldman goto bad_option; 3421e8db6e2SBrian Feldman } 3435e8dbd04SDag-Erling Smørgrav host = cleanhostname(host); 344462c32cbSDag-Erling Smørgrav if (p == NULL || (port = permitopen_port(p)) < 0) { 3455e8dbd04SDag-Erling Smørgrav debug("%.100s, line %lu: Bad permitopen port " 3465e8dbd04SDag-Erling Smørgrav "<%.100s>", file, linenum, p ? p : ""); 347545d5ecaSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: " 348ae1f160dSDag-Erling Smørgrav "Bad permitopen port", file, linenum); 349*e4a9863fSDag-Erling Smørgrav free(patterns); 3501e8db6e2SBrian Feldman goto bad_option; 3511e8db6e2SBrian Feldman } 3526888a9beSDag-Erling Smørgrav if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) 353ae1f160dSDag-Erling Smørgrav channel_add_permitted_opens(host, port); 354*e4a9863fSDag-Erling Smørgrav free(patterns); 3551e8db6e2SBrian Feldman goto next_option; 3561e8db6e2SBrian Feldman } 357021d409fSDag-Erling Smørgrav cp = "tunnel=\""; 358021d409fSDag-Erling Smørgrav if (strncasecmp(opts, cp, strlen(cp)) == 0) { 359021d409fSDag-Erling Smørgrav char *tun = NULL; 360021d409fSDag-Erling Smørgrav opts += strlen(cp); 361021d409fSDag-Erling Smørgrav tun = xmalloc(strlen(opts) + 1); 362021d409fSDag-Erling Smørgrav i = 0; 363021d409fSDag-Erling Smørgrav while (*opts) { 364021d409fSDag-Erling Smørgrav if (*opts == '"') 365021d409fSDag-Erling Smørgrav break; 366021d409fSDag-Erling Smørgrav tun[i++] = *opts++; 367021d409fSDag-Erling Smørgrav } 368021d409fSDag-Erling Smørgrav if (!*opts) { 369021d409fSDag-Erling Smørgrav debug("%.100s, line %lu: missing end quote", 370021d409fSDag-Erling Smørgrav file, linenum); 371021d409fSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: missing end quote", 372021d409fSDag-Erling Smørgrav file, linenum); 373*e4a9863fSDag-Erling Smørgrav free(tun); 374021d409fSDag-Erling Smørgrav forced_tun_device = -1; 375021d409fSDag-Erling Smørgrav goto bad_option; 376021d409fSDag-Erling Smørgrav } 377761efaa7SDag-Erling Smørgrav tun[i] = '\0'; 378021d409fSDag-Erling Smørgrav forced_tun_device = a2tun(tun, NULL); 379*e4a9863fSDag-Erling Smørgrav free(tun); 380021d409fSDag-Erling Smørgrav if (forced_tun_device == SSH_TUNID_ERR) { 381021d409fSDag-Erling Smørgrav debug("%.100s, line %lu: invalid tun device", 382021d409fSDag-Erling Smørgrav file, linenum); 383021d409fSDag-Erling Smørgrav auth_debug_add("%.100s, line %lu: invalid tun device", 384021d409fSDag-Erling Smørgrav file, linenum); 385021d409fSDag-Erling Smørgrav forced_tun_device = -1; 386021d409fSDag-Erling Smørgrav goto bad_option; 387021d409fSDag-Erling Smørgrav } 388021d409fSDag-Erling Smørgrav auth_debug_add("Forced tun device: %d", forced_tun_device); 389021d409fSDag-Erling Smørgrav opts++; 390021d409fSDag-Erling Smørgrav goto next_option; 391021d409fSDag-Erling Smørgrav } 392b66f2d16SKris Kennaway next_option: 393b66f2d16SKris Kennaway /* 394b66f2d16SKris Kennaway * Skip the comma, and move to the next option 395b66f2d16SKris Kennaway * (or break out if there are no more). 396b66f2d16SKris Kennaway */ 3971e8db6e2SBrian Feldman if (!*opts) 398b66f2d16SKris Kennaway fatal("Bugs in auth-options.c option processing."); 3991e8db6e2SBrian Feldman if (*opts == ' ' || *opts == '\t') 400b66f2d16SKris Kennaway break; /* End of options. */ 4011e8db6e2SBrian Feldman if (*opts != ',') 402b66f2d16SKris Kennaway goto bad_option; 4031e8db6e2SBrian Feldman opts++; 404b66f2d16SKris Kennaway /* Process the next option. */ 405b66f2d16SKris Kennaway } 406545d5ecaSDag-Erling Smørgrav 407b66f2d16SKris Kennaway /* grant access */ 408b66f2d16SKris Kennaway return 1; 409b66f2d16SKris Kennaway 410b66f2d16SKris Kennaway bad_option: 411d95e11bfSDag-Erling Smørgrav logit("Bad options in %.100s file, line %lu: %.50s", 4121e8db6e2SBrian Feldman file, linenum, opts); 413545d5ecaSDag-Erling Smørgrav auth_debug_add("Bad options in %.100s file, line %lu: %.50s", 4141e8db6e2SBrian Feldman file, linenum, opts); 415545d5ecaSDag-Erling Smørgrav 416b66f2d16SKris Kennaway /* deny access */ 417b66f2d16SKris Kennaway return 0; 418b66f2d16SKris Kennaway } 419b15c8340SDag-Erling Smørgrav 420e2f6069cSDag-Erling Smørgrav #define OPTIONS_CRITICAL 1 421e2f6069cSDag-Erling Smørgrav #define OPTIONS_EXTENSIONS 2 422e2f6069cSDag-Erling Smørgrav static int 423e2f6069cSDag-Erling Smørgrav parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, 424e2f6069cSDag-Erling Smørgrav u_int which, int crit, 425e2f6069cSDag-Erling Smørgrav int *cert_no_port_forwarding_flag, 426e2f6069cSDag-Erling Smørgrav int *cert_no_agent_forwarding_flag, 427e2f6069cSDag-Erling Smørgrav int *cert_no_x11_forwarding_flag, 428e2f6069cSDag-Erling Smørgrav int *cert_no_pty_flag, 429e2f6069cSDag-Erling Smørgrav int *cert_no_user_rc, 430e2f6069cSDag-Erling Smørgrav char **cert_forced_command, 431e2f6069cSDag-Erling Smørgrav int *cert_source_address_done) 432b15c8340SDag-Erling Smørgrav { 433e2f6069cSDag-Erling Smørgrav char *command, *allowed; 434e2f6069cSDag-Erling Smørgrav const char *remote_ip; 435*e4a9863fSDag-Erling Smørgrav char *name = NULL; 436*e4a9863fSDag-Erling Smørgrav u_char *data_blob = NULL; 437b15c8340SDag-Erling Smørgrav u_int nlen, dlen, clen; 438b15c8340SDag-Erling Smørgrav Buffer c, data; 439e2f6069cSDag-Erling Smørgrav int ret = -1, found; 440b15c8340SDag-Erling Smørgrav 441b15c8340SDag-Erling Smørgrav buffer_init(&data); 442b15c8340SDag-Erling Smørgrav 443b15c8340SDag-Erling Smørgrav /* Make copy to avoid altering original */ 444b15c8340SDag-Erling Smørgrav buffer_init(&c); 445e2f6069cSDag-Erling Smørgrav buffer_append(&c, optblob, optblob_len); 446b15c8340SDag-Erling Smørgrav 447b15c8340SDag-Erling Smørgrav while (buffer_len(&c) > 0) { 4484a421b63SDag-Erling Smørgrav if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL || 449b15c8340SDag-Erling Smørgrav (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { 450e2f6069cSDag-Erling Smørgrav error("Certificate options corrupt"); 451b15c8340SDag-Erling Smørgrav goto out; 452b15c8340SDag-Erling Smørgrav } 453b15c8340SDag-Erling Smørgrav buffer_append(&data, data_blob, dlen); 454e2f6069cSDag-Erling Smørgrav debug3("found certificate option \"%.100s\" len %u", 455b15c8340SDag-Erling Smørgrav name, dlen); 456e2f6069cSDag-Erling Smørgrav found = 0; 457e2f6069cSDag-Erling Smørgrav if ((which & OPTIONS_EXTENSIONS) != 0) { 458e2f6069cSDag-Erling Smørgrav if (strcmp(name, "permit-X11-forwarding") == 0) { 459e2f6069cSDag-Erling Smørgrav *cert_no_x11_forwarding_flag = 0; 460e2f6069cSDag-Erling Smørgrav found = 1; 461e2f6069cSDag-Erling Smørgrav } else if (strcmp(name, 462e2f6069cSDag-Erling Smørgrav "permit-agent-forwarding") == 0) { 463e2f6069cSDag-Erling Smørgrav *cert_no_agent_forwarding_flag = 0; 464e2f6069cSDag-Erling Smørgrav found = 1; 465e2f6069cSDag-Erling Smørgrav } else if (strcmp(name, 466e2f6069cSDag-Erling Smørgrav "permit-port-forwarding") == 0) { 467e2f6069cSDag-Erling Smørgrav *cert_no_port_forwarding_flag = 0; 468e2f6069cSDag-Erling Smørgrav found = 1; 469e2f6069cSDag-Erling Smørgrav } else if (strcmp(name, "permit-pty") == 0) { 470e2f6069cSDag-Erling Smørgrav *cert_no_pty_flag = 0; 471e2f6069cSDag-Erling Smørgrav found = 1; 472e2f6069cSDag-Erling Smørgrav } else if (strcmp(name, "permit-user-rc") == 0) { 473e2f6069cSDag-Erling Smørgrav *cert_no_user_rc = 0; 474e2f6069cSDag-Erling Smørgrav found = 1; 475e2f6069cSDag-Erling Smørgrav } 476e2f6069cSDag-Erling Smørgrav } 477e2f6069cSDag-Erling Smørgrav if (!found && (which & OPTIONS_CRITICAL) != 0) { 478e2f6069cSDag-Erling Smørgrav if (strcmp(name, "force-command") == 0) { 4794a421b63SDag-Erling Smørgrav if ((command = buffer_get_cstring_ret(&data, 480e2f6069cSDag-Erling Smørgrav &clen)) == NULL) { 481e2f6069cSDag-Erling Smørgrav error("Certificate constraint \"%s\" " 482e2f6069cSDag-Erling Smørgrav "corrupt", name); 483b15c8340SDag-Erling Smørgrav goto out; 484b15c8340SDag-Erling Smørgrav } 485e2f6069cSDag-Erling Smørgrav if (*cert_forced_command != NULL) { 486b15c8340SDag-Erling Smørgrav error("Certificate has multiple " 487e2f6069cSDag-Erling Smørgrav "force-command options"); 488*e4a9863fSDag-Erling Smørgrav free(command); 489b15c8340SDag-Erling Smørgrav goto out; 490b15c8340SDag-Erling Smørgrav } 491e2f6069cSDag-Erling Smørgrav *cert_forced_command = command; 492e2f6069cSDag-Erling Smørgrav found = 1; 493e2f6069cSDag-Erling Smørgrav } 494e2f6069cSDag-Erling Smørgrav if (strcmp(name, "source-address") == 0) { 4954a421b63SDag-Erling Smørgrav if ((allowed = buffer_get_cstring_ret(&data, 496e2f6069cSDag-Erling Smørgrav &clen)) == NULL) { 497e2f6069cSDag-Erling Smørgrav error("Certificate constraint " 498e2f6069cSDag-Erling Smørgrav "\"%s\" corrupt", name); 499b15c8340SDag-Erling Smørgrav goto out; 500b15c8340SDag-Erling Smørgrav } 501e2f6069cSDag-Erling Smørgrav if ((*cert_source_address_done)++) { 502b15c8340SDag-Erling Smørgrav error("Certificate has multiple " 503e2f6069cSDag-Erling Smørgrav "source-address options"); 504*e4a9863fSDag-Erling Smørgrav free(allowed); 505b15c8340SDag-Erling Smørgrav goto out; 506b15c8340SDag-Erling Smørgrav } 507e2f6069cSDag-Erling Smørgrav remote_ip = get_remote_ipaddr(); 508e2f6069cSDag-Erling Smørgrav switch (addr_match_cidr_list(remote_ip, 509e2f6069cSDag-Erling Smørgrav allowed)) { 510b15c8340SDag-Erling Smørgrav case 1: 511b15c8340SDag-Erling Smørgrav /* accepted */ 512*e4a9863fSDag-Erling Smørgrav free(allowed); 513b15c8340SDag-Erling Smørgrav break; 514b15c8340SDag-Erling Smørgrav case 0: 515b15c8340SDag-Erling Smørgrav /* no match */ 516e2f6069cSDag-Erling Smørgrav logit("Authentication tried for %.100s " 517e2f6069cSDag-Erling Smørgrav "with valid certificate but not " 518e2f6069cSDag-Erling Smørgrav "from a permitted host " 519e2f6069cSDag-Erling Smørgrav "(ip=%.200s).", pw->pw_name, 520e2f6069cSDag-Erling Smørgrav remote_ip); 521e2f6069cSDag-Erling Smørgrav auth_debug_add("Your address '%.200s' " 522e2f6069cSDag-Erling Smørgrav "is not permitted to use this " 523e2f6069cSDag-Erling Smørgrav "certificate for login.", 524e2f6069cSDag-Erling Smørgrav remote_ip); 525*e4a9863fSDag-Erling Smørgrav free(allowed); 526b15c8340SDag-Erling Smørgrav goto out; 527b15c8340SDag-Erling Smørgrav case -1: 528e2f6069cSDag-Erling Smørgrav error("Certificate source-address " 529e2f6069cSDag-Erling Smørgrav "contents invalid"); 530*e4a9863fSDag-Erling Smørgrav free(allowed); 531b15c8340SDag-Erling Smørgrav goto out; 532b15c8340SDag-Erling Smørgrav } 533e2f6069cSDag-Erling Smørgrav found = 1; 534e2f6069cSDag-Erling Smørgrav } 535b15c8340SDag-Erling Smørgrav } 536b15c8340SDag-Erling Smørgrav 537e2f6069cSDag-Erling Smørgrav if (!found) { 538e2f6069cSDag-Erling Smørgrav if (crit) { 539e2f6069cSDag-Erling Smørgrav error("Certificate critical option \"%s\" " 540e2f6069cSDag-Erling Smørgrav "is not supported", name); 541e2f6069cSDag-Erling Smørgrav goto out; 542e2f6069cSDag-Erling Smørgrav } else { 543e2f6069cSDag-Erling Smørgrav logit("Certificate extension \"%s\" " 544e2f6069cSDag-Erling Smørgrav "is not supported", name); 545e2f6069cSDag-Erling Smørgrav } 546e2f6069cSDag-Erling Smørgrav } else if (buffer_len(&data) != 0) { 547e2f6069cSDag-Erling Smørgrav error("Certificate option \"%s\" corrupt " 548b15c8340SDag-Erling Smørgrav "(extra data)", name); 549b15c8340SDag-Erling Smørgrav goto out; 550b15c8340SDag-Erling Smørgrav } 551b15c8340SDag-Erling Smørgrav buffer_clear(&data); 552*e4a9863fSDag-Erling Smørgrav free(name); 553*e4a9863fSDag-Erling Smørgrav free(data_blob); 554*e4a9863fSDag-Erling Smørgrav name = NULL; 555*e4a9863fSDag-Erling Smørgrav data_blob = NULL; 556b15c8340SDag-Erling Smørgrav } 557e2f6069cSDag-Erling Smørgrav /* successfully parsed all options */ 558b15c8340SDag-Erling Smørgrav ret = 0; 559b15c8340SDag-Erling Smørgrav 560e2f6069cSDag-Erling Smørgrav out: 561e2f6069cSDag-Erling Smørgrav if (ret != 0 && 562e2f6069cSDag-Erling Smørgrav cert_forced_command != NULL && 563e2f6069cSDag-Erling Smørgrav *cert_forced_command != NULL) { 564*e4a9863fSDag-Erling Smørgrav free(*cert_forced_command); 565e2f6069cSDag-Erling Smørgrav *cert_forced_command = NULL; 566e2f6069cSDag-Erling Smørgrav } 567e2f6069cSDag-Erling Smørgrav if (name != NULL) 568*e4a9863fSDag-Erling Smørgrav free(name); 569e2f6069cSDag-Erling Smørgrav if (data_blob != NULL) 570*e4a9863fSDag-Erling Smørgrav free(data_blob); 571e2f6069cSDag-Erling Smørgrav buffer_free(&data); 572e2f6069cSDag-Erling Smørgrav buffer_free(&c); 573e2f6069cSDag-Erling Smørgrav return ret; 574e2f6069cSDag-Erling Smørgrav } 575e2f6069cSDag-Erling Smørgrav 576e2f6069cSDag-Erling Smørgrav /* 577e2f6069cSDag-Erling Smørgrav * Set options from critical certificate options. These supersede user key 578e2f6069cSDag-Erling Smørgrav * options so this must be called after auth_parse_options(). 579e2f6069cSDag-Erling Smørgrav */ 580e2f6069cSDag-Erling Smørgrav int 581e2f6069cSDag-Erling Smørgrav auth_cert_options(Key *k, struct passwd *pw) 582e2f6069cSDag-Erling Smørgrav { 583e2f6069cSDag-Erling Smørgrav int cert_no_port_forwarding_flag = 1; 584e2f6069cSDag-Erling Smørgrav int cert_no_agent_forwarding_flag = 1; 585e2f6069cSDag-Erling Smørgrav int cert_no_x11_forwarding_flag = 1; 586e2f6069cSDag-Erling Smørgrav int cert_no_pty_flag = 1; 587e2f6069cSDag-Erling Smørgrav int cert_no_user_rc = 1; 588e2f6069cSDag-Erling Smørgrav char *cert_forced_command = NULL; 589e2f6069cSDag-Erling Smørgrav int cert_source_address_done = 0; 590e2f6069cSDag-Erling Smørgrav 591e2f6069cSDag-Erling Smørgrav if (key_cert_is_legacy(k)) { 592e2f6069cSDag-Erling Smørgrav /* All options are in the one field for v00 certs */ 593e2f6069cSDag-Erling Smørgrav if (parse_option_list(buffer_ptr(&k->cert->critical), 594e2f6069cSDag-Erling Smørgrav buffer_len(&k->cert->critical), pw, 595e2f6069cSDag-Erling Smørgrav OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, 596e2f6069cSDag-Erling Smørgrav &cert_no_port_forwarding_flag, 597e2f6069cSDag-Erling Smørgrav &cert_no_agent_forwarding_flag, 598e2f6069cSDag-Erling Smørgrav &cert_no_x11_forwarding_flag, 599e2f6069cSDag-Erling Smørgrav &cert_no_pty_flag, 600e2f6069cSDag-Erling Smørgrav &cert_no_user_rc, 601e2f6069cSDag-Erling Smørgrav &cert_forced_command, 602e2f6069cSDag-Erling Smørgrav &cert_source_address_done) == -1) 603e2f6069cSDag-Erling Smørgrav return -1; 604e2f6069cSDag-Erling Smørgrav } else { 605e2f6069cSDag-Erling Smørgrav /* Separate options and extensions for v01 certs */ 606e2f6069cSDag-Erling Smørgrav if (parse_option_list(buffer_ptr(&k->cert->critical), 607e2f6069cSDag-Erling Smørgrav buffer_len(&k->cert->critical), pw, 608e2f6069cSDag-Erling Smørgrav OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, 609e2f6069cSDag-Erling Smørgrav &cert_forced_command, 610e2f6069cSDag-Erling Smørgrav &cert_source_address_done) == -1) 611e2f6069cSDag-Erling Smørgrav return -1; 612e2f6069cSDag-Erling Smørgrav if (parse_option_list(buffer_ptr(&k->cert->extensions), 613e2f6069cSDag-Erling Smørgrav buffer_len(&k->cert->extensions), pw, 614e2f6069cSDag-Erling Smørgrav OPTIONS_EXTENSIONS, 1, 615e2f6069cSDag-Erling Smørgrav &cert_no_port_forwarding_flag, 616e2f6069cSDag-Erling Smørgrav &cert_no_agent_forwarding_flag, 617e2f6069cSDag-Erling Smørgrav &cert_no_x11_forwarding_flag, 618e2f6069cSDag-Erling Smørgrav &cert_no_pty_flag, 619e2f6069cSDag-Erling Smørgrav &cert_no_user_rc, 620e2f6069cSDag-Erling Smørgrav NULL, NULL) == -1) 621e2f6069cSDag-Erling Smørgrav return -1; 622e2f6069cSDag-Erling Smørgrav } 623e2f6069cSDag-Erling Smørgrav 624b15c8340SDag-Erling Smørgrav no_port_forwarding_flag |= cert_no_port_forwarding_flag; 625b15c8340SDag-Erling Smørgrav no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; 626b15c8340SDag-Erling Smørgrav no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; 627b15c8340SDag-Erling Smørgrav no_pty_flag |= cert_no_pty_flag; 628b15c8340SDag-Erling Smørgrav no_user_rc |= cert_no_user_rc; 629b15c8340SDag-Erling Smørgrav /* CA-specified forced command supersedes key option */ 630b15c8340SDag-Erling Smørgrav if (cert_forced_command != NULL) { 631b15c8340SDag-Erling Smørgrav if (forced_command != NULL) 632*e4a9863fSDag-Erling Smørgrav free(forced_command); 633b15c8340SDag-Erling Smørgrav forced_command = cert_forced_command; 634b15c8340SDag-Erling Smørgrav } 635e2f6069cSDag-Erling Smørgrav return 0; 636b15c8340SDag-Erling Smørgrav } 637b15c8340SDag-Erling Smørgrav 638