Commit 3fe0e366 authored by Nikos Mavrogiannopoulos's avatar Nikos Mavrogiannopoulos Committed by Nikos Mavrogiannopoulos

When using setuid() also use setgid() and setgroups()

Signed-off-by: default avatarNikos Mavrogiannopoulos <nmav@redhat.com>
parent c00609ad
......@@ -30,6 +30,7 @@
#ifndef _WIN32
#include <sys/wait.h>
#include <pwd.h>
#include <grp.h>
#endif
#include <libxml/parser.h>
......@@ -1067,21 +1068,40 @@ static int run_csd_script(struct openconnect_info *vpninfo, char *buf, int bufle
if (vpninfo->uid_csd_given && vpninfo->uid_csd != getuid()) {
struct passwd *pw;
int e;
if (setgid(vpninfo->gid_csd)) {
e = errno;
fprintf(stderr, _("Failed to set gid %ld: %s\n"),
(long)vpninfo->uid_csd, strerror(e));
exit(1);
}
if (setgroups(1, &vpninfo->gid_csd)) {
e = errno;
fprintf(stderr, _("Failed to set groups to %ld: %s\n"),
(long)vpninfo->uid_csd, strerror(e));
exit(1);
}
if (setuid(vpninfo->uid_csd)) {
fprintf(stderr, _("Failed to set uid %ld\n"),
(long)vpninfo->uid_csd);
e = errno;
fprintf(stderr, _("Failed to set uid %ld: %s\n"),
(long)vpninfo->uid_csd, strerror(e));
exit(1);
}
if (!(pw = getpwuid(vpninfo->uid_csd))) {
fprintf(stderr, _("Invalid user uid=%ld\n"),
(long)vpninfo->uid_csd);
e = errno;
fprintf(stderr, _("Invalid user uid=%ld: %s\n"),
(long)vpninfo->uid_csd, strerror(e));
exit(1);
}
setenv("HOME", pw->pw_dir, 1);
if (chdir(pw->pw_dir)) {
e = errno;
fprintf(stderr, _("Failed to change to CSD home directory '%s': %s\n"),
pw->pw_dir, strerror(errno));
pw->pw_dir, strerror(e));
exit(1);
}
}
......
......@@ -963,6 +963,37 @@ static int next_option(int argc, char **argv, char **config_arg)
}
#ifndef _WIN32
static void get_uids(const char *config_arg, uid_t *uid, gid_t *gid)
{
char *strend;
struct passwd *pw;
int e;
*uid = strtol(config_arg, &strend, 0);
if (strend[0]) {
pw = getpwnam(config_arg);
if (!pw) {
e = errno;
fprintf(stderr, _("Invalid user \"%s\": %s\n"),
config_arg, strerror(e));
exit(1);
}
*uid = pw->pw_uid;
*gid = pw->pw_gid;
} else {
pw = getpwuid(*uid);
if (!pw) {
e = errno;
fprintf(stderr, _("Invalid user ID \"%d\": %s\n"),
(int)*uid, strerror(e));
exit(1);
}
*gid = pw->pw_gid;
}
}
#endif
int main(int argc, char **argv)
{
struct openconnect_info *vpninfo;
......@@ -1033,6 +1064,7 @@ int main(int argc, char **argv)
#else
vpninfo->use_tun_script = 0;
vpninfo->uid = getuid();
vpninfo->gid = getgid();
if (!uname(&utsbuf)) {
free(vpninfo->localname);
vpninfo->localname = xstrdup(utsbuf.nodename);
......@@ -1055,35 +1087,13 @@ int main(int argc, char **argv)
case 'S':
vpninfo->use_tun_script = 1;
break;
case 'U': {
char *strend;
vpninfo->uid = strtol(config_arg, &strend, 0);
if (strend[0]) {
struct passwd *pw = getpwnam(config_arg);
if (!pw) {
fprintf(stderr, _("Invalid user \"%s\"\n"),
config_arg);
exit(1);
}
vpninfo->uid = pw->pw_uid;
}
case 'U':
get_uids(config_arg, &vpninfo->uid, &vpninfo->gid);
break;
}
case OPT_CSD_USER: {
char *strend;
vpninfo->uid_csd = strtol(config_arg, &strend, 0);
if (strend[0]) {
struct passwd *pw = getpwnam(config_arg);
if (!pw) {
fprintf(stderr, _("Invalid user \"%s\"\n"),
config_arg);
exit(1);
}
vpninfo->uid_csd = pw->pw_uid;
}
case OPT_CSD_USER:
get_uids(config_arg, &vpninfo->uid_csd, &vpninfo->gid_csd);
vpninfo->uid_csd_given = 1;
break;
}
case OPT_CSD_WRAPPER:
vpninfo->csd_wrapper = keep_config_arg();
break;
......
......@@ -22,6 +22,11 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#ifndef _WIN32
/* for setgroups() */
# include <sys/types.h>
# include <grp.h>
#endif
#include "openconnect-internal.h"
......@@ -122,9 +127,26 @@ static int setup_tun_device(struct openconnect_info *vpninfo)
#ifndef _WIN32
if (vpninfo->uid != getuid()) {
int e;
if (setgid(vpninfo->gid)) {
e = errno;
fprintf(stderr, _("Failed to set gid %ld: %s\n"),
(long)vpninfo->gid, strerror(e));
return -EPERM;
}
if (setgroups(1, &vpninfo->gid)) {
e = errno;
fprintf(stderr, _("Failed to set groups to %ld: %s\n"),
(long)vpninfo->gid, strerror(e));
return -EPERM;
}
if (setuid(vpninfo->uid)) {
fprintf(stderr, _("Failed to set uid %ld\n"),
(long)vpninfo->uid);
e = errno;
fprintf(stderr, _("Failed to set uid %ld: %s\n"),
(long)vpninfo->uid, strerror(e));
return -EPERM;
}
}
......
......@@ -400,6 +400,7 @@ struct openconnect_info {
int xmlpost;
char *dtls_ciphers;
uid_t uid_csd;
gid_t gid_csd;
char *csd_wrapper;
int uid_csd_given;
int no_http_keepalive;
......@@ -538,6 +539,7 @@ struct openconnect_info {
char *vpnc_script;
#ifndef _WIN32
uid_t uid;
gid_t gid;
#endif
int tun_is_up; /* whether the tun device is setup */
int use_tun_script;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment