Пример #1
0
bool master_threads2::run_alone(const char* addrs, const char* path /* = NULL */,
	unsigned int count /* = 1 */, int threads_count /* = 1 */)
{
	// 每个进程只能有一个实例在运行
	acl_assert(has_called == false);
	has_called = true;
	daemon_mode_ = false;
	acl_assert(addrs && *addrs);

	__count_limit = count;

#ifdef WIN32
	acl_init();
#endif

	std::vector<ACL_VSTREAM*> sstreams;
	ACL_EVENT* eventp = acl_event_new_select_thr(1, 0);
	set_event(eventp);  // 设置基类的事件句柄

	ACL_ARGV*  tokens = acl_argv_split(addrs, ";,| \t");
	ACL_ITER   iter;

	acl_foreach(iter, tokens)
	{
		const char* addr = (const char*) iter.data;
		ACL_VSTREAM* sstream = acl_vstream_listen(addr, 128);
		if (sstream == NULL)
		{
			logger_error("listen %s error(%s)",
				addr, acl_last_serror());
			acl_argv_free(tokens);
			close_sstreams(eventp, sstreams);
			acl_event_free(eventp);
			return false;
		}
		acl_event_enable_listen(eventp, sstream, 0,
			listen_callback, sstream);
		sstreams.push_back(sstream);
	}

	acl_argv_free(tokens);

	// 初始化配置参数
	conf_.load(path);

	service_pre_jail(NULL);
	service_init(NULL);

	if (threads_count > 1)
	{
		__thread_pool = acl_thread_pool_create(threads_count, 120);
		acl_pthread_pool_atinit(__thread_pool, thread_begin, NULL);
		acl_pthread_pool_atfree(__thread_pool, thread_finish, NULL);
	}
	else
		thread_init(NULL);

	while (!__stop)
		acl_event_loop(eventp);

	if (__thread_pool)
		acl_pthread_pool_destroy(__thread_pool);
	else
		thread_exit(NULL);

	service_exit(NULL);

	// 必须在调用 acl_event_free 前调用 close_sstreams,因为在关闭
	// 网络流对象时依然有对 ACL_EVENT 引擎的使用
	close_sstreams(eventp, sstreams);
	acl_event_free(eventp);
	eventp = NULL;

	return true;
}
Пример #2
0
static int CheckPosixLinuxACEs(EvalContext *ctx, Rlist *aces, AclMethod method, const char *file_path, acl_type_t acl_type, Attributes a,
                               const Promise *pp, PromiseResult *result)
{
    acl_t acl_existing;
    acl_t acl_new;
    acl_t acl_tmp;
    acl_entry_t ace_parsed;
    acl_entry_t ace_current;
    acl_permset_t perms;
    char *cf_ace;
    int retv;
    int has_mask;
    Rlist *rp;
    char *acl_type_str;

    acl_new = NULL;
    acl_existing = NULL;
    acl_tmp = NULL;
    has_mask = false;

    acl_type_str = acl_type == ACL_TYPE_ACCESS ? "Access" : "Default";

// read existing acl

    if ((acl_existing = acl_get_file(file_path, acl_type)) == NULL)
    {
        Log(LOG_LEVEL_VERBOSE, "No ACL for '%s' could be read. (acl_get_file: %s)", file_path, GetErrorStr());
        return false;
    }

// allocate memory for temp ace (it needs to reside in a temp acl)

    if ((acl_tmp = acl_init(1)) == NULL)
    {
        Log(LOG_LEVEL_ERR, "New ACL could not be allocated (acl_init: %s)", GetErrorStr());
        acl_free((void *) acl_existing);
        return false;
    }

    if (acl_create_entry(&acl_tmp, &ace_parsed) != 0)
    {
        Log(LOG_LEVEL_ERR, "New ACL could not be allocated (acl_create_entry: %s)", GetErrorStr());
        acl_free((void *) acl_existing);
        acl_free((void *) acl_tmp);
        return false;
    }

// copy existing aces if we are appending

    if (method == ACL_METHOD_APPEND)
    {
        if ((acl_new = acl_dup(acl_existing)) == NULL)
        {
            Log(LOG_LEVEL_ERR, "Error copying existing ACL (acl_dup: %s)", GetErrorStr());
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            return false;
        }
    }
    else                        // overwrite existing acl
    {
        if ((acl_new = acl_init(5)) == NULL)    // TODO: Always OK with 5 here ?
        {
            Log(LOG_LEVEL_ERR, "New ACL could not be allocated (acl_init: %s)", GetErrorStr());
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            return false;
        }
    }

    for (rp = aces; rp != NULL; rp = rp->next)
    {
        cf_ace = RlistScalarValue(rp);

        if (!ParseEntityPosixLinux(&cf_ace, ace_parsed, &has_mask))
        {
            Log(LOG_LEVEL_ERR, "Error parsing entity in 'cf_ace'.");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }

        // check if an ACE with this entity-type and id already exist in the Posix Linux ACL

        ace_current = FindACE(acl_new, ace_parsed);

        // create new entry in ACL if it did not exist

        if (ace_current == NULL)
        {
            if (acl_create_entry(&acl_new, &ace_current) != 0)
            {
                Log(LOG_LEVEL_ERR, "Failed to allocate ace (acl_create_entry: %s)", GetErrorStr());
                acl_free((void *) acl_existing);
                acl_free((void *) acl_tmp);
                acl_free((void *) acl_new);
                return false;
            }

            // copy parsed entity-type and id

            if (acl_copy_entry(ace_current, ace_parsed) != 0)
            {
                Log(LOG_LEVEL_ERR, "Error copying Linux entry in 'cf_ace' (acl_copy_entry: %s)", GetErrorStr());
                acl_free((void *) acl_existing);
                acl_free((void *) acl_tmp);
                acl_free((void *) acl_new);
                return false;
            }

            // clear ace_current's permissions to avoid ace_parsed from last
            // loop iteration to be taken into account when applying mode below
            if ((acl_get_permset(ace_current, &perms) != 0))
            {
                Log(LOG_LEVEL_ERR, "Error obtaining permset for 'ace_current' (acl_get_permset: %s)", GetErrorStr());
                acl_free((void *) acl_existing);
                acl_free((void *) acl_tmp);
                acl_free((void *) acl_new);
                return false;
            }

            if (acl_clear_perms(perms) != 0)
            {
                Log(LOG_LEVEL_ERR, "Error clearing permset for 'ace_current'. (acl_clear_perms: %s)", GetErrorStr());
                acl_free((void *) acl_existing);
                acl_free((void *) acl_tmp);
                acl_free((void *) acl_new);
                return false;
            }
        }

        // mode string should be prefixed with an entry seperator

        if (*cf_ace != ':')
        {
            Log(LOG_LEVEL_ERR, "No separator before mode-string in 'cf_ace'");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }

        cf_ace += 1;

        if (acl_get_permset(ace_current, &perms) != 0)
        {
            Log(LOG_LEVEL_ERR, "Error obtaining permset for 'cf_ace'");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }

        if (!ParseModePosixLinux(cf_ace, perms))
        {
            Log(LOG_LEVEL_ERR, "Error parsing mode-string in 'cf_ace'");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }

        // only allow permissions exist on posix acls, so we do
        // not check what follows next
    }

// if no mask exists, calculate one (or both?): run acl_calc_mask and add one
    if (!has_mask)
    {
        if (acl_calc_mask(&acl_new) != 0)
        {
            Log(LOG_LEVEL_ERR, "Error calculating new acl mask");
            acl_free((void *) acl_existing);
            acl_free((void *) acl_tmp);
            acl_free((void *) acl_new);
            return false;
        }
    }

    if ((retv = ACLEquals(acl_existing, acl_new)) == -1)
    {
        Log(LOG_LEVEL_ERR, "Error while comparing existing and new ACL, unable to repair.");
        acl_free((void *) acl_existing);
        acl_free((void *) acl_tmp);
        acl_free((void *) acl_new);
        return false;
    }

    if (retv == 1)              // existing and new acl differ, update existing
    {

        switch (a.transaction.action)
        {
        case cfa_warn:

            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "%s ACL on file '%s' needs to be updated", acl_type_str, file_path);
            *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN);
            break;

        case cfa_fix:

            if (!DONTDO)
            {
                if ((retv = acl_set_file(file_path, acl_type, acl_new)) != 0)
                {
                    Log(LOG_LEVEL_ERR, "Error setting new %s ACL on file '%s' (acl_set_file: %s), are required ACEs present ?",
                          acl_type_str, file_path, GetErrorStr());
                    acl_free((void *) acl_existing);
                    acl_free((void *) acl_tmp);
                    acl_free((void *) acl_new);
                    return false;
                }
            }

            cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "%s ACL on '%s' successfully changed.", acl_type_str, file_path);
            *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE);

            break;

        default:
            ProgrammingError("CFEngine: internal error: illegal file action");
        }

    }
    else
    {
        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "'%s' ACL on '%s' needs no modification.", acl_type_str, file_path);
    }

    acl_free((void *) acl_existing);
    acl_free((void *) acl_new);
    acl_free((void *) acl_tmp);
    return true;
}
Пример #3
0
int
slap_init( int mode, const char *name )
{
	int rc;

	assert( mode );

	if ( slapMode != SLAP_UNDEFINED_MODE ) {
		/* Make sure we write something to stderr */
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		 "%s init: init called twice (old=%d, new=%d)\n",
		 name, slapMode, mode );

		return 1;
	}

	slapMode = mode;

	slap_op_init();

#ifdef SLAPD_MODULES
	if ( module_init() != 0 ) {
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		    "%s: module_init failed\n",
			name, 0, 0 );
		return 1;
	}
