Beispiel #1
0
gboolean
mdm_common_is_action_available (gchar *action)
{
	gchar **allowsyscmd = NULL;
	const gchar *allowsyscmdval;
	gboolean ret = FALSE;
	int i;

	allowsyscmdval = mdm_config_get_string (MDM_KEY_SYSTEM_COMMANDS_IN_MENU);
	if (allowsyscmdval)
		allowsyscmd = g_strsplit (allowsyscmdval, ";", 0);

	if (allowsyscmd) {
		for (i = 0; allowsyscmd[i] != NULL; i++) {
			if (strcmp (allowsyscmd[i], action) == 0) {
				ret = TRUE;
				break;
			}
		}
	}

#ifdef HAVE_CHKAUTHATTR
	if (ret == TRUE) {
		gchar **rbackeys = NULL;
		const gchar *rbackeysval;
		const char *mdmuser;

		mdmuser     = mdm_config_get_string (MDM_KEY_USER);
		rbackeysval = mdm_config_get_string (MDM_KEY_RBAC_SYSTEM_COMMAND_KEYS);
		if (rbackeysval)
			rbackeys = g_strsplit (rbackeysval, ";", 0);

		if (rbackeys) {
			for (i = 0; rbackeys[i] != NULL; i++) {
				gchar **rbackey = g_strsplit (rbackeys[i], ":", 2);

				if (mdm_vector_len (rbackey) == 2 &&
				    ! ve_string_empty (rbackey[0]) &&
				    ! ve_string_empty (rbackey[1]) &&
				    strcmp (rbackey[0], action) == 0) {

					if (!chkauthattr (rbackey[1], mdmuser)) {
						g_strfreev (rbackey);
						ret = FALSE;
						break;
					}
				}
				g_strfreev (rbackey);
			}
		}
		g_strfreev (rbackeys);
	}
#endif
	g_strfreev (allowsyscmd);

	return ret;
}
Beispiel #2
0
static boolean_t
smbadm_checkauth(const char *auth)
{
	struct passwd *pw;

	if ((pw = getpwuid(getuid())) == NULL)
		return (B_FALSE);

	if (chkauthattr(auth, pw->pw_name) == 0)
		return (B_FALSE);

	return (B_TRUE);
}
Beispiel #3
0
/*
 * check_auth()
 *
 *	Perform an RBAC authorization check.
 */
static int
check_auth(ucred_t *ucred, const char *auth)
{
    struct passwd	pwd;
    uid_t		euid;
    char		buf[MAXPATHLEN];

    euid = ucred_geteuid(ucred);

    if ((getpwuid_r(euid, &pwd, buf, sizeof (buf)) == NULL) ||
            (chkauthattr(auth, pwd.pw_name) == 0)) {
        log_info("Unauthorized door call.\n");
        return (-1);
    }

    return (0);
}
/*
 * pm_poweroff - similar to poweroff(1M)
 * This should do the same auditing as poweroff(1m) would do when it
 * becomes a libpower function.  Till then we use poweroff(1m).
 */
static void
pm_poweroff(void)
{
	if (chkauthattr(AUTHNAME_SHUTDOWN, user) != 1) {
		(void) printf(gettext("User %s does not have correct "
		    "authorizations to shutdown this machine.\n"), user);
		exit(1);
	}
	openlog("suspend", 0, LOG_DAEMON);
	syslog(LOG_NOTICE, "System is being shut down.");
	closelog();

	/*
	 * Call poweroff(1m) to shut down the system.
	 */
	(void) execl("/usr/sbin/poweroff", "poweroff", NULL);

}
Beispiel #5
0
/*
 * vs_stats_check_auth
 *
 * Returns: 0 caller authorized to reset stats
 *         -1 caller not authorized to reset stats
 */
