Print this page
5857 add -o option to lofiadm
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Andy Stormont <astormont@racktopsystems.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>

@@ -23,10 +23,11 @@
  * Use is subject to license terms.
  * Copyright 2012 Joyent, Inc.  All rights reserved.
  *
  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2014 Gary Mills
+ * Copyright (c) 2016 Andrey Sokolov
  */
 
 /*
  * lofiadm - administer lofi(7d). Very simple, add and remove file<->device
  * associations, and display status. All the ioctls are private between

@@ -151,10 +152,12 @@
 #define KILOBYTE                1024
 #define MEGABYTE                (KILOBYTE * KILOBYTE)
 #define GIGABYTE                (KILOBYTE * MEGABYTE)
 #define LIBZ                    "libz.so.1"
 
+const char lofi_crypto_magic[6] = LOFI_CRYPTO_MAGIC;
+
 static void
 usage(const char *pname)
 {
         (void) fprintf(stderr, gettext(USAGE), pname, pname, pname,
             pname, pname, pname, pname, pname, pname, pname);

@@ -833,11 +836,12 @@
 
 /*
  * PBE the passphrase into a raw key
  */
 static void
-getkeyfromuser(mech_alias_t *cipher, char **raw_key, size_t *raw_key_sz)
+getkeyfromuser(mech_alias_t *cipher, char **raw_key, size_t *raw_key_sz,
+    boolean_t with_confirmation)
 {
         CK_SESSION_HANDLE sess;
         CK_RV   rv;
         char    *pass = NULL;
         size_t  passlen = 0;

@@ -864,11 +868,12 @@
         rv = C_OpenSession(cipher->slot, CKF_SERIAL_SESSION, NULL, NULL, &sess);
         if (rv != CKR_OK)
                 goto cleanup;
 
         /* get user passphrase with 8 byte minimum */
-        if (pkcs11_get_pass(NULL, &pass, &passlen, MIN_PASSLEN, B_TRUE) < 0) {
+        if (pkcs11_get_pass(NULL, &pass, &passlen, MIN_PASSLEN,
+            with_confirmation) < 0) {
                 die(gettext("passphrases do not match\n"));
         }
 
         /*
          * salt should not be NULL, or else pkcs11_PasswdToKey() will

@@ -1757,10 +1762,45 @@
         if (name_to_minor(filename) != 0) {
                 die(gettext("cannot use %s on itself\n"), LOFI_DRIVER_NAME);
         }
 }
 
+static boolean_t
+check_file_is_encrypted(const char *filename)
+{
+        int     fd;
+        char    buf[sizeof (lofi_crypto_magic)];
+        int     got;
+        int     rest = sizeof (lofi_crypto_magic);
+
+        fd = open64(filename, O_RDONLY);
+        if (fd == -1)
+                die(gettext("failed to open: %s"), filename);
+
+        if (lseek(fd, CRYOFF, SEEK_SET) != CRYOFF)
+                die(gettext("failed to seek to offset 0x%lx in file %s"),
+                    CRYOFF, filename);
+
+        do {
+                got = read(fd, buf + sizeof (lofi_crypto_magic) - rest, rest);
+                if ((got == 0) || ((got == -1) && (errno != EINTR)))
+                        die(gettext("failed to read crypto header"
+                            " at offset 0x%lx in file %s"), CRYOFF, filename);
+
+                if (got > 0)
+                        rest -= got;
+        } while (rest > 0);
+
+        while (close(fd) == -1) {
+                if (errno != EINTR)
+                        die(gettext("failed to close file %s"), filename);
+        }
+
+        return (strncmp(buf, lofi_crypto_magic,
+            sizeof (lofi_crypto_magic)) == 0);
+}
+
 static uint32_t
 convert_to_num(const char *str)
 {
         int len;
         uint32_t segsize, mult = 1;

@@ -1830,11 +1870,11 @@
         pname = getpname(argv[0]);
 
         (void) setlocale(LC_ALL, "");
         (void) textdomain(TEXT_DOMAIN);
 
-        while ((c = getopt(argc, argv, "a:c:Cd:efk:o:rs:T:U")) != EOF) {
+        while ((c = getopt(argc, argv, "a:c:Cd:efk:rs:T:U")) != EOF) {
                 switch (c) {
                 case 'a':
                         addflag = B_TRUE;
                         if ((filename = realpath(optarg, realfilename)) == NULL)
                                 die("%s", optarg);

@@ -2019,11 +2059,12 @@
                             "mechanisms\n"));
 
                 init_crypto(token, cipher, &sess);
 
                 if (cipher_only) {
-                        getkeyfromuser(cipher, &rkey, &rksz);
+                        getkeyfromuser(cipher, &rkey, &rksz,
+                            !check_file_is_encrypted(filename));
                 } else if (token != NULL) {
                         getkeyfromtoken(sess, token, keyfile, cipher,
                             &rkey, &rksz);
                 } else {
                         /* this also handles ephemeral keys */