Skip to content

Commit

Permalink
Add accessor functions for library use, convert nm-auth-dialog to use…
Browse files Browse the repository at this point in the history
… them

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Mar 9, 2011
1 parent e30284d commit ad4c0f6
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 44 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -64,7 +64,7 @@ endif

OPENCONNECT_OBJS := xml.o main.o $(SSL_UI)
CONNECTION_OBJS := dtls.o cstp.o mainloop.o tun.o
AUTH_OBJECTS := ssl.o http.o version.o auth.o
AUTH_OBJECTS := ssl.o http.o version.o auth.o library.o

VERSION_OBJS := $(filter-out version.o, \
$(OPENCONNECT_OBJS) $(CONNECTION_OBJS) $(AUTH_OBJECTS))
Expand Down
133 changes: 133 additions & 0 deletions library.c
@@ -0,0 +1,133 @@
/*
* OpenConnect (SSL + DTLS) VPN client
*
* Copyright © 2008-2011 Intel Corporation.
*
* Authors: David Woodhouse <dwmw2@infradead.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to:
*
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

#include "openconnect-internal.h"

struct openconnect_info *openconnect_vpninfo_new (char *useragent,
openconnect_validate_peer_cert_fn validate_peer_cert,
openconnect_write_new_config_fn write_new_config,
openconnect_process_auth_form_fn process_auth_form,
openconnect_progress_fn progress)
{
struct openconnect_info *vpninfo = calloc (sizeof(*vpninfo), 1);

vpninfo->mtu = 1406;
vpninfo->ssl_fd = -1;
vpninfo->useragent = openconnect_create_useragent (useragent);
vpninfo->validate_peer_cert = validate_peer_cert;
vpninfo->write_new_config = write_new_config;
vpninfo->process_auth_form = process_auth_form;
vpninfo->progress = progress;

return vpninfo;
}

char *openconnect_get_hostname (struct openconnect_info *vpninfo)
{
return vpninfo->hostname;
}

void openconnect_set_hostname (struct openconnect_info *vpninfo, char *hostname)
{
vpninfo->hostname = hostname;
}

char *openconnect_get_urlpath (struct openconnect_info *vpninfo)
{
return vpninfo->urlpath;
}

void openconnect_set_urlpath (struct openconnect_info *vpninfo, char *urlpath)
{
vpninfo->urlpath = urlpath;
}

void openconnect_set_xmlsha1 (struct openconnect_info *vpninfo, char *xmlsha1, int size)
{
if (size != sizeof (vpninfo->xmlsha1))
return;

memcpy (&vpninfo->xmlsha1, xmlsha1, size);

}

void openconnect_set_cafile (struct openconnect_info *vpninfo, char *cafile)
{
vpninfo->cafile = cafile;
}

void openconnect_setup_csd (struct openconnect_info *vpninfo, uid_t uid, int silent, char *wrapper)
{
vpninfo->uid_csd = uid;
vpninfo->uid_csd_given = silent?2:1;
vpninfo->csd_wrapper = wrapper;
}

void openconnect_set_client_cert (struct openconnect_info *vpninfo, char *cert, char *sslkey)
{
vpninfo->cert = cert;
if (sslkey)
vpninfo->sslkey = sslkey;
else
vpninfo->sslkey = cert;
}

struct x509_st *openconnect_get_peer_cert (struct openconnect_info *vpninfo)
{
return SSL_get_peer_certificate(vpninfo->https_ssl);
}

int openconnect_get_port (struct openconnect_info *vpninfo)
{
return vpninfo->port;
}

char *openconnect_get_cookie (struct openconnect_info *vpninfo)
{
return vpninfo->cookie;
}

void openconnect_clear_cookie (struct openconnect_info *vpninfo)
{
memset(vpninfo->cookie, 0, sizeof(vpninfo->cookie));
}

void openconnect_reset_ssl (struct openconnect_info *vpninfo)
{
if (vpninfo->https_ssl) {
free(vpninfo->peer_addr);
vpninfo->peer_addr = NULL;
openconnect_close_https(vpninfo);
}
if (vpninfo->https_ctx) {
SSL_CTX_free(vpninfo->https_ctx);
vpninfo->https_ctx = NULL;
}
}

int openconnect_parse_url (struct openconnect_info *vpninfo, char *url)
{
return internal_parse_url (url, NULL, &vpninfo->hostname,
&vpninfo->port, &vpninfo->urlpath, 443);
}
76 changes: 33 additions & 43 deletions nm-auth-dialog.c
Expand Up @@ -38,8 +38,9 @@

#include "auth-dlg-settings.h"

#include "openconnect-internal.h"
#include "openconnect.h"

#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/ui.h>

Expand Down Expand Up @@ -642,7 +643,8 @@ static gboolean user_validate_cert(cert_data *data)
title = get_title(data->ui_data->vpn_name);
msg = g_strdup_printf("Certificate from VPN server \"%s\" failed verification.\n"
"Reason: %s\nDo you want to accept it?",
data->ui_data->vpninfo->hostname, data->reason);
openconnect_get_hostname(data->ui_data->vpninfo),
data->reason);

dlg = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_QUESTION,
GTK_BUTTONS_OK_CANCEL,
Expand Down Expand Up @@ -894,6 +896,7 @@ static int get_config(char *vpn_uuid, struct openconnect_info *vpninfo)
char *hostname;
char *group;
char *csd;
char *sslkey, *cert;
char *csd_wrapper;
char *pem_passphrase_fsid;

Expand Down Expand Up @@ -941,6 +944,7 @@ if (0) {
xmlconfig = get_gconf_setting(gcl, config_path, NM_OPENCONNECT_KEY_XMLCONFIG);
if (xmlconfig) {
unsigned char sha1[SHA_DIGEST_LENGTH];
char sha1_text[SHA_DIGEST_LENGTH * 2];
EVP_MD_CTX c;
int i;

Expand All @@ -949,42 +953,41 @@ if (0) {
EVP_MD_CTX_cleanup(&c);

for (i = 0; i < SHA_DIGEST_LENGTH; i++)
sprintf(&vpninfo->xmlsha1[i*2], "%02x", sha1[i]);
sprintf(&sha1_text[i*2], "%02x", sha1[i]);

openconnect_set_xmlsha1(vpninfo, sha1_text, sizeof(sha1_text));
parse_xmlconfig(xmlconfig);
g_free(xmlconfig);
}

vpninfo->cafile = get_gconf_setting(gcl, config_path, NM_OPENCONNECT_KEY_CACERT);
openconnect_set_cafile(vpninfo,
get_gconf_setting(gcl, config_path, NM_OPENCONNECT_KEY_CACERT));

csd = get_gconf_setting(gcl, config_path, "enable_csd_trojan");
if (csd && !strcmp(csd, "yes")) {
/* We're not running as root; we can't setuid(). */
vpninfo->uid_csd = getuid();
vpninfo->uid_csd_given = 2;