static int
vs_stats_check_auth()
{
	ucred_t *uc = NULL;
	uid_t uid;
	struct passwd *pw;

	if (door_ucred(&uc) != 0)
		return (-1);

	if (((uid = ucred_getsuid(uc)) == (uid_t)-1) ||
	    ((pw = getpwuid(uid)) == NULL) ||
	    (chkauthattr(VS_VALUE_AUTH, pw->pw_name) != 1)) {
		ucred_free(uc);
		return (-1);
	}

	ucred_free(uc);
	return (0);
}
Beispiel #6
0
int
check_auth(uid_t uid)
{
	struct passwd *pw;


	pw = getpwuid(uid);

	if (pw == NULL) {
		/* fail if we cannot get password entry */
		return (0);
	}

	/*
	 * check in the RBAC authority files to see if
	 * the user has permission to use CDRW
	 */
	if (chkauthattr(CDRW_AUTH, pw->pw_name) != 1) {
		/* user is not in database, return failure */
		return (0);
	} else {
		return (1);
	}
}
Beispiel #7
0
int
main(int argc, char *argv[], char *envp[])
{
	struct passwd *pw = getpwuid(getuid());
	char **newargv;
	int j;

	if (pw && chkauthattr(MAILQ_AUTH, pw->pw_name)) {
		/* The extra 2 is 1 for the "-bp" + 1 for the terminator. */
		newargv = (char **)malloc((argc + 2) * sizeof (char *));
		if (newargv == NULL)
			exit(EX_UNAVAILABLE);
		newargv[0] = _PATH_SENDMAIL_BIN;
		newargv[1] = "-bp";
		for (j = 1; j <= argc; j++)
			newargv[j + 1] = argv[j];
		(void) execve(_PATH_SENDMAIL_BIN, newargv, envp);
		perror("Cannot exec " _PATH_SENDMAIL_BIN);
		exit(EX_OSERR);
	}
	(void) fputs("No authorization to run mailq; "
	    "see mailq(1) for details.\n", stderr);
	return (EX_NOPERM);
}
Beispiel #8
0
/* ARGSUSED */
void
ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp,
    uint_t n_desc)
{
	ipmgmt_door_info_t	*infop = NULL;
	ipmgmt_retval_t		retval;
	int			i;
	uint_t			err;
	ucred_t			*cred = NULL;

	for (i = 0; i_ipmgmt_door_info_tbl[i].idi_cmd != 0; i++) {
		if (i_ipmgmt_door_info_tbl[i].idi_cmd ==
		    ((ipmgmt_arg_t *)(void *)argp)->ia_cmd) {
			infop = &i_ipmgmt_door_info_tbl[i];
			break;
		}
	}

	if (infop == NULL) {
		ipmgmt_log(LOG_ERR, "Invalid door command specified");
		err = EINVAL;
		goto fail;
	}

	/* check for solaris.network.interface.config authorization */
	if (infop->idi_set) {
		uid_t		uid;
		struct passwd	pwd;
		char		buf[1024];

		if (door_ucred(&cred) != 0) {
			err = errno;
			ipmgmt_log(LOG_ERR, "Could not get user credentials.");
			goto fail;
		}
		uid = ucred_getruid(cred);
		if ((int)uid < 0) {
			err = errno;
			ipmgmt_log(LOG_ERR, "Could not get user id.");
			goto fail;
		}
		if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) ==
		    NULL) {
			err = errno;
			ipmgmt_log(LOG_ERR, "Could not get password entry.");
			goto fail;
		}
		if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH,
		    pwd.pw_name) != 1) {
			err = EPERM;
			ipmgmt_log(LOG_ERR, "Not authorized for operation.");
			goto fail;
		}
		ucred_free(cred);
	}

	/* individual handlers take care of calling door_return */
	infop->idi_handler((void *)argp);
	return;
