Skip to content

Commit

Permalink
When using setuid() also use setgid() and setgroups()
Browse files Browse the repository at this point in the history
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
  • Loading branch information
Nikos Mavrogiannopoulos authored and nmav committed Dec 5, 2015
1 parent c00609a commit 3fe0e36
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 33 deletions.
30 changes: 25 additions & 5 deletions auth.c
Expand Up @@ -30,6 +30,7 @@
#ifndef _WIN32
#include <sys/wait.h>
#include <pwd.h>
#include <grp.h>
#endif

#include <libxml/parser.h>
Expand Down Expand Up @@ -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);
}
}
Expand Down
62 changes: 36 additions & 26 deletions main.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down
26 changes: 24 additions & 2 deletions mainloop.c
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
}
}
Expand Down
2 changes: 2 additions & 0 deletions openconnect-internal.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 3fe0e36

Please sign in to comment.