#endif

	if ( slap_schema_init( ) != 0 ) {
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		    "%s: slap_schema_init failed\n",
		    name, 0, 0 );
		return 1;
	}

	if ( filter_init() != 0 ) {
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		    "%s: filter_init failed\n",
		    name, 0, 0 );
		return 1;
	}

	if ( entry_init() != 0 ) {
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		    "%s: entry_init failed\n",
		    name, 0, 0 );
		return 1;
	}

	switch ( slapMode & SLAP_MODE ) {
	case SLAP_SERVER_MODE:
		root_dse_init();

		/* FALLTHRU */
	case SLAP_TOOL_MODE:
		Debug( LDAP_DEBUG_TRACE,
			"%s init: initiated %s.\n",	name,
			(mode & SLAP_MODE) == SLAP_TOOL_MODE ? "tool" : "server",
			0 );

		slap_name = name;

		ldap_pvt_thread_pool_init_q( &connection_pool,
				connection_pool_max, 0, connection_pool_queues);

		slap_counters_init( &slap_counters );

		ldap_pvt_thread_mutex_init( &slapd_rq.rq_mutex );
		LDAP_STAILQ_INIT( &slapd_rq.task_list );
		LDAP_STAILQ_INIT( &slapd_rq.run_list );

		slap_passwd_init();

		rc = slap_sasl_init();

		if( rc == 0 ) {
			rc = backend_init( );
		}
		if ( rc )
			return rc;

		break;

	default:
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
			"%s init: undefined mode (%d).\n", name, mode, 0 );

		rc = 1;
		break;
	}

	if ( slap_controls_init( ) != 0 ) {
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		    "%s: slap_controls_init failed\n",
		    name, 0, 0 );
		return 1;
	}

	if ( frontend_init() ) {
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		    "%s: frontend_init failed\n",
		    name, 0, 0 );
		return 1;
	}

	if ( overlay_init() ) {
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		    "%s: overlay_init failed\n",
		    name, 0, 0 );
		return 1;
	}

	if ( glue_sub_init() ) {
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		    "%s: glue/subordinate init failed\n",
		    name, 0, 0 );

		return 1;
	}

	if ( acl_init() ) {
		slap_debug |= LDAP_DEBUG_NONE;
		Debug( LDAP_DEBUG_ANY,
		    "%s: acl_init failed\n",
		    name, 0, 0 );
		return 1;
	}

	return rc;
}
Пример #4
0
int CheckDefaultClearACL(char *file_path, Attributes a, Promise *pp)
{
    acl_t acl_existing;
    acl_t acl_empty;
    acl_entry_t ace_dummy;
    int retv;
    int result = false;

    acl_existing = NULL;
    acl_empty = NULL;

    if ((acl_existing = acl_get_file(file_path, ACL_TYPE_DEFAULT)) == NULL)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "acl_get_file", "Unable to read default acl for %s", file_path);
        return false;
    }

    retv = acl_get_entry(acl_existing, ACL_FIRST_ENTRY, &ace_dummy);

    switch (retv)
    {
    case -1:
        CfOut(OUTPUT_LEVEL_VERBOSE, "acl_get_entry", "Couldn't retrieve ACE for %s", file_path);
        result = false;
        break;

    case 0:                    // no entries, as desired
        cfPS(OUTPUT_LEVEL_INFORM, CF_NOP, "", pp, a, "-> Default ACL on \"%s\" needs no modification.", file_path);
        result = true;
        break;

    case 1:                    // entries exist, set empty ACL

        if ((acl_empty = acl_init(0)) == NULL)
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "Could not reinitialize ACL for %s", file_path);
            result = false;
            break;
        }

        switch (a.transaction.action)
        {
        case cfa_warn:

            cfPS(OUTPUT_LEVEL_ERROR, CF_WARN, "", pp, a, " !! Default ACL on \"%s\" needs to be cleared", file_path);
            break;

        case cfa_fix:

            if (!DONTDO)
            {
                if (acl_set_file(file_path, ACL_TYPE_DEFAULT, acl_empty) != 0)
                {
                    CfOut(OUTPUT_LEVEL_ERROR, "", "Could not reset ACL for %s", file_path);
                    result = false;
                    break;
                }
            }

            cfPS(OUTPUT_LEVEL_INFORM, CF_CHG, "", pp, a, "-> Default ACL on \"%s\" successfully cleared", file_path);
            result = true;

            break;

        default:
            ProgrammingError("Cfengine: internal error: illegal file action\n");
            result = false;
        }

        break;

    default:
        result = false;
    }

    acl_free(acl_empty);
    acl_free(acl_existing);
    return result;
}
Пример #5
0
/*
 * return an ACL corresponding to the permissions
 * contained in struct stat
 */
static acl_t
acl_from_stat(struct stat sb)
{
	acl_t acl;
	acl_entry_t entry;
	acl_permset_t perms;

	/* create the ACL */
	acl = acl_init(3);
	if (!acl)
		return NULL;

	/* First entry: ACL_USER_OBJ */
	if (acl_create_entry(&acl, &entry) == -1)
		return NULL;
	if (acl_set_tag_type(entry, ACL_USER_OBJ) == -1)
		return NULL;

	if (acl_get_permset(entry, &perms) == -1)
		return NULL;
	if (acl_clear_perms(perms) == -1)
		return NULL;

	/* calculate user mode */
	if (sb.st_mode & S_IRUSR)
		if (acl_add_perm(perms, ACL_READ) == -1)
			return NULL;
	if (sb.st_mode & S_IWUSR)
		if (acl_add_perm(perms, ACL_WRITE) == -1)
			return NULL;
	if (sb.st_mode & S_IXUSR)
		if (acl_add_perm(perms, ACL_EXECUTE) == -1)
			return NULL;
	if (acl_set_permset(entry, perms) == -1)
		return NULL;

	/* Second entry: ACL_GROUP_OBJ */
	if (acl_create_entry(&acl, &entry) == -1)
		return NULL;
	if (acl_set_tag_type(entry, ACL_GROUP_OBJ) == -1)
		return NULL;

	if (acl_get_permset(entry, &perms) == -1)
		return NULL;
	if (acl_clear_perms(perms) == -1)
		return NULL;

	/* calculate group mode */
	if (sb.st_mode & S_IRGRP)
		if (acl_add_perm(perms, ACL_READ) == -1)
			return NULL;
	if (sb.st_mode & S_IWGRP)
		if (acl_add_perm(perms, ACL_WRITE) == -1)
			return NULL;
	if (sb.st_mode & S_IXGRP)
		if (acl_add_perm(perms, ACL_EXECUTE) == -1)
			return NULL;
	if (acl_set_permset(entry, perms) == -1)
		return NULL;

	/* Third entry: ACL_OTHER */
	if (acl_create_entry(&acl, &entry) == -1)
		return NULL;
	if (acl_set_tag_type(entry, ACL_OTHER) == -1)
		return NULL;

	if (acl_get_permset(entry, &perms) == -1)
		return NULL;
	if (acl_clear_perms(perms) == -1)
		return NULL;

	/* calculate other mode */
	if (sb.st_mode & S_IROTH)
		if (acl_add_perm(perms, ACL_READ) == -1)
			return NULL;
	if (sb.st_mode & S_IWOTH)
		if (acl_add_perm(perms, ACL_WRITE) == -1)
			return NULL;
	if (sb.st_mode & S_IXOTH)
		if (acl_add_perm(perms, ACL_EXECUTE) == -1)
			return NULL;
	if (acl_set_permset(entry, perms) == -1)
		return NULL;

	return(acl);
}
Пример #6
0
/* 初始化函数 */
void service_init(void *init_ctx)
{
	acl_init();
	http_service_init(init_ctx);
}
Пример #7
0
int
modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int position, int inheritance_level, int follow) {
	
	acl_t oacl = NULL;
	unsigned aindex  = 0, flag_new_acl = 0;
	acl_entry_t newent = NULL;
	acl_entry_t entry = NULL;
	unsigned retval = 0;

	extern int chmod_fflag;

/* XXX acl_get_file() returns a zero entry ACL if an ACL was previously
 * associated with the file, and has had its entries removed.
 * However, POSIX 1003.1e states that a zero entry ACL should be 
 * returned if the caller asks for ACL_TYPE_DEFAULT, and no ACL is 
 * associated with the path; it
 * does not specifically state that a request for ACL_TYPE_EXTENDED
 * should not return a zero entry ACL, however.
 */

/* Determine if we've been given a zero entry ACL, or create an ACL if 
 * none exists. There are some issues to consider here: Should we create
 * a zero-entry ACL for a delete or check canonicity operation?
 */

	if (path == NULL)
		chmod_usage();

	if (optflags & ACL_CLEAR_FLAG) {
		filesec_t fsec = filesec_init();
		if (fsec == NULL) {
			// err(1, "filesec_init() failed");
            fprintf(stderr, "chmod: filesec_init() failed: %s\n", strerror(errno));
            pthread_exit(NULL);
		}
		if (filesec_set_property(fsec, FILESEC_ACL, _FILESEC_REMOVE_ACL) != 0) {
            // err(1, "filesec_set_property() failed");
            fprintf(stderr, "chmod: filesec_set_property() failed: %s\n", strerror(errno));
            pthread_exit(NULL);
                }
		if (follow) {
			if (chmodx_np(path, fsec) != 0) {
                if (!chmod_fflag) {
					// warn("Failed to clear ACL on file %s", path);
                    fprintf(stderr, "chmod: Failed to clear ACL on file %s: %s\n", path, strerror(errno));
				}
				retval = 1;
			}
		} else {
			int fd = open(path, O_SYMLINK);
			if (fd != -1) {
				if (fchmodx_np(fd, fsec) != 0) {
					if (!chmod_fflag) {
                        fprintf(stderr, "chmod: Failed to clear ACL on file %s: %s\n", path, strerror(errno));
                        // warn("Failed to clear ACL on file %s", path);
					}
					retval = 1;
				}
				close(fd);
			} else {
				if (!chmod_fflag) {
					// warn("Failed to open file %s", path);
                    fprintf(stderr, "chmod: Failed to open file %s: %s\n", path, strerror(errno));
				}
				retval = 1;
			}
		}
		filesec_free(fsec);
		return (retval);
	}

	if (optflags & ACL_FROM_STDIN) {
		oacl = acl_dup(modifier);
	} else {
		if (follow) {
			oacl = acl_get_file(path, ACL_TYPE_EXTENDED);
		} else {
			int fd = open(path, O_SYMLINK);
			if (fd != -1) {
				oacl = acl_get_fd_np(fd, ACL_TYPE_EXTENDED);
				close(fd);
			}
		}
		if ((oacl == NULL) ||
		    (acl_get_entry(oacl,ACL_FIRST_ENTRY, &newent) != 0)) {
            if ((oacl = acl_init(1)) == NULL) {
				// err(1, "acl_init() failed");
                fprintf(stderr, "chmod: acl_init() failed: %s\n", strerror(errno));
                pthread_exit(NULL);
            }
			flag_new_acl = 1;
			position = 0;
		}
	
		if ((0 == flag_new_acl) && (optflags & (ACL_REMOVE_INHERIT_FLAG | 
							ACL_REMOVE_INHERITED_ENTRIES))) {
			acl_t facl = NULL;
            if ((facl = acl_init(1)) == NULL) {
				//err(1, "acl_init() failed");
                fprintf(stderr, "chmod: acl_init() failed: %s\n", strerror(errno));
                pthread_exit(NULL);
            }
			for (aindex = 0; 
			     acl_get_entry(oacl, 
					   (entry == NULL ? ACL_FIRST_ENTRY : 
					    ACL_NEXT_ENTRY), &entry) == 0; 
			     aindex++) {
				acl_flagset_t eflags;
				acl_entry_t fent = NULL;
				if (acl_get_flagset_np(entry, &eflags) != 0) {
                    fprintf(stderr,  "chmod: Unable to obtain flagset: %s\n", strerror(errno));
                    pthread_exit(NULL);
                    // err(1, "Unable to obtain flagset");
				}
				
				if (acl_get_flag_np(eflags, ACL_ENTRY_INHERITED)) {
					if (optflags & ACL_REMOVE_INHERIT_FLAG) {
						acl_delete_flag_np(eflags, ACL_ENTRY_INHERITED);
						acl_set_flagset_np(entry, eflags);
						acl_create_entry(&facl, &fent);
						acl_copy_entry(fent, entry);
					}
				}
				else {
					acl_create_entry(&facl, &fent);
					acl_copy_entry(fent, entry);
				}
			}
			if (oacl)
				acl_free(oacl);
			oacl = facl;
		} else if (optflags & ACL_TO_STDOUT) {
			ssize_t len; /* need to get printacl() from ls(1) */
			char *text = acl_to_text(oacl, &len);
			puts(text);
			acl_free(text);
		} else if (optflags & ACL_CHECK_CANONICITY) {
			if (flag_new_acl) {
				// warnx("No ACL currently associated with file '%s'", path);
                fprintf(stderr, "chmod: No ACL currently associated with file '%s'\n", path);
			}
			retval = is_canonical(oacl);
		} else if ((optflags & ACL_SET_FLAG) && (position == -1) && 
		    (!is_canonical(oacl))) {
			// warnx("The specified file '%s' does not have an ACL in canonical order, please specify a position with +a# ", path);
            fprintf(stderr, "chmod: The specified file '%s' does not have an ACL in canonical order, please specify a position with +a# \n", path);
			retval = 1;
		} else if (((optflags & ACL_DELETE_FLAG) && (position != -1))
		    || (optflags & ACL_CHECK_CANONICITY)) {
			retval = modify_acl(&oacl, NULL, optflags, position, 
					    inheritance_level, flag_new_acl, path);
		} else if ((optflags & (ACL_REMOVE_INHERIT_FLAG|ACL_REMOVE_INHERITED_ENTRIES)) && flag_new_acl) {
			// warnx("No ACL currently associated with file '%s'", path);
            fprintf(stderr, "chmod: No ACL currently associated with file '%s'\n", path);
			retval = 1;
		} else {
			if (!modifier) { /* avoid bus error in acl_get_entry */
				// errx(1, "Internal error: modifier should not be NULL");
                fprintf(stderr, "Internal error: modifier should not be NULL\n");
                pthread_exit(NULL);
			}
			for (aindex = 0; 
			     acl_get_entry(modifier, 
					   (entry == NULL ? ACL_FIRST_ENTRY : 
					    ACL_NEXT_ENTRY), &entry) == 0; 
			     aindex++) {

				retval += modify_acl(&oacl, entry, optflags, 
						     position, inheritance_level, 
						     flag_new_acl, path);
			}
		}
	}

/* XXX Potential race here, since someone else could've modified or
 * read the ACL on this file (with the intention of modifying it) in
 * the interval from acl_get_file() to acl_set_file(); we can
 * minimize one aspect of this  window by comparing the original acl
 * to a fresh one from acl_get_file() but we could consider a
 * "changeset" mechanism, common locking  strategy, or kernel
 * supplied reservation mechanism to prevent this race.
 */
	if (!(optflags & (ACL_TO_STDOUT|ACL_CHECK_CANONICITY))) {
		int status = -1;
		if (follow) {
	    		status = acl_set_file(path, ACL_TYPE_EXTENDED, oacl);
		} else {
			int fd = open(path, O_SYMLINK);
			if (fd != -1) {
				status = acl_set_fd_np(fd, oacl,
							ACL_TYPE_EXTENDED);
				close(fd);
			}
		}
		if (status != 0) {
			if (!chmod_fflag)
                fprintf(stderr, "chmod: Failed to set ACL on file '%s': %s\n", path, strerror(errno));
            // warn("Failed to set ACL on file '%s'", path);
			retval = 1;
		}
	}
	
	if (oacl)
		acl_free(oacl);
	
	return retval;
}
int
acl_readonly_example(uuid_t *uuid)
{
	int fd;
	acl_t	acl;
	acl_entry_t ace;
	acl_permset_t perms;
	filesec_t fsec;

	/* initialize our ACL */
	if (NULL == (acl = acl_init(32)))
		err(1, "acl_init()");

	/*
	 * create an ACE
	 *
	 * acl_create_entry_np() has a position capability via the
	 * 'entry_index' argument (ACL_FIRST_ENTRY or ACL_LAST_ENTRY)
	 */
	if (0 != acl_create_entry(&acl, &ace))
		err(1, "acl_create_entry()");

	/* allow or deny */
	if (0 != acl_set_tag_type(ace, ACL_EXTENDED_ALLOW))
		err(1, "acl_set_tag_type()");

	/* associate this with our uuid */
	if (0 != acl_set_qualifier(ace, uuid))
		err(1, "acl_set_qualifier()");

	/* grant "read only" permissions */
	if (0 != acl_get_permset(ace, &perms))
		err(1, "acl_get_permset()");

	if (0 != acl_clear_perms(perms))
		err(1, "acl_clear_perms()");

	if (0 != acl_add_perm(perms, ROPERMS))
		err(1, "acl_add_perm()");

	if (0 != acl_set_permset(ace, perms))
		err(1, "acl_set_permset()");


	/* create a file security object */
	fsec = filesec_init();

	/* add the ACL to the security descriptor */
	filesec_set_property(fsec, FILESEC_ACL, &acl);
	acl_free(acl);

	/* turn off all other permissions on the file */
	filesec_set_property(fsec, FILESEC_MODE, 0);

	/* create a file using our ACL */
	fd = openx_np("foo", O_CREAT|O_EXCL|O_RDWR, fsec);

	/* clean up */
	filesec_free(fsec);
	if (-1 != fd )
		close(fd);

	return(fd);
}
Пример #9
0
int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp) /* {{{ */
{
    struct fpm_worker_pool_config_s *c = wp->config;
#ifdef HAVE_FPM_ACL
    int n;

    /* uninitialized */
    wp->socket_acl  = NULL;
#endif
    wp->socket_uid = -1;
    wp->socket_gid = -1;
    wp->socket_mode = 0660;

    if (!c) {
        return 0;
    }

    if (c->listen_mode && *c->listen_mode) {
        wp->socket_mode = strtoul(c->listen_mode, 0, 8);
    }

#ifdef HAVE_FPM_ACL
    /* count the users and groups configured */
    n = 0;
    if (c->listen_acl_users && *c->listen_acl_users) {
        char *p;
        n++;
        for (p=strchr(c->listen_acl_users, ',') ; p ; p=strchr(p+1, ',')) {
            n++;
        }
    }
    if (c->listen_acl_groups && *c->listen_acl_groups) {
        char *p;
        n++;
        for (p=strchr(c->listen_acl_groups, ',') ; p ; p=strchr(p+1, ',')) {
            n++;
        }
    }
    /* if ACL configured */
    if (n) {
        acl_t acl;
        acl_entry_t entry;
        acl_permset_t perm;
        char *tmp, *p, *end;

        acl = acl_init(n);
        if (!acl) {
            zlog(ZLOG_SYSERROR, "[pool %s] cannot allocate ACL", wp->config->name);
            return -1;
        }
        /* Create USER ACL */
        if (c->listen_acl_users && *c->listen_acl_users) {
            struct passwd *pwd;

            tmp = estrdup(c->listen_acl_users);
            for (p=tmp ; p ; p=end) {
                if ((end = strchr(p, ','))) {
                    *end++ = 0;
                }
                pwd = getpwnam(p);
                if (pwd) {
                    zlog(ZLOG_DEBUG, "[pool %s] user '%s' have uid=%d", wp->config->name, p, pwd->pw_uid);
                } else {
                    zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, p);
                    acl_free(acl);
                    efree(tmp);
                    return -1;
                }
                if (0 > acl_create_entry(&acl, &entry) ||
                        0 > acl_set_tag_type(entry, ACL_USER) ||
                        0 > acl_set_qualifier(entry, &pwd->pw_uid) ||
                        0 > acl_get_permset(entry, &perm) ||
                        0 > acl_clear_perms (perm) ||
                        0 > acl_add_perm (perm, ACL_READ) ||
                        0 > acl_add_perm (perm, ACL_WRITE)) {
                    zlog(ZLOG_SYSERROR, "[pool %s] cannot create ACL for user '%s'", wp->config->name, p);
                    acl_free(acl);
                    efree(tmp);
                    return -1;
                }
            }
            efree(tmp);
        }
        /* Create GROUP ACL */
        if (c->listen_acl_groups && *c->listen_acl_groups) {
            struct group *grp;

            tmp = estrdup(c->listen_acl_groups);
            for (p=tmp ; p ; p=end) {
                if ((end = strchr(p, ','))) {
                    *end++ = 0;
                }
                grp = getgrnam(p);
                if (grp) {
                    zlog(ZLOG_DEBUG, "[pool %s] group '%s' have gid=%d", wp->config->name, p, grp->gr_gid);
                } else {
                    zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, p);
                    acl_free(acl);
                    efree(tmp);
                    return -1;
                }
                if (0 > acl_create_entry(&acl, &entry) ||
                        0 > acl_set_tag_type(entry, ACL_GROUP) ||
                        0 > acl_set_qualifier(entry, &grp->gr_gid) ||
                        0 > acl_get_permset(entry, &perm) ||
                        0 > acl_clear_perms (perm) ||
                        0 > acl_add_perm (perm, ACL_READ) ||
                        0 > acl_add_perm (perm, ACL_WRITE)) {
                    zlog(ZLOG_SYSERROR, "[pool %s] cannot create ACL for group '%s'", wp->config->name, p);
                    acl_free(acl);
                    efree(tmp);
                    return -1;
                }
            }
            efree(tmp);
        }
        if (c->listen_owner && *c->listen_owner) {
            zlog(ZLOG_WARNING, "[pool %s] ACL set, listen.owner = '%s' is ignored", wp->config->name, c->listen_owner);
        }
        if (c->listen_group && *c->listen_group) {
            zlog(ZLOG_WARNING, "[pool %s] ACL set, listen.group = '%s' is ignored", wp->config->name, c->listen_group);
        }
        wp->socket_acl  = acl;
        return 0;
    }
    /* When listen.users and listen.groups not configured, continue with standard right */
