diff options
Diffstat (limited to 'qarsh/qarshd.c')
-rw-r--r-- | qarsh/qarshd.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/qarsh/qarshd.c b/qarsh/qarshd.c index 9a90782..d443704 100644 --- a/qarsh/qarshd.c +++ b/qarsh/qarshd.c @@ -11,6 +11,9 @@ #include <sys/wait.h> #include <sys/socket.h> #include <arpa/inet.h> +#include <pwd.h> +#include <grp.h> + #include "sockutil.h" #include "qarsh_packet.h" @@ -23,6 +26,28 @@ /* Globals */ struct sockaddr_in peername; +int +setup_user(char *user, char *group) +{ + struct passwd *pw; + struct group *grp; + + if ((pw = getpwnam(user)) == NULL) { + syslog(LOG_WARNING, "User \"%s\" not found\n", user); + return 0; + } + + if (group && (grp = getgrnam(group))) { + setgid(grp->gr_gid); + initgroups(pw->pw_name, grp->gr_gid); + } else { + setgid(pw->pw_gid); + initgroups(pw->pw_name, pw->pw_gid); + } + /* setuid is last so we can still do setgid and initgroups */ + setuid(pw->pw_uid); + return 1; +} pid_t run_cmd(const char *cmd, int p_in, int p_out, int p_err) @@ -109,6 +134,16 @@ handle_packets(int infd) break; } switch (qp->qp_type) { + case QP_SETUSER: + if (setup_user(qp->qp_setuser.qp_user, + qp->qp_setuser.qp_group) == 0) { + rp = make_qp_returncode(-1, 0, "User not found"); + } else { + rp = make_qp_ack(QP_SETUSER, 1); + } + send_packet(fileno(stdout), rp); + qpfree(rp); + break; case QP_RUNCMD: child_pid = run_cmd(qp->qp_runcmd.qp_cmdline, qp->qp_runcmd.qp_stdin_port, @@ -117,6 +152,7 @@ handle_packets(int infd) waitpid(child_pid, &child_status, 0); rp = make_qp_cmdexit(child_pid, child_status); send_packet(fileno(stdout), rp); + qpfree(rp); break; default: syslog(LOG_WARNING, |