static void runas_setgroups(void);
static void restore_groups(void);
-static int current_perm = -1;
+/*
+ * We keep track of the current permisstions and use a stack to restore
+ * the old permissions. A depth of 16 is overkill.
+ */
+#define PERM_STACK_MAX 16
+static int perm_stack[PERM_STACK_MAX];
+static int perm_stack_depth = 0;
+static int perm_current = PERM_INITIAL;
+
+/*
+ * XXX - better to push what we've changed:
+ * ruid, euid, suid, gids group vector.
+ */
+
+int
+restore_perms(void)
+{
+ int old_perm;
+
+ if (!perm_stack_depth) {
+ /* nothing to do */
+ return TRUE;
+ }
+ old_perm = perm_stack[--perm_stack_depth];
+ return set_perms2(old_perm, FALSE);
+}
+
+int
+set_perms(int perm)
+{
+ return set_perms2(perm, TRUE);
+}
#ifdef HAVE_SETRESUID
/*
* This version of set_perms() works fine with the "stay_setuid" option.
*/
int
-set_perms(perm)
- int perm;
+set_perms2(int perm, int push_it)
{
const char *errstr;
int noexit;
noexit = ISSET(perm, PERM_NOEXIT);
CLR(perm, PERM_MASK);
- if (perm == current_perm)
- return(1);
+ if (perm_stack_depth == PERM_STACK_MAX) {
+ errno = EINVAL;
+ goto bad;
+ }
+ if (perm == perm_current)
+ goto done;
switch (perm) {
+ case PERM_INITIAL:
+ /* Setuid root */
+ if (setuid(ROOT_UID)) {
+ errstr = "setuid(ROOT_UID)";
+ goto bad;
+ }
+ (void) setresgid(-1, user_gid, -1);
+ if (perm_current == PERM_RUNAS)
+ restore_groups();
+ (void) setresuid(user_uid, -1, -1);
+ break;
case PERM_ROOT:
if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID)) {
errstr = "setresuid(ROOT_UID, ROOT_UID, ROOT_UID)";
goto bad;
}
(void) setresgid(-1, user_gid, -1);
- if (current_perm == PERM_RUNAS)
+ if (perm_current == PERM_RUNAS)
restore_groups();
break;
break;
}
- current_perm = perm;
+done:
+ if (push_it)
+ perm_stack[perm_stack_depth++] = perm_current;
+ perm_current = perm;
return(1);
bad:
warningx("%s: %s", errstr,
noexit = ISSET(perm, PERM_NOEXIT);
CLR(perm, PERM_MASK);
- if (perm == current_perm)
+ if (perm == perm_current)
return(1);
switch (perm) {
goto bad;
}
(void) setregid(-1, user_gid);
- if (current_perm == PERM_RUNAS)
+ if (perm_current == PERM_RUNAS)
restore_groups();
break;
break;
}
- current_perm = perm;
+ perm_current = perm;
return(1);
bad:
warningx("%s: %s", errstr,
noexit = ISSET(perm, PERM_NOEXIT);
CLR(perm, PERM_MASK);
- if (perm == current_perm)
+ if (perm == perm_current)
return(1);
/*
case PERM_ROOT:
/* uid set above */
(void) setegid(user_gid);
- if (current_perm == PERM_RUNAS)
+ if (perm_current == PERM_RUNAS)
restore_groups();
break;
break;
}
- current_perm = perm;
+ perm_current = perm;
return(1);
bad:
warningx("%s: %s", errstr,
noexit = ISSET(perm, PERM_NOEXIT);
CLR(perm, PERM_MASK);
- if (perm == current_perm)
+ if (perm == perm_current)
return(1);
switch (perm) {
errstr = "setuid(ROOT_UID)";
goto bad;
}
- if (current_perm == PERM_RUNAS)
+ if (perm_current == PERM_RUNAS)
restore_groups();
break;
break;
}
- current_perm = perm;
+ perm_current = perm;
return(1);
bad:
warningx("%s: %s", errstr,
/*
* Used with set_perms()
*/
-#define PERM_ROOT 0x00
-#define PERM_USER 0x01
-#define PERM_FULL_USER 0x02
-#define PERM_SUDOERS 0x03
-#define PERM_RUNAS 0x04
-#define PERM_FULL_RUNAS 0x05
-#define PERM_TIMESTAMP 0x06
+#define PERM_INITIAL 0x00
+#define PERM_ROOT 0x01
+#define PERM_USER 0x02
+#define PERM_FULL_USER 0x03
+#define PERM_SUDOERS 0x04
+#define PERM_RUNAS 0x05
+#define PERM_FULL_RUNAS 0x06
+#define PERM_TIMESTAMP 0x07
#define PERM_NOEXIT 0x10 /* flag */
#define PERM_MASK 0xf0
int sudo_file_display_bound_defaults(struct sudo_nss *, struct passwd *, struct lbuf *);
int sudo_file_display_privs(struct sudo_nss *, struct passwd *, struct lbuf *);
int set_perms(int);
+int restore_perms(void);
void remove_timestamp(int);
int check_secureware(char *);
void sia_attempt_auth(void);