support for stroke listcerts|listcacerts|listall and left|rightca=
authorAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 12 Jun 2006 08:43:46 +0000 (08:43 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 12 Jun 2006 08:43:46 +0000 (08:43 -0000)
src/charon/threads/stroke_interface.c
src/starter/starterstroke.c
src/stroke/Makefile.am
src/stroke/stroke.c
src/stroke/stroke.h

index 2ca9a0a..a98d476 100755 (executable)
@@ -112,7 +112,7 @@ static void pop_string(stroke_msg_t *msg, char **string)
 /**
  * Load end entitity certificate
  */
-static void load_end_certificate(const char *filename, identification_t **idp, logger_t *logger)
+static x509_t* load_end_certificate(const char *filename, identification_t **idp, logger_t *logger)
 {
        char path[PATH_BUF];
        x509_t *cert;
@@ -147,8 +147,9 @@ static void load_end_certificate(const char *filename, identification_t **idp, l
                        id = subject;
                        *idp = id->clone(id);
                }
-               charon->credentials->add_certificate(charon->credentials, cert);
+               return charon->credentials->add_certificate(charon->credentials, cert);
        }
+       return NULL;
 }
 
 /**
@@ -158,7 +159,11 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
 {
        connection_t *connection;
        policy_t *policy;
-       identification_t *my_id, *other_id, *my_ca, *other_ca;
+       identification_t *my_id, *other_id;
+       identification_t *my_ca = NULL;
+       identification_t *other_ca = NULL;
+       bool my_ca_same = FALSE;
+    bool other_ca_same =FALSE;
        host_t *my_host, *other_host, *my_subnet, *other_subnet;
        proposal_t *proposal;
        traffic_selector_t *my_ts, *other_ts;
@@ -194,6 +199,30 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
                return;
        }
 
+       if (charon->socket->is_listening_on(charon->socket, other_host))
+       {
+               stroke_end_t tmp_end;
+               host_t *tmp_host;
+
+               this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is other host, swapping ends");
+
+               tmp_host = my_host;
+               my_host = other_host;
+               other_host = tmp_host;
+
+               tmp_end = msg->add_conn.me;
+               msg->add_conn.me = msg->add_conn.other;
+               msg->add_conn.other = tmp_end;
+       }
+       else if (!charon->socket->is_listening_on(charon->socket, my_host))
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "left nor right host is our side, aborting");
+               
+               my_host->destroy(my_host);
+               other_host->destroy(other_host);
+               return;
+       }
+
        my_id = identification_create_from_string(msg->add_conn.me.id ?
                                                                                          msg->add_conn.me.id : msg->add_conn.me.address);
        if (my_id == NULL)
@@ -240,10 +269,6 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
                return;
        }
                                
-       /* TODO check for %same */
-       my_ca = identification_create_from_string(msg->add_conn.me.ca);
-       other_ca = identification_create_from_string(msg->add_conn.other.ca);
-
        my_ts = traffic_selector_create_from_subnet(my_subnet, msg->add_conn.me.subnet ?
                                                                                                                   msg->add_conn.me.subnet_mask : 32);
        my_subnet->destroy(my_subnet);
@@ -251,62 +276,70 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
        other_ts = traffic_selector_create_from_subnet(other_subnet, msg->add_conn.other.subnet ?
                                                                                                                                 msg->add_conn.other.subnet_mask : 32);
        other_subnet->destroy(other_subnet);
