static struct oc_text_buf *get_qs(char **str) { struct oc_text_buf *res; int escaped = 0; char *p = *str; if (*p != '\"') return NULL; res = buf_alloc(); while (*++p) { if (!escaped && *p == '\"') { *str = p+1; if (buf_error(res)) break; return res; } if (escaped) escaped = 0; else if (*p == '\\') escaped = 1; buf_append_bytes(res, p, 1); } buf_free(res); return NULL; }
static SSL_SESSION *generate_dtls_session(struct openconnect_info *vpninfo, int dtlsver, const SSL_CIPHER *cipher) { struct oc_text_buf *buf = buf_alloc(); SSL_SESSION *dtls_session; const unsigned char *asn; uint16_t cid; buf_append_bytes(buf, "\x30\x80", 2); // SEQUENCE, indeterminate length buf_append_INTEGER(buf, 1 /* SSL_SESSION_ASN1_VERSION */); buf_append_INTEGER(buf, dtlsver); store_be16(&cid, SSL_CIPHER_get_id(cipher) & 0xffff); buf_append_OCTET_STRING(buf, &cid, 2); buf_append_OCTET_STRING(buf, vpninfo->dtls_session_id, sizeof(vpninfo->dtls_session_id)); buf_append_OCTET_STRING(buf, vpninfo->dtls_secret, sizeof(vpninfo->dtls_secret)); /* If the length actually fits in one byte (which it should), do * it that way. Else, leave it indeterminate and add two * end-of-contents octets to mark the end of the SEQUENCE. */ if (!buf_error(buf) && buf->pos <= 0x80) buf->data[1] = buf->pos - 2; else buf_append_bytes(buf, "\0\0", 2); if (buf_error(buf)) { vpn_progress(vpninfo, PRG_ERR, _("Failed to create SSL_SESSION ASN.1 for OpenSSL: %s\n"), strerror(buf_error(buf))); buf_free(buf); return NULL; } asn = (void *)buf->data; dtls_session = d2i_SSL_SESSION(NULL, &asn, buf->pos); buf_free(buf); if (!dtls_session) { vpn_progress(vpninfo, PRG_ERR, _("OpenSSL failed to parse SSL_SESSION ASN.1\n")); openconnect_report_ssl_errors(vpninfo); return NULL; } return dtls_session; }
static void buf_append_unq(struct oc_text_buf *buf, const char *str) { while (*str) { if (*str == '\"' || *str == '\\') buf_append(buf, "\\"); buf_append_bytes(buf, str, 1); str++; } }
static wchar_t *create_script_env(struct openconnect_info *vpninfo) { struct oc_vpn_option *opt; struct oc_text_buf *envbuf; wchar_t **oldenv, **p, *newenv = NULL; int nr_envs = 0, i; /* _wenviron is NULL until we call _wgetenv() */ (void)_wgetenv(L"PATH"); /* Take a copy of _wenviron (but not of its strings) */ for (p = _wenviron; *p; p++) nr_envs++; oldenv = malloc(nr_envs * sizeof(*oldenv)); if (!oldenv) return NULL; memcpy(oldenv, _wenviron, nr_envs * sizeof(*oldenv)); envbuf = buf_alloc(); /* Add the script environment variables, prodding out any members of oldenv which are obsoleted by them. */ for (opt = vpninfo->script_env; opt && !buf_error(envbuf); opt = opt->next) { struct oc_text_buf *buf; buf = buf_alloc(); buf_append_utf16le(buf, opt->option); buf_append_utf16le(buf, "="); if (buf_error(buf)) { buf_free(buf); goto err; } /* See if we can find it in the existing environment */ for (i = 0; i < nr_envs; i++) { if (oldenv[i] && !wcsncmp((wchar_t *)buf->data, oldenv[i], buf->pos / 2)) { oldenv[i] = NULL; break; } } if (opt->value) { buf_append_bytes(envbuf, buf->data, buf->pos); buf_append_utf16le(envbuf, opt->value); buf_append_bytes(envbuf, "\0\0", 2); } buf_free(buf); } for (i = 0; i < nr_envs && !buf_error(envbuf); i++) { if (oldenv[i]) buf_append_bytes(envbuf, oldenv[i], (wcslen(oldenv[i]) + 1) * sizeof(wchar_t)); } buf_append_bytes(envbuf, "\0\0", 2); if (!buf_error(envbuf)) { newenv = (wchar_t *)envbuf->data; envbuf->data = NULL; } err: free(oldenv); buf_free(envbuf); return newenv; }