1 /* 2 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "includes.h" 26 RCSID("$OpenBSD: auth.c,v 1.35 2002/03/01 13:12:10 markus Exp $"); 27 RCSID("$FreeBSD$"); 28 29 #include <libgen.h> 30 31 #include "xmalloc.h" 32 #include "match.h" 33 #include "groupaccess.h" 34 #include "log.h" 35 #include "servconf.h" 36 #include "auth.h" 37 #include "auth-options.h" 38 #include "canohost.h" 39 #include "buffer.h" 40 #include "bufaux.h" 41 #include "uidswap.h" 42 #include "tildexpand.h" 43 44 /* import */ 45 extern ServerOptions options; 46 47 /* 48 * Check if the user is allowed to log in via ssh. If user is listed 49 * in DenyUsers or one of user's groups is listed in DenyGroups, false 50 * will be returned. If AllowUsers isn't empty and user isn't listed 51 * there, or if AllowGroups isn't empty and one of user's groups isn't 52 * listed there, false will be returned. 53 * If the user's shell is not executable, false will be returned. 54 * Otherwise true is returned. 55 */ 56 int 57 allowed_user(struct passwd * pw) 58 { 59 struct stat st; 60 const char *hostname = NULL, *ipaddr = NULL; 61 char *shell; 62 int i; 63 64 /* Shouldn't be called if pw is NULL, but better safe than sorry... */ 65 if (!pw || !pw->pw_name) 66 return 0; 67 68 /* 69 * Get the shell from the password data. An empty shell field is 70 * legal, and means /bin/sh. 71 */ 72 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; 73 74 /* deny if shell does not exists or is not executable */ 75 if (stat(shell, &st) != 0) { 76 log("User %.100s not allowed because shell %.100s does not exist", 77 pw->pw_name, shell); 78 return 0; 79 } 80 if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) { 81 log("User %.100s not allowed because shell %.100s is not executable", 82 pw->pw_name, shell); 83 return 0; 84 } 85 86 if (options.num_deny_users > 0 || options.num_allow_users > 0) { 87 hostname = get_canonical_hostname(options.verify_reverse_mapping); 88 ipaddr = get_remote_ipaddr(); 89 } 90 91 /* Return false if user is listed in DenyUsers */ 92 if (options.num_deny_users > 0) { 93 for (i = 0; i < options.num_deny_users; i++) 94 if (match_user(pw->pw_name, hostname, ipaddr, 95 options.deny_users[i])) { 96 log("User %.100s not allowed because listed in DenyUsers", 97 pw->pw_name); 98 return 0; 99 } 100 } 101 /* Return false if AllowUsers isn't empty and user isn't listed there */ 102 if (options.num_allow_users > 0) { 103 for (i = 0; i < options.num_allow_users; i++) 104 if (match_user(pw->pw_name, hostname, ipaddr, 105 options.allow_users[i])) 106 break; 107 /* i < options.num_allow_users iff we break for loop */ 108 if (i >= options.num_allow_users) { 109 log("User %.100s not allowed because not listed in AllowUsers", 110 pw->pw_name); 111 return 0; 112 } 113 } 114 if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { 115 /* Get the user's group access list (primary and supplementary) */ 116 if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 117 log("User %.100s not allowed because not in any group", 118 pw->pw_name); 119 return 0; 120 } 121 122 /* Return false if one of user's groups is listed in DenyGroups */ 123 if (options.num_deny_groups > 0) 124 if (ga_match(options.deny_groups, 125 options.num_deny_groups)) { 126 ga_free(); 127 log("User %.100s not allowed because a group is listed in DenyGroups", 128 pw->pw_name); 129 return 0; 130 } 131 /* 132 * Return false if AllowGroups isn't empty and one of user's groups 133 * isn't listed there 134 */ 135 if (options.num_allow_groups > 0) 136 if (!ga_match(options.allow_groups, 137 options.num_allow_groups)) { 138 ga_free(); 139 log("User %.100s not allowed because none of user's groups are listed in AllowGroups", 140 pw->pw_name); 141 return 0; 142 } 143 ga_free(); 144 } 145 /* We found no reason not to let this user try to log on... */ 146 return 1; 147 } 148 149 Authctxt * 150 authctxt_new(void) 151 { 152 Authctxt *authctxt = xmalloc(sizeof(*authctxt)); 153 memset(authctxt, 0, sizeof(*authctxt)); 154 return authctxt; 155 } 156 157 void 158 auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) 159 { 160 void (*authlog) (const char *fmt,...) = verbose; 161 char *authmsg; 162 163 /* Raise logging level */ 164 if (authenticated == 1 || 165 !authctxt->valid || 166 authctxt->failures >= AUTH_FAIL_LOG || 167 strcmp(method, "password") == 0) 168 authlog = log; 169 170 if (authctxt->postponed) 171 authmsg = "Postponed"; 172 else 173 authmsg = authenticated ? "Accepted" : "Failed"; 174 175 authlog("%s %s for %s%.100s from %.200s port %d%s", 176 authmsg, 177 method, 178 authctxt->valid ? "" : "illegal user ", 179 authctxt->user, 180 get_remote_ipaddr(), 181 get_remote_port(), 182 info); 183 } 184 185 /* 186 * Check whether root logins are disallowed. 187 */ 188 int 189 auth_root_allowed(char *method) 190 { 191 switch (options.permit_root_login) { 192 case PERMIT_YES: 193 return 1; 194 break; 195 case PERMIT_NO_PASSWD: 196 if (strcmp(method, "password") != 0) 197 return 1; 198 break; 199 case PERMIT_FORCED_ONLY: 200 if (forced_command) { 201 log("Root login accepted for forced command."); 202 return 1; 203 } 204 break; 205 } 206 log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr()); 207 return 0; 208 } 209 210 211 /* 212 * Given a template and a passwd structure, build a filename 213 * by substituting % tokenised options. Currently, %% becomes '%', 214 * %h becomes the home directory and %u the username. 215 * 216 * This returns a buffer allocated by xmalloc. 217 */ 218 char * 219 expand_filename(const char *filename, struct passwd *pw) 220 { 221 Buffer buffer; 222 char *file; 223 const char *cp; 224 225 /* 226 * Build the filename string in the buffer by making the appropriate 227 * substitutions to the given file name. 228 */ 229 buffer_init(&buffer); 230 for (cp = filename; *cp; cp++) { 231 if (cp[0] == '%' && cp[1] == '%') { 232 buffer_append(&buffer, "%", 1); 233 cp++; 234 continue; 235 } 236 if (cp[0] == '%' && cp[1] == 'h') { 237 buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir)); 238 cp++; 239 continue; 240 } 241 if (cp[0] == '%' && cp[1] == 'u') { 242 buffer_append(&buffer, pw->pw_name, 243 strlen(pw->pw_name)); 244 cp++; 245 continue; 246 } 247 buffer_append(&buffer, cp, 1); 248 } 249 buffer_append(&buffer, "\0", 1); 250 251 /* 252 * Ensure that filename starts anchored. If not, be backward 253 * compatible and prepend the '%h/' 254 */ 255 file = xmalloc(MAXPATHLEN); 256 cp = buffer_ptr(&buffer); 257 if (*cp != '/') 258 snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp); 259 else 260 strlcpy(file, cp, MAXPATHLEN); 261 262 buffer_free(&buffer); 263 return file; 264 } 265 266 char * 267 authorized_keys_file(struct passwd *pw) 268 { 269 return expand_filename(options.authorized_keys_file, pw); 270 } 271 272 char * 273 authorized_keys_file2(struct passwd *pw) 274 { 275 return expand_filename(options.authorized_keys_file2, pw); 276 } 277 278 /* return ok if key exists in sysfile or userfile */ 279 HostStatus 280 check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, 281 const char *sysfile, const char *userfile) 282 { 283 Key *found; 284 char *user_hostfile; 285 struct stat st; 286 HostStatus host_status; 287 288 /* Check if we know the host and its host key. */ 289 found = key_new(key->type); 290 host_status = check_host_in_hostfile(sysfile, host, key, found, NULL); 291 292 if (host_status != HOST_OK && userfile != NULL) { 293 user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); 294 if (options.strict_modes && 295 (stat(user_hostfile, &st) == 0) && 296 ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || 297 (st.st_mode & 022) != 0)) { 298 log("Authentication refused for %.100s: " 299 "bad owner or modes for %.200s", 300 pw->pw_name, user_hostfile); 301 } else { 302 temporarily_use_uid(pw); 303 host_status = check_host_in_hostfile(user_hostfile, 304 host, key, found, NULL); 305 restore_uid(); 306 } 307 xfree(user_hostfile); 308 } 309 key_free(found); 310 311 debug2("check_key_in_hostfiles: key %s for %s", host_status == HOST_OK ? 312 "ok" : "not found", host); 313 return host_status; 314 } 315 316 317 /* 318 * Check a given file for security. This is defined as all components 319 * of the path to the file must either be owned by either the owner of 320 * of the file or root and no directories must be group or world writable. 321 * 322 * XXX Should any specific check be done for sym links ? 323 * 324 * Takes an open file descriptor, the file name, a uid and and 325 * error buffer plus max size as arguments. 326 * 327 * Returns 0 on success and -1 on failure 328 */ 329 int 330 secure_filename(FILE *f, const char *file, struct passwd *pw, 331 char *err, size_t errlen) 332 { 333 uid_t uid = pw->pw_uid; 334 char buf[MAXPATHLEN], homedir[MAXPATHLEN]; 335 char *cp; 336 struct stat st; 337 338 if (realpath(file, buf) == NULL) { 339 snprintf(err, errlen, "realpath %s failed: %s", file, 340 strerror(errno)); 341 return -1; 342 } 343 if (realpath(pw->pw_dir, homedir) == NULL) { 344 snprintf(err, errlen, "realpath %s failed: %s", pw->pw_dir, 345 strerror(errno)); 346 return -1; 347 } 348 349 /* check the open file to avoid races */ 350 if (fstat(fileno(f), &st) < 0 || 351 (st.st_uid != 0 && st.st_uid != uid) || 352 (st.st_mode & 022) != 0) { 353 snprintf(err, errlen, "bad ownership or modes for file %s", 354 buf); 355 return -1; 356 } 357 358 /* for each component of the canonical path, walking upwards */ 359 for (;;) { 360 if ((cp = dirname(buf)) == NULL) { 361 snprintf(err, errlen, "dirname() failed"); 362 return -1; 363 } 364 strlcpy(buf, cp, sizeof(buf)); 365 366 debug3("secure_filename: checking '%s'", buf); 367 if (stat(buf, &st) < 0 || 368 (st.st_uid != 0 && st.st_uid != uid) || 369 (st.st_mode & 022) != 0) { 370 snprintf(err, errlen, 371 "bad ownership or modes for directory %s", buf); 372 return -1; 373 } 374 375 /* If are passed the homedir then we can stop */ 376 if (strcmp(homedir, buf) == 0) { 377 debug3("secure_filename: terminating check at '%s'", 378 buf); 379 break; 380 } 381 /* 382 * dirname should always complete with a "/" path, 383 * but we can be paranoid and check for "." too 384 */ 385 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) 386 break; 387 } 388 return 0; 389 } 390