-                               
-       if (charon->socket->is_listening_on(charon->socket, other_host))
+
+       if (msg->add_conn.me.ca)
        {
-               this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is other host, switching");
-               
-               host_t *tmp_host;
-               identification_t *tmp_id, *tmp_ca;
-               traffic_selector_t *tmp_ts;
-               char *tmp_cert;
-               
-               tmp_host   = my_host;
-               my_host    = other_host;
-               other_host = tmp_host;
+               if (streq(msg->add_conn.me.ca, "%same"))
+               {
+                       my_ca_same = TRUE;
+               }
+               else
+               {
+                       my_ca = identification_create_from_string(msg->add_conn.me.ca);
+               }
+       }
+       if (msg->add_conn.other.ca)
+       {
+               if (streq(msg->add_conn.other.ca, "%same"))
+               {
+                       other_ca_same = TRUE;
+               }
+               else
+               {
+                       other_ca = identification_create_from_string(msg->add_conn.other.ca);
+               }
+       }
+       if (msg->add_conn.me.cert)
+       {
+               x509_t *cert = load_end_certificate(msg->add_conn.me.cert, &my_id, this->stroke_logger);
 
-               tmp_id   = my_id;
-               my_id    = other_id;
-               other_id = tmp_id;
+               if (my_ca == NULL && !my_ca_same && cert)
+               {
+                       identification_t *issuer = cert->get_issuer(cert);
 
-               tmp_ca   = my_ca;
-               my_ca    = other_ca;
-               other_ca = tmp_ca;
+                       my_ca = issuer->clone(issuer);
+               }
+       }
+       if (msg->add_conn.other.cert)
+       {
+               x509_t *cert = load_end_certificate(msg->add_conn.other.cert, &other_id, this->stroke_logger);
 
-               tmp_ts   = my_ts;
-               my_ts    = other_ts;
-               other_ts = tmp_ts;
+               if (other_ca == NULL && !other_ca_same && cert)
+               {
+                       identification_t *issuer = cert->get_issuer(cert);
 
-        tmp_cert                 = msg->add_conn.me.cert;
-               msg->add_conn.me.cert    = msg->add_conn.other.cert;
-               msg->add_conn.other.cert = tmp_cert;
+                       other_ca = issuer->clone(issuer);
+               }
        }
-       else if (charon->socket->is_listening_on(charon->socket, my_host))
+       if (other_ca_same && my_ca)
        {
-               this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is own host, not switching");
+               other_ca = my_ca->clone(my_ca);
        }
-       else
+       else if (my_ca_same && other_ca)
        {
-               this->stroke_logger->log(this->stroke_logger, ERROR, "left nor right host is our, aborting");
-               
-               my_host->destroy(my_host);
-               other_host->destroy(other_host);
-               my_id->destroy(my_id);
-               other_id->destroy(other_id);
-               my_ts->destroy(my_ts);
-               other_ts->destroy(other_ts);
-               return;
+               my_ca = other_ca->clone(other_ca);
        }
-       
-       if (msg->add_conn.me.cert)
+       if (my_ca == NULL)
        {
-               load_end_certificate(msg->add_conn.me.cert, &my_id, this->stroke_logger);
+               my_ca = identification_create_from_string("%any");
        }
-       if (msg->add_conn.other.cert)
+       if (other_ca == NULL)
        {
-               load_end_certificate(msg->add_conn.other.cert, &other_id, this->stroke_logger);
+               other_ca = identification_create_from_string("%any");
        }
-       
+       this->logger->log(this->logger, CONTROL|LEVEL1, "  my ca:   '%s'", my_ca->get_string(my_ca));
+       this->logger->log(this->logger, CONTROL|LEVEL1, "  other ca:'%s'", other_ca->get_string(other_ca));
+
        connection = connection_create(msg->add_conn.name, msg->add_conn.ikev2,
                                                                   my_host, other_host,
                                                                   RSA_DIGITAL_SIGNATURE);
@@ -492,12 +525,15 @@ static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
 /**
  * list various information
  */
-static void stroke_list(private_stroke_t *this, stroke_msg_t *msg, bool utc)
+static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
 {
-       if (msg->type == STR_LIST_CERTS)
+       if (msg->list.flags & LIST_CERTS)
+       {
+               charon->credentials->log_certificates(charon->credentials, this->stroke_logger, msg->list.utc);
+       }
+       if (msg->list.flags & LIST_CACERTS)
        {
-               charon->credentials->log_certificates(charon->credentials, this->stroke_logger, utc);
-               charon->credentials->log_ca_certificates(charon->credentials, this->stroke_logger, utc);
+               charon->credentials->log_ca_certificates(charon->credentials, this->stroke_logger, msg->list.utc);
        }
 }
 
@@ -694,8 +730,8 @@ static void stroke_receive(private_stroke_t *this)
                        case STR_LOGLEVEL:
                                stroke_loglevel(this, msg);
                                break;
-                       case STR_LIST_CERTS:
-                               stroke_list(this, msg, FALSE);
+                       case STR_LIST:
+                               stroke_list(this, msg);
                                break;
                        default:
                                this->logger->log(this->logger, ERROR, "received invalid stroke");
