http.c | 26 +++++++++++++++++++++++++- main.c | 12 ++++++------ openconnect.h | 1 + 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/http.c b/http.c index c90ddc2..696ffbd 100644 --- a/http.c +++ b/http.c @@ -30,7 +30,9 @@ #include #include #include +#include #include +#include #include #include @@ -317,7 +319,7 @@ static int run_csd_script(struct openconnect_info *vpninfo, char *buf, int bufle return err; } write(fd, buf, buflen); - fchmod(fd, 0700); + fchmod(fd, 0755); close(fd); if (!fork()) { @@ -326,6 +328,28 @@ static int run_csd_script(struct openconnect_info *vpninfo, char *buf, int bufle char *csd_argv[32]; int i = 0; + if (vpninfo->uid != getuid()) { + struct passwd *pw; + + if (setuid(vpninfo->uid)) { + fprintf(stderr, "Failed to set uid %d\n", + vpninfo->uid); + exit(1); + } + if (!(pw = getpwuid(vpninfo->uid))) { + fprintf(stderr, "Invalid user uid=%d\n", + vpninfo->uid); + exit(1); + } + setenv("HOME", pw->pw_dir, 1); + chdir(pw->pw_dir); + } + if (vpninfo->uid == 0) { + fprintf(stderr, "Warning: you are running unsecure " + "CSD code with root privileges\n" + "\t Use command line option \"-U\"\n"); + } + csd_argv[i++] = fname; csd_argv[i++] = "-ticket"; asprintf(&csd_argv[i++], "\"%s\"", vpninfo->csd_ticket); diff --git a/main.c b/main.c index b831417..bab814e 100644 --- a/main.c +++ b/main.c @@ -155,7 +155,6 @@ int main(int argc, char **argv) struct utsname utsbuf; int cookieonly = 0; int use_syslog = 0; - uid_t uid = getuid(); int opt; openconnect_init_openssl(); @@ -176,6 +175,7 @@ int main(int argc, char **argv) vpninfo->max_qlen = 10; vpninfo->reconnect_interval = RECONNECT_INTERVAL_MIN; vpninfo->reconnect_timeout = 300; + vpninfo->uid = getuid(); if (RAND_bytes(vpninfo->dtls_secret, sizeof(vpninfo->dtls_secret)) != 1) { fprintf(stderr, "Failed to initialise DTLS secret\n"); @@ -293,7 +293,7 @@ int main(int argc, char **argv) break; case 'U': { char *strend; - uid = strtol(optarg, &strend, 0); + vpninfo->uid = strtol(optarg, &strend, 0); if (strend[0]) { struct passwd *pw = getpwnam(optarg); if (!pw) { @@ -301,7 +301,7 @@ int main(int argc, char **argv) optarg); exit(1); } - uid = pw->pw_uid; + vpninfo->uid = pw->pw_uid; } break; } @@ -385,9 +385,9 @@ int main(int argc, char **argv) exit(1); } - if (uid != getuid()) { - if (setuid(uid)) { - fprintf(stderr, "Failed to set uid %d\n", uid); + if (vpninfo->uid != getuid()) { + if (setuid(vpninfo->uid)) { + fprintf(stderr, "Failed to set uid %d\n", vpninfo->uid); exit(1); } } diff --git a/openconnect.h b/openconnect.h index 2ace6ea..d29fea1 100644 --- a/openconnect.h +++ b/openconnect.h @@ -161,6 +161,7 @@ struct openconnect_info { char *authgroup; int nopasswd; char *dtls_ciphers; + uid_t uid; char *cookie; struct vpn_option *cookies;