Define a sha1sum_file() function in utils.c (which requires configure.ac
to check for -lcrypto and -lssl).  Use that in lxcapi_create to write out
the sha1sum of the template being used.

Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
---
 configure.ac           |    2 +
 src/lxc/Makefile.am    |    2 +-
 src/lxc/lxccontainer.c |  109 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/lxc/utils.c        |   36 ++++++++++++++++
 src/lxc/utils.h        |    2 +
 5 files changed, 146 insertions(+), 5 deletions(-)

diff --git a/configure.ac b/configure.ac
index 4567001..a7de8c8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -105,6 +105,8 @@ if test "$enable_apparmor" = "check" ; then
 fi
 AM_CONDITIONAL([ENABLE_APPARMOR], [test "x$enable_apparmor" = "xyes"])
 
+AC_CHECK_LIB([crypto], [EVP_get_digestbyname], [], AC_MSG_ERROR([You must 
install the ssl and crypto libraries]))
+
 AM_COND_IF([ENABLE_APPARMOR],
        [AC_CHECK_HEADER([sys/apparmor.h],[],[AC_MSG_ERROR([You must install 
the AppArmor development package in order to compile lxc])])
        AC_CHECK_LIB([apparmor], [aa_change_profile],[],[AC_MSG_ERROR([You must 
install the AppArmor development package in order to compile lxc])])
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 18469a1..fa090c4 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -116,7 +116,7 @@ liblxc_so_LDFLAGS = \
        -shared \
        -Wl,-soname,liblxc.so.$(firstword $(subst ., ,$(VERSION)))
 
-liblxc_so_LDADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SECCOMP_LIBS)
+liblxc_so_LDADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SECCOMP_LIBS) -lssl -lcrypto
 
 bin_SCRIPTS = \
        lxc-ps \
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 4ff9d35..4b26051 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -862,6 +862,102 @@ static bool create_run_template(struct lxc_container *c, 
char *tpath,
        return true;
 }
 