index b4f85b3..25a66a0 100644 (file)
@@ -110,7 +110,7 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
 {
        msg_end->id = push_string(msg, conn_end->id);
        msg_end->cert = push_string(msg, conn_end->cert);
-       msg_end->cert = push_string(msg, conn_end->cert);
+       msg_end->ca = push_string(msg, conn_end->ca);
        msg_end->address = push_string(msg, inet_ntoa(conn_end->addr.u.v4.sin_addr));
        msg_end->subnet = push_string(msg, inet_ntoa(conn_end->subnet.addr.u.v4.sin_addr));
        msg_end->subnet_mask = conn_end->subnet.maskbits;
index 0de0134..761c3b8 100644 (file)
@@ -1,4 +1,8 @@
 ipsec_PROGRAMS = stroke
 
-stroke_SOURCES = stroke.c stroke.h
+stroke_SOURCES = stroke.c stroke.h stroke_keywords.c stroke_keywords.h
 INCLUDES = -I$(top_srcdir)/src/libstrongswan
+EXTRA_DIST = stroke_keywords.txt
+
+stroke_keywords.c:     stroke_keywords.txt stroke_keywords.h
+               $(GPERF) -C -G -t < stroke_keywords.txt > stroke_keywords.c
index d535722..b8b0cc0 100644 (file)
 #include <types.h>
 
 #include "stroke.h"
+#include "stroke_keywords.h"
+
+struct stroke_token {
+    char *name;
+    stroke_keyword_t kw;
+};
 
 static char* push_string(stroke_msg_t *msg, char *string)
 {
@@ -156,26 +162,31 @@ static int terminate_connection(char *name)
        return send_stroke_msg(&msg);
 }
 
-static int show_status(char *mode, char *connection)
+static int show_status(stroke_keyword_t kw, char *connection)
 {
        stroke_msg_t msg;
        
-       if (strcmp(mode, "statusall") == 0)
-               msg.type = STR_STATUS_ALL;
-       else
-               msg.type = STR_STATUS;
-
+       msg.type = (kw == STROKE_STATUS)? STR_STATUS:STR_STATUS_ALL;
        msg.length = offsetof(stroke_msg_t, buffer);
        msg.status.name = push_string(&msg, connection);
        return send_stroke_msg(&msg);
 }
 
-static int list_certs(void)
+static int list_flags[] = {
+       LIST_CERTS,
+       LIST_CACERTS,
+       LIST_CRLS,
+       LIST_ALL
+};
+
+static int list(stroke_keyword_t kw, bool utc)
 {
        stroke_msg_t msg;
        
-       msg.type = STR_LIST_CERTS;
+       msg.type = STR_LIST;
        msg.length = offsetof(stroke_msg_t, buffer);
+       msg.list.utc = utc;
+       msg.list.flags = list_flags[kw - STROKE_LIST_FIRST];
        return send_stroke_msg(&msg);
 }
 
@@ -250,80 +261,82 @@ static void exit_usage(char *error)
 
 int main(int argc, char *argv[])
 {
+       const stroke_token_t *token;
        int res = 0;
-       char *op;
-       
+
        if (argc < 2)
        {
                exit_usage(NULL);
        }
        
-       op = argv[1];
+       token = in_word_set(argv[1], strlen(argv[1]));
 
-       if (streq(op, "status") || streq(op, "statusall"))
-       {
-               res = show_status(op, argc > 2 ? argv[2] : NULL);
-       }
-       else if (streq(op, "listcerts") || streq(op, "listall"))
-       {
-               res = list_certs();
-       }
-       else if (streq(op, "up"))
-       {
-               if (argc < 3)
-               {
-                       exit_usage("\"up\" needs a connection name");
-               }
-               res = initiate_connection(argv[2]);
-       }
-       else if (streq(op, "down"))
+       if (token == NULL)
        {
-               if (argc < 3)
-               {
-                       exit_usage("\"down\" needs a connection name");
-               }
-               res = terminate_connection(argv[2]);
+               exit_usage("unknown keyword");
        }
-       else if (streq(op, "add"))
-       {
-               if (argc < 11)
-               {
-                       exit_usage("\"add\" needs more parameters...");
-               }
-               res = add_connection(argv[2],
-                                                        argv[3], argv[4], 
-                                                        argv[5], argv[6], 
-                                                        argv[7], argv[8], 
-                                                        atoi(argv[9]), atoi(argv[10]));
-       }
-       else if (streq(op, "delete"))
-       {
-               if (argc < 3)
-               {
-                       exit_usage("\"delete\" needs a connection name");
-               }
-               res = del_connection(argv[2]);
-       }
-       else if (streq(op, "logtype"))
-       {
-               if (argc < 5)
-               {
-                       exit_usage("\"logtype\" needs more parameters...");
-               }
-               res = set_logtype(argv[2], argv[3], atoi(argv[4])); 
-       }
-       else if (streq(op, "loglevel"))
-       {
-               if (argc < 4)
-               {
-                       exit_usage("\"logtype\" needs more parameters...");
-               }
-               res = set_loglevel(argv[2], atoi(argv[3])); 
-       }
-       else
+
+       switch (token->kw)
        {
-               exit_usage(NULL);
+               case STROKE_ADD:
+                       if (argc < 11)
+                       {
+                               exit_usage("\"add\" needs more parameters...");
+                       }
+                       res = add_connection(argv[2],
+                                                                argv[3], argv[4], 
+                                                                argv[5], argv[6], 
+                                                                argv[7], argv[8], 
+                                                                atoi(argv[9]), atoi(argv[10]));
+                       break;
+               case STROKE_DELETE:
+               case STROKE_DEL:
+                       if (argc < 3)
+                       {
+                               exit_usage("\"delete\" needs a connection name");
+                       }
+                       res = del_connection(argv[2]);
+                       break;
+               case STROKE_UP:
+                       if (argc < 3)
+                       {
+                               exit_usage("\"up\" needs a connection name");
+                       }
+                       res = initiate_connection(argv[2]);
+                       break;
+               case STROKE_DOWN:
+                       if (argc < 3)
+                       {
+                               exit_usage("\"down\" needs a connection name");
+                       }
+                       res = terminate_connection(argv[2]);
+                       break;
+               case STROKE_LOGTYPE:
+                       if (argc < 5)
+                       {
+                               exit_usage("\"logtype\" needs more parameters...");
+                       }
+                       res = set_logtype(argv[2], argv[3], atoi(argv[4])); 
+                       break;
+               case STROKE_LOGLEVEL:
+                       if (argc < 4)
+                       {
+                               exit_usage("\"logtype\" needs more parameters...");
+                       }
+                       res = set_loglevel(argv[2], atoi(argv[3])); 
+                       break;
+               case STROKE_STATUS:
+               case STROKE_STATUSALL:
+                       res = show_status(token->kw, argc > 2 ? argv[2] : NULL);
+                       break;
+               case STROKE_LIST_CERTS:
+               case STROKE_LIST_CACERTS:
+               case STROKE_LIST_CRLS:
+               case STROKE_LIST_ALL:
+                       res = list(token->kw, argc > 2 && streq(argv[2], "--utc"));
+                       break;
+               default:
+                       exit_usage(NULL);
        }
-       
        return res;
 }
index e9bdedd..0544ca8 100644 (file)
 
 #define STROKE_BUF_LEN         2048
 
+/**
+  * Definition of the LIST flags
+  */
+#define LIST_NONE              0x0000  /* don't list anything */
+#define LIST_CERTS             0x0001  /* list all host/user certs */
+#define LIST_CACERTS   0x0002  /* list all ca certs */
+#define LIST_CRLS              0x0004  /* list all crls */
+#define LIST_ALL               0x0007  /* all list options */
+
 typedef struct stroke_end_t stroke_end_t;
 
 struct stroke_end_t {
@@ -72,7 +81,7 @@ struct stroke_msg_t {
                /* set the verbosity of a logging context */
                STR_LOGLEVEL,
                /* show list of locally loaded certificates */
-               STR_LIST_CERTS
+               STR_LIST
                /* more to come */
        } type;
 
@@ -96,16 +105,24 @@ struct stroke_msg_t {
                        stroke_end_t me, other;
                } add_conn;
 
+               /* data for STR_LOGTYPE */
                struct {
                        char *context;
                        char *type;
                        int enable;
                } logtype;
 
+               /* data for STR_LOGLEVEL */
                struct {
                        char *context;
                        int level;
                } loglevel;
+
+               /* data for STR_LIST */
+               struct {
+                       u_int flags;
+                       bool  utc;
+               } list;
        };
        char buffer[STROKE_BUF_LEN];
 };