FreeBSD/crypto/openssh/auth.c
/*
 * Check a given path for security. This is defined as all components
 * of the path to the file must be owned by either the owner of
 * of the file or root and no directories must be group or world writable.
 *
 * XXX Should any specific check be done for sym links ?
 *
 * Takes a file name, its stat information (preferably from fstat() to
 * avoid races), the uid of the expected owner, their home directory and an
 * error buffer plus max size as arguments.
 *
 * Returns 0 on success and -1 on failure
 */
Check a given path for security. This is defined as all components
of the path to the file must be owned by either the owner of
of the file or root and no directories must be group or world writable.



Takes a file name, its stat information (preferably from fstat() to
avoid races), the uid of the expected owner, their home directory and an
error buffer plus max size as arguments.

Returns 0 on success and -1 on failure
Check a given path for security . This is defined as all components of the path to the file must be owned by either the owner of of the file or root and no directories must be group or world writable . Takes a file name its stat information ( preferably from fstat () to avoid races ) the uid of the expected owner their home directory and an error buffer plus max size as arguments . Returns 0 on success and - 1 on failure
int
auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
    uid_t uid, char *err, size_t errlen)
{
	char buf[PATH_MAX], homedir[PATH_MAX];
	char *cp;
	int comparehome = 0;
	struct stat st;
	if (realpath(name, buf) == NULL) {
		snprintf(err, errlen, "realpath %s failed: %s", name,
		    strerror(errno));
		return -1;
	}
	if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
		comparehome = 1;
	if (!S_ISREG(stp->st_mode)) {
		snprintf(err, errlen, "%s is not a regular file", buf);
		return -1;
	}
	if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
	    (stp->st_mode & 022) != 0) {
		snprintf(err, errlen, "bad ownership or modes for file %s",
		    buf);
		return -1;
	}
	for (;;) {
		if ((cp = dirname(buf)) == NULL) {
			snprintf(err, errlen, "dirname() failed");
			return -1;
		}
		strlcpy(buf, cp, sizeof(buf));
		if (stat(buf, &st) < 0 ||
		    (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
		    (st.st_mode & 022) != 0) {
			snprintf(err, errlen,
			    "bad ownership or modes for directory %s", buf);
			return -1;
		}
		if (comparehome && strcmp(homedir, buf) == 0)
			break;
		if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
			break;
	}
	return 0;
}
int auth_secure_path ( const char * name , struct stat * stp , const char * pw_dir , uid_t uid , char * err , size_t errlen ) { char buf [ PATH_MAX ] , homedir [ PATH_MAX ] ; char * cp ; int comparehome = 0 ; struct stat st ; if ( realpath ( name , buf ) == NULL ) { snprintf ( err , errlen , " " , name , strerror ( errno ) ) ; return -1 ; } if ( pw_dir != NULL && realpath ( pw_dir , homedir ) != NULL ) comparehome = 1 ; if ( ! S_ISREG ( stp -> st_mode ) ) { snprintf ( err , errlen , " " , buf ) ; return -1 ; } if ( ( ! platform_sys_dir_uid ( stp -> st_uid ) && stp -> st_uid != uid ) || ( stp -> st_mode & 022 ) != 0 ) { snprintf ( err , errlen , " " , buf ) ; return -1 ; } for ( ; ; ) { if ( ( cp = dirname ( buf ) ) == NULL ) { snprintf ( err , errlen , " " ) ; return -1 ; } strlcpy ( buf , cp , sizeof ( buf ) ) ; if ( stat ( buf , & st ) < 0 || ( ! platform_sys_dir_uid ( st . st_uid ) && st . st_uid != uid ) || ( st . st_mode & 022 ) != 0 ) { snprintf ( err , errlen , " " , buf ) ; return -1 ; } if ( comparehome && strcmp ( homedir , buf ) == 0 ) break ; if ( ( strcmp ( " " , buf ) == 0 ) || ( strcmp ( " " , buf ) == 0 ) ) break ; } return 0 ; }
Check a given path for security.
Check a given path for security .
/* for each component of the canonical path, walking upwards */ /* If are past the homedir then we can stop */ /*
		 * dirname should always complete with a "/" path,
		 * but we can be paranoid and check for "." too
		 */