#endif

    if (c->listen_owner && *c->listen_owner) {
        struct passwd *pwd;

        pwd = getpwnam(c->listen_owner);
        if (!pwd) {
            zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, c->listen_owner);
            return -1;
        }

        wp->socket_uid = pwd->pw_uid;
        wp->socket_gid = pwd->pw_gid;
    }

    if (c->listen_group && *c->listen_group) {
        struct group *grp;

        grp = getgrnam(c->listen_group);
        if (!grp) {
            zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, c->listen_group);
            return -1;
        }
        wp->socket_gid = grp->gr_gid;
    }

    return 0;
}
Пример #10
0
static acl_t
_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask)
{
	acl_t acl_new, acl_old;
	acl_entry_t entry, entry_new;
	acl_permset_t perm;
	acl_tag_t tag;
	int entry_id, have_mask_entry;

	assert(_acl_brand(aclp) == ACL_BRAND_POSIX);

	acl_old = acl_dup(aclp);
	if (acl_old == NULL)
		return (NULL);

	assert(_acl_brand(acl_old) == ACL_BRAND_POSIX);

	have_mask_entry = 0;
	acl_new = acl_init(ACL_MAX_ENTRIES);
	if (acl_new == NULL) {
		acl_free(acl_old);
		return (NULL);
	}
	tag = ACL_UNDEFINED_TAG;

	/* only save the default user/group/other entries */
	entry_id = ACL_FIRST_ENTRY;
	while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
		entry_id = ACL_NEXT_ENTRY;

		assert(_entry_brand(entry) == ACL_BRAND_POSIX);

		if (acl_get_tag_type(entry, &tag) == -1)
			goto fail;

		switch(tag) {
		case ACL_USER_OBJ:
		case ACL_GROUP_OBJ:
		case ACL_OTHER:
			if (acl_get_tag_type(entry, &tag) == -1)
				goto fail;
			if (acl_get_permset(entry, &perm) == -1)
				goto fail;
			if (acl_create_entry(&acl_new, &entry_new) == -1)
				return (NULL);
			if (acl_set_tag_type(entry_new, tag) == -1)
				return (NULL);
			if (acl_set_permset(entry_new, perm) == -1)
				return (NULL);
			if (acl_copy_entry(entry_new, entry) == -1)
				return (NULL);
			assert(_entry_brand(entry_new) == ACL_BRAND_POSIX);
			break;
		case ACL_MASK:
			have_mask_entry = 1;
			break;
		default:
			break;
		}
fail:
	acl_free(acl_new);
	acl_free(acl_old);
	return (NULL);
	}

	assert(_acl_brand(acl_new) == ACL_BRAND_POSIX);

	if (have_mask_entry && recalculate_mask) {
		if (acl_calc_mask(&acl_new) == -1)
			return (NULL);
	}

	return (acl_new);
}
Пример #11
0
static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
{
	acl_t result;
	int i;

	result = acl_init(acl->count);
	if (result == NULL) {
		DEBUG(10, ("acl_init failed\n"));
		return NULL;
	}

	for (i=0; i<acl->count; i++) {
		const struct smb_acl_entry *entry = &acl->acl[i];
		acl_entry_t e;
		acl_tag_t tag;

		if (acl_create_entry(&result, &e) != 0) {
			DEBUG(1, ("acl_create_entry failed: %s\n",
				  strerror(errno)));
			goto fail;
		}

		switch (entry->a_type) {
		case SMB_ACL_USER:
			tag = ACL_USER;
			break;
		case SMB_ACL_USER_OBJ:
			tag = ACL_USER_OBJ;
			break;
		case SMB_ACL_GROUP:
			tag = ACL_GROUP;
			break;
		case SMB_ACL_GROUP_OBJ:
			tag = ACL_GROUP_OBJ;
			break;
		case SMB_ACL_OTHER:
			tag = ACL_OTHER;
			break;
		case SMB_ACL_MASK:
			tag = ACL_MASK;
			break;
		default:
			DEBUG(1, ("Unknown tag value %d\n", entry->a_type));
			goto fail;
		}

		if (acl_set_tag_type(e, tag) != 0) {
			DEBUG(10, ("acl_set_tag_type(%d) failed: %s\n",
				   tag, strerror(errno)));
			goto fail;
		}

		switch (entry->a_type) {
		case SMB_ACL_USER:
			if (acl_set_qualifier(e, &entry->uid) != 0) {
				DEBUG(1, ("acl_set_qualifiier failed: %s\n",
					  strerror(errno)));
				goto fail;
			}
			break;
		case SMB_ACL_GROUP:
			if (acl_set_qualifier(e, &entry->gid) != 0) {
				DEBUG(1, ("acl_set_qualifiier failed: %s\n",
					  strerror(errno)));
				goto fail;
			}
			break;
		default: 	/* Shut up, compiler! :-) */
			break;
		}

		if (smb_acl_set_mode(e, entry->a_perm) != 0) {
			goto fail;
		}
	}

	if (acl_valid(result) != 0) {
		DEBUG(0, ("smb_acl_to_posix: ACL is invalid for set (%s)\n",
			  strerror(errno)));
		goto fail;
	}

	return result;

 fail:
	if (result != NULL) {
		acl_free(result);
	}
	return NULL;
}
Пример #12
0
acl_t
acl_from_text(const char *buf_p)
{
    int i, error = 0, need_tag, ug_tag;
    char *buf, *orig_buf;
    char *entry, *field, *sub;
    uuid_t *uu = NULL;
    struct passwd *tpass = NULL;
    struct group *tgrp = NULL;
    acl_entry_t acl_entry;
    acl_flagset_t flags = NULL;
    acl_permset_t perms = NULL;
    acl_tag_t tag;
    acl_t acl_ret;

    if (buf_p == NULL)
    {
	errno = EINVAL;
	return NULL;
    }

    if ((buf = strdup(buf_p)) == NULL)
	return NULL;

    if ((acl_ret = acl_init(1)) == NULL)
	return NULL;

    orig_buf = buf;

    /* global acl flags
     * format: !#acl <version> [<flags>]
     */
    if ((entry = strsep(&buf, "\n")) != NULL && *entry)
    {
	/* field 1: !#acl */
	field = strsep(&entry, " ");
	if (*field && strncmp(field, "!#acl", strlen("!#acl")))
	{
	    error = EINVAL;
	    goto exit;
	}

	/* field 2: <version>
	 * currently only accepts 1
	 */
	field = strsep(&entry, " ");
	errno = 0;
	if (!*field || strtol(field, NULL, 0) != 1)
	{
	    error = EINVAL;
	    goto exit;
	}

	/* field 3: <flags>
	 * optional
	 */
	if((field = strsep(&entry, " ")) != NULL && *field)
	{
	    acl_get_flagset_np(acl_ret, &flags);
	    while ((sub = strsep(&field, ",")) && *sub)
	    {
		for (i = 0; acl_flags[i].name != NULL; ++i)
		{
		    if (acl_flags[i].type & ACL_TYPE_ACL
			    && !strcmp(acl_flags[i].name, sub))
		    {
			acl_add_flag_np(flags, acl_flags[i].flag);
			break;
		    }
		}
		if (acl_flags[i].name == NULL)
		{
		    /* couldn't find flag */
		    error = EINVAL;
		    goto exit;
		}
	    }
	}
    } else {
	error = EINVAL;
	goto exit;
    }

    /* parse each acl line
     * format: <user|group>:
     *	    [<uuid>]:
     *	    [<user|group>]:
     *	    [<uid|gid>]:
     *	    <allow|deny>[,<flags>]
     *	    [:<permissions>[,<permissions>]]
     *
     * only one of the user/group identifies is required
     * the first one found is used
     */
    while ((entry = strsep(&buf, "\n")) && *entry)
    {
	need_tag = 1;
	ug_tag = -1;

	/* field 1: <user|group> */
	field = strsep(&entry, ":");

	if(uu)
	    bzero(uu, sizeof(uuid_t));
	else if((uu = calloc(1, sizeof(uuid_t))) == NULL)
	{
	    error = errno;
	    goto exit;
	}

	if(acl_create_entry(&acl_ret, &acl_entry))
	{
	    error = errno;
	    goto exit;
	}

	if (-1 == acl_get_flagset_np(acl_entry, &flags)
	 || -1 == acl_get_permset(acl_entry, &perms))
	{
	    error = errno;
	    goto exit;
	}

	switch(*field)
	{
	    case 'u':
		if(!strcmp(field, "user"))
		    ug_tag = ID_TYPE_UID;
		break;
	    case 'g':
		if(!strcmp(field, "group"))
		    ug_tag = ID_TYPE_GID;
		break;
	    default:
		error = EINVAL;
		goto exit;
	}

	/* field 2: <uuid> */
	if ((field = strsep(&entry, ":")) != NULL && *field)
	{
	    uuid_parse(field, *uu);
	    need_tag = 0;
	}

	/* field 3: <username|groupname> */
	if ((field = strsep(&entry, ":")) != NULL && *field && need_tag)
	{
	    switch(ug_tag)
	    {
		case ID_TYPE_UID:
		    if((tpass = getpwnam(field)) != NULL)
			if (mbr_uid_to_uuid(tpass->pw_uid, *uu) != 0)
			{
			    error = EINVAL;
			    goto exit;
			}
		    break;
		case ID_TYPE_GID:
		    if ((tgrp = getgrnam(field)) != NULL)
			if (mbr_gid_to_uuid(tgrp->gr_gid, *uu) != 0)
			{
			    error = EINVAL;
			    goto exit;
			}
		    break;
		default:
		    error = EINVAL;
		    goto exit;
	    }
	    need_tag = 0;
	}

	/* field 4: <uid|gid> */
	if ((field = strsep(&entry, ":")) != NULL && *field && need_tag)
	{
	    uid_t id;
	    error = 0;

	    if((id = strtol(field, NULL, 10)) == 0 && error)
	    {
		error = EINVAL;
		goto exit;
	    }

	    switch(ug_tag)
	    {
		case ID_TYPE_UID:
		    if((tpass = getpwuid((uid_t)id)) != NULL)
			if (mbr_uid_to_uuid(tpass->pw_uid, *uu) != 0)
			{
			    error = EINVAL;
			    goto exit;
			}
		    break;
		case ID_TYPE_GID:
		    if ((tgrp = getgrgid((gid_t)id)) != NULL)
			if (mbr_gid_to_uuid(tgrp->gr_gid, *uu) != 0)
			{
			    error = EINVAL;
			    goto exit;
			}
		    break;
	    }
	    need_tag = 0;
	}

	/* sanity check: nothing set as qualifier */
	if (need_tag)
	{
	    error = EINVAL;
	    goto exit;
	}

	/* field 5: <flags> */
	if((field = strsep(&entry, ":")) == NULL || !*field)
	{
	    error = EINVAL;
	    goto exit;
	}

	for (tag = 0; (sub = strsep(&field, ",")) && *sub;)
	{
	    if (!tag)
	    {
		if (!strcmp(sub, "allow"))
		    tag = ACL_EXTENDED_ALLOW;
		else if (!strcmp(sub, "deny"))
		    tag = ACL_EXTENDED_DENY;
		else {
		    error = EINVAL;
		    goto exit;
		}
		continue;
	    }

	    for (i = 0; acl_flags[i].name != NULL; ++i)
	    {
		if (acl_flags[i].type & (ACL_TYPE_FILE | ACL_TYPE_DIR)
			&& !strcmp(acl_flags[i].name, sub))
		{
		    acl_add_flag_np(flags, acl_flags[i].flag);
		    break;
		}
	    }
	    if (acl_flags[i].name == NULL)
	    {
		/* couldn't find perm */
		error = EINVAL;
		goto exit;
	    }
	}

	/* field 6: <perms> (can be empty) */
	if((field = strsep(&entry, ":")) != NULL && *field)
	{
	    while ((sub = strsep(&field, ",")) && *sub)
	    {
		for (i = 0; acl_perms[i].name != NULL; i++)
		{
		    if (acl_perms[i].type & (ACL_TYPE_FILE | ACL_TYPE_DIR)
			    && !strcmp(acl_perms[i].name, sub))
		    {
			acl_add_perm(perms, acl_perms[i].perm);
			break;
		    }
		}
		if (acl_perms[i].name == NULL)
		{
		    /* couldn't find perm */
		    error = EINVAL;
		    goto exit;
		}
	    }
	}
	acl_set_tag_type(acl_entry, tag);
	acl_set_qualifier(acl_entry, *uu);
    }
exit:
    if(uu)
	free(uu);
    free(orig_buf);
    if (error)
    {
	acl_free(acl_ret);
	acl_ret = NULL;
	errno = error;
    }
    return acl_ret;
}
Пример #13
0
/*
 * acl_from_text -- Convert a string into an ACL.
 * Postpone most validity checking until the end and call acl_valid() to do
 * that.
 */