csd_wrapper = get_gconf_setting(gcl, config_path, "csd_wrapper");
if (csd_wrapper && csd_wrapper[0] )
vpninfo->csd_wrapper = csd_wrapper;
else
if (csd_wrapper && !csd_wrapper[0]) {
g_free(csd_wrapper);
csd_wrapper = NULL;
}
openconnect_setup_csd(vpninfo, getuid(), 1, csd_wrapper);
}
g_free(csd);

proxy = get_gconf_setting(gcl, config_path, "proxy");
if (proxy && proxy[0] && openconnect_set_http_proxy(vpninfo, proxy))
return -EINVAL;

vpninfo->cert = get_gconf_setting(gcl, config_path, NM_OPENCONNECT_KEY_USERCERT);
vpninfo->sslkey = get_gconf_setting(gcl, config_path, NM_OPENCONNECT_KEY_PRIVKEY);
if (!vpninfo->sslkey)
vpninfo->sslkey = vpninfo->cert;
cert = get_gconf_setting(gcl, config_path, NM_OPENCONNECT_KEY_USERCERT);
sslkey = get_gconf_setting(gcl, config_path, NM_OPENCONNECT_KEY_PRIVKEY);
openconnect_set_client_cert (vpninfo, cert, sslkey);

pem_passphrase_fsid = get_gconf_setting(gcl, config_path, "pem_passphrase_fsid");
if (pem_passphrase_fsid && vpninfo->sslkey && !strcmp(pem_passphrase_fsid, "yes"))
if (pem_passphrase_fsid && cert && !strcmp(pem_passphrase_fsid, "yes"))
openconnect_passphrase_from_fsid(vpninfo);
g_free(pem_passphrase_fsid);

