125670Sdavidn/*-
225670Sdavidn * Based on code copyright (c) 1995,1997 by
325670Sdavidn * Berkeley Software Design, Inc.
425670Sdavidn * All rights reserved.
525670Sdavidn *
625670Sdavidn * Redistribution and use in source and binary forms, with or without
725670Sdavidn * modification, is permitted provided that the following conditions
825670Sdavidn * are met:
925670Sdavidn * 1. Redistributions of source code must retain the above copyright
1025670Sdavidn *    notice immediately at the beginning of the file, without modification,
1125670Sdavidn *    this list of conditions, and the following disclaimer.
1225670Sdavidn * 2. Redistributions in binary form must reproduce the above copyright
1325670Sdavidn *    notice, this list of conditions and the following disclaimer in the
1425670Sdavidn *    documentation and/or other materials provided with the distribution.
1525670Sdavidn * 3. This work was done expressly for inclusion into FreeBSD.  Other use
1625670Sdavidn *    is permitted provided this notation is included.
1725670Sdavidn * 4. Absolutely no warranty of function or purpose is made by the authors.
1825670Sdavidn * 5. Modifications may be freely made to this file providing the above
1925670Sdavidn *    conditions are met.
2025670Sdavidn */
2125670Sdavidn
2284225Sdillon#include <sys/cdefs.h>
2384225Sdillon__FBSDID("$FreeBSD$");
2425670Sdavidn
2525670Sdavidn#include <sys/types.h>
2625670Sdavidn#include <sys/stat.h>
2791211Sbde
2825670Sdavidn#include <errno.h>
2925670Sdavidn#include <libutil.h>
3091211Sbde#include <stddef.h>
3191211Sbde#include <syslog.h>
3225670Sdavidn
3325670Sdavidn/*
3425670Sdavidn * Check for common security problems on a given path
3525670Sdavidn * It must be:
3625670Sdavidn * 1. A regular file, and exists
37139012Sru * 2. Owned and writable only by root (or given owner)
3825670Sdavidn * 3. Group ownership is given group or is non-group writable
3925670Sdavidn *
4025670Sdavidn * Returns:	-2 if file does not exist,
4125670Sdavidn *		-1 if security test failure
4225670Sdavidn *		0  otherwise
4325670Sdavidn */
4425670Sdavidn
4525670Sdavidnint
4625670Sdavidn_secure_path(const char *path, uid_t uid, gid_t gid)
4725670Sdavidn{
4825670Sdavidn    int		r = -1;
4925670Sdavidn    struct stat	sb;
5025670Sdavidn    const char	*msg = NULL;
5125670Sdavidn
5225670Sdavidn    if (lstat(path, &sb) < 0) {
5325670Sdavidn	if (errno == ENOENT) /* special case */
5425670Sdavidn	    r = -2;  /* if it is just missing, skip the log entry */
5525670Sdavidn	else
5625670Sdavidn	    msg = "%s: cannot stat %s: %m";
5725670Sdavidn    }
5825670Sdavidn    else if (!S_ISREG(sb.st_mode))
5925670Sdavidn    	msg = "%s: %s is not a regular file";
6025670Sdavidn    else if (sb.st_mode & S_IWOTH)
6125670Sdavidn    	msg = "%s: %s is world writable";
62121193Smarkm    else if ((int)uid != -1 && sb.st_uid != uid && sb.st_uid != 0) {
6325670Sdavidn    	if (uid == 0)
6425670Sdavidn    		msg = "%s: %s is not owned by root";
6525670Sdavidn    	else
6625670Sdavidn    		msg = "%s: %s is not owned by uid %d";
67121193Smarkm    } else if ((int)gid != -1 && sb.st_gid != gid && (sb.st_mode & S_IWGRP))
6825670Sdavidn    	msg = "%s: %s is group writeable by non-authorised groups";
6925670Sdavidn    else
7025670Sdavidn    	r = 0;
7125670Sdavidn    if (msg != NULL)
7225670Sdavidn	syslog(LOG_ERR, msg, "_secure_path", path, uid);
7325670Sdavidn    return r;
7425670Sdavidn}
75