acl_t
acl_from_text(const char *buf_p)
{
	acl_t		 acl;
	char		*mybuf_p, *line, *cur, *notcomment, *comment, *entry;
	int		 error;

	/* Local copy we can mess up. */
	mybuf_p = strdup(buf_p);
	if (mybuf_p == NULL)
		return(NULL);

	acl = acl_init(3); /* XXX: WTF, 3? */
	if (acl == NULL) {
		free(mybuf_p);
		return(NULL);
	}

	/* Outer loop: delimit at \n boundaries. */
	cur = mybuf_p;
	while ((line = strsep(&cur, "\n"))) {
		/* Now split the line on the first # to strip out comments. */
		comment = line;
		notcomment = strsep(&comment, "#");

		/* Inner loop: delimit at ',' boundaries. */
		while ((entry = strsep(&notcomment, ","))) {

			/* Skip empty lines. */
			if (strlen(string_skip_whitespace(entry)) == 0)
				continue;

			if (_acl_brand(acl) == ACL_BRAND_UNKNOWN) {
				if (_text_is_nfs4_entry(entry))
					_acl_brand_as(acl, ACL_BRAND_NFS4);
				else
					_acl_brand_as(acl, ACL_BRAND_POSIX);
			}

			switch (_acl_brand(acl)) {
			case ACL_BRAND_NFS4:
				error = _nfs4_acl_entry_from_text(acl, entry);
				break;

			case ACL_BRAND_POSIX:
				error = _posix1e_acl_entry_from_text(acl, entry);
				break;

			default:
				error = EINVAL;
				break;
			}

			if (error)
				goto error_label;
		}
	}

#if 0
	/* XXX Should we only return ACLs valid according to acl_valid? */
	/* Verify validity of the ACL we read in. */
	if (acl_valid(acl) == -1) {
		errno = EINVAL;
		goto error_label;
	}
#endif

	free(mybuf_p);
	return(acl);

error_label:
	acl_free(acl);
	free(mybuf_p);
	return(NULL);
}
Пример #14
0
int CheckDefaultClearACL(EvalContext *ctx, const char *file_path, Attributes a, const Promise *pp, PromiseResult *result)
{
    acl_t acl_existing;
    acl_t acl_empty;
    acl_entry_t ace_dummy;
    int retv;
    int retval = false;

    acl_existing = NULL;
    acl_empty = NULL;

    if ((acl_existing = acl_get_file(file_path, ACL_TYPE_DEFAULT)) == NULL)
    {
        Log(LOG_LEVEL_ERR, "Unable to read default acl for '%s'. (acl_get_file: %s)", file_path, GetErrorStr());
        return false;
    }

    retv = acl_get_entry(acl_existing, ACL_FIRST_ENTRY, &ace_dummy);

    switch (retv)
    {
    case -1:
        Log(LOG_LEVEL_VERBOSE, "Couldn't retrieve ACE for '%s'. (acl_get_entry: %s)", file_path, GetErrorStr());
        retval = false;
        break;

    case 0:                    // no entries, as desired
        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Default ACL on '%s' needs no modification.", file_path);
        retval = true;
        break;

    case 1:                    // entries exist, set empty ACL

        if ((acl_empty = acl_init(0)) == NULL)
        {
            Log(LOG_LEVEL_ERR, "Could not reinitialize ACL for '%s'. (acl_init: %s)", file_path, GetErrorStr());
            retval = false;
            break;
        }

        switch (a.transaction.action)
        {
        case cfa_warn:

            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Default ACL on '%s' needs to be cleared", file_path);
            *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN);
            break;

        case cfa_fix:

            if (!DONTDO)
            {
                if (acl_set_file(file_path, ACL_TYPE_DEFAULT, acl_empty) != 0)
                {
                    Log(LOG_LEVEL_ERR, "Could not reset ACL for %s", file_path);
                    retval = false;
                    break;
                }
            }

            cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Default ACL on '%s' successfully cleared", file_path);
            *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE);
            retval = true;

            break;

        default:
            ProgrammingError("CFEngine: internal error: illegal file action");
            retval = false;
        }

        break;

    default:
        retval = false;
    }

    acl_free(acl_empty);
    acl_free(acl_existing);
    return retval;
}
Пример #15
0
/* ------------------------------------------------------------------------- *\
 * FUNCTION main (argc, argv)                                                *
 * --------------------------                                                *
 * Goes over configured host-groups and fishes for hosts in /var/state/n2    *
 * for some summary information. Prints out the information either in a CSV  *
 * format (default), in XML (with -x) or as tabulated human-readable data    *
 * (with -f). An optional groupname argument will limit the scope of the     *
 * search to a single host-group.                                            *
\* ------------------------------------------------------------------------- */
int main (int argc, char *argv[])
{
	DIR *dir;
	struct dirent *de;
	FILE *fsumm;
	char *name;
	unsigned int addr;
	hostgroup *grp;
	int first=1;
	netload_rec *rec;
	hstat *info;
	unsigned long long netin, netout;
	int numwarn, numalert, numcrit;
	int rtt, count;
	int asxml;
	int ascsv;
	int asjson=0;
	int op;
	int firstmember=0;
	int firstgroup=1;
	char outline[256];
	char addrbuf[32];
	const char *groupname = NULL;
	ipnode *firstnode = NULL;
	ipnode *currentnode = NULL;
	ipnode *newnode = NULL;
	int isacked;
	
	asxml = 0;
	ascsv = 1;
	
	while ((op = getopt (argc, argv, "xfjg:")) > 0)
	{
		switch (op)
		{
			case 'x': asjson=0; asxml=1; ascsv=0; break;
			case 'f': asjson=0; ascsv=0; asxml=0; break;
			case 'j': asxml=0; ascsv=0; asjson=1; break;
			case 'g': groupname=optarg; break;
		}
	}
	
	conf_init ();
	acl_init ();
	load_config ("/etc/n2/n2rxd.conf");
	
	if (asxml)
	{
		printf ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
		printf ("<nl.madscience.svc.n2.groups>\n");
	}
	else if ((!ascsv)&&(!asjson))
	{
		printf ("Host              Status   Load      CPU    RTT   "
				"Loss  Net In/    Out     i/o\n");
				//                    Kb/s   "
	}
	else if (asjson)
	{
		printf ("{");
	}
	
	fsumm = fopen ("/var/state/n2/current/summary", "r");
	if (! fsumm)
	{
		fprintf (stderr, "%% Error loading summary file\n");
		return 1;
	}

	newnode = (ipnode *) malloc (sizeof (ipnode));

	while (fread (newnode, sizeof (hstat), 1, fsumm) > 0)
	{
		newnode->next = NULL;
		if (currentnode)
		{
			currentnode->next = newnode;
			currentnode = newnode;
		}
		else
		{
			currentnode = firstnode = newnode;
		}

		newnode = (ipnode *) malloc (sizeof (ipnode));
	}
	fclose (fsumm);
	free (newnode);

	grp = GROUPS.groups;
	
	while (grp)
	{
		if ((! groupname) || (! strcmp (groupname, grp->name)))
		{
			netin = netout = 0;
			numwarn = numalert = numcrit = rtt = count = 0;
			if (ascsv)
			{
				if (ascsv) printf ("%s:", grp->name);
			}
			else if (asjson)
			{
				if (firstgroup) firstgroup=0;
				else printf (",");
				printf ("\"%s\":{\"description\":\"%s\",\"members\":{",
						grp->name, grp->description);
				firstmember=1;
			}
			else if (asxml)
			{
				printf ("  <group name=\"%s\" description=\"%s\">\n",
											grp->name, grp->description);
				printf ("    <members>\n");
			}
			first = 1;
			currentnode = firstnode;
			while (currentnode)
			{
				addr = currentnode->st.addr;
				printip (addr, addrbuf);
				if (grp == hostgroup_acl_resolve (addr))
				{
					isacked = 0;
					if (asxml)
					{
						printf ("      <member ip=\"%s\"", addrbuf);
					}
					else if (asjson)
					{
						if (firstmember) firstmember=0;
						else printf (",");
						printf ("\"%s\":{", addrbuf);
					}
					else if (ascsv)
					{
						printf ("%s%s", first ? "" : " ", addrbuf);
					}
					first = 0;
					info = &(currentnode->st);
					if (info)
					{
						if (CHKOFLAG(info->oflags,OFLAG_ACKED))
						{
							// hide the flag, but keep it tracked.
							info->oflags ^= 1<<OFLAG_ACKED;
							isacked = 1;
						}
						else isacked = 0;
						if (asxml || asjson)
						{
							// FIXME@ koert: potential stack overflow here if error flags are added
							// or get longer names
							char flags[512];
							flags[0] = '\0';

							if( CHKSTATUSFLAG(info->status,FLAG_RTT) ) strcat(flags,", rtt");
							if( CHKSTATUSFLAG(info->status,FLAG_LOSS) ) strcat(flags,", loss");
							if( CHKSTATUSFLAG(info->status,FLAG_LOAD) ) strcat(flags,", load");
							if( CHKOFLAG(info->oflags,OFLAG_RAM) ) strcat(flags,", ram");
							if( CHKOFLAG(info->oflags,OFLAG_SWAP) ) strcat(flags,", swap");
							if( CHKOFLAG(info->oflags,OFLAG_NETIN) ) strcat(flags,", netin");
							if( CHKOFLAG(info->oflags,OFLAG_NETOUT) ) strcat(flags,", netout");
							if( CHKOFLAG(info->oflags,OFLAG_SVCDOWN) ) strcat(flags,", svcdown");
							if( CHKOFLAG(info->oflags,OFLAG_DISKIO) ) strcat(flags,", diskio");
							if( CHKOFLAG(info->oflags,OFLAG_DISKSPACE) ) strcat(flags,", diskspace");
							if( CHKOFLAG(info->oflags,OFLAG_DECODINGERR) ) strcat(flags,", decodingerr");
							if( CHKOFLAG(info->oflags,OFLAG_IOWAIT) ) strcat(flags,", iowait");
							// if( CHKSTATUSFLAG(info->status,FLAG_OTHER) ) strcat(flags,", other");

							if (asxml)
							{
								printf (" netin=\"%u\" netout=\"%u\" "
										"rtt=\"%.1f\" cpu=\"%.2f\" "
										"loadavg=\"%.2f\" status=\"%s\" "
										"diskio=\"%u\" flags=\"%s\" ",
										info->netin, info->netout,
										((double) info->ping10) / 10.0,
										((double) info->cpu) / 2.56,
										((double) info->load1) / 100.0,
										isacked ? "ACKED" : STR_STATUS[info->status & 15],
										info->diskio,
										*flags ? flags+2 : flags );
							}
							else
							{
								printf ("\"netin\":%u,", info->netin);
								printf ("\"netout\":%u,", info->netout);
								printf ("\"rtt\":%.1f,", ((double)info->ping10)/10.0);
								printf ("\"cpu\":%.2f,",((double) info->cpu)/2.56);
								printf ("\"loadavg\":%.2f,",((double)info->load1)/100.0);
								printf ("\"status\":\"%s\",",isacked?"ACKED":STR_STATUS[info->status&15]);
								printf ("\"diskio\":%u,",info->diskio);
								printf ("\"flags\":\"%s\"", *flags?flags+2:flags);
							}
						}
						else if (! ascsv)
						{
							sprintf (outline, "%-17s                  ",
									 addrbuf);
							sprintf (outline+18, "%s        ",
									 isacked ? "ACKED" : STR_STATUS[info->status&15]);
							if (info->status == ST_DEAD)
							{
								sprintf (outline+24, "   -.--   -.-- %% "
										 "%6.1f  %3i %%       -/      -"
										 "       -",
										 ((double)info->ping10) / 10.0,
										 info->loss/100
										);
							}
							else sprintf (outline+24, " %6.2f %6.2f %% "
									 "%6.1f  %3i %% %7i/%7i %7i",
									 ((double) info->load1) / 100.0,
									 ((double) info->cpu) / 2.56,
									 ((double) info->ping10) / 10.0,
									 info->loss/100,
									 info->netin, info->netout,
									 info->diskio);
									 
							printf ("%s\n", outline); 
						}
						netin += info->netin;
						netout += info->netout;
						rtt += info->ping10;
						if (ascsv)
						{
							switch (RDSTATUS(info->status))
							{
								case ST_WARNING:
									if (isacked) break;
									printf ("=WARNING");
									++numwarn; break;

								case ST_STALE:
								case ST_ALERT:
								case ST_DEAD:
									if (isacked) break;
									printf ("=ALERT");
									++numalert; break;

								case ST_CRITICAL:
									if (isacked) break;
									printf ("=CRITICAL");
									++numcrit; break;
								
								default:
									printf ("=OK");
									break;
							}
						}
						pool_free (info);
					}
					else
					{
						free (rec);
					}
					if (asxml) printf ("/>\n");
					if (asjson) printf ("}");
					++count;
				}
				currentnode = currentnode->next;
			}
			if (asjson)
			{
				printf ("},\"summary\":{");
				printf ("\"netin\":%u,", netin);
				printf ("\"netout\":%u,",netout);
				printf ("\"rtt\":%.1f,",((double)rtt/(10.0*((double)count))));
				printf ("\"counts.warning\":%i,", numwarn);
				printf ("\"counts.alert\":%i,", numalert);
				printf ("\"counts.critical\":%i", numcrit);
				printf ("}}");
			}
			else if (! asxml)
			{
				if (! count) count=1;
				if (ascsv)
				{
					printf (":%i:%llu:%llu:%.1f:%i:%i:%i\n",
							count, netin, netout,
							((double) rtt / (10.0 * ((double) count))),
							numwarn, numalert, numcrit);
				}
			}
			else if (! ascsv)
			{
				printf ("    </members>\n");
				printf ("    <summary>\n");
				printf ("      <netin>%u</netin>\n", netin);
				printf ("      <netout>%u</netout>\n", netout);
				printf ("      <rtt>%.1f</rtt>\n",
						((double) rtt / (10.0 * ((double) count))));
				printf ("      <counts.warning>%i</counts.warning>\n", numwarn);
				printf ("      <counts.alert>%i</counts.alert>\n", numalert);
				printf ("      <counts.critical>%i</counts.critical>\n",
						numcrit);
				printf ("    </summary>\n");
				printf ("  </group>\n");
			}
		}
		grp = grp->next;
	}
	if (asxml)
	{
		printf ("</nl.madscience.svc.n2.groups>\n");
	}
	if (asjson) printf ("}\n");
	exit(0);
}
Пример #16
0
int
do_set(
	const char *path_p,
	const struct stat *st,
	const seq_t seq)
{
	acl_t old_acl = NULL, old_default_acl = NULL;
	acl_t acl = NULL, default_acl = NULL;
	acl_t *xacl, *old_xacl;
	acl_entry_t ent;
	cmd_t cmd;
	int which_entry;
	int errors = 0, error;
	char *acl_text;
	int acl_modified = 0, default_acl_modified = 0;
	int acl_mask_provided = 0, default_acl_mask_provided = 0;

	/* Execute the commands in seq (read ACLs on demand) */
	error = seq_get_cmd(seq, SEQ_FIRST_CMD, &cmd);
	if (error == 0)
		return 0;
	while (error == 1) {
		if (cmd->c_type == ACL_TYPE_ACCESS) {
			xacl = &acl;
			old_xacl = &old_acl;
			acl_modified = 1;
			if (cmd->c_tag == ACL_MASK)
				acl_mask_provided = 1;
		} else {
			xacl = &default_acl;
			old_xacl = &old_default_acl;
			default_acl_modified = 1;
			if (cmd->c_tag == ACL_MASK)
				default_acl_mask_provided = 1;
		}

		RETRIEVE_ACL(cmd->c_type);

		/* Check for `X', and replace with `x' as appropriate. */
		if (cmd->c_perm & CMD_PERM_COND_EXECUTE) {
			cmd->c_perm &= ~CMD_PERM_COND_EXECUTE;
			if (S_ISDIR(st->st_mode) || has_execute_perms(*xacl))
				cmd->c_perm |= CMD_PERM_EXECUTE;
		}

		switch(cmd->c_cmd) {
			case CMD_ENTRY_REPLACE:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (!ent) {
					if (acl_create_entry(xacl, &ent) != 0)
						goto fail;
					acl_set_tag_type(ent, cmd->c_tag);
					if (cmd->c_id != ACL_UNDEFINED_ID)
						acl_set_qualifier(ent,
								  &cmd->c_id);
				}
				set_perm(ent, cmd->c_perm, ~cmd->c_perm);
				break;

			case CMD_ENTRY_ADD:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (ent)
					set_perm(ent, cmd->c_perm, 0);
				break;

			case CMD_ENTRY_SUBTRACT:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (ent)
					set_perm(ent, 0, cmd->c_perm);
				break;

			case CMD_REMOVE_ENTRY:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (ent)
					acl_delete_entry(*xacl, ent);
				else
					/* ignore */;
				break;

			case CMD_REMOVE_EXTENDED_ACL:
				remove_extended_entries(acl);
				break;

			case CMD_REMOVE_ACL:
				acl_free(*xacl);
				*xacl = acl_init(5);
				if (!*xacl)
					goto fail;
				break;

			default:
				errno = EINVAL;
				goto fail;
		}

		error = seq_get_cmd(seq, SEQ_NEXT_CMD, &cmd);
	}

	if (error < 0)
		goto fail;

	/* Try to fill in missing entries */
	if (default_acl && acl_entries(default_acl) != 0) {
		xacl = &acl;
		old_xacl = &old_acl;
	
		if (!find_entry(default_acl, ACL_USER_OBJ, ACL_UNDEFINED_ID)) {
			if (!acl)
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
			clone_entry(acl, ACL_USER_OBJ,
			            &default_acl, ACL_USER_OBJ);
		}
		if (!find_entry(default_acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) {
			if (!acl)
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
			clone_entry(acl, ACL_GROUP_OBJ,
			            &default_acl, ACL_GROUP_OBJ);
		}
		if (!find_entry(default_acl, ACL_OTHER, ACL_UNDEFINED_ID)) {
			if (!acl)
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
			clone_entry(acl, ACL_OTHER,
			            &default_acl, ACL_OTHER);
		}
	}

	/* update mask entries and check if ACLs are valid */
	if (acl && acl_modified) {
		if (acl_equiv_mode(acl, NULL) != 0) {
			if (!acl_mask_provided &&
			    !find_entry(acl, ACL_MASK, ACL_UNDEFINED_ID))
				clone_entry(acl, ACL_GROUP_OBJ,
				            &acl, ACL_MASK);
			if (opt_recalculate != -1 &&
			    (!acl_mask_provided || opt_recalculate == 1))
				acl_calc_mask(&acl);
		}

		error = acl_check(acl, &which_entry);
		if (error < 0)
			goto fail;
		if (error > 0) {
			acl_text = acl_to_any_text(acl, NULL, ',', 0);
			fprintf(stderr, gettext("%s: %s: Malformed access ACL "
				"`%s': %s at entry %d\n"), progname, path_p,
				acl_text, acl_error(error), which_entry+1);
			acl_free(acl_text);
			errors++;
			goto cleanup;
		}
	}

	if (default_acl && acl_entries(default_acl) != 0 &&
	    default_acl_modified) {
		if (acl_equiv_mode(default_acl, NULL) != 0) {
			if (!default_acl_mask_provided &&
			    !find_entry(default_acl,ACL_MASK,ACL_UNDEFINED_ID))
				clone_entry(default_acl, ACL_GROUP_OBJ,
				            &default_acl, ACL_MASK);
			if (opt_recalculate != -1 &&
			    (!default_acl_mask_provided ||
			     opt_recalculate == 1))
				acl_calc_mask(&default_acl);
		}

		error = acl_check(default_acl, &which_entry);
		if (error < 0)
			goto fail;
		if (error > 0) {
			acl_text = acl_to_any_text(default_acl, NULL, ',', 0);
			fprintf(stderr, gettext("%s: %s: Malformed default ACL "
			                  "`%s': %s at entry %d\n"),
				progname, path_p, acl_text,
				acl_error(error), which_entry+1);
			acl_free(acl_text);
			errors++;
			goto cleanup;
		}
	}

	/* Only directores can have default ACLs */
	if (default_acl && !S_ISDIR(st->st_mode) && opt_recursive) {
		/* In recursive mode, ignore default ACLs for files */
		acl_free(default_acl);
		default_acl = NULL;
	}

	/* check which ACLs have changed */
	if (acl && old_acl && acl_cmp(old_acl, acl) == 0) {
		acl_free(acl);
		acl = NULL;
	}
	if ((default_acl && old_default_acl &&
	    acl_cmp(old_default_acl, default_acl) == 0)) {
		acl_free(default_acl);
		default_acl = NULL;
	}

	/* update the file system */
	if (opt_test) {
		print_test(stdout, path_p, st,
		           acl, default_acl);
		goto cleanup;
	}
	if (acl) {
		if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) != 0) {
			if (errno == ENOSYS || errno == ENOTSUP) {
				int saved_errno = errno;
				mode_t mode;

				if (acl_equiv_mode(acl, &mode) != 0) {
					errno = saved_errno;
					goto fail;
				} else if (chmod(path_p, mode) != 0)
					goto fail;
			} else
				goto fail;
		}
	}
	if (default_acl) {
		if (S_ISDIR(st->st_mode)) {
			if (acl_entries(default_acl) == 0) {
				if (acl_delete_def_file(path_p) != 0 &&
				    errno != ENOSYS && errno != ENOTSUP)
					goto fail;
			} else {
				if (acl_set_file(path_p, ACL_TYPE_DEFAULT,
						 default_acl) != 0)
					goto fail;
			}
		} else {
			if (acl_entries(default_acl) != 0) {
				fprintf(stderr, gettext(
						"%s: %s: Only directories "
						"can have default ACLs\n"),
					progname, path_p);
				errors++;
				goto cleanup;
			}
		}
	}

	error = 0;