fail:
	ucred_free(cred);
	retval.ir_err = err;
	(void) door_return((char *)&retval, sizeof (retval), NULL, 0);
}
int
main(int argc, char **argv)
{
	int		c;
	char		display_name[MAXNAMELEN + 9] = "DISPLAY=";
	char		xauthority[MAXPATHLEN + 12] = "XAUTHORITY=";
	struct passwd 	*pw;

	(void) signal(SIGHUP, SIG_IGN);
	(void) signal(SIGINT, SIG_IGN);
	(void) signal(SIGQUIT, SIG_IGN);
	(void) signal(SIGTSTP, SIG_IGN);
	(void) signal(SIGTTIN, SIG_IGN);
	(void) signal(SIGTTOU, SIG_IGN);

	/*
	 * If suspend is invoked from a daemon (case 1 above), it
	 * will not have a working stdin, stdout and stderr. We need
	 * these to print proper error messages and possibly get user
	 * input. We attach them to console and hope that attachment
	 * works.
	 */
	if (ttyname(0) == NULL) {
		no_tty = 1;
		(void) dup2(open("/dev/console", O_RDONLY), 0);
		(void) dup2(open("/dev/console", O_WRONLY), 1);
		(void) dup2(open("/dev/console", O_WRONLY), 2);
	}

	while ((c = getopt(argc, argv, "fnxhtd:")) != EOF) {
		switch (c) {
			case 'f':
				/*
				 * Force machine to poweroff if
				 * suspend fails
				 */
				flags |= FORCE;
				break;
			case 'n':
				/* No warning popups - Obsolete */
				flags |= NO_WARN;
				break;
			case 'x':
				/* Don't try to screenlock */
				flags |= NO_XLOCK;
				break;
			case 'h':
				/* Do a shutdown instead of suspend */
				flags |= SHUTDOWN;
				break;
			case 'd':
				/* Needswork */
				/* Set the DISPLAY value in the environment */
				if (strlen(optarg) >= MAXNAMELEN) {
					(void) printf(gettext("Error: "
					    "display name is too long.\n"));
					return (1);
				}
				(void) strcat(display_name, optarg);
				if (putenv(display_name) != 0) {
					(void) printf(gettext("Error: "
					    "unable to set DISPLAY "
					    "environment variable.\n"));
					return (1);
				}
				break;
			case 't':
				/* Test, don't actually do any operation */
				flags |= TEST;
				break;
			default:
				(void) printf(gettext("USAGE: suspend "
				    "[-fnxh] [-d <display>]\n"));
				return (1);
		}
	}

	/*
	 * The action of pressing power key and power button on a MOU-3 machine
	 * causes suspend being invoked with SYSSUSPENDDODEFAULT
	 * enviromental variable set - indicating the default action is machine
	 * dependent: for MOU-3 type machine, "LowPower" mode is the default,
	 * for all the rest, "Suspend" is the default.  Existing suspend
	 * flags works the same.
	 */
	if (getenv("SYSSUSPENDDODEFAULT"))
		if (is_mou3())
			flags |= LOWPOWER;

	if ((flags & FORCE) && (flags & LOWPOWER))
		flags &= ~LOWPOWER;

	/*
	 * Flag "-h" overrides flag "-f".
	 */
	if ((flags & SHUTDOWN) && (flags & FORCE))
		flags &= ~(FORCE | LOWPOWER);

	if (flags & FORCE)
		flags |= NO_WARN;

	/*
	 * Check initally if the user has the authorizations to
	 * do either a suspend or shutdown.  pm_suspend() will also
	 * make this test, so we could defer till then, but if we
	 * do it now, we at least prevent a lot of unneeded setup.
	 */
	pw = getpwuid(getuid());
	(void) strncpy(user, pw->pw_name, NMAX);

	if ((flags & (FORCE|SHUTDOWN)) &&
	    (chkauthattr(AUTHNAME_SHUTDOWN, pw->pw_name) != 1)) {
		(void) printf(gettext("User does not have correct "
		    "authorizations to shutdown the machine.\n"));
		exit(1);
	}
	if (!(flags & SHUTDOWN) &&
	    (chkauthattr(AUTHNAME_SUSPEND, pw->pw_name) != 1)) {
		(void) printf(gettext("User does not have correct "
		    "authorizations to suspend.\n"));
		exit(1);
	}

	/*
	 * If we are only shutting down, there isn't much to do, just
	 * call pm_poweroff(), and let it do all the work.
	 */
	if (flags & SHUTDOWN) {
		/*
		 * pm_poweroff either powers off or exits,
		 * so there is no return.
		 */
		if (flags & TEST) {
			(void) printf("TEST: This machine would have "
			    "powered off\n");
			exit(1);
		} else {
			pm_poweroff();
		}
		/* NOTREACHED */
	}

	/*
	 * If XAUTHORITY environment variable is not set, try to set
	 * one up.
	 */
	if (getenv("XAUTHORITY") == NULL)
		(void) putenv(get_xauthority(xauthority));

	/*
	 * In case of "suspend" being called from daemon "powerd",
	 * signal SIGALRM is blocked so use "sigset()" instead of "signal()".
	 */
	(void) sigset(SIGALRM, alarm_handler);

	/* Call the "suspend" function to do the last of the work */
	pm_suspend();

	if (refresh_dt() == -1) {
		(void) printf("%s: Failed to refresh screen.\n", argv[0]);
		return (1);
	}
	return (0);
}
Beispiel #10
0
/*
 * This entry point _should_ be the common entry to suspend.  It is in
 * it's entirety here, but would be best moved to libpower when that
 * is available.
 */
