예제 #1
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);
}
예제 #2
0
int chirp_acl_ticket_modify(const char *ticket_dir, const char *subject, const char *ticket_subject, const char *path, int flags)
{
	char ticket_filename[CHIRP_PATH_MAX];
	const char *digest;
	char *esubject;
	struct chirp_ticket ct;
	int status = 0;

	if(!chirp_ticket_isticketsubject(ticket_subject, &digest)) {
		errno = EINVAL;
		return -1;
	}
	/* Note about tickets making tickets:
	 * We check whether the ticket has the rights associated with the mask in
	 * the next line. So, a ticket can only make a ticket with rights it
	 * already has.
	 */
	if(!chirp_acl_check_dir(path, subject, flags))
		return -1;	/* you don't have the rights for the mask */
	if(!chirp_acl_whoami(subject, &esubject))
		return -1;

	chirp_ticket_filename(ticket_filename, ticket_subject, NULL);

	if(!ticket_read(ticket_filename, &ct)) {
		free(esubject);
		return -1;
	}

	if(strcmp(esubject, ct.subject) == 0 || strcmp(chirp_super_user, subject) == 0) {
		size_t n;
		int replaced = 0;
		for(n = 0; n < ct.nrights; n++) {
			char safewhere[CHIRP_PATH_MAX];
			char where[CHIRP_PATH_MAX];
			sprintf(safewhere, "%s/%s", ticket_dir, ct.rights[n].directory);
			string_collapse_path(safewhere, where, 1);

			if(strcmp(where, path) == 0) {
				free(ct.rights[n].acl);
				ct.rights[n].acl = xxstrdup(chirp_acl_flags_to_text(flags));	/* replace old acl mask */
				replaced = 1;
			}
		}
		if(!replaced) {
			assert(strlen(path) >= strlen(ticket_dir));
			ct.rights = xxrealloc(ct.rights, sizeof(*ct.rights) * (++ct.nrights) + 1);
			char directory[CHIRP_PATH_MAX];
			char collapsed_directory[CHIRP_PATH_MAX];
			sprintf(directory, "/%s", path + strlen(ticket_dir));
			string_collapse_path(directory, collapsed_directory, 1);
			ct.rights[ct.nrights - 1].directory = xxstrdup(collapsed_directory);
			ct.rights[ct.nrights - 1].acl = xxstrdup(chirp_acl_flags_to_text(flags));
		}
		status = ticket_write(ticket_filename, &ct);
	} else {
		errno = EACCES;
		status = -1;
	}
	chirp_ticket_free(&ct);
	free(esubject);
	return status;
}
예제 #3
0
static void make_acl_name(const char *filename, int get_parent, char *aclname)
{
	char tmp[CHIRP_PATH_MAX];
	sprintf(tmp, "%s/%s", filename, CHIRP_ACL_BASE_NAME);
	string_collapse_path(tmp, aclname, 1);
}
예제 #4
0
static int do_chirp_acl_get(const char *dirname, const char *subject, int *totalflags)
{
	CHIRP_FILE *aclfile;
	char aclsubject[CHIRP_LINE_MAX];
	int aclflags;

	errno = 0;
	*totalflags = 0;

	/* if the subject is a ticket, then we need the rights we have for the
	 * directory along with the rights of the subject in that directory
	 */
	const char *digest;
	if(chirp_ticket_isticketsubject(subject, &digest)) {
		/* open the ticket file, read the public key */
		char ticket_filename[CHIRP_PATH_MAX];
		struct chirp_ticket ct;
		chirp_ticket_filename(ticket_filename, subject, NULL);
		if(!ticket_read(ticket_filename, &ct))
			return 0;
		if(!do_chirp_acl_get(dirname, ct.subject, totalflags)) {
			chirp_ticket_free(&ct);
			return 0;
		}
		size_t i;
		size_t longest = 0;
		int mask = 0;
		for(i = 0; i < ct.nrights; i++) {
			char safewhere[CHIRP_PATH_MAX];
			char where[CHIRP_PATH_MAX];
			sprintf(safewhere, "%s/%s", chirp_ticket_path, ct.rights[i].directory);
			string_collapse_path(safewhere, where, 1);

			if(strncmp(dirname, where, strlen(where)) == 0) {
				if(strlen(where) > longest) {
					longest = strlen(where);
					mask = chirp_acl_text_to_flags(ct.rights[i].acl);
				}
			}
		}
		*totalflags &= mask;
	} else {
		aclfile = chirp_acl_open(dirname);
		if(aclfile) {
			while(chirp_acl_read(aclfile, aclsubject, &aclflags)) {
				if(string_match(aclsubject, subject)) {
					*totalflags |= aclflags;
				} else if(!strncmp(aclsubject, "group:", 6)) {
					if(chirp_group_lookup(aclsubject, subject)) {
						*totalflags |= aclflags;
					}
				}
			}
			chirp_acl_close(aclfile);
		} else {
			return 0;
		}
	}

	if(read_only_mode) {
		*totalflags &= CHIRP_ACL_READ | CHIRP_ACL_LIST;
	}

	return 1;
}