+bool prepend_lxc_header(char *path, const char *t, char *const argv[])
+{
+       size_t flen;
+       char *contents, *tpath;
+       int i, md_len;
+       FILE *f;
+       unsigned char md_value[EVP_MAX_MD_SIZE];
+       bool have_tpath = false;
+
+       if ((f = fopen(path, "r")) == NULL) {
+               SYSERROR("Opening old config");
+               return false;
+       }
+       if (fseek(f, 0, SEEK_END) < 0) {
+               SYSERROR("Seeking to end of old config file");
+               fclose(f);
+               return false;
+       }
+       if ((flen = ftell(f)) < 0) {
+               SYSERROR("telling size of old config");
+               fclose(f);
+               return false;
+       }
+       if (fseek(f, 0, SEEK_SET) < 0) {
+               SYSERROR("rewinding old config");
+               fclose(f);
+               return false;
+       }
+       if ((contents = malloc(flen + 1)) == NULL) {
+               SYSERROR("out of memory");
+               fclose(f);
+               return false;
+       }
+       if (fread(contents, 1, flen, f) != flen) {
+               SYSERROR("Reading old config");
+               free(contents);
+               fclose(f);
+               return false;
+       }
+       contents[flen] = '\0';
+       if (fclose(f) < 0) {
+               SYSERROR("closing old config");
+               free(contents);
+               return false;
+       }
+
+       if ((tpath = get_template_path(t)) < 0) {
+               ERROR("bad template: %s\n", t);
+               free(contents);
+               return false;
+       }
+
+       if (tpath) {
+               have_tpath = true;
+               md_len = sha1sum_file(tpath, md_value);
+               free(tpath);
+               if (md_len < 0) {
+                       free(contents);
+                       return false;
+               }
+       }
+
+       if ((f = fopen(path, "w")) == NULL) {
+               SYSERROR("reopening config for writing");
+               free(contents);
+               return false;
+       }
+       fprintf(f, "# Template used to create this container: %s\n", t);
+       if (argv) {
+               fprintf(f, "# Parameters passed to the template:");
+               while (*argv) {
+                       fprintf(f, " %s", *argv);
+                       argv++;
+               }
+               fprintf(f, "\n");
+       }
+       if (have_tpath) {
+               fprintf(f, "# Template script checksum (SHA-1): ");
+               for (i=0; i<md_len; i++)
+                       fprintf(f, "%02x", md_value[i]);
+               fprintf(f, "\n");
+       }
+       if (fwrite(contents, 1, flen, f) != flen) {
+               SYSERROR("Writing original contents");
+               free(contents);
+               fclose(f);
+               return false;
+       }
+       free(contents);
+       if (fclose(f) < 0) {
+               SYSERROR("Closing config file after write");
+               return false;
+       }
+       return true;
+}
+
 static bool lxcapi_destroy(struct lxc_container *c);
 /*
  * lxcapi_create:
@@ -959,6 +1055,11 @@ static bool lxcapi_create(struct lxc_container *c, const 
char *t,
        if (c->lxc_conf)
                lxc_conf_free(c->lxc_conf);
        c->lxc_conf = NULL;
+
+       if (!prepend_lxc_header(c->configfile, tpath, argv)) {
+               ERROR("Error prepending header to configuration file");
+               goto out_unlock;
+       }
        bret = load_config_locked(c, c->configfile);
 
 out_unlock:
@@ -1612,13 +1713,13 @@ static int update_name_and_paths(const char *path, 
struct lxc_container *oldc,
        }
        flen = ftell(f);
        if (flen < 0) {
-               fclose(f);
                SYSERROR("telling size of old config");
+               fclose(f);
                return -1;
        }
        if (fseek(f, 0, SEEK_SET) < 0) {
-               fclose(f);
                SYSERROR("rewinding old config");
+               fclose(f);
                return -1;
        }
        contents = malloc(flen+1);
@@ -1628,15 +1729,15 @@ static int update_name_and_paths(const char *path, 
struct lxc_container *oldc,
                return -1;
        }
        if (fread(contents, 1, flen, f) != flen) {
+               SYSERROR("reading old config");
                free(contents);
                fclose(f);
-               SYSERROR("reading old config");
                return -1;
        }
        contents[flen] = '\0';
        if (fclose(f) < 0) {
-               free(contents);
                SYSERROR("closing old config");
+               free(contents);
                return -1;
        }
 
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 136f943..b595d13 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -36,6 +36,7 @@
 #include <libgen.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <openssl/evp.h>
 
 #include "log.h"
 
@@ -392,3 +393,38 @@ int lxc_read_nointr_expect(int fd, void* buf, size_t 
count, const void* expected
        }
        return ret;
 }
+
+int sha1sum_file(char *fnam, unsigned char *md_value)
+{
+       EVP_MD_CTX *mdctx;
+       const EVP_MD *md;
+       char *line = NULL;
+       size_t len = 0, ret;
+       FILE *f;
+
+       unsigned int md_len;
+
+       OpenSSL_add_all_digests();
+       md = EVP_get_digestbyname("sha1");
+       if(!md) {
+               ERROR("Unknown message digest sha1\n");
+               return -1;
+       }
+
+       if ((f = fopen(fnam, "r")) < 0) {
+               SYSERROR("failed to open %s", fnam);
+               return -1;
+       }
+
+       mdctx = EVP_MD_CTX_create();
+       EVP_DigestInit_ex(mdctx, md, NULL);
+
+       while ((ret = getline(&line, &len, f)) != -1)
+               EVP_DigestUpdate(mdctx, line, ret);
+       EVP_DigestFinal_ex(mdctx, md_value, &md_len);
+       EVP_MD_CTX_destroy(mdctx);
+       fclose(f);
+       if (line)
+               free(line);
+       return (int) md_len;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 063f76c..ffcd4e5 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -26,6 +26,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include "config.h"
+#include <openssl/evp.h>
 
 /* returns 1 on success, 0 if there were any failures */
 extern int lxc_rmdir_onedev(char *path);
@@ -176,5 +177,6 @@ extern int lxc_wait_for_pid_status(pid_t pid);
 extern int lxc_write_nointr(int fd, const void* buf, size_t count);
 extern int lxc_read_nointr(int fd, void* buf, size_t count);
 extern int lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* 
expected_buf);
+extern int sha1sum_file(char *fnam, unsigned char *md_value);
 
 #endif
-- 
1.7.9.5


------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to