static void
pm_suspend(void)
{
	int			cprarg = AD_SUSPEND;
	enum adt_uadmin_fcn	fcn_id = ADT_FCN;
	au_event_t		event_id = ADT_uadmin_freeze;
	adt_event_data_t	*event = NULL; /* event to be generated */
	adt_session_data_t	*ah = NULL;  /* audit session handle */

	/*
	 * Does the user have permission to use this command?
	 */
	if (chkauthattr(AUTHNAME_SUSPEND, user) != 1) {
		(void) printf(gettext("User %s does not have correct "
		    "authorizations to suspend this machine.\n"), user);
		exit(1);
	}

	if (flags & LOWPOWER) {
		if (bringto_lowpower() == -1) {
			(void) printf(gettext("LowPower Failed\n"));
			exit(1);
		}
	} else if (flags & TEST) {
		/*
		 * Test mode, do checks as if a real suspend, but
		 * don't actually do the suspend.
		 */
		/* Check if suspend is supported */
		if (pm_check_suspend() == -1) {
			suspend_error(errno);
		}

		(void) printf(gettext("TEST: Suspend would have been"
		    " performed\n"));

	} else {
		/* Check if suspend is supported */
		if (pm_check_suspend() == -1) {
			suspend_error(errno);
		}

		/*
		 * We are about to suspend this machine, try and
		 * lock the screen.  We don't really care if this
		 * succeeds or not, but that we actually tried. We
		 * also know that we have sufficient privileges to
		 * be here, so we lock the screen now, even if
		 * suspend actually fails.
		 * Note that garbage is sometimes displayed, and
		 * we don't really care about it, so we toss all
		 * text response.
		 * it would also be good if there were another option
		 * instead of launcing a file, as the disk might be
		 * spun down if we are suspending due to idle.
		 */
		if (!(flags & NO_XLOCK)) {
			(void) system("/usr/bin/xdg-screensaver lock "
			    " >/dev/null 2>&1");
		}

		/* Time to do the actual deed!  */
		/*
		 * Before we actually suspend, we need to audit and
		 * "suspend" the audit files.
		 */
		/* set up audit session and event */
		if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) == 0) {
			if ((event = adt_alloc_event(ah, event_id)) != NULL) {
				event->adt_uadmin_freeze.fcn = fcn_id;
				event->adt_uadmin_freeze.mdep = NULL;
				if (adt_put_event(event, ADT_SUCCESS, 0) != 0) {
					(void) fprintf(stderr, gettext(
					    "%s: can't put audit event\n"),
					    argvl[0]);
				} else {
					wait_for_auqueue();
				}
			}
			(void) change_audit_file();
		} else {
			(void) fprintf(stderr, gettext(
			    "%s: can't start audit session\n"), argvl[0]);
		}

		if (uadmin(A_FREEZE, cprarg, 0) != 0) {
			(void) printf(gettext("Suspend Failed\n"));
			if (flags & FORCE) {
				/*
				 * Note, that if we actually poweroff,
				 * that the poweroff function will handle
				 * that audit trail, and the resume
				 * trail is effectively done.
				 */
				pm_poweroff();
			} else {
				/* suspend_error() will exit. */
				suspend_error(errno);
				/*
				 * Audit the suspend failure and
				 * reuse the event, but don't create one
				 * if we don't already have one.
				 */
				if (event != NULL) {
					(void) adt_put_event(event,
					    ADT_FAILURE, 0);
				}
			}
		}

		/*
		 * Write the thaw event.
		 */
		if (ah != NULL) {
			if ((event == NULL) &&
			    ((event = adt_alloc_event(ah, ADT_uadmin_thaw))
			    == NULL)) {
				(void) fprintf(stderr, gettext(
				    "%s: can't allocate thaw audit event\n"),
				    argvl[0]);
			} else {
				event->adt_uadmin_thaw.fcn = fcn_id;
				if (adt_put_event(event, ADT_SUCCESS, 0) != 0) {
					(void) fprintf(stderr, gettext(
					    "%s: can't put thaw audit event\n"),
					    argvl[0]);
				}
				(void) adt_free_event(event);
			}
		}
	}
	if ((no_tty ? 0 : 1) && !(flags & NO_XLOCK)) {
		pm_do_auth(ah);
	}

	(void) adt_end_session(ah);
}
Beispiel #11
0
/*
 * build_mgmt_request -- extracts the request info from the given XML doc.
 *
 * x_doc: ptr to the request XML doc
 * req: ptr to the request struct to be filled up.
 *
 * Return value: ISNS_RSP_SUCCESSFUL if successful or an error code.
 */