cleanup:
	if (acl)
		acl_free(acl);
	if (old_acl)
		acl_free(old_acl);
	if (default_acl)
		acl_free(default_acl);
	if (old_default_acl)
		acl_free(old_default_acl);
	return errors;
	
fail:
	fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno));
	errors++;
	goto cleanup;
}
Пример #17
0
void acl_cpp_init(void)
{
	acl_init();
}
Пример #18
0
static int
set_acl(struct archive *a, int fd, const char *name,
        struct archive_acl *abstract_acl,
        acl_type_t acl_type, int ae_requested_type, const char *tname)
{
    acl_t		 acl;
    acl_entry_t	 acl_entry;
    acl_permset_t	 acl_permset;
#ifdef ACL_TYPE_NFS4
    acl_flagset_t	 acl_flagset;
    int		 r;
#endif
    int		 ret;
    int		 ae_type, ae_permset, ae_tag, ae_id;
    uid_t		 ae_uid;
    gid_t		 ae_gid;
    const char	*ae_name;
    int		 entries;
    int		 i;

    ret = ARCHIVE_OK;
    entries = archive_acl_reset(abstract_acl, ae_requested_type);
    if (entries == 0)
        return (ARCHIVE_OK);
    acl = acl_init(entries);
    while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
                            &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
        acl_create_entry(&acl, &acl_entry);

        switch (ae_tag) {
        case ARCHIVE_ENTRY_ACL_USER:
            acl_set_tag_type(acl_entry, ACL_USER);
            ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
            acl_set_qualifier(acl_entry, &ae_uid);
            break;
        case ARCHIVE_ENTRY_ACL_GROUP:
            acl_set_tag_type(acl_entry, ACL_GROUP);
            ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
            acl_set_qualifier(acl_entry, &ae_gid);
            break;
        case ARCHIVE_ENTRY_ACL_USER_OBJ:
            acl_set_tag_type(acl_entry, ACL_USER_OBJ);
            break;
        case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
            acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
            break;
        case ARCHIVE_ENTRY_ACL_MASK:
            acl_set_tag_type(acl_entry, ACL_MASK);
            break;
        case ARCHIVE_ENTRY_ACL_OTHER:
            acl_set_tag_type(acl_entry, ACL_OTHER);
            break;
#ifdef ACL_TYPE_NFS4
        case ARCHIVE_ENTRY_ACL_EVERYONE:
            acl_set_tag_type(acl_entry, ACL_EVERYONE);
            break;
#endif
        default:
            /* XXX */
            break;
        }

#ifdef ACL_TYPE_NFS4
        switch (ae_type) {
        case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
            acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
            break;
        case ARCHIVE_ENTRY_ACL_TYPE_DENY:
            acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
            break;
        case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
            acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
            break;
        case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
            acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
            break;
        case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
        case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
            // These don't translate directly into the system ACL.
            break;
        default:
            // XXX error handling here.
            break;
        }
#endif

        acl_get_permset(acl_entry, &acl_permset);
        acl_clear_perms(acl_permset);

        for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
            if (ae_permset & acl_perm_map[i].archive_perm)
                acl_add_perm(acl_permset,
                             acl_perm_map[i].platform_perm);
        }

