Переглянути джерело

* Add auto encrypt/decrypt/migration of files

This will encode the encryption type into the first few bytes of the file.
This properly handles opening the old socksfile format, as well as
the old userfile format.
Bryan Drewery 17 роки тому
батько
коміт
e54d552ab4
3 змінених файлів з 133 додано та 28 видалено
  1. 1 1
      lib/bdlib
  2. 112 25
      src/EncryptedStream.c
  3. 20 2
      src/EncryptedStream.h

+ 1 - 1
lib/bdlib

@@ -1 +1 @@
-Subproject commit 30ad27174a49f82c9f59865ec3a4b1bacc7f2d3e
+Subproject commit 892bcf5134d9a274e292d0b1f67ea269595f4e35

+ 112 - 25
src/EncryptedStream.c

@@ -3,36 +3,123 @@
  */
  */
 #include "base64.h"
 #include "base64.h"
 #include <bdlib/src/String.h>
 #include <bdlib/src/String.h>
+#include <bdlib/src/base64.h>
 #include "EncryptedStream.h"
 #include "EncryptedStream.h"
 #include <stdarg.h>
 #include <stdarg.h>
 #include "compat/compat.h"
 #include "compat/compat.h"
 
 
-bd::String EncryptedStream::gets (size_t maxSize, char delim) {
-  if (!key.length()) return bd::Stream::gets(maxSize, delim);
-  bd::String tmp(bd::Stream::gets(maxSize, delim));
-  if (delim && tmp[tmp.length() - 1] == delim)
-    --tmp;
-  bd::String decrypted(decrypt_string(key, broken_base64Decode(tmp)));
-  /* The delimeter (\n) is not encrypted */
-  if (delim)
-    decrypted += delim;
-  return decrypted;
-}
+int EncryptedStream::loadFile (const int fd) {
+  if (!key.length()) return bd::Stream::loadFile(fd);
+  if (bd::Stream::loadFile(fd) == 1)
+    return 1;
+
+  bd::String in_buf;
+  char enc_flags = 0;
+
+  /* Peak at the first few bytes to determine the algorithm used */
+  if (str[0] == 0x7F && str[2] == 0x7F) {
+    enc_flags = str[1];
+    in_buf = str(3, str.length() - 3);
+  } else {
+    enc_flags |= ENC_NO_HEADER;
 
 
-void EncryptedStream::puts (const bd::String& str_in)
-{
-  if (loading) {
-    bd::Stream::puts(str_in);
-    return;
+    // Old socksfile format?
+    if (bd::String(str(0, 5)) == "+enc\n") {
+      enc_flags |= (ENC_KEEP_NEWLINES|ENC_AES_256_ECB|ENC_BASE64_BROKEN);
+      in_buf = str(5, str.length() - 5);
+    } else {
+      /* Peak at the first block to see if it matches a userfile */
+      if (decrypt_string(key, broken_base64Decode(str(0, 32)))(0, 4) == "#4v:")
+        enc_flags |= (ENC_KEEP_NEWLINES|ENC_AES_256_ECB|ENC_BASE64_BROKEN|ENC_NO_HEADER);
+      in_buf = str;
+    }
   }
   }
-  bd::String string(str_in);
-  if (key.length()) {
-    if (string[string.length() - 1] == '\n')
-      --string;
-    bd::String encrypted(broken_base64Encode(encrypt_string(key, string)));
-    encrypted += '\n';
-    bd::Stream::puts(encrypted);
-    return;
+
+  if (enc_flags & ENC_KEEP_NEWLINES) {
+    bd::String buf(in_buf), line, out_buf;
+    /* terribly ineffecient, but this is used infrequently */
+    while (buf.find('\n') != bd::String::npos) {
+      line = newsplit(buf, '\n');
+      unapply_filters(line, enc_flags);
+      line += '\n';
+      out_buf += line;
+    }
+
+    /* Finish the rest off */
+    if (buf.length()) {
+      line = buf;
+      unapply_filters(line, enc_flags);
+      line += '\n';
+      out_buf += line;
+    }
+    in_buf = out_buf;
+  } else {
+    unapply_filters(in_buf, enc_flags);
   }
   }
-  bd::Stream::puts(string);
+
+  str = in_buf;
+  return 0;
+}
+
+void EncryptedStream::apply_filters(bd::String& buf, const char enc_flags) const {
+#ifdef unimplemented
+  if (enc_flags & ENC_AES_256_CBC)
+    buf = encrypt_string_cbc(key, buf);
+#endif
+  if (enc_flags & ENC_AES_256_ECB)
+    buf = encrypt_string(key, buf);
+  if (enc_flags & ENC_BASE64_BROKEN)
+    buf = broken_base64Encode(buf);
+  if (enc_flags & ENC_BASE64)
+    buf = bd::base64Encode(buf);
+}
+
+void EncryptedStream::unapply_filters(bd::String& buf, const char enc_flags) const {
+  if (enc_flags & ENC_BASE64_BROKEN)
+    buf = broken_base64Decode(buf);
+  if (enc_flags & ENC_BASE64)
+    buf = bd::base64Decode(buf);
+#ifdef unimplemented
+  if (enc_flags & ENC_AES_256_CBC)
+    buf = decrypt_string_cbc(key, buf);
+#endif
+  if (enc_flags & ENC_AES_256_ECB)
+    buf = decrypt_string(key, buf);
+}
+
+int EncryptedStream::writeFile (const int fd, const char enc_flags) const {
+  if (!key.length()) return bd::Stream::writeFile(fd);
+
+  /* Encrypt the stream before writing it out */
+  bd::String out_buf;
+
+  if (enc_flags & ENC_KEEP_NEWLINES) {
+    bd::String buf(str), line;
+    /* terribly ineffecient, but this is used infrequently */
+    while (buf.find('\n') != bd::String::npos) {
+      line = newsplit(buf, '\n');
+      apply_filters(line, enc_flags);
+      line += '\n';
+      out_buf += line;
+    }
+
+    /* Finish the rest off */
+    if (buf.length()) {
+      line = buf;
+      apply_filters(line, enc_flags);
+      line += '\n';
+      out_buf += line;
+    }
+
+  } else {
+    out_buf = str;
+    apply_filters(out_buf, enc_flags);
+  }
+
+  if (enc_flags & ENC_NO_HEADER)
+    return bd::Stream(out_buf).writeFile(fd);
+
+  const char encoding[3] = {0x7F, enc_flags, 0x7F};
+  bd::String encrypted = bd::String(encoding, 3) + out_buf;
+  return bd::Stream(encrypted).writeFile(fd);
 }
 }