return 0;
}

Expand Down Expand Up @@ -1075,7 +1078,7 @@ void write_progress(struct openconnect_info *info, int level, const char *fmt, .
static void print_peer_cert(struct openconnect_info *vpninfo)
{
char fingerprint[EVP_MAX_MD_SIZE * 2 + 1];
X509 *cert = SSL_get_peer_certificate(vpninfo->https_ssl);
X509 *cert = openconnect_get_peer_cert(vpninfo);

if (cert && !get_cert_sha1_fingerprint(vpninfo, cert, fingerprint))
printf("gwcert\n%s\n", fingerprint);
Expand Down Expand Up @@ -1124,11 +1127,12 @@ static gboolean cookie_obtained(auth_ui_data *ui_data)
}

printf("%s\n%s:%d\n", NM_OPENCONNECT_KEY_GATEWAY,
ui_data->vpninfo->hostname, ui_data->vpninfo->port);
openconnect_get_hostname(ui_data->vpninfo),
openconnect_get_port(ui_data->vpninfo));
printf("%s\n%s\n", NM_OPENCONNECT_KEY_COOKIE,
ui_data->vpninfo->cookie);
openconnect_get_cookie(ui_data->vpninfo));
print_peer_cert(ui_data->vpninfo);
memset((void *)ui_data->vpninfo->cookie, 0, strlen(ui_data->vpninfo->cookie));
openconnect_clear_cookie(ui_data->vpninfo);
printf("\n\n");
fflush(stdout);
ui_data->retval = 0;
Expand Down Expand Up @@ -1183,31 +1187,21 @@ static void connect_host(auth_ui_data *ui_data)

/* reset ssl context.
* TODO: this is probably not the way to go... */
if (ui_data->vpninfo->https_ssl) {
free(ui_data->vpninfo->peer_addr);
ui_data->vpninfo->peer_addr = NULL;
openconnect_close_https(ui_data->vpninfo);
}
if (ui_data->vpninfo->https_ctx) {
SSL_CTX_free(ui_data->vpninfo->https_ctx);
ui_data->vpninfo->https_ctx = NULL;
}
openconnect_reset_ssl(ui_data->vpninfo);

host_nr = gtk_combo_box_get_active(GTK_COMBO_BOX(ui_data->combo));
host = vpnhosts;
for (i = 0; i < host_nr; i++)
host = host->next;

