1132718Skan/*- 2132718Skan * Based on code copyright (c) 1995,1997 by 3169689Skan * Berkeley Software Design, Inc. 4169689Skan * All rights reserved. 5132718Skan * 6132718Skan * Redistribution and use in source and binary forms, with or without 7132718Skan * modification, is permitted provided that the following conditions 8132718Skan * are met: 9132718Skan * 1. Redistributions of source code must retain the above copyright 10132718Skan * notice immediately at the beginning of the file, without modification, 11132718Skan * this list of conditions, and the following disclaimer. 12132718Skan * 2. Redistributions in binary form must reproduce the above copyright 13132718Skan * notice, this list of conditions and the following disclaimer in the 14132718Skan * documentation and/or other materials provided with the distribution. 15132718Skan * 3. This work was done expressly for inclusion into FreeBSD. Other use 16132718Skan * is permitted provided this notation is included. 17132718Skan * 4. Absolutely no warranty of function or purpose is made by the authors. 18132718Skan * 5. Modifications may be freely made to this file providing the above 19132718Skan * conditions are met. 20169689Skan */ 21132718Skan 22132718Skan#include <sys/cdefs.h> 23132718Skan__FBSDID("$FreeBSD: releng/10.3/lib/libutil/_secure_path.c 139012 2004-12-18 12:31:12Z ru $"); 24132718Skan 25169689Skan#include <sys/types.h> 26169689Skan#include <sys/stat.h> 27132718Skan 28132718Skan#include <errno.h> 29132718Skan#include <libutil.h> 30132718Skan#include <stddef.h> 31132718Skan#include <syslog.h> 32132718Skan 33132718Skan/* 34132718Skan * Check for common security problems on a given path 35132718Skan * It must be: 36132718Skan * 1. A regular file, and exists 37132718Skan * 2. Owned and writable only by root (or given owner) 38132718Skan * 3. Group ownership is given group or is non-group writable 39132718Skan * 40132718Skan * Returns: -2 if file does not exist, 41169689Skan * -1 if security test failure 42132718Skan * 0 otherwise 43132718Skan */ 44132718Skan 45132718Skanint 46132718Skan_secure_path(const char *path, uid_t uid, gid_t gid) 47132718Skan{ 48132718Skan int r = -1; 49169689Skan struct stat sb; 50169689Skan const char *msg = NULL; 51132718Skan 52169689Skan if (lstat(path, &sb) < 0) { 53132718Skan if (errno == ENOENT) /* special case */ 54132718Skan r = -2; /* if it is just missing, skip the log entry */ 55132718Skan else 56132718Skan msg = "%s: cannot stat %s: %m"; 57132718Skan } 58132718Skan else if (!S_ISREG(sb.st_mode)) 59132718Skan msg = "%s: %s is not a regular file"; 60132718Skan else if (sb.st_mode & S_IWOTH) 61132718Skan msg = "%s: %s is world writable"; 62132718Skan else if ((int)uid != -1 && sb.st_uid != uid && sb.st_uid != 0) { 63132718Skan if (uid == 0) 64132718Skan msg = "%s: %s is not owned by root"; 65132718Skan else 66132718Skan msg = "%s: %s is not owned by uid %d"; 67132718Skan } else if ((int)gid != -1 && sb.st_gid != gid && (sb.st_mode & S_IWGRP)) 68132718Skan msg = "%s: %s is group writeable by non-authorised groups"; 69132718Skan else 70132718Skan r = 0; 71132718Skan if (msg != NULL) 72132718Skan syslog(LOG_ERR, msg, "_secure_path", path, uid); 73132718Skan return r; 74132718Skan} 75260011Spfg