Compare commits
No commits in common. "e2284c301b07dabbf2e704f026eac1ed4314960d" and "37967a87c0f8ebf8cadab1e098ff4df54a58e0c5" have entirely different histories.
e2284c301b
...
37967a87c0
14
makefile
14
makefile
@ -18,17 +18,13 @@ install: us
|
|||||||
cp -f us ${DESTDIR}${PREFIX}/bin/us
|
cp -f us ${DESTDIR}${PREFIX}/bin/us
|
||||||
chown 0:0 ${DESTDIR}${PREFIX}/bin/us
|
chown 0:0 ${DESTDIR}${PREFIX}/bin/us
|
||||||
chmod 4755 ${DESTDIR}${PREFIX}/bin/us
|
chmod 4755 ${DESTDIR}${PREFIX}/bin/us
|
||||||
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
# mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||||
cp -f us.1 ${DESTDIR}${MANPREFIX}/man1/us.1
|
# cp -f us.1 ${DESTDIR}${MANPREFIX}/man1/us.1
|
||||||
chmod 644 ${DESTDIR}${MANPREFIX}/man1/us.1
|
# chmod 644 ${DESTDIR}${MANPREFIX}/man1/us.1
|
||||||
mkdir -p ${DESTDIR}${MANPREFIX}/man5
|
|
||||||
cp -f us.conf.5 ${DESTDIR}${MANPREFIX}/man5/us.conf.5
|
|
||||||
chmod 644 ${DESTDIR}${MANPREFIX}/man5/us.conf.5
|
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f ${DESTDIR}${PREFIX}/bin/us \
|
rm -f ${DESTDIR}${PREFIX}/bin/us
|
||||||
${DESTDIR}${MANPREFIX}/man1/us.1
|
# ${DESTDIR}${MANPREFIX}/man1/us.1
|
||||||
${DESTDIR}${MANPREFIX}/man1/us.conf.5
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f us us-dbg
|
rm -f us us-dbg
|
||||||
|
78
us.1
78
us.1
@ -1,78 +1,2 @@
|
|||||||
.TH US 1 "JULY 2021" "Alessandro Mauri"
|
US-0.1
|
||||||
|
|
||||||
.SH NAME
|
|
||||||
us \- execute command with another identity
|
|
||||||
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.SY us
|
|
||||||
.OP \-hseA
|
|
||||||
.OP \-u user
|
|
||||||
.OP \-g group
|
|
||||||
.OP \-C config
|
|
||||||
.OP command
|
|
||||||
.OP args
|
|
||||||
.YS
|
|
||||||
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.PP
|
|
||||||
The
|
|
||||||
.BR us
|
|
||||||
utility executes the given command as another identity, which by default is
|
|
||||||
root. If no command is specified, it starts a shell as that user.
|
|
||||||
.PP
|
|
||||||
In order to execute anything users need to authenticate and the user + target
|
|
||||||
identity configuration must be allowed in the configuration file, see
|
|
||||||
.BR us.conf(5)
|
|
||||||
for more information.
|
|
||||||
.PP
|
|
||||||
By default when a command or shell gets executed a new environment gets created,
|
|
||||||
USER is set with the target user, as well as LOGNAME, SHELL and HOME get all set
|
|
||||||
with the default values for the target user.
|
|
||||||
PATH, TERM, EDITOR, VISUAL, DISPLAY and XAUTHORITY instead are kept between
|
|
||||||
execution.
|
|
||||||
Lastly a new variable US_USER is added (but not overridden) which contains the
|
|
||||||
calling user's username.
|
|
||||||
.PP
|
|
||||||
Invoking the program logs by default to
|
|
||||||
.BR syslog(2)
|
|
||||||
the outcome of the invocation, this behaviour can be changed in the config.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
|
||||||
.IP \-h
|
|
||||||
Print usage info message.
|
|
||||||
.IP \-s
|
|
||||||
Use the calling user's SHELL instead of the target user's one.
|
|
||||||
.IP \-e
|
|
||||||
Keep the entire environment between execution instead of just PATH, TERM,
|
|
||||||
EDITOR, VISUAL, DISPLAY and XAUTHORITY; user variables still get overridden.
|
|
||||||
.IP \-A
|
|
||||||
Instead of prompting for a password,
|
|
||||||
.BR us
|
|
||||||
executes the command specified in the variable US_ASKPASS and reads it's stdout
|
|
||||||
as the password. If US_ASKPASS is not specified then it will fall back
|
|
||||||
prompting the password.
|
|
||||||
.IP "\-u user"
|
|
||||||
Change the target identity to
|
|
||||||
.I user
|
|
||||||
(default is root).
|
|
||||||
.IP "\-g group"
|
|
||||||
Set the group of the target user to
|
|
||||||
.I group
|
|
||||||
instead of the target user's default, also add it to the group list.
|
|
||||||
.IP "\-C config"
|
|
||||||
Use the specified config file
|
|
||||||
|
|
||||||
.SH "RETURN VALUE"
|
|
||||||
The
|
|
||||||
.BR us
|
|
||||||
utility returns 0 on success and != 0 on failure which may occur on
|
|
||||||
various occasions, along with an error a message will be outputted to specify
|
|
||||||
the reason.
|
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR su(1)
|
|
||||||
.BR us.conf(5)
|
|
||||||
|
|
||||||
.SH AUTHOR
|
|
||||||
Alessandro Mauri <alemauri001@tuta.io>
|
|
||||||
|
|
||||||
|
24
us.c
24
us.c
@ -158,10 +158,6 @@ int main(int argc, char *argv[])
|
|||||||
if (!t_pw)
|
if (!t_pw)
|
||||||
die("user_to_passwd:");
|
die("user_to_passwd:");
|
||||||
t_gr = group_to_grp(t_grp, &t_gr_info);
|
t_gr = group_to_grp(t_grp, &t_gr_info);
|
||||||
gid_t t_groups[GROUPS_MAX];
|
|
||||||
int nt_groups = GROUPS_MAX;
|
|
||||||
if (getgrouplist(t_pw->pw_name, t_pw->pw_gid, t_groups, &nt_groups) == -1)
|
|
||||||
die("getgrouplist:");
|
|
||||||
|
|
||||||
/* Don't have to wait for children */
|
/* Don't have to wait for children */
|
||||||
struct sigaction sa = {0};
|
struct sigaction sa = {0};
|
||||||
@ -190,7 +186,6 @@ int main(int argc, char *argv[])
|
|||||||
struct user_info who_info = {0}, as_info = {0};
|
struct user_info who_info = {0}, as_info = {0};
|
||||||
int who_usr = conf[i].who[0] == ':' ? 0 : 1;
|
int who_usr = conf[i].who[0] == ':' ? 0 : 1;
|
||||||
int as_usr = conf[i].as[0] == ':' ? 0 : 1;
|
int as_usr = conf[i].as[0] == ':' ? 0 : 1;
|
||||||
|
|
||||||
if (who_usr) {
|
if (who_usr) {
|
||||||
who_pw = user_to_passwd(conf[i].who, &who_info);
|
who_pw = user_to_passwd(conf[i].who, &who_info);
|
||||||
if (!who_pw)
|
if (!who_pw)
|
||||||
@ -198,13 +193,13 @@ int main(int argc, char *argv[])
|
|||||||
if (my_pw->pw_uid != who_pw->pw_uid)
|
if (my_pw->pw_uid != who_pw->pw_uid)
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
who_gr = group_to_grp(conf[i].who+1, &who_info);
|
who_gr = group_to_grp(conf[i].who, &who_info);
|
||||||
if (!who_gr)
|
if (!who_gr)
|
||||||
die("%s not a valid group", conf[i].who);
|
die("%s not a valid group", conf[i].who);
|
||||||
gid_t w_gid = who_gr->gr_gid;
|
gid_t w_gid = who_gr->gr_gid;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (; x < n_groups && w_gid != my_groups[x]; x++);
|
for (; x < n_groups && w_gid != my_groups[x]; x++);
|
||||||
if (x == n_groups)
|
if (w_gid != my_groups[x])
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,15 +209,14 @@ int main(int argc, char *argv[])
|
|||||||
die("%s not a valid user", conf[i].as);
|
die("%s not a valid user", conf[i].as);
|
||||||
if (t_pw->pw_uid != as_pw->pw_uid)
|
if (t_pw->pw_uid != as_pw->pw_uid)
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else if (t_gr) {
|
||||||
as_gr = group_to_grp(conf[i].as+1, &as_info);
|
as_gr = group_to_grp(conf[i].as, &as_info);
|
||||||
if (!as_gr)
|
if (!as_gr)
|
||||||
die("%s not a valid group", conf[i].as);
|
die("%s not a valid group", conf[i].as);
|
||||||
gid_t a_gid = as_gr->gr_gid;
|
if (t_gr->gr_gid != as_gr->gr_gid)
|
||||||
int x = 0;
|
|
||||||
for (; x < nt_groups && a_gid != t_groups[x]; x++);
|
|
||||||
if (x == nt_groups)
|
|
||||||
continue;
|
continue;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
here = 1;
|
here = 1;
|
||||||
if (conf[i].type == 0)
|
if (conf[i].type == 0)
|
||||||
@ -388,7 +382,7 @@ static inline void usage(int complete)
|
|||||||
"-e keep the user's entire environment\n"
|
"-e keep the user's entire environment\n"
|
||||||
"-A use the command in US_ASKPASS as askpass helper\n"
|
"-A use the command in US_ASKPASS as askpass helper\n"
|
||||||
"-u user set new user to 'user' instead of root\n"
|
"-u user set new user to 'user' instead of root\n"
|
||||||
"-g group set new group to 'group'\n"
|
"-s group set new group to 'group'\n"
|
||||||
"-C config use specifi config file\n");
|
"-C config use specifi config file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,7 +746,7 @@ static int get_config(struct config **conf, int *num)
|
|||||||
struct config c = {0};
|
struct config c = {0};
|
||||||
for (s = line;; s = NULL, n++) {
|
for (s = line;; s = NULL, n++) {
|
||||||
int getflags = 0;
|
int getflags = 0;
|
||||||
if (!(t = strtok_r(s, " \t", &sv)))
|
if (!(t = strtok_r(s, " ", &sv)))
|
||||||
break;
|
break;
|
||||||
if (*t == '#')
|
if (*t == '#')
|
||||||
break;
|
break;
|
||||||
|
97
us.conf.5
97
us.conf.5
@ -1,97 +0,0 @@
|
|||||||
.TH US.CONF 5 "JULY 2021" "Alessandro Mauri"
|
|
||||||
|
|
||||||
.SH NAME
|
|
||||||
us.conf \- us configuration file
|
|
||||||
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.PP
|
|
||||||
The
|
|
||||||
.BR us(1)
|
|
||||||
utility executes commands as another identity according to the rules in the
|
|
||||||
.BR us.conf
|
|
||||||
configuration file.
|
|
||||||
.PP
|
|
||||||
The rules have the following format:
|
|
||||||
.IP
|
|
||||||
.BR "+|\-"
|
|
||||||
.BR user
|
|
||||||
as
|
|
||||||
.BR target
|
|
||||||
.OP options
|
|
||||||
.OP ENV
|
|
||||||
.SS Options
|
|
||||||
Possible options are:
|
|
||||||
.IP nopass
|
|
||||||
The user is not required to enter a password.
|
|
||||||
.IP persist
|
|
||||||
Once entering the password for the first time, a timer for five minutes is
|
|
||||||
started, during those five minutes the user is not required to re-enter
|
|
||||||
the password for that session. Re-invoking us resets that timer.
|
|
||||||
.IP nolog
|
|
||||||
Do not log to
|
|
||||||
.BR syslog(2)
|
|
||||||
command outcome
|
|
||||||
.PP
|
|
||||||
The sum of matching rules determines the action taken, if no rules match
|
|
||||||
the action is denied.
|
|
||||||
.PP
|
|
||||||
Comments are made by having the first non-blank character of a line be an hash
|
|
||||||
mark ('#'), comments take up the whole line and cannot be embedded in the
|
|
||||||
middle of a line.
|
|
||||||
.PP
|
|
||||||
A valid user or target is an alphanumeric string containing the name of the
|
|
||||||
target. If the target is a user, the string begins with [0-9A-z]; if the
|
|
||||||
target is a group then the has to begin with ':'. Instead of the name of the
|
|
||||||
user/group it's number can be used, in that case the part of the string that
|
|
||||||
would contain the name must begin with '#' (so after a possible ':').
|
|
||||||
.PP
|
|
||||||
As options a comma separated list of environment variables can be specified,
|
|
||||||
these will be added or will override existing environment variables during
|
|
||||||
execution of the command. A valid environment variable list starts with an
|
|
||||||
uppercase letter and ends at the next space.
|
|
||||||
.PP
|
|
||||||
A valid config line must be owned by root:root and should not be readable,
|
|
||||||
writeable or executable for any other user or group, if the config file fails
|
|
||||||
to meet this requirements it will get rejected and invocation will fail.
|
|
||||||
|
|
||||||
.SH FILES
|
|
||||||
.IP /etc/us.conf
|
|
||||||
us(1) configuration file
|
|
||||||
|
|
||||||
.SH EXAMPLES
|
|
||||||
.PP
|
|
||||||
The following example will allow root to execute commands as itself without
|
|
||||||
requiring a password and without logging:
|
|
||||||
.PP
|
|
||||||
.EX
|
|
||||||
+ root as root nopass nolog
|
|
||||||
.EE
|
|
||||||
.PP
|
|
||||||
This next example allows users in the wheel group to execute commands as
|
|
||||||
root including a new environment variable IS_WHEEL set to 'yes' and the variable
|
|
||||||
EDITOR will be set to ed, the standard unix editor:
|
|
||||||
.PP
|
|
||||||
.EX
|
|
||||||
+ :wheel as root IS_WHEEL=yes,EDITOR=ed
|
|
||||||
.EE
|
|
||||||
.PP
|
|
||||||
In this example the user maria is allowed to execute commands as a member of
|
|
||||||
the group wheel and the session is remembered so that in the next five
|
|
||||||
minutes the password won't be needed:
|
|
||||||
.PP
|
|
||||||
.EX
|
|
||||||
+ maria as :wheel persist
|
|
||||||
.EE
|
|
||||||
.PP
|
|
||||||
This time the user joe is denied to execute commands as anyone who's member of
|
|
||||||
the group 'coolppl' because joe is uncool
|
|
||||||
.PP
|
|
||||||
.EX
|
|
||||||
- joe as :coolppl
|
|
||||||
.EE
|
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR us(1)
|
|
||||||
|
|
||||||
.SH AUTHOR
|
|
||||||
Alessandro Mauri <alemauri001@tuta.io>
|
|
Loading…
x
Reference in New Issue
Block a user