Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Run Cisco CSD script as child, not daemonized grandchild
This allows us to capture a failure in the CSD script/binary much more
quickly, rather than spinning endlessly (see #108 for one of many examples
where this confuses users).

Tested with both “real” CSD trojan binaries and wrapper script, as well as
`trojans/csd-post.sh`.

GP already does this for the HIP script, and it works fine, including with
NM and Android clients based on libopenconnect.

Signed-off-by: Daniel Lenski <dlenski@gmail.com>
  • Loading branch information
dlenski authored and dwmw2 committed Mar 30, 2020
1 parent c00bdc4 commit ad3ef66
Showing 1 changed file with 82 additions and 74 deletions.
156 changes: 82 additions & 74 deletions auth.c
Expand Up @@ -1124,85 +1124,93 @@ static int run_csd_script(struct openconnect_info *vpninfo, char *buf, int bufle
/* in parent: must reap child process */
int status;
waitpid(child, &status, 0);
} else {
/* in child: run CSD script as daemon */
if (fork()) {
/* child must use _exit(2) */
_exit(0);
if (!WIFEXITED(status)) {
vpn_progress(vpninfo, PRG_ERR,
_("CSD script '%s' exited abnormally\n"),
vpninfo->csd_wrapper ?: fname);
ret = -EINVAL;
} else if (WEXITSTATUS(status) != 0) {
vpn_progress(vpninfo, PRG_ERR,
_("CSD script '%s' returned non-zero status: %d\n"),
vpninfo->csd_wrapper ?: fname, WEXITSTATUS(status));
ret = -EINVAL;
} else {
/* in grandchild: will be reaped by init */
char scertbuf[MD5_SIZE * 2 + 1];
char ccertbuf[MD5_SIZE * 2 + 1];
char *csd_argv[32];
int i = 0;

if (set_csd_user(vpninfo) < 0)
exit(1);
if (getuid() == 0 && !vpninfo->csd_wrapper) {
fprintf(stderr, _("Warning: you are running insecure "
"CSD code with root privileges\n"
"\t Use command line option \"--csd-user\"\n"));
}
/* Spurious stdout output from the CSD trojan will break both
the NM tool and the various cookieonly modes. */
dup2(2, 1);
if (vpninfo->csd_wrapper)
csd_argv[i++] = openconnect_utf8_to_legacy(vpninfo,
vpninfo->csd_wrapper);
csd_argv[i++] = fname;
csd_argv[i++] = (char *)"-ticket";
if (asprintf(&csd_argv[i++], "\"%s\"", vpninfo->csd_ticket) == -1)
goto out;
csd_argv[i++] = (char *)"-stub";
csd_argv[i++] = (char *)"\"0\"";
csd_argv[i++] = (char *)"-group";
if (asprintf(&csd_argv[i++], "\"%s\"", vpninfo->authgroup?:"") == -1)
goto out;

openconnect_local_cert_md5(vpninfo, ccertbuf);
scertbuf[0] = 0;
get_cert_md5_fingerprint(vpninfo, vpninfo->peer_cert, scertbuf);
csd_argv[i++] = (char *)"-certhash";
if (asprintf(&csd_argv[i++], "\"%s:%s\"", scertbuf, ccertbuf) == -1)
goto out;


csd_argv[i++] = (char *)"-url";
if (asprintf(&csd_argv[i++], "\"https://%s%s\"", openconnect_get_hostname(vpninfo), vpninfo->csd_starturl) == -1)
goto out;

csd_argv[i++] = (char *)"-langselen";
csd_argv[i++] = NULL;

if (setenv("CSD_SHA256", openconnect_get_peer_cert_hash(vpninfo)+11, 1)) /* remove initial 'pin-sha256:' */
goto out;
if (setenv("CSD_TOKEN", vpninfo->csd_token, 1))
goto out;
if (setenv("CSD_HOSTNAME", openconnect_get_hostname(vpninfo), 1))
goto out;

apply_script_env(vpninfo->csd_env);
free(vpninfo->urlpath);
vpninfo->urlpath = strdup(vpninfo->csd_waiturl +
(vpninfo->csd_waiturl[0] == '/' ? 1 : 0));
vpninfo->csd_scriptname = strdup(fname);
http_add_cookie(vpninfo, "sdesktop", vpninfo->csd_token, 1);
ret = 0;
}

execv(csd_argv[0], csd_argv);
free(vpninfo->csd_stuburl);
vpninfo->csd_stuburl = NULL;
free(vpninfo->csd_waiturl);
vpninfo->csd_waiturl = NULL;

out:
vpn_progress(vpninfo, PRG_ERR,
_("Failed to exec CSD script %s\n"), csd_argv[0]);
exit(1);
}
return ret;
} else {
/* in child: will be reaped by init */
char scertbuf[MD5_SIZE * 2 + 1];
char ccertbuf[MD5_SIZE * 2 + 1];
char *csd_argv[32];
int i = 0;

if (set_csd_user(vpninfo) < 0)
exit(1);
if (getuid() == 0 && !vpninfo->csd_wrapper) {
fprintf(stderr, _("Warning: you are running insecure "
"CSD code with root privileges\n"
"\t Use command line option \"--csd-user\"\n"));
}
/* Spurious stdout output from the CSD trojan will break both
the NM tool and the various cookieonly modes. */
dup2(2, 1);
if (vpninfo->csd_wrapper)
csd_argv[i++] = openconnect_utf8_to_legacy(vpninfo,
vpninfo->csd_wrapper);
csd_argv[i++] = fname;
csd_argv[i++] = (char *)"-ticket";
if (asprintf(&csd_argv[i++], "\"%s\"", vpninfo->csd_ticket) == -1)
goto out;
csd_argv[i++] = (char *)"-stub";
csd_argv[i++] = (char *)"\"0\"";
csd_argv[i++] = (char *)"-group";
if (asprintf(&csd_argv[i++], "\"%s\"", vpninfo->authgroup?:"") == -1)
goto out;

openconnect_local_cert_md5(vpninfo, ccertbuf);
scertbuf[0] = 0;
get_cert_md5_fingerprint(vpninfo, vpninfo->peer_cert, scertbuf);
csd_argv[i++] = (char *)"-certhash";
if (asprintf(&csd_argv[i++], "\"%s:%s\"", scertbuf, ccertbuf) == -1)
goto out;


csd_argv[i++] = (char *)"-url";
if (asprintf(&csd_argv[i++], "\"https://%s%s\"", openconnect_get_hostname(vpninfo), vpninfo->csd_starturl) == -1)
goto out;

csd_argv[i++] = (char *)"-langselen";
csd_argv[i++] = NULL;

if (setenv("CSD_SHA256", openconnect_get_peer_cert_hash(vpninfo)+11, 1)) /* remove initial 'pin-sha256:' */
goto out;
if (setenv("CSD_TOKEN", vpninfo->csd_token, 1))
goto out;
if (setenv("CSD_HOSTNAME", openconnect_get_hostname(vpninfo), 1))
goto out;

apply_script_env(vpninfo->csd_env);

execv(csd_argv[0], csd_argv);

out:
vpn_progress(vpninfo, PRG_ERR,
_("Failed to exec CSD script %s\n"), vpninfo->csd_wrapper ?: fname);
exit(1);
}

free(vpninfo->csd_stuburl);
vpninfo->csd_stuburl = NULL;
free(vpninfo->urlpath);
vpninfo->urlpath = strdup(vpninfo->csd_waiturl +
(vpninfo->csd_waiturl[0] == '/' ? 1 : 0));
free(vpninfo->csd_waiturl);
vpninfo->csd_waiturl = NULL;
vpninfo->csd_scriptname = strdup(fname);

http_add_cookie(vpninfo, "sdesktop", vpninfo->csd_token, 1);
return 0;
#endif /* !_WIN32 && !__native_client__ */
}

Expand Down

0 comments on commit ad3ef66

Please sign in to comment.