コード例 #1
0
ファイル: chirp_acl.c プロジェクト: bbockelm/cctools
int chirp_acl_check_dir(const char *dirname, const char *subject, int flags)
{
	int myflags = 0;
	int paflags = 0;

	if(cfs->do_acl_check() == 0)
		return 1;

	/* If flags is CHIRP_ACL_DELETE, then check if we have delete permissions in the *containing directory*. */
	if (flags & CHIRP_ACL_DELETE) {
		char dir[CHIRP_PATH_MAX];
		path_dirname(dirname, dir);
		if(!do_chirp_acl_get(dir, subject, &paflags)) {
			/* Applications are very sensitive to this error condition. A
			 * missing ACL file indicates permission denied, but a missing
			 * directory entirely indicates no such entry.
			 */
			if(cfs_isdir(dirname)) {
				errno = EACCES;
			} else {
				errno = ENOENT;
			}
			return 0;
		}
	}
	/* other flags require checking the actual directory... */
	if ((flags & ~CHIRP_ACL_DELETE)) {
		if(!do_chirp_acl_get(dirname, subject, &myflags)) {
			/* Applications are very sensitive to this error condition. A
			 * missing ACL file indicates permission denied, but a missing
			 * directory entirely indicates no such entry.
			 */
			if(cfs_isdir(dirname)) {
				errno = EACCES;
			} else {
				errno = ENOENT;
			}
			return 0;
		}
	}
	myflags |= (paflags & CHIRP_ACL_DELETE);

	/* The superuser can implicitly list and admin */

	if(strcmp(subject, chirp_super_user) == 0) {
		myflags |= CHIRP_ACL_LIST | CHIRP_ACL_ADMIN;
	}

	if((flags & myflags) == flags) {
		return 1;
	} else {
		errno = EACCES;
		return 0;
	}
}
コード例 #2
0
ファイル: chirp_acl.c プロジェクト: ailurus1991/cctools
int chirp_acl_check_dir(const char *dirname, const char *subject, int flags)
{
	int myflags;

	if(cfs->do_acl_check() == 0)
		return 1;

	if(!do_chirp_acl_get(dirname, subject, &myflags)) {
		/*
		   Applications are very sensitive to this error condition.
		   A missing ACL file indicates permission denied,
		   but a missing directory entirely indicates no such entry.
		 */

		if(cfs_isdir(dirname)) {
			errno = EACCES;
		} else {
			errno = ENOENT;
		}
		return 0;
	}

	/* The superuser can implicitly list and admin */

	if(chirp_super_user && !strcmp(subject, chirp_super_user)) {
		myflags |= CHIRP_ACL_LIST | CHIRP_ACL_ADMIN;
	}

	if((flags & myflags) == flags) {
		return 1;
	} else {
		errno = EACCES;
		return 0;
	}
}
コード例 #3
0
static int do_chirp_acl_check(const char *filename, const char *subject, int flags, int follow_links)
{
	char linkname[CHIRP_PATH_MAX];
	char temp[CHIRP_PATH_MAX];
	char dirname[CHIRP_PATH_MAX];

	if(cfs->do_acl_check()==0) return 1;

	/*
	   Symbolic links require special handling.
	   If requested, follow the link and look for rights in that directory.
	 */

	if(follow_links && flags != CHIRP_ACL_DELETE) {
		int length = cfs->readlink(filename, linkname, sizeof(linkname));
		if(length > 0) {
			linkname[length] = 0;

			/* If the link is relative, construct a full path */

			if(linkname[0] != '/') {
				sprintf(temp, "%s/../%s", filename, linkname);
				string_collapse_path(temp, linkname, 1);
			}

			/* Use the linkname now to look up the ACL */

			debug(D_DEBUG, "symlink %s points to %s", filename, linkname);
			filename = linkname;
		}
	}

	/*
	   If the file being checked is an ACL file,
	   then it may be written with the admin flag, but never deleted.
	 */

	if(!strcmp(string_back(filename, CHIRP_ACL_BASE_LENGTH), CHIRP_ACL_BASE_NAME)) {
		if(flags & CHIRP_ACL_DELETE) {
			errno = EACCES;
			return 0;
		}
		if(flags & CHIRP_ACL_WRITE) {
			flags &= ~CHIRP_ACL_WRITE;
			flags |= CHIRP_ACL_ADMIN;
		}
	}

	/* Now get the name of the directory containing the file */

	string_collapse_path(filename, temp, 1);
	if(!cfs_isdir(temp))
		string_dirname(temp, dirname);
	else
		strcpy(dirname, temp);

	/* Perform the permissions check on that directory. */

	return chirp_acl_check_dir(dirname, subject, flags);
}
コード例 #4
0
ファイル: chirp_acl.c プロジェクト: ailurus1991/cctools
int chirp_acl_ticket_create(const char *subject, const char *newsubject, const char *ticket, const char *duration)
{
	time_t now;		/*, delta; */
	time_t offset = (time_t) strtoul(duration, NULL, 10);
	const char *digest;
	char ticket_subject[CHIRP_PATH_MAX];
	char ticket_filename[CHIRP_PATH_MAX];
	char expiration[128];

	now = time(NULL);
	now = mktime(gmtime(&now));	/* convert to UTC */
	sprintf(expiration, "%lu", (unsigned long) (now + offset));

	/* Note about tickets making tickets:
	 * A ticket created by a ticket authenticated user has the same effective
	 * subject (see the ticket_register RPC in chirp_server.c). Also, the
	 * expiration time is less than or equal to the expiration time of the
	 * ticket used to authenticate.
	 */
	if(chirp_ticket_isticketsubject(subject, &digest)) {
		struct chirp_ticket ct;
		chirp_ticket_filename(ticket_filename, subject, NULL);
		if(!ticket_read(ticket_filename, &ct))
			return -1;
		if(ct.expiration < now + offset) {
			sprintf(expiration, "%lu", (unsigned long) ct.expiration);
		}
		chirp_ticket_free(&ct);
	}

	if(!cfs_isdir("/")) {
		errno = ENOTDIR;
		return -1;
	}

	chirp_ticket_name(ticket, ticket_subject, ticket_filename);

	CHIRP_FILE *f = cfs_fopen(ticket_filename, "w");
	if(!f) {
		errno = EACCES;
		return -1;
	}
	cfs_fprintf(f, "subject \"%s\"\n", newsubject);
	cfs_fprintf(f, "expiration \"%s\"\n", expiration);
	cfs_fprintf(f, "ticket \"%s\"\n", ticket);
	cfs_fprintf(f, "rights \"/\" \"n\"\n");

	cfs_fflush(f);
	int result = cfs_ferror(f);
	if(result) {
		errno = EACCES;
		return -1;
	}
	cfs_fclose(f);
	return 0;
}
コード例 #5
0
static int search_directory(const char *subject, const char *const base, char fullpath[CHIRP_PATH_MAX], const char *pattern, int flags, struct link *l, time_t stoptime)
{
	if(strlen(pattern) == 0)
		return 0;

	debug(D_DEBUG, "search_directory(subject = `%s', base = `%s', fullpath = `%s', pattern = `%s', flags = %d, ...)", subject, base, fullpath, pattern, flags);

	int access_flags = search_to_access(flags);
	int includeroot = flags & CHIRP_SEARCH_INCLUDEROOT;
	int metadata = flags & CHIRP_SEARCH_METADATA;
	int stopatfirst = flags & CHIRP_SEARCH_STOPATFIRST;

	int result = 0;
	struct chirp_dir *dirp = cfs->opendir(fullpath);
	char *current = fullpath + strlen(fullpath);	/* point to end to current directory */

	if(dirp) {
		errno = 0;
		struct chirp_dirent *entry;
		while((entry = cfs->readdir(dirp))) {
			char *name = entry->name;

			if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0 || strncmp(name, ".__", 3) == 0)
				continue;
			sprintf(current, "/%s", name);

			if(search_match_file(pattern, base)) {
				const char *matched;
				if(includeroot) {
					if(base - fullpath == 1 && fullpath[0] == '/') {
						matched = base;
					} else {
						matched = fullpath;
					}
				} else {
					matched = base;
				}

				result += 1;
				if(access_flags == F_OK || cfs->access(fullpath, access_flags) == 0) {
					if(metadata) {
						/* A match was found, but the matched file couldn't be statted. Generate a result and an error. */
						if(entry->lstatus == -1) {
							link_putfstring(l, "0:%s::\n", stoptime, matched);	// FIXME is this a bug?
							link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_STAT, matched);
						} else {
							BUFFER_STACK_ABORT(B, 4096)
							chirp_stat_encode(B, &entry->info);
							link_putfstring(l, "0:%s:%s:\n", stoptime, matched, buffer_tostring(B));
							if(stopatfirst)
								return 1;
						}
					} else {
						link_putfstring(l, "0:%s::\n", stoptime, matched);
						if(stopatfirst)
							return 1;
					}
				}	/* FIXME access failure */
			}

			if(cfs_isdir(fullpath) && search_should_recurse(base, pattern)) {
				if(chirp_acl_check_dir(fullpath, subject, CHIRP_ACL_LIST)) {
					int n = search_directory(subject, base, fullpath, pattern, flags, l, stoptime);
					if(n > 0) {
						result += n;
						if(stopatfirst)
							return result;
					}
				} else {
					link_putfstring(l, "%d:%d:%s:\n", stoptime, EPERM, CHIRP_SEARCH_ERR_OPEN, fullpath);
				}
			}
			*current = '\0';	/* clear current entry */
			errno = 0;
		}

		if(errno)
			link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_READ, fullpath);

		errno = 0;
		cfs->closedir(dirp);
		if(errno)
			link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_CLOSE, fullpath);
	} else {
		link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_OPEN, fullpath);
	}

	return result;
}
コード例 #6
0
ファイル: chirp_acl.c プロジェクト: ailurus1991/cctools
int chirp_acl_set(const char *dirname, const char *subject, int flags, int reset_acl)
{
	char aclname[CHIRP_PATH_MAX];
	char newaclname[CHIRP_PATH_MAX];
	char aclsubject[CHIRP_LINE_MAX];
	int aclflags;
	CHIRP_FILE *aclfile, *newaclfile;
	int result;
	int replaced_acl_entry = 0;

	if(!cfs_isdir(dirname)) {
		errno = ENOTDIR;
		return -1;
	}

	sprintf(aclname, "%s/%s", dirname, CHIRP_ACL_BASE_NAME);
	sprintf(newaclname, "%s/%s.%d", dirname, CHIRP_ACL_BASE_NAME, (int) getpid());

	if(reset_acl) {
		aclfile = cfs_fopen_local("/dev/null", "r");
	} else {
		aclfile = chirp_acl_open(dirname);

		/* If the acl never existed, then we can simply create it. */
		if(!aclfile && errno == ENOENT) {
			aclfile = cfs_fopen_local("/dev/null", "r");	/* use local... */
		}
	}

	if(!aclfile) {
		errno = EACCES;
		return -1;
	}

	replaced_acl_entry = 0;

	newaclfile = cfs_fopen(newaclname, "w");
	if(!newaclfile) {
		cfs_fclose(aclfile);
		errno = EACCES;
		return -1;
	}

	while(chirp_acl_read(aclfile, aclsubject, &aclflags)) {
		if(!strcmp(subject, aclsubject)) {
			aclflags = flags;
			replaced_acl_entry = 1;
		}
		if(aclflags != 0) {
			cfs_fprintf(newaclfile, "%s %s\n", aclsubject, chirp_acl_flags_to_text(aclflags));
		}
	}
	cfs_fclose(aclfile);

	if(!replaced_acl_entry) {
		cfs_fprintf(newaclfile, "%s %s\n", subject, chirp_acl_flags_to_text(flags));
	}

	/* Need to force a write in order to get response from ferror */

	cfs_fflush(newaclfile);
	result = cfs_ferror(newaclfile);
	cfs_fclose(newaclfile);

	if(result) {
		errno = EACCES;
		result = -1;
	} else {
		result = cfs->rename(newaclname, aclname);
		if(result < 0) {
			cfs->unlink(newaclname);
			errno = EACCES;
			result = -1;
		}
	}

	return result;
}
コード例 #7
0
ファイル: chirp_fs_local.c プロジェクト: nfillmore/cctools
static int search_directory(const char *subject, const char * const base, char *fullpath, const char *pattern, int flags, struct link *l, time_t stoptime)
{
	if(strlen(pattern) == 0)
		return 0;

	debug(D_DEBUG, "search_directory(subject = `%s', base = `%s', fullpath = `%s', pattern = `%s', flags = %d, ...)", subject, base, fullpath, pattern, flags);

	int access_flags = search_to_access(flags);
	int includeroot = flags & CHIRP_SEARCH_INCLUDEROOT;
	int metadata = flags & CHIRP_SEARCH_METADATA;
	int stopatfirst = flags & CHIRP_SEARCH_STOPATFIRST;

	int result = 0;
	void *dirp = chirp_fs_local_opendir(fullpath);
	char *current = fullpath + strlen(fullpath);	/* point to end to current directory */

	if(dirp) {
		errno = 0;
		struct chirp_dirent *entry;
		while((entry = chirp_fs_local_readdir(dirp))) {
			char *name = entry->name;

			if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0 || strncmp(name, ".__", 3) == 0)
				continue;
			sprintf(current, "/%s", name);

			if(search_match_file(pattern, base)) {
				const char *matched = includeroot ? fullpath+strlen(chirp_root_path) : base; /* add strlen(chirp_root_path) to strip out */

				result += 1;
				if (access_flags == F_OK || chirp_fs_local_access(fullpath, access_flags) == 0) {
					if(metadata) {
						/* A match was found, but the matched file couldn't be statted. Generate a result and an error. */
						struct chirp_stat buf;
						if((chirp_fs_local_stat(fullpath, &buf)) == -1) {
							link_putfstring(l, "0:%s::\n", stoptime, matched); // FIXME is this a bug?
							link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_STAT, matched);
						} else {
							link_putfstring(l, "0:%s:%s:\n", stoptime, matched, chirp_stat_string(&buf));
							if(stopatfirst) return 1;
						}
					} else {
						link_putfstring(l, "0:%s::\n", stoptime, matched);
						if(stopatfirst) return 1;
					}
				} /* FIXME access failure */
			}

			if(cfs_isdir(fullpath) && search_should_recurse(base, pattern)) {
				if(chirp_acl_check_dir(fullpath, subject, CHIRP_ACL_LIST)) {
					int n = search_directory(subject, base, fullpath, pattern, flags, l, stoptime);
					if(n > 0) {
						result += n;
						if(stopatfirst)
							return result;
					}
				} else {
					link_putfstring(l, "%d:%d:%s:\n", stoptime, EPERM, CHIRP_SEARCH_ERR_OPEN, fullpath);
				}
			}
			*current = '\0';	/* clear current entry */
			errno = 0;
		}

		if(errno)
			link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_READ, fullpath);

		errno = 0;
		chirp_alloc_closedir(dirp);
		if(errno)
			link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_CLOSE, fullpath);
	} else {
		link_putfstring(l, "%d:%d:%s:\n", stoptime, errno, CHIRP_SEARCH_ERR_OPEN, fullpath);
	}

	return result;
}