static int
process_mgmt_request(xmlDocPtr x_doc, request_t *req, ucred_t *uc)
{
	result_code_t   ret;
	int		op;
	xmlXPathContextPtr ctext = NULL;
	uid_t			user;
	struct passwd		pwds, *pwd;
	char			buf_pwd[1024];


	isnslog(LOG_DEBUG, "process_mgmt_request", "entered");
	(void) memset(req, 0, sizeof (request_t));
	/* get the operation first. */
	ctext = xmlXPathNewContext(x_doc);
	if (ctext == NULL) {
	    return (ERR_XML_FAILED_TO_SET_XPATH_CONTEXT);
	}

	isnslog(LOG_DEBUG, "process_mgmt_request", "xpath context succeeded");
	op = get_op_id_from_doc(ctext);
	if (op == -1) {
	    if (ctext) xmlXPathFreeContext(ctext);
	    return (ERR_XML_VALID_OPERATION_NOT_FOUND);
	}

	user = ucred_getruid(uc);
	ret = getpwuid_r(user, &pwds, buf_pwd, sizeof (buf_pwd), &pwd);
	if (ret != 0) {
	    if (ctext) xmlXPathFreeContext(ctext);
	    return (ERR_DOOR_SERVER_DETECTED_INVALID_USER);
	}

	/* write operations are restricted. */
	if ((op == delete_op) || (op == createModify_op)) {
	    if (!chkauthattr(ISNS_ADMIN_WRITE_AUTH, pwd->pw_name)) {
		if (ctext) xmlXPathFreeContext(ctext);
		return (ERR_DOOR_SERVER_DETECTED_NOT_AUTHORIZED_USER);
	    }
	}

	req->op_info.op = op;

	if (ISNS_MGMT_OPERATION_TYPE_ENABLED()) {
	    ISNS_MGMT_OPERATION_TYPE(op);
	}

	switch (op) {
	    case (get_op):
		ret = process_get_request_from_doc(ctext, req);
		break;
	    case (getAssociated_op):
		ret = process_getAssociated_request_from_doc(ctext, req);
		break;
	    case (enumerate_op):
		ret = process_enumerate_request_from_doc(ctext, req);
		break;
	    case (delete_op):
		ret = process_delete_request_from_doc(ctext, req);
		break;
	    case (createModify_op):
		ret = process_createModify_request_from_doc(ctext, req);
		break;
	    default:
		ret = ERR_XML_VALID_OPERATION_NOT_FOUND;
	}

	if (ctext) xmlXPathFreeContext(ctext);
	return (ret);
}
Beispiel #12
0
static void
main_loop(char *devname, boolean_t cttyflag)
{
	int		fd, fb, i;
	char		*user = NULL;		/* authorized user */
	char		*pass;			/* password from user */
	char		*cpass;			/* crypted password */
	struct spwd	spwd;
	struct spwd	*lshpw;			/* local shadow */
	char		shadow[NSS_BUFLEN_SHADOW];
	FILE		*sysmsgfd;

	for (i = 0; i < 3; i++)
		(void) close(i);
	if (cttyflag == B_FALSE) {
		if (setsid() == -1)
			exit(EXIT_FAILURE);
	}
	if ((fd = open(devname, O_RDWR)) < 0)
		exit(EXIT_FAILURE);

	/*
	 * In system maintenance mode, all virtual console instances
	 * of the svc:/system/console-login service are not available
	 * any more, and only the system console is available. So here
	 * we always switch to the system console in case at the moment
	 * the active console isn't it.
	 */
	(void) ioctl(fd, VT_ACTIVATE, 1);

	if (fd != 0)
		(void) dup2(fd, STDIN_FILENO);
	if (fd != 1)
		(void) dup2(fd, STDOUT_FILENO);
	if (fd != 2)
		(void) dup2(fd, STDERR_FILENO);
	if (fd > 2)
		(void) close(fd);

	/* Stop progress bar and reset console mode to text */
	if ((fb = open("/dev/fb", O_RDONLY)) >= 0) {
		(void) ioctl(fb, KDSETMODE, KD_RESETTEXT);
		(void) close(fb);
	}

	sysmsgfd = fopen("/dev/sysmsg", "w");

	sanitize_tty(fileno(stdin));

	for (;;) {
		do {
			(void) printf("\nEnter user name for system "
			    "maintenance (control-d to bypass): ");
			user = sulogin_getinput(devname, ECHOON);
			if (user == NULL) {
				/* signal other children to exit */
				(void) sigsend(P_PID, masterpid, SIGUSR1);
				/* ^D, so straight to default init state */
				exit(EXIT_FAILURE);
			}
		} while (user[0] == '\0');
		(void) printf("Enter %s password (control-d to bypass): ",
		    user);

		if ((pass = sulogin_getinput(devname, ECHOOFF)) == NULL) {
			/* signal other children to exit */
			(void) sigsend(P_PID, masterpid, SIGUSR1);
			/* ^D, so straight to default init state */
			free(user);
			exit(EXIT_FAILURE);
		}
		lshpw = getspnam_r(user, &spwd, shadow, sizeof (shadow));
		if (lshpw == NULL) {
			/*
			 * the user entered doesn't exist, too bad.
			 */
			goto sorry;
		}

		/*
		 * There is a special case error to catch here:
		 * If the password is hashed with an algorithm
		 * other than the old unix crypt the call to crypt(3c)
		 * could fail if /usr is corrupt or not available
		 * since by default /etc/security/crypt.conf will
		 * have the crypt_ modules located under /usr/lib.
		 * Or it could happen if /etc/security/crypt.conf
		 * is corrupted.
		 *
		 * If this happens crypt(3c) will return NULL and
		 * set errno to ELIBACC for the former condition or
		 * EINVAL for the latter, in this case we bypass
		 * authentication and just verify that the user is
		 * authorized.
		 */

		errno = 0;
		cpass = crypt(pass, lshpw->sp_pwdp);
		if (((cpass == NULL) && (lshpw->sp_pwdp[0] == '$')) &&
		    ((errno == ELIBACC) || (errno == EINVAL))) {
			goto checkauth;
		} else if ((cpass == NULL) ||
		    (strcmp(cpass, lshpw->sp_pwdp) != 0)) {
			goto sorry;
		}

checkauth:
		/*
		 * There is a special case error here as well.
		 * If /etc/user_attr is corrupt, getusernam("root")
		 * returns NULL.
		 * In this case, we just give access because this is similar
		 * to the case of root not existing in /etc/passwd.
		 */

		if ((getusernam("root") != NULL) &&
		    (chkauthattr(MAINTENANCE_AUTH, user) != 1)) {
			goto sorry;
		}
		(void) fprintf(sysmsgfd, "\nsingle-user privilege "
		    "assigned to %s on %s.\n", user, devname);
		(void) sigsend(P_PID, masterpid, SIGUSR1);
		(void) wait(NULL);
		free(user);
		free(pass);
		single(su, devname);
		/* single never returns */

sorry:
		(void) printf("\nLogin incorrect or user %s not authorized\n",
		    user);
		free(user);
		free(pass);
		(void) sleep(sleeptime);
	}
}
Beispiel #13
0
/*
 * Verifies the provided list of authorizations are all valid.
 *
 * Returns NULL if all authorization names are valid.
 * Otherwise, returns the invalid authorization name
 *
 */
