vici: Support loading of different certificate types
authorMartin Willi <martin@revosec.ch>
Wed, 19 Feb 2014 09:51:09 +0000 (10:51 +0100)
committerMartin Willi <martin@revosec.ch>
Wed, 7 May 2014 12:13:36 +0000 (14:13 +0200)
src/libcharon/plugins/vici/vici_cred.c

index da5e955..95446e5 100644 (file)
@@ -44,6 +44,98 @@ struct private_vici_cred_t {
        mem_cred_t *creds;
 };
 
+/**
+ * Create a (error) reply message
+ */
+static vici_message_t* create_reply(char *fmt, ...)
+{
+       vici_builder_t *builder;
+       va_list args;
+
+       builder = vici_builder_create();
+       builder->add_kv(builder, "success", fmt ? "no" : "yes");
+       if (fmt)
+       {
+               va_start(args, fmt);
+               builder->vadd_kv(builder, "errmsg", fmt, args);
+               va_end(args);
+       }
+       return builder->finalize(builder);
+}
+
+CALLBACK(load_cert, vici_message_t*,
+       private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+       certificate_type_t type;
+       x509_flag_t required_flags = 0, additional_flags = 0;
+       certificate_t *cert;
+       x509_t *x509;
+       chunk_t data;
+       char *str;
+
+       str = message->get_str(message, NULL, "type");
+       if (!str)
+       {
+               return create_reply("certificate type missing");
+       }
+       if (strcaseeq(str, "x509"))
+       {
+               type = CERT_X509;
+       }
+       else if (strcaseeq(str, "x509ca"))
+       {
+               type = CERT_X509;
+               required_flags = X509_CA;
+       }
+       else if (strcaseeq(str, "x509aa"))
+       {
+               type = CERT_X509;
+               additional_flags = X509_AA;
+       }
+       else if (strcaseeq(str, "x509crl"))
+       {
+               type = CERT_X509_CRL;
+       }
+       else if (strcaseeq(str, "x509ac"))
+       {
+               type = CERT_X509_AC;
+       }
+       else
+       {
+               return create_reply("invalid certificate type: %s", str);
+       }
+       data = message->get_value(message, chunk_empty, "data");
+       if (!data.len)
+       {
+               return create_reply("certificate data missing");
+       }
+       cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
+                                                         BUILD_BLOB_PEM, data,
+                                                         BUILD_X509_FLAG, additional_flags,
+                                                         BUILD_END);
+       if (!cert)
+       {
+               return create_reply("parsing %N certificate failed",
+                                                       certificate_type_names, type);
+       }
+       if (cert->get_type(cert) == CERT_X509)
+       {
+               x509 = (x509_t*)cert;
+
+               if ((required_flags & x509->get_flags(x509)) != required_flags)
+               {
+                       cert->destroy(cert);
+                       return create_reply("certificate misses required flag, rejected");
+               }
+       }
+
+       DBG1(DBG_CFG, "loaded certificate '%Y'", cert->get_subject(cert));
+
+       this->creds->add_cert(this->creds, TRUE, cert);
+
+       return create_reply(NULL);
+}
+
 CALLBACK(clear_creds, vici_message_t*,
        private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
 {
@@ -68,6 +160,7 @@ static void manage_command(private_vici_cred_t *this,
 static void manage_commands(private_vici_cred_t *this, bool reg)
 {
        manage_command(this, "clear-creds", clear_creds, reg);
+       manage_command(this, "load-cert", load_cert, reg);
 }
 
 METHOD(vici_cred_t, destroy, void,