2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2008-2012 Intel Corporation.
6 * Authors: David Woodhouse <dwmw2@infradead.org>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * version 2.1, as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA
30 #include LIBSTOKEN_HDR
33 #include <libxml/tree.h>
35 #include "openconnect-internal.h"
37 struct openconnect_info *openconnect_vpninfo_new (char *useragent,
38 openconnect_validate_peer_cert_vfn validate_peer_cert,
39 openconnect_write_new_config_vfn write_new_config,
40 openconnect_process_auth_form_vfn process_auth_form,
41 openconnect_progress_vfn progress,
44 struct openconnect_info *vpninfo = calloc (sizeof(*vpninfo), 1);
47 vpninfo->cert_expire_warning = 60 * 86400;
48 vpninfo->useragent = openconnect_create_useragent (useragent);
49 vpninfo->validate_peer_cert = validate_peer_cert;
50 vpninfo->write_new_config = write_new_config;
51 vpninfo->process_auth_form = process_auth_form;
52 vpninfo->progress = progress;
53 vpninfo->cbdata = privdata?:vpninfo;
54 vpninfo->cancel_fd = -1;
55 openconnect_set_reported_os(vpninfo, NULL);
58 bindtextdomain("openconnect", LOCALEDIR);
64 int openconnect_set_reported_os (struct openconnect_info *vpninfo, const char *os)
67 #if defined(__APPLE__)
70 os = sizeof(long) > 4 ? "linux-64" : "linux";
74 /* FIXME: is there a special platname for 64-bit Windows? */
75 if (!strcmp(os, "mac"))
76 vpninfo->csd_xmltag = "csdMac";
77 else if (!strcmp(os, "linux") || !strcmp(os, "linux-64"))
78 vpninfo->csd_xmltag = "csdLinux";
79 else if (!strcmp(os, "win"))
80 vpninfo->csd_xmltag = "csd";
84 vpninfo->platname = os;
88 static void free_optlist (struct vpn_option *opt)
90 struct vpn_option *next;
92 for (; opt; opt = next) {
100 void openconnect_vpninfo_free (struct openconnect_info *vpninfo)
102 openconnect_close_https(vpninfo, 1);
103 free(vpninfo->peer_addr);
104 free_optlist(vpninfo->cookies);
105 free_optlist(vpninfo->cstp_options);
106 free_optlist(vpninfo->dtls_options);
107 free(vpninfo->hostname);
108 free(vpninfo->urlpath);
109 free(vpninfo->redirect_url);
110 free(vpninfo->proxy_type);
111 free(vpninfo->proxy);
113 if (vpninfo->csd_scriptname) {
114 unlink(vpninfo->csd_scriptname);
115 free(vpninfo->csd_scriptname);
117 free(vpninfo->csd_token);
118 free(vpninfo->csd_ticket);
119 free(vpninfo->csd_stuburl);
120 free(vpninfo->csd_starturl);
121 free(vpninfo->csd_waiturl);
122 free(vpninfo->csd_preurl);
123 if (vpninfo->opaque_srvdata)
124 xmlFreeNode(vpninfo->opaque_srvdata);
126 /* These are const in openconnect itself, but for consistency of
127 the library API we do take ownership of the strings we're given,
128 and thus we have to free them too. */
129 free((void *)vpninfo->cafile);
130 if (vpninfo->cert != vpninfo->sslkey)
131 free((void *)vpninfo->sslkey);
132 free((void *)vpninfo->cert);
133 if (vpninfo->peer_cert) {
134 #if defined (OPENCONNECT_OPENSSL)
135 X509_free(vpninfo->peer_cert);
136 #elif defined (OPENCONNECT_GNUTLS)
137 gnutls_x509_crt_deinit(vpninfo->peer_cert);
139 vpninfo->peer_cert = NULL;
141 free(vpninfo->useragent);
143 if (vpninfo->stoken_pin)
144 free(vpninfo->stoken_pin);
145 if (vpninfo->stoken_ctx)
146 stoken_destroy(vpninfo->stoken_ctx);
148 /* No need to free deflate streams; they weren't initialised */
152 char *openconnect_get_hostname (struct openconnect_info *vpninfo)
154 return vpninfo->hostname;
157 void openconnect_set_hostname (struct openconnect_info *vpninfo, char *hostname)
159 vpninfo->hostname = hostname;
162 char *openconnect_get_urlpath (struct openconnect_info *vpninfo)
164 return vpninfo->urlpath;
167 void openconnect_set_urlpath (struct openconnect_info *vpninfo, char *urlpath)
169 vpninfo->urlpath = urlpath;
172 void openconnect_set_xmlsha1 (struct openconnect_info *vpninfo, const char *xmlsha1, int size)
174 if (size != sizeof (vpninfo->xmlsha1))
177 memcpy (&vpninfo->xmlsha1, xmlsha1, size);
180 void openconnect_set_cafile (struct openconnect_info *vpninfo, char *cafile)
182 vpninfo->cafile = cafile;
185 void openconnect_setup_csd (struct openconnect_info *vpninfo, uid_t uid, int silent, char *wrapper)
187 vpninfo->uid_csd = uid;
188 vpninfo->uid_csd_given = silent?2:1;
189 vpninfo->csd_wrapper = wrapper;
192 void openconnect_set_client_cert (struct openconnect_info *vpninfo, char *cert, char *sslkey)
194 vpninfo->cert = cert;
196 vpninfo->sslkey = sslkey;
198 vpninfo->sslkey = cert;
201 OPENCONNECT_X509 *openconnect_get_peer_cert (struct openconnect_info *vpninfo)
203 return vpninfo->peer_cert;
206 int openconnect_get_port (struct openconnect_info *vpninfo)
208 return vpninfo->port;
211 char *openconnect_get_cookie (struct openconnect_info *vpninfo)
213 return vpninfo->cookie;
216 void openconnect_clear_cookie (struct openconnect_info *vpninfo)
219 memset(vpninfo->cookie, 0, strlen(vpninfo->cookie));
222 void openconnect_reset_ssl (struct openconnect_info *vpninfo)
224 openconnect_close_https(vpninfo, 0);
225 if (vpninfo->peer_addr) {
226 free(vpninfo->peer_addr);
227 vpninfo->peer_addr = NULL;
231 int openconnect_parse_url (struct openconnect_info *vpninfo, char *url)
236 if (vpninfo->peer_addr) {
237 free(vpninfo->peer_addr);
238 vpninfo->peer_addr = NULL;
241 free(vpninfo->hostname);
242 vpninfo->hostname = NULL;
243 free(vpninfo->urlpath);
244 vpninfo->urlpath = NULL;
246 ret = internal_parse_url (url, &scheme, &vpninfo->hostname,
247 &vpninfo->port, &vpninfo->urlpath, 443);
250 vpn_progress(vpninfo, PRG_ERR,
251 _("Failed to parse server URL '%s'\n"),
255 if (scheme && strcmp(scheme, "https")) {
256 vpn_progress(vpninfo, PRG_ERR,
257 _("Only https:// permitted for server URL\n"));
264 void openconnect_set_cert_expiry_warning (struct openconnect_info *vpninfo,
267 vpninfo->cert_expire_warning = seconds;
270 void openconnect_set_cancel_fd (struct openconnect_info *vpninfo, int fd)
272 vpninfo->cancel_fd = fd;
275 const char *openconnect_get_version (void)
277 return openconnect_version_str;
280 int openconnect_has_pkcs11_support(void)
282 #if defined (OPENCONNECT_GNUTLS) && defined (HAVE_P11KIT)
289 #if defined (OPENCONNECT_OPENSSL) && defined (HAVE_ENGINE)
290 #include <openssl/engine.h>
292 int openconnect_has_tss_blob_support(void)
294 #if defined (OPENCONNECT_OPENSSL) && defined (HAVE_ENGINE)
297 ENGINE_load_builtin_engines();
299 e = ENGINE_by_id("tpm");
304 #elif defined (OPENCONNECT_GNUTLS) && defined (HAVE_TROUSERS)
310 int openconnect_has_stoken_support(void)
320 * Enable software token generation if use_stoken == 1.
322 * If token_str is not NULL, try to parse the string. Otherwise, try to read
323 * the token data from ~/.stokenrc
326 * = -EOPNOTSUPP, if libstoken is not available
327 * = -EINVAL, if the token string is invalid (token_str was provided)
328 * = -ENOENT, if ~/.stokenrc is missing (token_str was NULL)
329 * = -EIO, for other libstoken failures
332 int openconnect_set_stoken_mode (struct openconnect_info *vpninfo,
333 int use_stoken, const char *token_str)
338 vpninfo->use_stoken = 0;
342 if (!vpninfo->stoken_ctx) {
343 vpninfo->stoken_ctx = stoken_new();
344 if (!vpninfo->stoken_ctx)
349 stoken_import_string(vpninfo->stoken_ctx, token_str) :
350 stoken_import_rcfile(vpninfo->stoken_ctx, NULL);
354 vpninfo->use_stoken = 1;