static const char *
check_auth(const char *auths)
{
	char *authname;
	authattr_t *result;
	char *tmp;
	struct passwd   *pw;
	int have_grant = 0;

	tmp = strdup(auths);
	if (tmp == NULL) {
		errmsg(M_NOSPACE);
		exit(EX_FAILURE);
	}

	authname = strtok(tmp, AUTH_SEP);
	pw = getpwuid(getuid());
	if (pw == NULL) {
		return (authname);
	}

	while (authname != NULL) {
		char *suffix;
		char *authtoks;

		/* Check if user has been granted this authorization */
		if (!chkauthattr(authname, pw->pw_name))
			return (authname);

		/* Remove named object after slash */
		if ((suffix = index(authname, KV_OBJECTCHAR)) != NULL)
			*suffix = '\0';

		/* Find the suffix */
		if ((suffix = rindex(authname, '.')) == NULL)
			return (authname);

		/* Check for existence in auth_attr */
		suffix++;
		if (strcmp(suffix, KV_WILDCARD)) { /* Not a wildcard */
			result = getauthnam(authname);
			if (result == NULL) {
			/* can't find the auth */
				free_authattr(result);
				return (authname);
			}
			free_authattr(result);
		}

		/* Check if user can delegate this authorization */
		if (strcmp(suffix, "grant")) { /* Not a grant option */
			authtoks = malloc(strlen(authname) + sizeof ("grant"));
			strcpy(authtoks, authname);
			have_grant = 0;
			while ((suffix = rindex(authtoks, '.')) &&
			    !have_grant) {
				strcpy(suffix, ".grant");
				if (chkauthattr(authtoks, pw->pw_name))
					have_grant = 1;
				else
					*suffix = '\0';
			}
			if (!have_grant)
				return (authname);
		}
		authname = strtok(NULL, AUTH_SEP);
	}
	free(tmp);
	return (NULL);
}