#ifdef ACL_TYPE_NFS4
        // XXX acl_get_flagset_np on FreeBSD returns EINVAL for
        // non-NFSv4 ACLs
        r = acl_get_flagset_np(acl_entry, &acl_flagset);
        if (r == 0) {
            acl_clear_flags_np(acl_flagset);
            for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
                if (ae_permset & acl_inherit_map[i].archive_inherit)
                    acl_add_flag_np(acl_flagset,
                                    acl_inherit_map[i].platform_inherit);
            }
        }
#endif
    }

    /* Try restoring the ACL through 'fd' if we can. */
#if HAVE_ACL_SET_FD
    if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0)
        ret = ARCHIVE_OK;
    else
#else
#if HAVE_ACL_SET_FD_NP
    if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0)
        ret = ARCHIVE_OK;
    else
#endif
#endif
#if HAVE_ACL_SET_LINK_NP
        if (acl_set_link_np(name, acl_type, acl) != 0) {
            archive_set_error(a, errno, "Failed to set %s acl", tname);
            ret = ARCHIVE_WARN;
        }
#else
        /* TODO: Skip this if 'name' is a symlink. */
        if (acl_set_file(name, acl_type, acl) != 0) {
            archive_set_error(a, errno, "Failed to set %s acl", tname);
            ret = ARCHIVE_WARN;
        }
