summaryrefslogtreecommitdiffstats
path: root/qarsh/qarshd.c
diff options
context:
space:
mode:
Diffstat (limited to 'qarsh/qarshd.c')
-rw-r--r--qarsh/qarshd.c36
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,