+ 20 - 2
src/EncryptedStream.h

@@ -7,10 +7,24 @@ namespace bd {
 #include <iostream>
 #include <iostream>
 #include <bdlib/src/Stream.h>
 #include <bdlib/src/Stream.h>
 #include <bdlib/src/String.h>
 #include <bdlib/src/String.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define ENC_AES_256_ECB 	1
+#define ENC_AES_256_CBC		2
+#define ENC_BASE64_BROKEN	4
+#define ENC_BASE64		8
+#define ENC_KEEP_NEWLINES	16
+#define ENC_NO_HEADER		32
+
+#define ENC_DEFAULT 		(ENC_AES_256_ECB)
 
 
 class EncryptedStream : public bd::Stream {
 class EncryptedStream : public bd::Stream {
   private:
   private:
         bd::String key;
         bd::String key;
+        void apply_filters(bd::String& buf, const char enc_flags) const;
+        void unapply_filters(bd::String& buf, const char enc_flags) const;
 
 
   protected:
   protected:
 
 
@@ -19,7 +33,11 @@ class EncryptedStream : public bd::Stream {
         EncryptedStream(bd::String& keyStr) : Stream(), key(keyStr) {};
         EncryptedStream(bd::String& keyStr) : Stream(), key(keyStr) {};
         EncryptedStream(EncryptedStream& stream) : Stream(stream), key(stream.key) {};
         EncryptedStream(EncryptedStream& stream) : Stream(stream), key(stream.key) {};
 
 
-        virtual bd::String gets(size_t, char delim = 0);
-        virtual void puts (const bd::String& string);
+        virtual int loadFile(const int fd);
+        virtual int loadFile(const char* fname) { return bd::Stream::loadFile(fname); }
+
+        virtual int writeFile(const int fd, const char enc_flags) const;
+        virtual int writeFile(const int fd) const { return writeFile(fd, ENC_DEFAULT); }
+        int writeFile(const char* fname, mode_t mode = (S_IRUSR|S_IWUSR)) const { return bd::Stream::writeFile(fname, mode); }
 };
 };
 #endif
 #endif