#endif
    acl_free(acl);
    return (ret);
}
Пример #19
0
int
qset_acl (char const *name, int desc, mode_t mode)
{
#if USE_ACL
# if HAVE_ACL_GET_FILE
  /* POSIX 1003.1e draft 17 (abandoned) specific version.  */
  /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */
#  if MODE_INSIDE_ACL
  /* Linux, FreeBSD, IRIX, Tru64 */

  /* We must also have acl_from_text and acl_delete_def_file.
     (acl_delete_def_file could be emulated with acl_init followed
      by acl_set_file, but acl_set_file with an empty acl is
      unspecified.)  */

#   ifndef HAVE_ACL_FROM_TEXT
#    error Must have acl_from_text (see POSIX 1003.1e draft 17).
#   endif
#   ifndef HAVE_ACL_DELETE_DEF_FILE
#    error Must have acl_delete_def_file (see POSIX 1003.1e draft 17).
#   endif

  acl_t acl;
  int ret;

  if (HAVE_ACL_FROM_MODE) /* Linux */
    {
      acl = acl_from_mode (mode);
      if (!acl)
        return -1;
    }
  else /* FreeBSD, IRIX, Tru64 */
    {
      /* If we were to create the ACL using the functions acl_init(),
         acl_create_entry(), acl_set_tag_type(), acl_set_qualifier(),
         acl_get_permset(), acl_clear_perm[s](), acl_add_perm(), we
         would need to create a qualifier.  I don't know how to do this.
         So create it using acl_from_text().  */

#   if HAVE_ACL_FREE_TEXT /* Tru64 */
      char acl_text[] = "u::---,g::---,o::---,";
#   else /* FreeBSD, IRIX */
      char acl_text[] = "u::---,g::---,o::---";
#   endif

      if (mode & S_IRUSR) acl_text[ 3] = 'r';
      if (mode & S_IWUSR) acl_text[ 4] = 'w';
      if (mode & S_IXUSR) acl_text[ 5] = 'x';
      if (mode & S_IRGRP) acl_text[10] = 'r';
      if (mode & S_IWGRP) acl_text[11] = 'w';
      if (mode & S_IXGRP) acl_text[12] = 'x';
      if (mode & S_IROTH) acl_text[17] = 'r';
      if (mode & S_IWOTH) acl_text[18] = 'w';
      if (mode & S_IXOTH) acl_text[19] = 'x';

      acl = acl_from_text (acl_text);
      if (!acl)
        return -1;
    }
  if (HAVE_ACL_SET_FD && desc != -1)
    ret = acl_set_fd (desc, acl);
  else
    ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
  if (ret != 0)
    {
      int saved_errno = errno;
      acl_free (acl);

      if (ACL_NOT_WELL_SUPPORTED (errno))
        return chmod_or_fchmod (name, desc, mode);
      else
        {
          errno = saved_errno;
          return -1;
        }
    }
  else
    acl_free (acl);

  if (S_ISDIR (mode) && acl_delete_def_file (name))
    return -1;

  if (mode & (S_ISUID | S_ISGID | S_ISVTX))
    {
      /* We did not call chmod so far, so the special bits have not yet
         been set.  */
      return chmod_or_fchmod (name, desc, mode);
    }
  return 0;

#  else /* !MODE_INSIDE_ACL */
  /* MacOS X */

#   if !HAVE_ACL_TYPE_EXTENDED
#    error Must have ACL_TYPE_EXTENDED
#   endif

  /* On MacOS X,  acl_get_file (name, ACL_TYPE_ACCESS)
     and          acl_get_file (name, ACL_TYPE_DEFAULT)
     always return NULL / EINVAL.  You have to use
                  acl_get_file (name, ACL_TYPE_EXTENDED)
     or           acl_get_fd (open (name, ...))
     to retrieve an ACL.
     On the other hand,
                  acl_set_file (name, ACL_TYPE_ACCESS, acl)
     and          acl_set_file (name, ACL_TYPE_DEFAULT, acl)
     have the same effect as
                  acl_set_file (name, ACL_TYPE_EXTENDED, acl):
     Each of these calls sets the file's ACL.  */

  acl_t acl;
  int ret;

  /* Remove the ACL if the file has ACLs.  */
  if (HAVE_ACL_GET_FD && desc != -1)
    acl = acl_get_fd (desc);
  else
    acl = acl_get_file (name, ACL_TYPE_EXTENDED);
  if (acl)
    {
      acl_free (acl);

      acl = acl_init (0);
      if (acl)
        {
          if (HAVE_ACL_SET_FD && desc != -1)
            ret = acl_set_fd (desc, acl);
          else
            ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl);
          if (ret != 0)
            {
              int saved_errno = errno;

              acl_free (acl);

              if (ACL_NOT_WELL_SUPPORTED (saved_errno))
                return chmod_or_fchmod (name, desc, mode);
              else
                {
                  errno = saved_errno;
                  return -1;
                }
            }
          acl_free (acl);
        }
    }

  /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly.  */
  return chmod_or_fchmod (name, desc, mode);
#  endif

# elif HAVE_ACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */

#  if defined ACL_NO_TRIVIAL
  /* Solaris 10 (newer version), which has additional API declared in
     <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
     acl_fromtext, ...).  */

  acl_t *aclp;
  char acl_text[] = "user::---,group::---,mask:---,other:---";
  int ret;
  int saved_errno;

  if (mode & S_IRUSR) acl_text[ 6] = 'r';
  if (mode & S_IWUSR) acl_text[ 7] = 'w';
  if (mode & S_IXUSR) acl_text[ 8] = 'x';
  if (mode & S_IRGRP) acl_text[17] = acl_text[26] = 'r';
  if (mode & S_IWGRP) acl_text[18] = acl_text[27] = 'w';
  if (mode & S_IXGRP) acl_text[19] = acl_text[28] = 'x';
  if (mode & S_IROTH) acl_text[36] = 'r';
  if (mode & S_IWOTH) acl_text[37] = 'w';
  if (mode & S_IXOTH) acl_text[38] = 'x';

  if (acl_fromtext (acl_text, &aclp) != 0)
    {
      errno = ENOMEM;
      return -1;
    }

  ret = (desc < 0 ? acl_set (name, aclp) : facl_set (desc, aclp));
  saved_errno = errno;
  acl_free (aclp);
  if (ret < 0)
    {
      if (saved_errno == ENOSYS || saved_errno == EOPNOTSUPP)
        return chmod_or_fchmod (name, desc, mode);
      errno = saved_errno;
      return -1;
    }

  if (mode & (S_ISUID | S_ISGID | S_ISVTX))
    {
      /* We did not call chmod so far, so the special bits have not yet
         been set.  */
      return chmod_or_fchmod (name, desc, mode);
    }
  return 0;

#  else /* Solaris, Cygwin, general case */

#   ifdef ACE_GETACL
  /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
     file systems (whereas the other ones are used in UFS file systems).  */

  /* The flags in the ace_t structure changed in a binary incompatible way
     when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
     How to distinguish the two conventions at runtime?
     We fetch the existing ACL.  In the old convention, usually three ACEs have
     a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400.
     In the new convention, these values are not used.  */
  int convention;

  {
    int count;
    ace_t *entries;

    for (;;)
      {
        if (desc != -1)
          count = facl (desc, ACE_GETACLCNT, 0, NULL);
        else
          count = acl (name, ACE_GETACLCNT, 0, NULL);
        if (count <= 0)
          {
            convention = -1;
            break;
          }
        entries = (ace_t *) malloc (count * sizeof (ace_t));
        if (entries == NULL)
          {
            errno = ENOMEM;
            return -1;
          }
        if ((desc != -1
             ? facl (desc, ACE_GETACL, count, entries)
             : acl (name, ACE_GETACL, count, entries))
            == count)
          {
            int i;

            convention = 0;
            for (i = 0; i < count; i++)
              if (entries[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_OTHER))
                {
                  convention = 1;
                  break;
                }
            free (entries);
            break;
          }
        /* Huh? The number of ACL entries changed since the last call.
           Repeat.  */
        free (entries);
      }
  }

  if (convention >= 0)
    {
      ace_t entries[3];
      int ret;

      if (convention)
        {
          /* Running on Solaris 10.  */
          entries[0].a_type = ALLOW;
          entries[0].a_flags = ACE_OWNER;
          entries[0].a_who = 0; /* irrelevant */
          entries[0].a_access_mask = (mode >> 6) & 7;
          entries[1].a_type = ALLOW;
          entries[1].a_flags = ACE_GROUP;
          entries[1].a_who = 0; /* irrelevant */
          entries[1].a_access_mask = (mode >> 3) & 7;
          entries[2].a_type = ALLOW;
          entries[2].a_flags = ACE_OTHER;
          entries[2].a_who = 0;
          entries[2].a_access_mask = mode & 7;
        }
      else
        {