Skip to content

Commit

Permalink
Merge branch 'master' of gitlab.com:dlenski/openconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
dwmw2 committed Aug 9, 2018
2 parents 6eb0a6e + 37fbeed commit f5b0922
Show file tree
Hide file tree
Showing 22 changed files with 264 additions and 120 deletions.
6 changes: 3 additions & 3 deletions auth-globalprotect.c
Expand Up @@ -173,6 +173,7 @@ static int parse_login_xml(struct openconnect_info *vpninfo, xmlNode *xml_node)
free(value);
value = NULL;
}
append_opt(cookie, "computer", vpninfo->localname);

if (!buf_error(cookie)) {
vpninfo->cookie = cookie->data;
Expand Down Expand Up @@ -294,7 +295,7 @@ static int parse_portal_xml(struct openconnect_info *vpninfo, xmlNode *xml_node)
buf_append(buf, " </ServerList>\n</GPPortal>\n");
if ((result = buf_error(buf)))
goto out;
if ((result = vpninfo->write_new_config(vpninfo, buf->data, buf->pos)))
if ((result = vpninfo->write_new_config(vpninfo->cbdata, buf->data, buf->pos)))
goto out;
}

Expand Down Expand Up @@ -475,8 +476,7 @@ int gpst_bye(struct openconnect_info *vpninfo, const char *reason)
*
* Don't blame me. I didn't design this.
*/
append_opt(request_body, "computer", vpninfo->localname);
buf_append(request_body, "&%s", vpninfo->cookie);
buf_append(request_body, "%s", vpninfo->cookie);
if ((result = buf_error(request_body)))
goto out;

