implemented xauth as a pluto plugin
authorAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 18 May 2010 11:51:15 +0000 (13:51 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 18 May 2010 11:51:27 +0000 (13:51 +0200)
22 files changed:
configure.in
src/checksum/Makefile.am
src/pluto/Makefile.am
src/pluto/keys.c
src/pluto/keys.h
src/pluto/modecfg.c
src/pluto/plugins/xauth/Makefile.am [new file with mode: 0644]
src/pluto/plugins/xauth/xauth_default_provider.c [new file with mode: 0644]
src/pluto/plugins/xauth/xauth_default_provider.h [new file with mode: 0644]
src/pluto/plugins/xauth/xauth_default_verifier.c [new file with mode: 0644]
src/pluto/plugins/xauth/xauth_default_verifier.h [new file with mode: 0644]
src/pluto/plugins/xauth/xauth_plugin.c [new file with mode: 0644]
src/pluto/plugins/xauth/xauth_plugin.h [new file with mode: 0644]
src/pluto/pluto.c [new file with mode: 0644]
src/pluto/pluto.h [new file with mode: 0644]
src/pluto/plutomain.c
src/pluto/xauth.c [deleted file]
src/pluto/xauth.h [deleted file]
src/pluto/xauth/xauth_manager.c [new file with mode: 0644]
src/pluto/xauth/xauth_manager.h [new file with mode: 0644]
src/pluto/xauth/xauth_provider.h [new file with mode: 0644]
src/pluto/xauth/xauth_verifier.h [new file with mode: 0644]

index 976d99b..b1a4e74 100644 (file)
@@ -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
index 27d615d..ad29237 100644 (file)
@@ -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
index b65c80c..7ba833d 100644 (file)
@@ -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
+
+
index 8cf28ac..a305a06 100644 (file)
 #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
@@ -556,120 +598,6 @@ static err_t process_keyfile(private_key_t **key, key_type_t type, int whackfd)
 }
 
 /**
- * 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
  */
 static err_t process_pin(secret_t *s, int whackfd)
@@ -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);
                }
index d856c00..73cc213 100644 (file)
@@ -21,6 +21,7 @@
 #include <credentials/keys/public_key.h>
 
 #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  */
index 2ca771d..bd046b3 100644 (file)
@@ -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 (file)
index 0000000..354325b
--- /dev/null
@@ -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 (file)
index 0000000..77c5fac
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <keys.h>
+
+#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 (file)
index 0000000..ff1a91d
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <xauth/xauth_provider.h>
+
+
+/**
+ * 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 (file)
index 0000000..776f771
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <keys.h>
+
+#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 (file)
index 0000000..e5814d7
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <xauth/xauth_verifier.h>
+
+
+/**
+ * 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 (file)
index 0000000..74e16ea
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 "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 (file)
index 0000000..4f14828
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <plugins/plugin.h>
+
+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 (file)
index 0000000..e9a4ed7
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <debug.h>
+
+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 (file)
index 0000000..37e6e3f
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <xauth/xauth_manager.h>
+
+#include <library.h>
+
+/**
+ * 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_ @}*/
+
index aa04594..2e27b00 100644 (file)
@@ -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 (file)
index 2086a92..0000000
+++ /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 <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * 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 <dlfcn.h>
-
-#include <freeswan.h>
-
-#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 (file)
index 23cae3e..0000000
+++ /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 <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * 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 <freeswan.h>
-#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 (file)
index 0000000..2e57cce
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 (file)
index 0000000..843eb2f
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 (file)
index 0000000..90adbff
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <library.h>
+
+#include <connections.h>
+
+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 (file)
index 0000000..7c9ff3a
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <library.h>
+
+#include <connections.h>
+
+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_ @}*/
+