From: Andreas Steffen Date: Tue, 18 May 2010 11:51:15 +0000 (+0200) Subject: implemented xauth as a pluto plugin X-Git-Tag: 4.4.1~255 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=26ec52a4053735c581f2372e782e31497e139be7;p=thirdparty%2Fstrongswan.git implemented xauth as a pluto plugin --- diff --git a/configure.in b/configure.in index 976d99bba8..b1a4e74fdc 100644 --- a/configure.in +++ b/configure.in @@ -127,6 +127,7 @@ ARG_ENABL_SET([manager], [enable web management console (proof of concept ARG_ENABL_SET([mediation], [enable IKEv2 Mediation Extension.]) ARG_ENABL_SET([integrity-test], [enable integrity testing of libstrongswan and plugins.]) ARG_DISBL_SET([pluto], [disable the IKEv1 keying daemon pluto.]) +ARG_DISBL_SET([xauth], [disable xauth plugin.]) ARG_DISBL_SET([threads], [disable the use of threads in pluto. Charon always uses threads.]) ARG_DISBL_SET([charon], [disable the IKEv2 keying daemon charon.]) ARG_DISBL_SET([tools], [disable additional utilities (openac, scepclient and pki).]) @@ -746,6 +747,9 @@ if test x$gmp = xtrue; then libstrongswan_plugins=${libstrongswan_plugins}" gmp" pluto_plugins=${pluto_plugins}" gmp" fi +if test x$xauth = xtrue; then + pluto_plugins=${pluto_plugins}" xauth" +fi if test x$attr = xtrue; then libhydra_plugins=${libhydra_plugins}" attr" fi @@ -789,7 +793,6 @@ AM_CONDITIONAL(USE_HMAC, test x$hmac = xtrue) AM_CONDITIONAL(USE_XCBC, test x$xcbc = xtrue) AM_CONDITIONAL(USE_MYSQL, test x$mysql = xtrue) AM_CONDITIONAL(USE_SQLITE, test x$sqlite = xtrue) -AM_CONDITIONAL(USE_ATTR_SQL, test x$attr_sql = xtrue -o x$sql = xtrue) AM_CONDITIONAL(USE_PADLOCK, test x$padlock = xtrue) AM_CONDITIONAL(USE_OPENSSL, test x$openssl = xtrue) AM_CONDITIONAL(USE_GCRYPT, test x$gcrypt = xtrue) @@ -806,9 +809,7 @@ AM_CONDITIONAL(USE_ANDROID, test x$android = xtrue) AM_CONDITIONAL(USE_SMP, test x$smp = xtrue) AM_CONDITIONAL(USE_SQL, test x$sql = xtrue) AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue) -AM_CONDITIONAL(USE_ATTR, test x$attr = xtrue) AM_CONDITIONAL(USE_DHCP, test x$dhcp = xtrue) -AM_CONDITIONAL(USE_RESOLVE, test x$resolve = xtrue) AM_CONDITIONAL(USE_UNIT_TESTS, test x$unit_tests = xtrue) AM_CONDITIONAL(USE_LOAD_TESTER, test x$load_tester = xtrue) AM_CONDITIONAL(USE_HA, test x$ha = xtrue) @@ -832,6 +833,16 @@ AM_CONDITIONAL(USE_SOCKET_RAW, test x$socket_raw = xtrue) AM_CONDITIONAL(USE_SOCKET_DYNAMIC, test x$socket_dynamic = xtrue) AM_CONDITIONAL(USE_FARP, test x$farp = xtrue) +dnl hydra plugins +dnl ============= +AM_CONDITIONAL(USE_ATTR, test x$attr = xtrue) +AM_CONDITIONAL(USE_ATTR_SQL, test x$attr_sql = xtrue -o x$sql = xtrue) +AM_CONDITIONAL(USE_RESOLVE, test x$resolve = xtrue) + +dnl pluto plugins +dnl ============= +AM_CONDITIONAL(USE_XAUTH, test x$xauth = xtrue) + dnl other options dnl ============= AM_CONDITIONAL(USE_SMARTCARD, test x$smartcard = xtrue) @@ -917,6 +928,7 @@ AC_OUTPUT( src/libfreeswan/Makefile src/libsimaka/Makefile src/pluto/Makefile + src/pluto/plugins/xauth/Makefile src/whack/Makefile src/charon/Makefile src/libcharon/Makefile diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am index 27d615dab7..ad2923799a 100644 --- a/src/checksum/Makefile.am +++ b/src/checksum/Makefile.am @@ -19,6 +19,7 @@ AM_CFLAGS = -rdynamic libs = $(shell find $(top_builddir)/src/libstrongswan \ $(top_builddir)/src/libcharon \ $(top_builddir)/src/libhydra \ + $(top_builddir)/src/pluto \ -name 'libstrongswan*.so') if USE_LIBHYDRA diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am index b65c80cdb4..7ba833d2d4 100644 --- a/src/pluto/Makefile.am +++ b/src/pluto/Makefile.am @@ -37,6 +37,7 @@ nat_traversal.c nat_traversal.h \ ocsp.c ocsp.h \ packet.c packet.h \ pkcs7.c pkcs7.h \ +pluto.c pluto.h \ plutomain.c \ rcv_whack.c rcv_whack.h \ server.c server.h \ @@ -47,7 +48,8 @@ timer.c timer.h \ vendor.c vendor.h \ virtual.c virtual.h \ whack_attribute.c whack_attribute.h \ -xauth.c xauth.h \ +xauth/xauth_manager.c xauth/xauth_manager.h \ +xauth/xauth_provider.h xauth/xauth_verifier.h \ x509.c x509.h \ builder.c builder.h \ rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h @@ -67,7 +69,7 @@ INCLUDES = \ -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/whack -AM_CFLAGS = \ +AM_CFLAGS = -rdynamic \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_CONFDIR=\"${sysconfdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" \ @@ -89,6 +91,9 @@ $(LIBFREESWANDIR)/libfreeswan.a \ dist_man_MANS = pluto.8 ipsec.secrets.5 +# compile options +################# + # This compile option activates the sending of a strongSwan VID if USE_VENDORID AM_CFLAGS += -DVENDORID @@ -121,3 +126,14 @@ endif if USE_THREADS AM_CFLAGS += -DTHREADS endif + +# build optional plugins +######################## + +SUBDIRS = . + +if USE_XAUTH + SUBDIRS += plugins/xauth +endif + + diff --git a/src/pluto/keys.c b/src/pluto/keys.c index 8cf28ace1a..a305a061b3 100644 --- a/src/pluto/keys.c +++ b/src/pluto/keys.c @@ -53,25 +53,26 @@ #include "whack.h" /* for RC_LOG_SERIOUS */ #include "timer.h" #include "fetch.h" -#include "xauth.h" const char *shared_secrets_file = SHARED_SECRETS_FILE; -typedef struct id_list id_list_t; -struct id_list { - identification_t *id; - id_list_t *next; +typedef enum secret_kind_t secret_kind_t; + +enum secret_kind_t { + SECRET_PSK, + SECRET_PUBKEY, + SECRET_XAUTH, + SECRET_PIN }; -typedef struct secret secret_t; +typedef struct secret_t secret_t; -struct secret { - id_list_t *ids; - enum PrivateKeyKind kind; +struct secret_t { + linked_list_t *ids; + secret_kind_t kind; union { chunk_t preshared_secret; - xauth_t xauth_secret; private_key_t *private_key; smartcard_t *smartcard; } u; @@ -92,12 +93,11 @@ static void free_public_key(pubkey_t *pk) secret_t *secrets = NULL; -/* find the struct secret associated with the combination of - * me and the peer. We match the Id (if none, the IP address). - * Failure is indicated by a NULL. +/** + * Find the secret associated with the combination of me and the peer. */ -static const secret_t* get_secret(const connection_t *c, - enum PrivateKeyKind kind, bool asym) +const secret_t* match_secret(identification_t *my_id, identification_t *his_id, + secret_kind_t kind) { enum { /* bits */ match_default = 0x01, @@ -106,128 +106,92 @@ static const secret_t* get_secret(const connection_t *c, }; unsigned int best_match = 0; - secret_t *best = NULL; - secret_t *s; - identification_t *my_id, *his_id; + secret_t *s, *best = NULL; - /* is there a certificate assigned to this connection? */ - if (kind == PPK_PUBKEY && c->spd.this.cert) + for (s = secrets; s != NULL; s = s->next) { - certificate_t *certificate = c->spd.this.cert->cert; + unsigned int match = 0; - public_key_t *pub_key = certificate->get_public_key(certificate); - - for (s = secrets; s != NULL; s = s->next) + if (s->kind != kind) { - if (s->kind == kind && - s->u.private_key->belongs_to(s->u.private_key, pub_key)) - { - best = s; - break; /* we have found the private key - no sense in searching further */ - } + continue; } - pub_key->destroy(pub_key); - return best; - } - - my_id = c->spd.this.id; - - if (his_id_was_instantiated(c)) - { - /* roadwarrior: replace him with 0.0.0.0 */ - his_id = identification_create_from_string("%any"); - } - else if (kind == PPK_PSK && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) && - ((c->kind == CK_TEMPLATE && - c->spd.that.id->get_type(c->spd.that.id) == ID_ANY) || - (c->kind == CK_INSTANCE && id_is_ipaddr(c->spd.that.id)))) - { - /* roadwarrior: replace him with 0.0.0.0 */ - his_id = identification_create_from_string("%any"); - } - else - { - his_id = c->spd.that.id->clone(c->spd.that.id); - } - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == kind) + if (s->ids->get_count(s->ids) == 0) + { + /* a default (signified by lack of ids): + * accept if no more specific match found + */ + match = match_default; + } + else { - unsigned int match = 0; + /* check if both ends match ids */ + enumerator_t *enumerator; + identification_t *id; - if (s->ids == NULL) - { - /* a default (signified by lack of ids): - * accept if no more specific match found - */ - match = match_default; - } - else + enumerator = s->ids->create_enumerator(s->ids); + while (enumerator->enumerate(enumerator, &id)) { - /* check if both ends match ids */ - id_list_t *i; - - for (i = s->ids; i != NULL; i = i->next) + if (my_id->equals(my_id, id)) { - if (my_id->equals(my_id, i->id)) - { - match |= match_me; - } - if (his_id->equals(his_id, i->id)) - { - match |= match_him; - } + match |= match_me; } - - /* If our end matched the only id in the list, - * default to matching any peer. - * A more specific match will trump this. - */ - if (match == match_me && s->ids->next == NULL) + if (his_id->equals(his_id, id)) { - match |= match_default; + match |= match_him; } } + enumerator->destroy(enumerator); - switch (match) + /* If our end matched the only id in the list, + * default to matching any peer. + * A more specific match will trump this. + */ + if (match == match_me && s->ids->get_count(s->ids) == 1) { + match |= match_default; + } + } + + switch (match) + { case match_me: /* if this is an asymmetric (eg. public key) system, * allow this-side-only match to count, even if * there are other ids in the list. */ - if (!asym) + if (kind != SECRET_PUBKEY) { break; } /* FALLTHROUGH */ - case match_default: /* default all */ - case match_me | match_default: /* default peer */ - case match_me | match_him: /* explicit */ + case match_default: /* default all */ + case match_me | match_default: /* default peer */ + case match_me | match_him: /* explicit */ if (match == best_match) { - /* two good matches are equally good: - * do they agree? - */ + /* two good matches are equally good: do they agree? */ bool same = FALSE; switch (kind) { - case PPK_PSK: - same = s->u.preshared_secret.len == best->u.preshared_secret.len - && memeq(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len); + case SECRET_PSK: + case SECRET_XAUTH: + same = chunk_equals(s->u.preshared_secret, + best->u.preshared_secret); break; - case PPK_PUBKEY: - same = s->u.private_key->equals(s->u.private_key, best->u.private_key); + case SECRET_PUBKEY: + same = s->u.private_key->equals(s->u.private_key, + best->u.private_key); break; default: bad_case(kind); } if (!same) { - loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with distinct secrets match endpoints:" - " first secret used"); + loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with " + "distinct secrets match endpoints: first secret used"); best = s; /* list is backwards: take latest in list */ } } @@ -237,9 +201,63 @@ static const secret_t* get_secret(const connection_t *c, best_match = match; best = s; } - } } } + return best; +} + +/** + * Retrieves an XAUTH secret primarily based on the user ID and + * secondarily based on the server ID + */ +bool get_xauth_secret(identification_t *user, identification_t *server, + chunk_t *secret) +{ + const secret_t *s; + + s = match_secret(user, server, SECRET_XAUTH); + if (s) + { + *secret = chunk_clone(s->u.preshared_secret); + return TRUE; + } + else + { + *secret = chunk_empty; + return FALSE; + } +} + +/** + * We match the ID (if none, the IP address). Failure is indicated by a NULL. + */ +static const secret_t* get_secret(const connection_t *c, secret_kind_t kind) +{ + identification_t *my_id, *his_id; + const secret_t *best; + + my_id = c->spd.this.id; + + if (his_id_was_instantiated(c)) + { + /* roadwarrior: replace him with 0.0.0.0 */ + his_id = identification_create_from_string("%any"); + } + else if (kind == SECRET_PSK && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) && + ((c->kind == CK_TEMPLATE && + c->spd.that.id->get_type(c->spd.that.id) == ID_ANY) || + (c->kind == CK_INSTANCE && id_is_ipaddr(c->spd.that.id)))) + { + /* roadwarrior: replace him with 0.0.0.0 */ + his_id = identification_create_from_string("%any"); + } + else + { + his_id = c->spd.that.id->clone(c->spd.that.id); + } + + best = match_secret(my_id, his_id, kind); + his_id->destroy(his_id); return best; } @@ -250,7 +268,7 @@ static const secret_t* get_secret(const connection_t *c, */ const chunk_t* get_preshared_secret(const connection_t *c) { - const secret_t *s = get_secret(c, PPK_PSK, FALSE); + const secret_t *s = get_secret(c, SECRET_PSK); DBG(DBG_PRIVATE, if (s == NULL) @@ -272,7 +290,7 @@ bool has_private_key(cert_t *cert) for (s = secrets; s != NULL; s = s->next) { - if (s->kind == PPK_PUBKEY && + if (s->kind == SECRET_PUBKEY && s->u.private_key->belongs_to(s->u.private_key, pub_key)) { has_key = TRUE; @@ -295,7 +313,7 @@ private_key_t* get_x509_private_key(const cert_t *cert) for (s = secrets; s != NULL; s = s->next) { - if (s->kind == PPK_PUBKEY && + if (s->kind == SECRET_PUBKEY && s->u.private_key->belongs_to(s->u.private_key, public_key)) { private_key = s->u.private_key; @@ -311,9 +329,33 @@ private_key_t* get_x509_private_key(const cert_t *cert) */ private_key_t* get_private_key(const connection_t *c) { - const secret_t *s = get_secret(c, PPK_PUBKEY, TRUE); + const secret_t *s, *best = NULL; + + /* is a certificate assigned to this connection? */ + if (c->spd.this.cert) + { + certificate_t *certificate; + public_key_t *pub_key; - return s == NULL? NULL : s->u.private_key; + certificate = c->spd.this.cert->cert; + pub_key = certificate->get_public_key(certificate); + + for (s = secrets; s != NULL; s = s->next) + { + if (s->kind == SECRET_PUBKEY && + s->u.private_key->belongs_to(s->u.private_key, pub_key)) + { + best = s; + break; /* found the private key - no sense in searching further */ + } + } + pub_key->destroy(pub_key); + } + else + { + best = get_secret(c, SECRET_PUBKEY); + } + return best ? best->u.private_key : NULL; } /* digest a secrets file @@ -555,120 +597,6 @@ static err_t process_keyfile(private_key_t **key, key_type_t type, int whackfd) return *key ? NULL : "Private key file -- could not be loaded"; } -/** - * Process xauth secret read from ipsec.secrets - */ -static err_t process_xauth(secret_t *s) -{ - chunk_t user_name; - - s->kind = PPK_XAUTH; - - if (!shift()) - return "missing xauth user name"; - if (*tok == '"' || *tok == '\'') /* quoted user name */ - { - user_name.ptr = tok + 1; - user_name.len = flp->cur - tok - 2; - } - else - { - user_name.ptr = tok; - user_name.len = flp->cur - tok; - } - plog(" loaded xauth credentials of user '%.*s'" - , user_name.len - , user_name.ptr); - s->u.xauth_secret.user_name = chunk_clone(user_name); - - if (!shift()) - return "missing xauth user password"; - return process_psk_secret(&s->u.xauth_secret.user_password); -} - -/** - * Get XAUTH secret from chained secrets lists - * only one entry is currently supported - */ -static bool xauth_get_secret(xauth_t *xauth_secret) -{ - secret_t *s; - bool found = FALSE; - - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == PPK_XAUTH) - { - if (found) - { - plog("found multiple xauth secrets - first selected"); - } - else - { - found = TRUE; - *xauth_secret = s->u.xauth_secret; - } - } - } - return found; -} - -/** - * find a matching secret - */ -static bool xauth_verify_secret(const xauth_peer_t *peer, - const xauth_t *xauth_secret) -{ - bool found = FALSE; - secret_t *s; - - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == PPK_XAUTH) - { - if (!chunk_equals(xauth_secret->user_name, s->u.xauth_secret.user_name)) - { - continue; - } - found = TRUE; - if (chunk_equals(xauth_secret->user_password, s->u.xauth_secret.user_password)) - { - return TRUE; - } - } - } - plog("xauth user '%.*s' %s" - , xauth_secret->user_name.len, xauth_secret->user_name.ptr - , found? "sent wrong password":"not found"); - return FALSE; -} - -/** - * the global xauth_module struct is defined here - */ -xauth_module_t xauth_module; - -/** - * Assign the default xauth functions to any null function pointers - */ -void xauth_defaults(void) -{ - if (xauth_module.get_secret == NULL) - { - DBG(DBG_CONTROL, - DBG_log("xauth module: using default get_secret() function") - ) - xauth_module.get_secret = xauth_get_secret; - } - if (xauth_module.verify_secret == NULL) - { - DBG(DBG_CONTROL, - DBG_log("xauth module: using default verify_secret() function") - ) - xauth_module.verify_secret = xauth_verify_secret; - } -}; - /** * Process pin read from ipsec.secrets or prompted for it using whack */ @@ -677,7 +605,7 @@ static err_t process_pin(secret_t *s, int whackfd) smartcard_t *sc; const char *pin_status = "no pin"; - s->kind = PPK_PIN; + s->kind = SECRET_PIN; /* looking for the smartcard keyword */ if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0) @@ -748,57 +676,69 @@ static err_t process_pin(secret_t *s, int whackfd) return NULL; } -static void log_psk(secret_t *s) +static void log_psk(char *label, secret_t *s) { int n = 0; char buf[BUF_LEN]; - id_list_t *id_list = s->ids; + enumerator_t *enumerator; + identification_t *id; - if (id_list == NULL) + if (s->ids->get_count(s->ids) == 0) { n = snprintf(buf, BUF_LEN, "%%any"); } else { - do + enumerator = s->ids->create_enumerator(s->ids); + while(enumerator->enumerate(enumerator, &id)) { - n += snprintf(buf + n, BUF_LEN - n, "%Y ", id_list->id); + n += snprintf(buf + n, BUF_LEN - n, "%Y ", id); if (n >= BUF_LEN) { n = BUF_LEN - 1; break; } - id_list = id_list->next; } - while (id_list); + enumerator->destroy(enumerator); } - plog(" loaded shared key for %.*s", n, buf); + plog(" loaded %s for %.*s", label, n, buf); } static void process_secret(secret_t *s, int whackfd) { err_t ugh = NULL; - s->kind = PPK_PSK; /* default */ + s->kind = SECRET_PSK; /* default */ if (*tok == '"' || *tok == '\'') { + log_psk("PSK", s); + /* old PSK format: just a string */ - log_psk(s); ugh = process_psk_secret(&s->u.preshared_secret); } else if (tokeqword("psk")) { + log_psk("PSK", s); + /* preshared key: quoted string or ttodata format */ - log_psk(s); ugh = !shift()? "unexpected end of record in PSK" : process_psk_secret(&s->u.preshared_secret); } + else if (tokeqword("xauth")) + { + s->kind = SECRET_XAUTH; + log_psk("XAUTH", s); + + /* xauth secret: quoted string or ttodata format */ + ugh = !shift()? "unexpected end of record in XAUTH" + : process_psk_secret(&s->u.preshared_secret); + } else if (tokeqword("rsa")) { /* RSA key: the fun begins. * A braced list of keyword and value pairs. */ - s->kind = PPK_PUBKEY; + s->kind = SECRET_PUBKEY; if (!shift()) { ugh = "bad RSA key syntax"; @@ -814,7 +754,7 @@ static void process_secret(secret_t *s, int whackfd) } else if (tokeqword("ecdsa")) { - s->kind = PPK_PUBKEY; + s->kind = SECRET_PUBKEY; if (!shift()) { ugh = "bad ECDSA key syntax"; @@ -824,10 +764,6 @@ static void process_secret(secret_t *s, int whackfd) ugh = process_keyfile(&s->u.private_key, KEY_ECDSA, whackfd); } } - else if (tokeqword("xauth")) - { - ugh = process_xauth(s); - } else if (tokeqword("pin")) { ugh = process_pin(s, whackfd); @@ -919,8 +855,8 @@ static void process_secret_records(int whackfd) secret_t *s = malloc_thing(secret_t); zero(s); - s->ids = NULL; - s->kind = PPK_PSK; /* default */ + s->ids = linked_list_create(); + s->kind = SECRET_PSK; /* default */ s->u.preshared_secret = chunk_empty; s->next = NULL; @@ -941,14 +877,10 @@ static void process_secret_records(int whackfd) } else { - /* an id - * See RFC2407 IPsec Domain of Interpretation 4.6.2 - */ - id_list_t *i = malloc_thing(id_list_t); + identification_t *id; - i->id = identification_create_from_string(tok); - i->next = s->ids; - s->ids = i; + id = identification_create_from_string(tok); + s->ids->insert_last(s->ids, id); if (!shift()) { @@ -1035,32 +967,23 @@ void free_preshared_secrets(void) for (s = secrets; s != NULL; s = ns) { - id_list_t *i, *ni; - ns = s->next; - for (i = s->ids; i != NULL; i = ni) - { - ni = i->next; - i->id->destroy(i->id); - free(i); - } + s->ids->destroy_offset(s->ids, offsetof(identification_t, destroy)); + switch (s->kind) { - case PPK_PSK: - free(s->u.preshared_secret.ptr); - break; - case PPK_PUBKEY: - DESTROY_IF(s->u.private_key); - break; - case PPK_XAUTH: - free(s->u.xauth_secret.user_name.ptr); - free(s->u.xauth_secret.user_password.ptr); - break; - case PPK_PIN: - scx_release(s->u.smartcard); - break; - default: - bad_case(s->kind); + case SECRET_PSK: + case SECRET_XAUTH: + free(s->u.preshared_secret.ptr); + break; + case SECRET_PUBKEY: + DESTROY_IF(s->u.private_key); + break; + case SECRET_PIN: + scx_release(s->u.smartcard); + break; + default: + bad_case(s->kind); } free(s); } diff --git a/src/pluto/keys.h b/src/pluto/keys.h index d856c00097..73cc21392e 100644 --- a/src/pluto/keys.h +++ b/src/pluto/keys.h @@ -21,6 +21,7 @@ #include #include "certs.h" +#include "connections.h" #ifndef SHARED_SECRETS_FILE # define SHARED_SECRETS_FILE IPSEC_CONFDIR "/ipsec.secrets" @@ -31,20 +32,12 @@ const char *shared_secrets_file; extern void load_preshared_secrets(int whackfd); extern void free_preshared_secrets(void); -enum PrivateKeyKind { - PPK_PSK, - PPK_PUBKEY, - PPK_XAUTH, - PPK_PIN -}; - extern void xauth_defaults(void); -/* forward declaration */ -struct connection; - -extern const chunk_t *get_preshared_secret(const struct connection *c); -extern private_key_t *get_private_key(const struct connection *c); +extern bool get_xauth_secret(identification_t *user, identification_t *server, + chunk_t *secret); +extern const chunk_t *get_preshared_secret(const connection_t *c); +extern private_key_t *get_private_key(const connection_t *c); extern private_key_t *get_x509_private_key(const cert_t *cert); /* public key machinery */ diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c index 2ca771d17d..bd046b30b1 100644 --- a/src/pluto/modecfg.c +++ b/src/pluto/modecfg.c @@ -40,7 +40,7 @@ #include "crypto.h" #include "modecfg.h" #include "whack.h" -#include "xauth.h" +#include "pluto.h" #define MAX_XAUTH_TRIES 3 @@ -929,13 +929,15 @@ stf_status xauth_send_request(struct state *st) stf_status xauth_inI0(struct msg_digest *md) { struct state *const st = md->st; + connection_t *c = st->st_connection; u_int16_t isama_id; stf_status stat, stat_build; modecfg_attribute_t *ca; - bool xauth_user_name = FALSE; - bool xauth_user_password = FALSE; + bool xauth_user_name_present = FALSE; + bool xauth_user_password_present = FALSE; bool xauth_type_present = FALSE; - xauth_t xauth_secret; + chunk_t xauth_user_name, xauth_user_password; + identification_t *user_id; linked_list_t *ca_list = linked_list_create(); plog("parsing XAUTH request"); @@ -963,10 +965,10 @@ stf_status xauth_inI0(struct msg_digest *md) } break; case XAUTH_USER_NAME: - xauth_user_name = TRUE; + xauth_user_name_present = TRUE; break; case XAUTH_USER_PASSWORD: - xauth_user_password = TRUE; + xauth_user_password_present = TRUE; break; case XAUTH_MESSAGE: if (ca->value.len) @@ -982,12 +984,12 @@ stf_status xauth_inI0(struct msg_digest *md) modecfg_attribute_destroy(ca); } - if (!xauth_user_name) + if (!xauth_user_name_present) { plog("user name attribute is missing in XAUTH request"); stat = STF_FAIL; } - if (!xauth_user_password) + if (!xauth_user_password_present) { plog("user password attribute is missing in XAUTH request"); stat = STF_FAIL; @@ -997,7 +999,7 @@ stf_status xauth_inI0(struct msg_digest *md) if (stat == STF_OK) { /* get user credentials using a plugin function */ - if (!xauth_module.get_secret(&xauth_secret)) + if (!pluto->xauth->get_secret(pluto->xauth, c, &xauth_user_password)) { plog("xauth user credentials not found"); stat = STF_FAIL; @@ -1005,23 +1007,31 @@ stf_status xauth_inI0(struct msg_digest *md) } if (stat == STF_OK) { + /* insert xauth type if present */ if (xauth_type_present) { ca = modecfg_attribute_create_tv(XAUTH_TYPE, XAUTH_TYPE_GENERIC); ca_list->insert_last(ca_list, ca); } + + /* insert xauth user name */ + user_id = (c->xauth_identity) ? c->xauth_identity : c->spd.this.id; + xauth_user_name = user_id->get_encoding(user_id); DBG(DBG_CONTROL, - DBG_log("my xauth user name is '%.*s'", xauth_secret.user_name.len, - xauth_secret.user_name.ptr) + DBG_log("my xauth user name is '%.*s'", xauth_user_name.len, + xauth_user_name.ptr) ) - ca = modecfg_attribute_create(XAUTH_USER_NAME, xauth_secret.user_name); + ca = modecfg_attribute_create(XAUTH_USER_NAME, xauth_user_name); ca_list->insert_last(ca_list, ca); + + /* insert xauth user password */ DBG(DBG_PRIVATE, - DBG_log("my xauth user password is '%.*s'", xauth_secret.user_password.len, - xauth_secret.user_password.ptr) + DBG_log("my xauth user password is '%.*s'", xauth_user_password.len, + xauth_user_password.ptr) ) - ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, xauth_secret.user_password); + ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, xauth_user_password); ca_list->insert_last(ca_list, ca); + chunk_clear(&xauth_user_password); } else { @@ -1065,9 +1075,10 @@ stf_status xauth_inI0(struct msg_digest *md) stf_status xauth_inR1(struct msg_digest *md) { struct state *const st = md->st; + connection_t *c = st->st_connection; u_int16_t isama_id; stf_status stat, stat_build; - xauth_t xauth_secret; + chunk_t xauth_user_name, xauth_user_password; int xauth_status = XAUTH_STATUS_OK; modecfg_attribute_t *ca; linked_list_t *ca_list = linked_list_create(); @@ -1081,8 +1092,8 @@ stf_status xauth_inR1(struct msg_digest *md) } /* initialize xauth_secret */ - xauth_secret.user_name = chunk_empty; - xauth_secret.user_password = chunk_empty; + xauth_user_name = chunk_empty; + xauth_user_password = chunk_empty; while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) { @@ -1092,10 +1103,10 @@ stf_status xauth_inR1(struct msg_digest *md) xauth_status = ca->value.len; break; case XAUTH_USER_NAME: - xauth_secret.user_name = chunk_clone(ca->value); + xauth_user_name = chunk_clone(ca->value); break; case XAUTH_USER_PASSWORD: - xauth_secret.user_password = chunk_clone(ca->value); + xauth_user_password = chunk_clone(ca->value); break; default: break; @@ -1108,44 +1119,44 @@ stf_status xauth_inR1(struct msg_digest *md) plog("received FAIL status in XAUTH reply"); /* client is not able to do XAUTH, delete ISAKMP SA */ + free(xauth_user_name.ptr); + free(xauth_user_password.ptr); delete_state(st); ca_list->destroy(ca_list); return STF_IGNORE; } /* check XAUTH reply */ - if (xauth_secret.user_name.ptr == NULL) + if (xauth_user_name.ptr == NULL) { plog("user name attribute is missing in XAUTH reply"); st->st_xauth.status = FALSE; } - else if (xauth_secret.user_password.ptr == NULL) + else if (xauth_user_password.ptr == NULL) { plog("user password attribute is missing in XAUTH reply"); st->st_xauth.status = FALSE; } else { - xauth_peer_t peer; - - peer.conn_name = st->st_connection->name; - addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address)); - snprintf(peer.id, sizeof(peer.id), "%Y", md->st->st_connection->spd.that.id); - DBG(DBG_CONTROL, - DBG_log("peer xauth user name is '%.*s'", xauth_secret.user_name.len, - xauth_secret.user_name.ptr) + DBG_log("peer xauth user name is '%.*s'", xauth_user_name.len, + xauth_user_name.ptr) ) + DESTROY_IF(c->xauth_identity); + c->xauth_identity = identification_create_from_data(xauth_user_name); + DBG(DBG_PRIVATE, - DBG_log("peer xauth user password is '%.*s'", xauth_secret.user_password.len, - xauth_secret.user_password.ptr) + DBG_log("peer xauth user password is '%.*s'", xauth_user_password.len, + xauth_user_password.ptr) ) /* verify the user credentials using a plugin function */ - st->st_xauth.status = xauth_module.verify_secret(&peer, &xauth_secret); + st->st_xauth.status = pluto->xauth->verify_secret(pluto->xauth, c, + xauth_user_password); plog("extended authentication %s", st->st_xauth.status? "was successful":"failed"); } - chunk_clear(&xauth_secret.user_name); - chunk_clear(&xauth_secret.user_password); + chunk_clear(&xauth_user_name); + chunk_clear(&xauth_user_password); plog("sending XAUTH status"); xauth_status = (st->st_xauth.status) ? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL; diff --git a/src/pluto/plugins/xauth/Makefile.am b/src/pluto/plugins/xauth/Makefile.am new file mode 100644 index 0000000000..354325b357 --- /dev/null +++ b/src/pluto/plugins/xauth/Makefile.am @@ -0,0 +1,15 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libfreeswan -I$(top_srcdir)/src/whack \ + -I$(top_srcdir)/src/pluto + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-xauth.la + +libstrongswan_xauth_la_SOURCES = \ + xauth_plugin.h xauth_plugin.c \ + xauth_default_provider.c xauth_default_provider.h \ + xauth_default_verifier.c xauth_default_verifier.h + +libstrongswan_xauth_la_LDFLAGS = -module -avoid-version diff --git a/src/pluto/plugins/xauth/xauth_default_provider.c b/src/pluto/plugins/xauth/xauth_default_provider.c new file mode 100644 index 0000000000..77c5facc42 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_default_provider.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +#include + +#include "xauth_default_provider.h" + +typedef struct private_xauth_default_provider_t private_xauth_default_provider_t; + +/** + * private data of xauth_default_provider + */ +struct private_xauth_default_provider_t { + + /** + * public functions + */ + xauth_provider_t public; +}; + +METHOD(xauth_provider_t, get_secret, bool, + private_xauth_default_provider_t *this, connection_t *c, chunk_t *secret) +{ + identification_t *user, *server; + + server = c->spd.that.id; + user = (c->xauth_identity) ? c->xauth_identity : c->spd.this.id; + + return get_xauth_secret(user, server, secret); +} + +METHOD(xauth_provider_t, destroy, void, + private_xauth_default_provider_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +xauth_provider_t *xauth_default_provider_create() +{ + private_xauth_default_provider_t *this; + + INIT(this, + .public = { + .get_secret = _get_secret, + .destroy = _destroy, + } + ); + + return &this->public; +} + diff --git a/src/pluto/plugins/xauth/xauth_default_provider.h b/src/pluto/plugins/xauth/xauth_default_provider.h new file mode 100644 index 0000000000..ff1a91d166 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_default_provider.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +/** + * @defgroup xauth_default_provider xauth_default_provider + * @{ @ingroup xauth + */ + +#ifndef XAUTH_DEFAULT_PROVIDER_H_ +#define XAUTH_DEFAULT_PROVIDER_H_ + +#include + + +/** + * Create an xauth_default_provider instance. + */ +xauth_provider_t *xauth_default_provider_create(); + +#endif /** XAUTH_DEFAULT_PROVIDER_H_ @}*/ + diff --git a/src/pluto/plugins/xauth/xauth_default_verifier.c b/src/pluto/plugins/xauth/xauth_default_verifier.c new file mode 100644 index 0000000000..776f771345 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_default_verifier.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +#include + +#include "xauth_default_verifier.h" + +typedef struct private_xauth_default_verifier_t private_xauth_default_verifier_t; + +/** + * private data of xauth_default_verifier + */ +struct private_xauth_default_verifier_t { + + /** + * public functions + */ + xauth_verifier_t public; +}; + +METHOD(xauth_verifier_t, verify_secret, bool, + private_xauth_default_verifier_t *this, connection_t *c, chunk_t secret) +{ + identification_t *user, *server; + chunk_t xauth_secret; + bool success = FALSE; + + server = c->spd.this.id; + user = (c->xauth_identity) ? c->xauth_identity : c->spd.that.id; + + if (get_xauth_secret(user, server, &xauth_secret)) + { + success = chunk_equals(secret, xauth_secret); + chunk_clear(&xauth_secret); + } + return success; +} + +METHOD(xauth_verifier_t, destroy, void, + private_xauth_default_verifier_t *this) +{ + free(this); +} + + +/* + * Described in header. + */ +xauth_verifier_t *xauth_default_verifier_create() +{ + private_xauth_default_verifier_t *this; + + INIT(this, + .public = { + .verify_secret = _verify_secret, + .destroy = _destroy, + } + ); + + return &this->public; +} + diff --git a/src/pluto/plugins/xauth/xauth_default_verifier.h b/src/pluto/plugins/xauth/xauth_default_verifier.h new file mode 100644 index 0000000000..e5814d7b4a --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_default_verifier.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +/** + * @defgroup xauth_default_verifier xauth_default_verifier + * @{ @ingroup xauth + */ + +#ifndef XAUTH_DEFAULT_VERIFIER_H_ +#define XAUTH_DEFAULT_VERIFIER_H_ + +#include + + +/** + * Create an xauth_default_verifier instance. + */ +xauth_verifier_t *xauth_default_verifier_create(); + +#endif /** XAUTH_DEFAULT_VERIFIER_H_ @}*/ + diff --git a/src/pluto/plugins/xauth/xauth_plugin.c b/src/pluto/plugins/xauth/xauth_plugin.c new file mode 100644 index 0000000000..74e16eacd1 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_plugin.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +#include + +#include "xauth_plugin.h" +#include "xauth_default_provider.h" +#include "xauth_default_verifier.h" +/** + * Implementation of plugin_t.destroy + */ +static void destroy(xauth_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *xauth_plugin_create() +{ + xauth_plugin_t *this = malloc_thing(xauth_plugin_t); + + this->plugin.destroy = (void(*)(plugin_t*))destroy; + + pluto->xauth->add_provider(pluto->xauth, xauth_default_provider_create()); + pluto->xauth->add_verifier(pluto->xauth, xauth_default_verifier_create()); + + return &this->plugin; +} + diff --git a/src/pluto/plugins/xauth/xauth_plugin.h b/src/pluto/plugins/xauth/xauth_plugin.h new file mode 100644 index 0000000000..4f14828d22 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +/** + * @defgroup xauth xauth + * @ingroup pplugins + * + * @defgroup xauth_plugin xauth_plugin + * @{ @ingroup xauth + */ + +#ifndef XAUTH_PLUGIN_H_ +#define XAUTH_PLUGIN_H_ + +#include + +typedef struct xauth_plugin_t xauth_plugin_t; + +/** + * XAUTH plugin + */ +struct xauth_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** XAUTH_PLUGIN_H_ @}*/ diff --git a/src/pluto/pluto.c b/src/pluto/pluto.c new file mode 100644 index 0000000000..e9a4ed75b8 --- /dev/null +++ b/src/pluto/pluto.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +#include "pluto.h" + +#include + +typedef struct private_pluto_t private_pluto_t; + +/** + * Private additions to hydra_t. + */ +struct private_pluto_t { + + /** + * Public members of pluto_t. + */ + pluto_t public; +}; + +/** + * Single instance of hydra_t. + */ +pluto_t *pluto; + +/** + * Described in header. + */ +void pluto_deinit() +{ + private_pluto_t *this = (private_pluto_t*)pluto; + this->public.xauth->destroy(this->public.xauth); + free(this); + pluto = NULL; +} + +/** + * Described in header. + */ +bool pluto_init(char *file) +{ + private_pluto_t *this; + + INIT(this, + .public = { + .xauth = xauth_manager_create(), + }, + ); + pluto = &this->public; + + if (lib->integrity && + !lib->integrity->check_file(lib->integrity, "pluto", file)) + { + DBG1(DBG_LIB, "integrity check of pluto failed"); + return FALSE; + } + return TRUE; +} + diff --git a/src/pluto/pluto.h b/src/pluto/pluto.h new file mode 100644 index 0000000000..37e6e3f33f --- /dev/null +++ b/src/pluto/pluto.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +/** + * @defgroup pluto pluto + * + * @defgroup xauth xauth + * @ingroup pluto + * + * @defgroup pplugins plugins + * @ingroup pluto + * + * @addtogroup pluto + * @{ + */ + +#ifndef PLUTO_H_ +#define PLUTO_H_ + +typedef struct pluto_t pluto_t; + +#include + +#include + +/** + * Pluto daemon support object. + */ +struct pluto_t { + + /** + * manager for payload attributes + */ + xauth_manager_t *xauth; +}; + +/** + * The single instance of pluto_t. + * + * Set between calls to pluto_init() and pluto_deinit() calls. + */ +extern pluto_t *pluto; + +/** + * Initialize pluto. + * + * @return FALSE if integrity check failed + */ +bool pluto_init(char *file); + +/** + * Deinitialize pluto. + */ +void pluto_deinit(void); + +#endif /** PLUTO_H_ @}*/ + diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index aa04594bca..2e27b00f85 100644 --- a/src/pluto/plutomain.c +++ b/src/pluto/plutomain.c @@ -68,7 +68,6 @@ #include "ocsp.h" #include "crl.h" #include "fetch.h" -#include "xauth.h" #include "crypto.h" #include "nat_traversal.h" #include "virtual.h" @@ -76,6 +75,7 @@ #include "vendor.h" #include "builder.h" #include "whack_attribute.h" +#include "pluto.h" static void usage(const char *mess) { @@ -268,18 +268,18 @@ int main(int argc, char **argv) library_deinit(); exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); } - if (lib->integrity && - !lib->integrity->check_file(lib->integrity, "pluto", argv[0])) + if (!libhydra_init("pluto")) { - fprintf(stderr, "integrity check of pluto failed\n"); + libhydra_deinit(); library_deinit(); - exit(SS_RC_DAEMON_INTEGRITY); + exit(SS_RC_INITIALIZATION_FAILED); } - if (!libhydra_init("pluto")) + if (!pluto_init(argv[0])) { + pluto_deinit(); libhydra_deinit(); library_deinit(); - exit(SS_RC_INITIALIZATION_FAILED); + exit(SS_RC_DAEMON_INTEGRITY); } options = options_create(); @@ -677,7 +677,6 @@ int main(int argc, char **argv) init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); init_virtual_ip(virtual_private); scx_init(pkcs11_module_path, pkcs11_init_args); - xauth_init(); init_states(); init_demux(); init_kernel(); @@ -771,7 +770,6 @@ void exit_pluto(int status) free_ifaces(); ac_finalize(); /* free X.509 attribute certificates */ scx_finalize(); /* finalize and unload PKCS #11 module */ - xauth_finalize(); /* finalize and unload XAUTH module */ stop_adns(); free_md_pool(); free_crypto(); @@ -781,6 +779,7 @@ void exit_pluto(int status) free_builder(); delete_lock(); options->destroy(options); + pluto_deinit(); lib->plugins->unload(lib->plugins); libhydra_deinit(); library_deinit(); diff --git a/src/pluto/xauth.c b/src/pluto/xauth.c deleted file mode 100644 index 2086a92cc9..0000000000 --- a/src/pluto/xauth.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Initialization and finalization of the dynamic XAUTH module - * Copyright (C) 2006 Andreas Steffen - * Hochschule fuer Technik Rapperswil, Switzerland - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * 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 General Public License - * for more details. - */ - -#include - -#include - -#include "constants.h" -#include "defs.h" -#include "xauth.h" -#include "keys.h" -#include "log.h" - -void -xauth_init(void) -{ -#ifdef XAUTH_DEFAULT_LIB - xauth_module.handle = dlopen(XAUTH_DEFAULT_LIB, RTLD_NOW); - - if (xauth_module.handle != NULL) - { - DBG(DBG_CONTROL, - DBG_log("xauth module '%s' loading'", XAUTH_DEFAULT_LIB) - ) - xauth_module.get_secret = (bool (*) (const xauth_t*)) - dlsym(xauth_module.handle, "get_secret"); - DBG(DBG_CONTROL, - if (xauth_module.get_secret != NULL) - { - DBG_log("xauth module: found get_secret() function"); - } - ) - xauth_module.verify_secret = (bool (*) (const xauth_peer_t*, const xauth_t*)) - dlsym(xauth_module.handle, "verify_secret"); - DBG(DBG_CONTROL, - if (xauth_module.verify_secret != NULL) - { - DBG_log("xauth module: found verify_secret() function"); - } - ) - } -#endif - /* any null function pointers will be filled in by default functions */ - xauth_defaults(); -} - -void -xauth_finalize(void) -{ -#ifdef XAUTH_DEFAULT_LIB - if (xauth_module.handle != NULL) - { - if (dlclose(xauth_module.handle)) - { - plog("failed to unload xauth module"); - } - else - { - DBG(DBG_CONTROL, - DBG_log("xauth module unloaded") - ) - } - } -#endif -} diff --git a/src/pluto/xauth.h b/src/pluto/xauth.h deleted file mode 100644 index 23cae3ed8d..0000000000 --- a/src/pluto/xauth.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Interface definition of the XAUTH server and|or client module - * Copyright (C) 2006 Andreas Steffen - * Hochschule fuer Technik Rapperswil, Switzerland - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * 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 General Public License - * for more details. - */ - -#ifndef _XAUTH_H -#define _XAUTH_H - -#include -#include "defs.h" - -/* XAUTH credentials */ - -struct chunk_t; - -typedef struct { - char *conn_name; - char id[BUF_LEN]; - char ip_address[ADDRTOT_BUF]; -} xauth_peer_t; - -typedef struct { - chunk_t user_name; - chunk_t user_password; -} xauth_t; - -typedef struct { - void *handle; - bool (*get_secret) (xauth_t *xauth_secret); - bool (*verify_secret) (const xauth_peer_t *peer, const xauth_t *xauth_secret); -} xauth_module_t; - -extern xauth_module_t xauth_module; - -extern void xauth_init(void); -extern void xauth_finalize(void); - -#endif /* _XAUTH_H */ diff --git a/src/pluto/xauth/xauth_manager.c b/src/pluto/xauth/xauth_manager.c new file mode 100644 index 0000000000..2e57ccefad --- /dev/null +++ b/src/pluto/xauth/xauth_manager.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +#include "xauth_manager.h" + +typedef struct private_xauth_manager_t private_xauth_manager_t; + +/** + * private data of xauth_manager + */ +struct private_xauth_manager_t { + + /** + * public functions + */ + xauth_manager_t public; + + /** + * list of registered secret providers + */ + linked_list_t *providers; + + /** + * list of registered secret verifiers + */ + linked_list_t *verifiers; +}; + +METHOD(xauth_manager_t, get_secret, bool, + private_xauth_manager_t *this, connection_t *c, chunk_t *secret) +{ + xauth_provider_t *provider; + enumerator_t *enumerator; + bool success = FALSE; + + *secret = chunk_empty; + + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, &provider)) + { + if (provider->get_secret(provider, c, secret)) + { + success = TRUE; + break; + } + } + enumerator->destroy(enumerator); + return success; +} + +METHOD(xauth_manager_t, verify_secret, bool, + private_xauth_manager_t *this, connection_t *c, chunk_t secret) +{ + xauth_verifier_t *verifier; + enumerator_t *enumerator; + bool success = FALSE; + + enumerator = this->verifiers->create_enumerator(this->verifiers); + while (enumerator->enumerate(enumerator, &verifier)) + { + if (verifier->verify_secret(verifier, c, secret)) + { + success = TRUE; + break; + } + } + enumerator->destroy(enumerator); + return success; +} + +METHOD(xauth_manager_t, add_provider, void, + private_xauth_manager_t *this, xauth_provider_t *provider) +{ + this->providers->insert_last(this->providers, provider); +} + +METHOD(xauth_manager_t, add_verifier, void, + private_xauth_manager_t *this, xauth_verifier_t *verifier) +{ + this->verifiers->insert_last(this->verifiers, verifier); +} + +METHOD(xauth_manager_t, destroy, void, + private_xauth_manager_t *this) +{ + this->providers->destroy_offset(this->providers, + offsetof(xauth_provider_t, destroy)); + this->verifiers->destroy_offset(this->verifiers, + offsetof(xauth_verifier_t, destroy)); + free(this); +} + +/* + * Described in header. + */ +xauth_manager_t *xauth_manager_create() +{ + private_xauth_manager_t *this; + + INIT(this, + .public = { + .get_secret = _get_secret, + .verify_secret = _verify_secret, + .add_provider = _add_provider, + .add_verifier = _add_verifier, + .destroy = _destroy, + } + ); + + this->providers = linked_list_create(); + this->verifiers = linked_list_create(); + + return &this->public; +} + diff --git a/src/pluto/xauth/xauth_manager.h b/src/pluto/xauth/xauth_manager.h new file mode 100644 index 0000000000..843eb2ff06 --- /dev/null +++ b/src/pluto/xauth/xauth_manager.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +/** + * @defgroup xauth_manager xauth_manager + * @{ @ingroup xauth + */ + +#ifndef XAUTH_MANAGER_H_ +#define XAUTH_MANAGER_H_ + +#include "xauth_provider.h" +#include "xauth_verifier.h" + +typedef struct xauth_manager_t xauth_manager_t; + +/** + * An xauth_manager registers xauth_providers and xauth_verifiers. + */ +struct xauth_manager_t { + + /** + * Register an xauth_provider + * + * @param provider xauth_provider to be registered + */ + void (*add_provider)(xauth_manager_t *this, xauth_provider_t *provider); + + /** + * Register an xauth_verifier + * + * @param verifier xauth_verifier to be registered + */ + void (*add_verifier)(xauth_manager_t *this, xauth_verifier_t *verifier); + + /** + * Use registered providers to retrieve an XAUTH user secret + * based on connection information. + * + * @param c connection information + * @param secret secret if found, chunk_empty otherwise + * @return TRUE if a matching secret was found + */ + bool (*get_secret)(xauth_manager_t *this, connection_t *c, chunk_t *secret); + + /** + * Use registered verifiers to verify an XAUTH user secret + * based on connection information + * + * @param c connection information + * @param secret secret to be compared + * @return TRUE if secret matches + */ + bool (*verify_secret)(xauth_manager_t *this, connection_t *c, chunk_t secret); + + /** + * Destroy an xauth_verifier instance. + */ + void (*destroy)(xauth_manager_t *this); +}; + +/** + * Create an xauth_manager instance. + */ +xauth_manager_t *xauth_manager_create(); + +#endif /** XAUTH_MANAGER_H_ @}*/ + diff --git a/src/pluto/xauth/xauth_provider.h b/src/pluto/xauth/xauth_provider.h new file mode 100644 index 0000000000..90adbff506 --- /dev/null +++ b/src/pluto/xauth/xauth_provider.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +/** + * @defgroup xauth_provider xauth_provider + * @{ @ingroup xauth + */ + +#ifndef XAUTH_PROVIDER_H_ +#define XAUTH_PROVIDER_H_ + +#include + +#include + +typedef struct xauth_provider_t xauth_provider_t; + +/** + * An xauth provider retrieves xauth user secrets on the client side. + */ +struct xauth_provider_t { + + /** + * Retrieve an XAUTH user secret based on connection information. + * + * @param c connection information + * @param secret secret if found, chunk_empty otherwise + * @return TRUE if a matching secret was found + */ + bool (*get_secret)(xauth_provider_t *this, connection_t *c, chunk_t *secret); + + /** + * Destroy an xauth_provider instance. + */ + void (*destroy)(xauth_provider_t *this); +}; + +/** + * Create an xauth_provider instance. + */ +xauth_provider_t *xauth_provider_create(); + +#endif /** XAUTH_PROVIDER_H_ @}*/ + diff --git a/src/pluto/xauth/xauth_verifier.h b/src/pluto/xauth/xauth_verifier.h new file mode 100644 index 0000000000..7c9ff3a7f1 --- /dev/null +++ b/src/pluto/xauth/xauth_verifier.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 General Public License + * for more details. + */ + +/** + * @defgroup xauth_verifier xauth_verifier + * @{ @ingroup xauth + */ + +#ifndef XAUTH_VERIFIER_H_ +#define XAUTH_VERIFIER_H_ + +#include + +#include + +typedef struct xauth_verifier_t xauth_verifier_t; + +/** + * An xauth verifier verifies xauth user secrets on the server side. + */ +struct xauth_verifier_t { + + /** + * Verify an XAUTH user secret base on connection information + * + * @param c connection information + * @param secret secret to be compared + * @return TRUE if secret matches + */ + bool (*verify_secret)(xauth_verifier_t *this, connection_t *c, chunk_t secret); + + /** + * Destroy an xauth_verifier instance. + */ + void (*destroy)(xauth_verifier_t *this); +}; + +/** + * Create an xauth_verifier instance. + */ +xauth_verifier_t *xauth_verifier_create(); + +#endif /** XAUTH_VERIFIER_H_ @}*/ +