Expand Down
1 change: 0 additions & 1 deletion auth-juniper.c
Expand Up @@ -47,7 +47,6 @@ void oncp_common_headers(struct openconnect_info *vpninfo, struct oc_text_buf *b
{
http_common_headers(vpninfo, buf);

buf_append(buf, "Connection: close\r\n");
// buf_append(buf, "Content-Length: 256\r\n");
buf_append(buf, "NCP-Version: 3\r\n");
// buf_append(buf, "Accept-Encoding: gzip\r\n");
Expand Down
25 changes: 17 additions & 8 deletions cstp.c
Expand Up @@ -462,6 +462,8 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)

if (!strcmp(buf + 7, "Keepalive")) {
vpninfo->ssl_times.keepalive = atol(colon);
} else if (!strcmp(buf + 7, "Idle-Timeout")) {
vpninfo->idle_timeout = atol(colon);
} else if (!strcmp(buf + 7, "DPD")) {
int j = atol(colon);
if (j && (!vpninfo->ssl_times.dpd || j < vpninfo->ssl_times.dpd))
Expand Down Expand Up @@ -729,7 +731,11 @@ static int cstp_reconnect(struct openconnect_info *vpninfo)
int decompress_and_queue_packet(struct openconnect_info *vpninfo, int compr_type,
unsigned char *buf, int len)
{
struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->ip_info.mtu);
/* Some servers send us packets that are larger than
negotiated MTU after decompression. We reserve some extra
space to handle that */
int receive_mtu = MAX(16384, vpninfo->ip_info.mtu);
struct pkt *new = malloc(sizeof(struct pkt) + receive_mtu);
const char *comprname = "";

if (!new)
Expand All @@ -746,7 +752,7 @@ int decompress_and_queue_packet(struct openconnect_info *vpninfo, int compr_type
vpninfo->inflate_strm.avail_in = len - 4;

vpninfo->inflate_strm.next_out = new->data;
vpninfo->inflate_strm.avail_out = vpninfo->ip_info.mtu;
vpninfo->inflate_strm.avail_out = receive_mtu;
vpninfo->inflate_strm.total_out = 0;

if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
Expand All @@ -768,7 +774,7 @@ int decompress_and_queue_packet(struct openconnect_info *vpninfo, int compr_type
} else if (compr_type == COMPR_LZS) {
comprname = "LZS";

new->len = lzs_decompress(new->data, vpninfo->ip_info.mtu, buf, len);
new->len = lzs_decompress(new->data, receive_mtu, buf, len);
if (new->len < 0) {
len = new->len;
if (len == 0)
Expand All @@ -781,7 +787,7 @@ int decompress_and_queue_packet(struct openconnect_info *vpninfo, int compr_type
#ifdef HAVE_LZ4
} else if (compr_type == COMPR_LZ4) {
comprname = "LZ4";
new->len = LZ4_decompress_safe((void *)buf, (void *)new->data, len, vpninfo->ip_info.mtu);
new->len = LZ4_decompress_safe((void *)buf, (void *)new->data, len, receive_mtu);
if (new->len <= 0) {
len = new->len;
if (len == 0)
Expand Down Expand Up @@ -882,18 +888,21 @@ int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
and add POLLOUT. As it is, though, it'll just chew CPU time in that
fairly unlikely situation, until the write backlog clears. */
while (1) {
int len = MAX(16384, vpninfo->deflate_pkt_size ? : vpninfo->ip_info.mtu);
int payload_len;
/* Some servers send us packets that are larger than
negotiated MTU. We reserve some extra space to
handle that */
int receive_mtu = MAX(16384, vpninfo->deflate_pkt_size ? : vpninfo->ip_info.mtu);
int len, payload_len;

if (!vpninfo->cstp_pkt) {
vpninfo->cstp_pkt = malloc(sizeof(struct pkt) + len);
vpninfo->cstp_pkt = malloc(sizeof(struct pkt) + receive_mtu);
if (!vpninfo->cstp_pkt) {
vpn_progress(vpninfo, PRG_ERR, _("Allocation failed\n"));
break;
}
}

len = ssl_nonblock_read(vpninfo, vpninfo->cstp_pkt->cstp.hdr, len + 8);
len = ssl_nonblock_read(vpninfo, vpninfo->cstp_pkt->cstp.hdr, receive_mtu + 8);
if (!len)
break;
if (len < 0)
Expand Down
12 changes: 11 additions & 1 deletion esp.c
Expand Up @@ -106,10 +106,14 @@ int esp_mainloop(struct openconnect_info *vpninfo, int *timeout)
struct esp *esp = &vpninfo->esp_in[vpninfo->current_esp_in];
struct esp *old_esp = &vpninfo->esp_in[vpninfo->current_esp_in ^ 1];
struct pkt *this;
int receive_mtu = MAX(2048, vpninfo->ip_info.mtu + 256);
int work_done = 0;
int ret;

/* Some servers send us packets that are larger than negotiated
MTU, or lack the ability to negotiate MTU (see gpst.c). We
reserve some extra space to handle that */
int receive_mtu = MAX(2048, vpninfo->ip_info.mtu + 256);

if (vpninfo->dtls_state == DTLS_SLEEPING) {
if (ka_check_deadline(timeout, time(NULL), vpninfo->new_dtls_started + vpninfo->dtls_attempt_period)
|| vpninfo->dtls_need_reconnect) {
Expand Down Expand Up @@ -142,6 +146,7 @@ int esp_mainloop(struct openconnect_info *vpninfo, int *timeout)
len);
work_done = 1;

/* both supported algos (SHA1 and MD5) have 12-byte MAC lengths (RFC2403 and RFC2404) */
if (len <= sizeof(pkt->esp) + 12)
continue;

Expand All @@ -165,6 +170,11 @@ int esp_mainloop(struct openconnect_info *vpninfo, int *timeout)
continue;
}

/* Possible values of the Next Header field are:
0x04: IP[v4]-in-IP
0x05: supposed to mean Internet Stream Protocol
(XXX: but used for LZO compressed packets by Juniper)
0x29: IPv6 encapsulation */
if (pkt->data[len - 1] != 0x04 && pkt->data[len - 1] != 0x29 &&
pkt->data[len - 1] != 0x05) {
vpn_progress(vpninfo, PRG_ERR,
Expand Down
30 changes: 20 additions & 10 deletions gpst.c
Expand Up @@ -481,6 +481,11 @@ static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_
else if (!xmlnode_get_text(xml_node, "mtu", &s)) {
vpninfo->ip_info.mtu = atoi(s);
free(s);
} else if (!xmlnode_get_text(xml_node, "disconnect-on-idle", &s)) {
int sec = atoi(s);
vpn_progress(vpninfo, PRG_INFO, _("Idle timeout is %d minutes.\n"), sec/60);
vpninfo->idle_timeout = sec;
free(s);
} else if (!xmlnode_get_text(xml_node, "ssl-tunnel-url", &s)) {
free(vpninfo->urlpath);
vpninfo->urlpath = s;
Expand Down Expand Up @@ -630,7 +635,7 @@ static int gpst_get_config(struct openconnect_info *vpninfo)
vpninfo->ip_info.mtu = calculate_mtu(vpninfo, !no_esp_reason);
vpn_progress(vpninfo, PRG_ERR,
_("No MTU received. Calculated %d for %s%s\n"), vpninfo->ip_info.mtu,
no_esp_reason ? "TLS tunnel. " : "ESP tunnel", no_esp_reason ? : "");
no_esp_reason ? "SSL tunnel. " : "ESP tunnel", no_esp_reason ? : "");
/* return -EINVAL; */
}
if (!vpninfo->ip_info.addr) {
Expand Down Expand Up @@ -789,9 +794,8 @@ static int build_csd_token(struct openconnect_info *vpninfo)
if (!vpninfo->csd_token)
return -ENOMEM;

/* use localname and cookie (excluding volatile authcookie and preferred-ip) to build md5sum */
/* use cookie (excluding volatile authcookie and preferred-ip) to build md5sum */
buf = buf_alloc();
append_opt(buf, "computer", vpninfo->localname);
filter_opts(buf, vpninfo->cookie, "authcookie,preferred-ip", 0);
if (buf_error(buf))
goto out;
Expand All @@ -815,9 +819,8 @@ static int check_or_submit_hip_report(struct openconnect_info *vpninfo, const ch
const char *method = "POST";
char *xml_buf=NULL, *orig_path;

/* cookie gives us these fields: authcookie, portal, user, domain, and (maybe the unnecessary) preferred-ip */
/* cookie gives us these fields: authcookie, portal, user, domain, computer, and (maybe the unnecessary) preferred-ip */
buf_append(request_body, "client-role=global-protect-full&%s", vpninfo->cookie);
append_opt(request_body, "computer", vpninfo->localname);
append_opt(request_body, "client-ip", vpninfo->ip_info.addr);
if (report) {
/* XML report contains many characters requiring URL-encoding (%xx) */
Expand Down Expand Up @@ -887,9 +890,15 @@ static int run_hip_script(struct openconnect_info *vpninfo)
buf_append_bytes(report_buf, b, i);

waitpid(child, &status, 0);
if (status != 0) {
if (!WIFEXITED(status)) {
vpn_progress(vpninfo, PRG_ERR,
_("HIP script '%s' exited abnormally\n"),
vpninfo->csd_wrapper);
ret = -EINVAL;
} else if (WEXITSTATUS(status) != 0) {
vpn_progress(vpninfo, PRG_ERR,
_("HIP script returned non-zero status: %d\n"), status);
_("HIP script '%s' returned non-zero status: %d\n"),
vpninfo->csd_wrapper, WEXITSTATUS(status));
ret = -EINVAL;
} else {
ret = check_or_submit_hip_report(vpninfo, report_buf->data);
Expand All @@ -912,8 +921,6 @@ static int run_hip_script(struct openconnect_info *vpninfo)
hip_argv[i++] = openconnect_utf8_to_legacy(vpninfo, vpninfo->csd_wrapper);
hip_argv[i++] = (char *)"--cookie";
hip_argv[i++] = vpninfo->cookie;
hip_argv[i++] = (char *)"--computer";
hip_argv[i++] = vpninfo->localname;
hip_argv[i++] = (char *)"--client-ip";
hip_argv[i++] = (char *)vpninfo->ip_info.addr;
hip_argv[i++] = (char *)"--md5";
Expand Down Expand Up @@ -1014,7 +1021,10 @@ int gpst_mainloop(struct openconnect_info *vpninfo, int *timeout)
goto do_reconnect;

while (1) {
int receive_mtu = MAX(2048, vpninfo->ip_info.mtu + 256);
/* Some servers send us packets that are larger than
negotiated MTU. We reserve some extra space to
handle that */
int receive_mtu = MAX(16384, vpninfo->ip_info.mtu);
int len, payload_len;

if (!vpninfo->cstp_pkt) {
Expand Down
12 changes: 4 additions & 8 deletions hipreport.sh
Expand Up @@ -6,10 +6,7 @@
#
# --cookie: a URL-encoded string, as output by openconnect
# --authenticate --protocol=gp, which includes parameters
# --from the /ssl-vpn/login.esp response
#
# --computer: local hostname, which can be overriden with
# --openconnect local-hostname=HOSTNAME
# from the /ssl-vpn/login.esp response
#
# --client-ip: IPv4 address allocated by the GlobalProtect VPN for
# this client (included in /ssl-vpn/getconfig.esp
Expand All @@ -22,26 +19,25 @@

# Read command line arguments into variables
COOKIE=
COMPUTER=
IP=
MD5=

while [ "$1" ]; do
if [ "$1" = "--cookie" ]; then shift; COOKIE="$1"; fi
if [ "$1" = "--computer" ]; then shift; COMPUTER="$1"; fi
if [ "$1" = "--client-ip" ]; then shift; IP="$1"; fi
if [ "$1" = "--md5" ]; then shift; MD5="$1"; fi
shift
done

if [ -z "$COOKIE" -o -z "$COMPUTER" -o -z "$IP" -o -z "$MD5" ]; then
if [ -z "$COOKIE" -o -z "$IP" -o -z "$MD5" ]; then
echo "Parameters --cookie, --computer, --client-ip, and --md5 are required" >&2
exit 1;
fi

# Extract username and domain from cookie
# Extract username and domain and computer from cookie
USER=$(echo "$COOKIE" | sed -rn 's/(.+&|^)user=([^&]+)(&.+|$)/\2/p')
DOMAIN=$(echo "$COOKIE" | sed -rn 's/(.+&|^)domain=([^&]+)(&.+|$)/\2/p')
COMPUTER=$(echo "$COOKIE" | sed -rn 's/(.+&|^)computer=([^&]+)(&.+|$)/\2/p')

# Timestamp in the format expected by GlobalProtect server
NOW=$(date +'%m/%d/%Y %H:%M:%S')
Expand Down
2 changes: 1 addition & 1 deletion java/README
Expand Up @@ -11,7 +11,7 @@ From the top level, run:
make
cd java
ant
sudo java -Djava.library.path=../.libs -jar dist/example.jar <server_ip>
sudo java -Djava.library.path=../.libs -jar dist/example.jar <server_name> [protocol]

If ocproxy[1] is installed somewhere in your $PATH, this can be run as a
non-root user and it should be pingable from across the VPN.
Expand Down
46 changes: 41 additions & 5 deletions java/src/com/example/LibTest.java
Expand Up @@ -204,26 +204,60 @@ private static void printIPInfo(LibOpenConnect.IPInfo ip) {
System.out.println("");
}

private static void describeProtocol(LibOpenConnect.VPNProto vp) {
ArrayList<String> flags = new ArrayList<String>();
if ((vp.flags & LibOpenConnect.OC_PROTO_PROXY) != 0) flags.add("proxy");
if ((vp.flags & LibOpenConnect.OC_PROTO_CSD) != 0) flags.add("CSD");
if ((vp.flags & LibOpenConnect.OC_PROTO_AUTH_CERT) != 0) flags.add("auth-cert");
if ((vp.flags & LibOpenConnect.OC_PROTO_AUTH_OTP) != 0) flags.add("auth-otp");
if ((vp.flags & LibOpenConnect.OC_PROTO_AUTH_OTP) != 0) flags.add("auth-stoken");

System.out.println(" " + vp.name +
") PRETTY_NAME=" + vp.prettyName +
", DESCRIPTION=" + vp.description +
", FLAGS=" + String.join("+", flags));
}

public static void main(String argv[]) {
System.loadLibrary("openconnect-wrapper");
LibOpenConnect lib = new TestLib();
String server_name, protocol;

if (argv.length != 1)
die("usage: LibTest <server_name>");
if (argv.length != 1 && argv.length != 2)
die("usage: LibTest <server_name> [protocol]");

server_name = argv[0];
protocol = argv.length == 2 ? argv[1] : null;

System.out.println("OpenConnect version: " + lib.getVersion());
System.out.println(" PKCS=" + lib.hasPKCS11Support() +
", TSS=" + lib.hasTSSBlobSupport() +
", STOKEN=" + lib.hasStokenSupport() +
", OATH=" + lib.hasOATHSupport() +
", YUBIOATH=" + lib.hasYubiOATHSupport());

System.out.println("Supported protocols:");
for (LibOpenConnect.VPNProto vp : lib.getSupportedProtocols())
describeProtocol(vp);
if (protocol == null) {
System.out.println("Using default VPN protocol of " + lib.getProtocol());
} else {
System.out.println("Setting VPN protocol to " + protocol);
if (lib.setProtocol(protocol) != 0)
die("Error setting VPN protocol");
}

lib.setReportedOS("win");
lib.setLogLevel(lib.PRG_DEBUG);
//lib.setTokenMode(LibOpenConnect.OC_TOKEN_MODE_STOKEN, null);
if (new File("csd.sh").exists()) {
lib.setCSDWrapper("csd.sh", null, null);
String csd_wrapper = "./csd-" + lib.getProtocol() + ".sh";
if (new File(csd_wrapper).exists()) {
System.out.println("Using CSD wrapper script " + csd_wrapper);
lib.setCSDWrapper(csd_wrapper, null, null);
} else {
System.out.println("Skipping CSD wrapper (script " + csd_wrapper + " doesn't exist)");
}
lib.parseURL(argv[0]);
lib.parseURL(server_name);
lib.setSystemTrust(true);
int ret = lib.obtainCookie();
if (ret < 0)
Expand All @@ -241,6 +275,8 @@ else if (ret > 0)
if (lib.makeCSTPConnection() != 0)
die("Error establishing VPN link");

int idleTimeout = lib.getIdleTimeout();
System.out.println("Idle Timeout: " + idleTimeout + " seconds");
printIPInfo(lib.getIPInfo());

if (lib.setupDTLS(60) != 0)
Expand Down

0 comments on commit f5b0922

Please sign in to comment.