if (internal_parse_url(host->hostaddress, NULL,
&ui_data->vpninfo->hostname, &ui_data->vpninfo->port,
&ui_data->vpninfo->urlpath, 443)) {
if (openconnect_parse_url(ui_data->vpninfo, host->hostaddress)) {
fprintf(stderr, "Failed to parse server URL '%s'\n",
host->hostaddress);
ui_data->vpninfo->hostname = g_strdup(host->hostaddress);
openconnect_set_hostname (ui_data->vpninfo, g_strdup(host->hostaddress));
}

if (!ui_data->vpninfo->urlpath && host->usergroup)
ui_data->vpninfo->urlpath = g_strdup(host->usergroup);
if (!openconnect_get_urlpath(ui_data->vpninfo) && host->usergroup)
openconnect_set_urlpath(ui_data->vpninfo, g_strdup(host->usergroup));

remember_gconf_key(ui_data, g_strdup("lasthost"), g_strdup(host->hostname));

Expand Down Expand Up @@ -1398,14 +1392,10 @@ static auth_ui_data *init_ui_data (char *vpn_name)
ui_data->cert_response_changed = g_cond_new();
ui_data->vpn_name = vpn_name;

ui_data->vpninfo = g_slice_new0(struct openconnect_info);
ui_data->vpninfo->mtu = 1406;
ui_data->vpninfo->useragent = openconnect_create_useragent("OpenConnect VPN Agent (NetworkManager)");
ui_data->vpninfo->ssl_fd = -1;
ui_data->vpninfo->write_new_config = write_new_config;
ui_data->vpninfo->progress = write_progress;
ui_data->vpninfo->validate_peer_cert = validate_peer_cert;
ui_data->vpninfo->process_auth_form = nm_process_auth_form;
ui_data->vpninfo = (void *)openconnect_vpninfo_new("OpenConnect VPN Agent (NetworkManager)",
validate_peer_cert, write_new_config,
nm_process_auth_form, write_progress);

#if 0
ui_data->vpninfo->proxy_factory = px_proxy_factory_new();
#endif
Expand Down
39 changes: 39 additions & 0 deletions openconnect.h
Expand Up @@ -86,6 +86,7 @@ struct oc_auth_form {
#define PRG_TRACE 3

struct openconnect_info;
/* We don't want to have to pull in OpenSSL stuff just for this */
struct x509_st;

int get_cert_sha1_fingerprint(struct openconnect_info *vpninfo,
Expand All @@ -98,3 +99,41 @@ char *openconnect_create_useragent(char *base);
void openconnect_init_openssl(void);

#endif /* __OPENCONNECT_H__ */

char *openconnect_get_vpn_name (struct openconnect_info *);
char *openconnect_get_hostname (struct openconnect_info *);
void openconnect_set_hostname (struct openconnect_info *, char *);
char *openconnect_get_urlpath (struct openconnect_info *);
void openconnect_set_urlpath (struct openconnect_info *, char *);
void openconnect_set_xmlsha1 (struct openconnect_info *, char *, int size);
void openconnect_set_cafile (struct openconnect_info *, char *);
void openconnect_setup_csd (struct openconnect_info *, uid_t, int silent, char *wrapper);
void openconnect_set_client_cert (struct openconnect_info *, char *cert, char *sslkey);
struct x509_st *openconnect_get_peer_cert (struct openconnect_info *);
int openconnect_get_port (struct openconnect_info *);
char *openconnect_get_cookie (struct openconnect_info *);
void openconnect_clear_cookie (struct openconnect_info *);
void openconnect_clear_peer_addr (struct openconnect_info *);
void openconnect_clear_https_ctx (struct openconnect_info *);

void openconnect_reset_ssl (struct openconnect_info *vpninfo);
int openconnect_parse_url (struct openconnect_info *vpninfo, char *url);


typedef int (*openconnect_validate_peer_cert_fn) (struct openconnect_info *vpninfo,
struct x509_st *cert, const char *reason);
typedef int (*openconnect_write_new_config_fn) (struct openconnect_info *vpninfo, char *buf,
int buflen);
typedef int (*openconnect_process_auth_form_fn) (struct openconnect_info *vpninfo,
struct oc_auth_form *form);
typedef void __attribute__ ((format(printf, 3, 4)))
(*openconnect_progress_fn) (struct openconnect_info *vpninfo, int level,
const char *fmt, ...);

struct openconnect_info *openconnect_vpninfo_new (char *useragent,
openconnect_validate_peer_cert_fn,
openconnect_write_new_config_fn,
openconnect_process_auth_form_fn,
openconnect_progress_fn);


0 comments on commit ad4c0f6

Please sign in to comment.