Explorar el Código

Merge branch 'EncryptedStream'

* EncryptedStream: (27 commits)
  * Don't write out a header for compat userfiles
  * Fix overloaded problems with writeFile() not passing the proper enc_flags around
  * Fix another case where Stream was not being initialized properly
  * Don't pass fileno(f) around to Stream, use the fd or filename only
  * Delete failed temp userfiles
  * Fix userfile saving not using correct compat encryption
  * Return error if cannot read in userfile
  * Update bdlib
  * Fix readconf not properly initializing EncryptedStream
  * Also peek to see if reading in the old conf file
  * If transfering a userfile, write out an old format
  * Remove old lfprintf
  * Use EncryptedStream for writing binary config
  * Read config using EncryptedStream
  * newsplit(String) now returns the last token
  * Remove MD5FILE, never used
  * Add auto encrypt/decrypt/migration of files
  * Update bdlib
  * Simplify helper functions for encrypting/decrypting files by using EncryptedStream
  * Add -Woverloaded-virtual
  ...

Conflicts:
	Makefile.in
	src/net.h
	src/users.c
Bryan Drewery hace 16 años
padre
commit
f486983be1
Se han modificado 21 ficheros con 443 adiciones y 522 borrados
  1. 1 1
      Makefile.in
  2. 1 1
      autotools/includes/depend.m4
  3. 1 1
      configure
  4. 1 1
      lib/bdlib
  5. 94 25
      src/EncryptedStream.c
  6. 25 5
      src/EncryptedStream.h
  7. 137 160
      src/conf.c
  8. 2 2
      src/conf.h
  9. 12 118
      src/crypt.c
  10. 0 2
      src/crypt.h
  11. 36 43
      src/dccutil.c
  12. 6 2
      src/dccutil.h
  13. 48 59
      src/misc.c
  14. 7 4
      src/mod/server.mod/server.c
  15. 4 1
      src/mod/server.mod/server.h
  16. 15 18
      src/mod/share.mod/share.c
  17. 28 34
      src/net.c
  18. 6 3
      src/net.h
  19. 16 38
      src/userrec.c
  20. 0 1
      src/userrec.h
  21. 3 3
      src/users.c

+ 1 - 1
Makefile.in

@@ -41,7 +41,7 @@ DIFF = @DIFF@
 LIBS = @LIBS@ @SSL_LIBS@
 
 DEBCXXFLAGS = -DDEBUG -fno-inline -g3 -ggdb3 -O0 -Wshadow -Wpointer-arith -Wcast-align @GCC3DEB@ @GCC4DEB@
-CFLGS = @GCC3@ @SSL_INCLUDES@
+CFLGS = @GCC3@ -fno-rtti @SSL_INCLUDES@
 _CFLGS = -fno-strict-aliasing -W -Wformat \
 #-Wshadow -Wnested-externs -Wno-format-y2k \
 #-Wlarger-than-6608 -Wpointer-arith -Wcast-align \

+ 1 - 1
autotools/includes/depend.m4

@@ -11,7 +11,7 @@ num=`$CXX -dumpversion | sed "s/^\\\(.\\\).*/\\\1/"`
 if test $num -ge "3"; then
   CCDEPMODE=gcc3
 #  GCC3="-Wpadded -Wpacked -Wno-unused-parameter -Wmissing-format-attribute -Wdisabled-optimization"
-  GCC3="-W -Wno-unused-parameter -Wdisabled-optimization -Wno-write-strings -Wno-format-security -fno-strict-aliasing"
+  GCC3="-W -Wno-unused-parameter -Wdisabled-optimization -Wno-write-strings -Wno-format-security -fno-strict-aliasing -Woverloaded-virtual"
   GCC3DEB="-Wno-disabled-optimization -Wmissing-format-attribute"
 fi
 if test $num -ge "4"; then

+ 1 - 1
configure

@@ -3848,7 +3848,7 @@ num=`$CXX -dumpversion | sed "s/^\\\(.\\\).*/\\\1/"`
 if test $num -ge "3"; then
   CCDEPMODE=gcc3
 #  GCC3="-Wpadded -Wpacked -Wno-unused-parameter -Wmissing-format-attribute -Wdisabled-optimization"
-  GCC3="-W -Wno-unused-parameter -Wdisabled-optimization -Wno-write-strings -Wno-format-security -fno-strict-aliasing"
+  GCC3="-W -Wno-unused-parameter -Wdisabled-optimization -Wno-write-strings -Wno-format-security -fno-strict-aliasing -Woverloaded-virtual"
   GCC3DEB="-Wno-disabled-optimization -Wmissing-format-attribute"
 fi
 if test $num -ge "4"; then

+ 1 - 1
lib/bdlib

@@ -1 +1 @@
-Subproject commit 92e0e6c9f04d9695b58f514e5e057029ef1f4292
+Subproject commit ff74da9df961fc71b0f225663488fbef59556f59

+ 94 - 25
src/EncryptedStream.c

@@ -3,36 +3,105 @@
  */
 #include "base64.h"
 #include <bdlib/src/String.h>
+#include <bdlib/src/base64.h>
 #include "EncryptedStream.h"
 #include <stdarg.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;
+
+  /* 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 or an old conf file */
+      bd::String peek(decrypt_string(key, broken_base64Decode(str(0, 32))));
+      if (peek(0, 4) == "#4v:" || peek(0, 2) == "! ")
+        enc_flags |= (ENC_KEEP_NEWLINES|ENC_AES_256_ECB|ENC_BASE64_BROKEN);
+      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;
+    while (buf.length()) {
+      line = newsplit(buf, '\n');
+      unapply_filters(line);
+      line += '\n';
+      out_buf += line;
+    }
+    in_buf = out_buf;
+  } else {
+    unapply_filters(in_buf);
   }
-  bd::Stream::puts(string);
+
+  str = in_buf;
+  return 0;
+}
+
+void EncryptedStream::apply_filters(bd::String& buf) 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 {
+  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 {
+  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;
+    while (buf.length()) {
+      line = newsplit(buf, '\n');
+      apply_filters(line);
+      line += '\n';
+      out_buf += line;
+    }
+
+  } else {
+    out_buf = str;
+    apply_filters(out_buf);
+  }
+
+  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);
 }

+ 25 - 5
src/EncryptedStream.h

@@ -7,19 +7,39 @@ namespace bd {
 #include <iostream>
 #include <bdlib/src/Stream.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 {
   private:
         bd::String key;
+        mutable char enc_flags;
+        void apply_filters(bd::String& buf) const;
+        void unapply_filters(bd::String& buf) const;
 
   protected:
 
   public:
-        EncryptedStream(const char* keyStr) : Stream(), key(bd::String(keyStr)) {};
-        EncryptedStream(bd::String& keyStr) : Stream(), key(keyStr) {};
-        EncryptedStream(EncryptedStream& stream) : Stream(stream), key(stream.key) {};
+        EncryptedStream(const char* keyStr) : Stream(), key(bd::String(keyStr)), enc_flags(0) {};
+        EncryptedStream(bd::String& keyStr) : Stream(), key(keyStr), enc_flags(0) {};
+        EncryptedStream(EncryptedStream& stream) : Stream(stream), key(stream.key), enc_flags(0) {};
+
+        void setFlags(const char _enc_flags) const { enc_flags = _enc_flags; }
+        virtual int loadFile(const int fd);
+        virtual int writeFile(const int fd) const;
 
-        virtual bd::String gets(size_t, char delim = 0);
-        virtual void puts (const bd::String& string);
+        // Overloaded virtuals need to be called to prevent 'hiding' ... good job compiler.
+        virtual int loadFile(const char* fname) { return bd::Stream::loadFile(fname); }
+        virtual int writeFile(const char* fname, mode_t mode = (S_IRUSR|S_IWUSR)) const { return bd::Stream::writeFile(fname, mode); }
 };
 #endif

+ 137 - 160
src/conf.c

@@ -22,6 +22,8 @@
 #include "botnet.h"
 #include "userrec.h"
 #include <errno.h>
+#include "EncryptedStream.h"
+#include <bdlib/src/String.h>
 #ifdef HAVE_PATHS_H
 #  include <paths.h>
 #endif /* HAVE_PATHS_H */
@@ -201,7 +203,7 @@ confedit()
 
   um = umask(077);
 
-  autowrote = writeconf(NULL, tmpconf.f, CONF_COMMENT);
+  autowrote = writeconf(NULL, tmpconf.fd, CONF_COMMENT);
   fstat(tmpconf.fd, &st);		/* for file modification compares */
 //  tmpconf.my_close();
 
@@ -446,7 +448,7 @@ checkpid(const char *nick, conf_bot *bot)
 }
 
 void
-conf_addbot(char *nick, char *ip, char *host, char *ip6)
+conf_addbot(const char *nick, const char *ip, const char *host, const char *ip6)
 {
   conf_bot *bot = (conf_bot *) my_calloc(1, sizeof(conf_bot));
 
@@ -495,7 +497,7 @@ conf_addbot(char *nick, char *ip, char *host, char *ip6)
 #endif /* USE_IPV6 */
 
   if (userlist)
-    bot->u = get_user_by_handle(userlist, nick);
+    bot->u = get_user_by_handle(userlist, (char*)nick);
   else
     bot->u = NULL;
 
@@ -639,180 +641,154 @@ parseconf(bool error)
 int
 readconf(const char *fname, int bits)
 {
-  FILE *f = NULL;
-  int i = 0, enc = (bits & CONF_ENC) ? 1 : 0;
-  char *inbuf = NULL;
-  const char salt1[] = SALT1;
+  int enc = (bits & CONF_ENC) ? 1 : 0;
+  bd::Stream* stream;
+
+  if (enc) {
+    const char salt1[] = SALT1;
+    stream = new EncryptedStream(salt1);
+  } else
+    stream = new bd::Stream;
 
   sdprintf(STR("readconf(%s, %d)"), fname, enc);
-  Context;
-  if (!(f = fopen(fname, "r")))
+
+  if (stream->loadFile(fname)) {
+    delete stream;
     fatal(STR("Cannot read config"), 0);
+  }
 
   free_conf_bots(conf.bots);
-  inbuf = (char *) my_calloc(1, 201);
-  while (fgets(inbuf, 201, f) != NULL) {
-    char *line = NULL, *temp_ptr = NULL;
-
-    remove_crlf(inbuf);
-    if (enc)
-      line = temp_ptr = decrypt_string(salt1, inbuf);
-    else
-      line = inbuf;
 
-    if ((line && !line[0]) || line[0] == '\n') {
-      if (enc)
-        free(line);
-      continue;
-    }
+  bd::String line, option;
 
-    i++;
+  while (stream->tell() < stream->length()) {
+    line = stream->getline().chomp().trim();
 
-    rmspace(line);
+    // Skip blank lines
+    if (!line)
+      continue;
 
-    sdprintf(STR("CONF LINE: %s"), line);
+    sdprintf(STR("CONF LINE: %s"), line.c_str());
 // !strchr("_`|}][{*/#-+!abcdefghijklmnopqrstuvwxyzABDEFGHIJKLMNOPWRSTUVWXYZ", line[0])) {
-    if (enc && line[0] > '~') {
-      sdprintf(STR("line %d, char %c "), i, line[0]);
-      fatal(STR("Bad encryption"), 0);
-    } else {                    /* line is good to parse */
-      /* - uid */
-      if (line[0] == '-') {
-        newsplit(&line);
-        if (conf.uid == -1)
-          conf.uid = atoi(line);
+    /* - uid */
+    if (line[0] == '-') {
+      if (conf.uid == -1)
+        conf.uid = atoi(newsplit(line).c_str());
+
+      /* + uname */
+    } else if (line[0] == '+') {
+      if (!conf.uname)
+        conf.uname = strdup(newsplit(line).c_str());
+
+      /* ! is misc options */
+    } else if (line[0] == '!') {
+      ++line;
+      line.trim();
+
+      option.clear();
+      if (line.length())
+        option = newsplit(line);
+
+      if (!option || !line)
+        continue;
 
-        /* + uname */
-      } else if (line[0] == '+') {
-        newsplit(&line);
-        if (!conf.uname)
-          conf.uname = strdup(line);
+//      option.toLower();
 
-        /* ! is misc options */
-      } else if (line[0] == '!') {
-        char *option = NULL;
+      if (option == STR("autocron")) {      /* automatically check/create crontab? */
+        if (egg_isdigit(line[0]))
+          conf.autocron = atoi(line.c_str());
 
-        /* Only newplit if they did '! option' */
-        if (line[1] == ' ')
-          newsplit(&line);
-        else
-          ++line;
+      } else if (option == STR("autouname")) {      /* auto update uname contents? */
+        if (egg_isdigit(line[0]))
+          conf.autouname = atoi(line.c_str());
 
-        if (line[0])
-          option = newsplit(&line);
+      } else if (option == STR("username")) {       /* shell username */
+        str_redup(&conf.username, line.c_str());
 
-        if (!option || !line[0])
-          continue;
+      } else if (option == STR("homedir")) {        /* homedir */
+        str_redup(&conf.homedir, line.c_str());
 
-        if (!strcasecmp(option, STR("autocron"))) {      /* automatically check/create crontab? */
-          if (egg_isdigit(line[0]))
-            conf.autocron = atoi(line);
+      } else if (option == STR("datadir")) {        /* datadir */
+        str_redup(&conf.datadir, line.c_str());
 
-        } else if (!strcasecmp(option, STR("autouname"))) {      /* auto update uname contents? */
-          if (egg_isdigit(line[0]))
-            conf.autouname = atoi(line);
+      } else if (option == STR("binpath")) {        /* path that the binary should move to? */
+        str_redup(&conf.binpath, line.c_str());
 
-        } else if (!strcasecmp(option, STR("username"))) {       /* shell username */
-          str_redup(&conf.username, line);
+      } else if (option == STR("binname")) {        /* filename of the binary? */
+        str_redup(&conf.binname, line.c_str());
 
-        } else if (!strcasecmp(option, STR("homedir"))) {        /* homedir */
-          str_redup(&conf.homedir, line);
+      } else if (option == STR("portmin")) {
+        if (egg_isdigit(line[0]))
+          conf.portmin = atoi(line.c_str());
 
-        } else if (!strcasecmp(option, STR("datadir"))) {        /* datadir */
-          str_redup(&conf.datadir, line);
+      } else if (option == STR("portmax")) {
+        if (egg_isdigit(line[0]))
+          conf.portmax = atoi(line.c_str());
 
-        } else if (!strcasecmp(option, STR("binpath"))) {        /* path that the binary should move to? */
-          str_redup(&conf.binpath, line);
+      } else if (option == STR("uid")) {    /* new method uid */
+        if (str_isdigit(line.c_str()))
+          conf.uid = atoi(line.c_str());
 
-        } else if (!strcasecmp(option, STR("binname"))) {        /* filename of the binary? */
-          str_redup(&conf.binname, line);
+      } else if (option == STR("uname")) {  /* new method uname */
+        str_redup(&conf.uname, line.c_str());
 
-        } else if (!strcasecmp(option, STR("portmin"))) {
-          if (egg_isdigit(line[0]))
-            conf.portmin = atoi(line);
+      } else if (option == STR("watcher")) {
+        if (egg_isdigit(line[0]))
+          conf.watcher = atoi(line.c_str());
 
-        } else if (!strcasecmp(option, STR("portmax"))) {
-          if (egg_isdigit(line[0]))
-            conf.portmax = atoi(line);
+      } else {
+        putlog(LOG_MISC, "*", STR("Unrecognized config option '%s'"), option.c_str());
 
-        } else if (!strcasecmp(option, STR("uid"))) {    /* new method uid */
-          if (str_isdigit(line))
-            conf.uid = atoi(line);
+      }
+      /* read in portmin */
+    } else if (line[0] == '>') {
+      conf.portmin = atoi(newsplit(line).c_str());
 
-        } else if (!strcasecmp(option, STR("uname"))) {  /* new method uname */
-          str_redup(&conf.uname, line);
+    } else if (line[0] == '<') {
+      conf.portmax = atoi(newsplit(line).c_str());
 
-        } else if (!strcasecmp(option, STR("watcher"))) {
-          if (egg_isdigit(line[0]))
-            conf.watcher = atoi(line);
+      /* now to parse nick/hosts */
+    } else if (line[0] != '#') {
+      bd::String nick, host, ip, ipsix;
 
-        } else {
-          putlog(LOG_MISC, "*", STR("Unrecognized config option '%s'"), option);
+      nick = newsplit(line);
+      if (!nick)
+        werr(ERR_BADCONF);
 
-        }
-        /* read in portmin */
-      } else if (line[0] == '>') {
-        newsplit(&line);
-        conf.portmin = atoi(line);
-
-      } else if (line[0] == '<') {
-        newsplit(&line);
-        conf.portmax = atoi(line);
-
-        /* now to parse nick/hosts */
-      } else if (line[0] != '#') {
-        char *nick = NULL, *host = NULL, *ip = NULL, *ipsix = NULL;
-
-        nick = newsplit(&line);
-        if (!nick || (nick && !nick[0]))
-          werr(ERR_BADCONF);
-
-        if (line[0])
-          ip = newsplit(&line);
-        if (line[0])
-          host = newsplit(&line);
-        if (line[0])
-          ipsix = newsplit(&line);
-
-        conf_addbot(nick, ip, host, ipsix);
-      }
+      ip = newsplit(line);
+      host = newsplit(line);
+      ipsix = newsplit(line);
+
+      conf_addbot(nick.c_str(), ip.c_str(), host.c_str(), ipsix.c_str());
     }
-    inbuf[0] = 0;
-    if (enc)
-      free(temp_ptr);
   }                             /* while(fgets()) */
-  fclose(f);
-  free(inbuf);
 
+  delete stream;
   return 0;
 }
 
 char s1_9[3] = "",s1_5[3] = "",s1_1[3] = "";
 
 int
-writeconf(char *filename, FILE * stream, int bits)
+writeconf(char *filename, int fd, int bits)
 {
-  FILE *f = NULL;
   conf_bot *bot = NULL;
-  int (*my_write) (FILE *, const char *, ... ) = NULL;
   int autowrote = 0;
 
-  if (bits & CONF_ENC)
-    my_write = lfprintf;
-  else if (!(bits & CONF_ENC))
-    my_write = fprintf;
+  bd::Stream* stream;
+  bd::String buf;
+
+  if (bits & CONF_ENC) {
+    const char salt1[] = SALT1;
+    stream = new EncryptedStream(salt1);
+  } else
+    stream = new bd::Stream;
 
 #define comment(text)	do {		\
 	if (bits & CONF_COMMENT)	\
-	  my_write(f, STR("%s\n"), text);	\
+	  *stream << buf.printf(STR("%s\n"), text);	\
 } while(0)
 
-  if (stream) {
-    f = stream;
-  } else if (filename) {
-    if (!(f = fopen(filename, "w")))
-      return 1;
-  }
 #ifndef CYGWIN_HACKS
   char *p = NULL;
 
@@ -830,10 +806,10 @@ writeconf(char *filename, FILE * stream, int bits)
 
   if ((bits & CONF_COMMENT) && conf.uid != (signed) myuid) {
     conf_com();
-    my_write(f, STR("%s! uid %d\n"), do_confedit == CONF_AUTO ? "" : "#", myuid);
-    my_write(f, STR("%s! uid %d\n"), do_confedit == CONF_STATIC ? "" : "#", conf.uid);
+    *stream << buf.printf(STR("%s! uid %d\n"), do_confedit == CONF_AUTO ? "" : "#", myuid);
+    *stream << buf.printf(STR("%s! uid %d\n"), do_confedit == CONF_STATIC ? "" : "#", conf.uid);
   } else
-    my_write(f, STR("! uid %d\n"), conf.uid);
+    *stream << buf.printf(STR("! uid %d\n"), conf.uid);
 
   if (!conf.uname || (conf.uname && conf.autouname && strcmp(conf.uname, my_uname()))) {
     autowrote = 1;
@@ -842,45 +818,45 @@ writeconf(char *filename, FILE * stream, int bits)
     else
       comment("# Automatically updated empty uname");
 
-    my_write(f, STR("! uname %s\n"), my_uname());
+    *stream << buf.printf(STR("! uname %s\n"), my_uname());
     if (conf.uname)
-      my_write(f, STR("#! uname %s\n"), conf.uname);
+      *stream << buf.printf(STR("#! uname %s\n"), conf.uname);
   } else if (conf.uname && !conf.autouname && strcmp(conf.uname, my_uname())) {
     conf_com();
-    my_write(f, STR("%s! uname %s\n"), do_confedit == CONF_AUTO ? "" : "#", my_uname());
-    my_write(f, STR("%s! uname %s\n"), do_confedit == CONF_STATIC ? "" : "#", conf.uname);
+    *stream << buf.printf(STR("%s! uname %s\n"), do_confedit == CONF_AUTO ? "" : "#", my_uname());
+    *stream << buf.printf(STR("%s! uname %s\n"), do_confedit == CONF_STATIC ? "" : "#", conf.uname);
   } else
-    my_write(f, STR("! uname %s\n"), conf.uname);
+    *stream << buf.printf(STR("! uname %s\n"), conf.uname);
 
   comment("");
 
   if (conf.username && my_username() && strcmp(conf.username, my_username())) {
     conf_com();
-    my_write(f, STR("%s! username %s\n"), do_confedit == CONF_AUTO ? "" : "#", my_username());
-    my_write(f, STR("%s! username %s\n"), do_confedit == CONF_STATIC ? "" : "#", conf.username);
+    *stream << buf.printf(STR("%s! username %s\n"), do_confedit == CONF_AUTO ? "" : "#", my_username());
+    *stream << buf.printf(STR("%s! username %s\n"), do_confedit == CONF_STATIC ? "" : "#", conf.username);
   } else
-    my_write(f, STR("! username %s\n"), conf.username ? conf.username : my_username() ? my_username() : "");
+    *stream << buf.printf(STR("! username %s\n"), conf.username ? conf.username : my_username() ? my_username() : "");
 
   if (conf.homedir && homedir(0) && strcmp(conf.homedir, homedir(0))) {
     conf_com();
-    my_write(f, STR("%s! homedir %s\n"), do_confedit == CONF_AUTO ? "" : "#", homedir(0));
-    my_write(f, STR("%s! homedir %s\n"), do_confedit == CONF_STATIC ? "" : "#", conf.homedir);
+    *stream << buf.printf(STR("%s! homedir %s\n"), do_confedit == CONF_AUTO ? "" : "#", homedir(0));
+    *stream << buf.printf(STR("%s! homedir %s\n"), do_confedit == CONF_STATIC ? "" : "#", conf.homedir);
   } else 
-    my_write(f, STR("! homedir %s\n"), conf.homedir ? conf.homedir : homedir(0) ? homedir(0) : "");
+    *stream << buf.printf(STR("! homedir %s\n"), conf.homedir ? conf.homedir : homedir(0) ? homedir(0) : "");
 
   comment("\n# binpath needs to be full path unless it begins with '~', which uses 'homedir', ie, '~/'");
 
   if (homedir() && strstr(conf.binpath, homedir())) {
     p = replace(conf.binpath, homedir(), "~");
-    my_write(f, STR("! binpath %s\n"), p);
+    *stream << buf.printf(STR("! binpath %s\n"), p);
   } else if (conf.homedir && strstr(conf.binpath, conf.homedir)) { /* Could be an older homedir */
     p = replace(conf.binpath, conf.homedir, "~");
-    my_write(f, STR("! binpath %s\n"), p);
+    *stream << buf.printf(STR("! binpath %s\n"), p);
   } else
-    my_write(f, STR("! binpath %s\n"), conf.binpath);
+    *stream << buf.printf(STR("! binpath %s\n"), conf.binpath);
 
   comment("# binname is relative to binpath, if you change this, you'll need to manually remove the old one from crontab.");
-  my_write(f, STR("! binname %s\n"), conf.binname);
+  *stream << buf.printf(STR("! binname %s\n"), conf.binname);
 
   comment("");
 
@@ -889,20 +865,20 @@ writeconf(char *filename, FILE * stream, int bits)
 
     if (homedir() && strstr(conf.datadir, homedir())) {
       p = replace(conf.datadir, homedir(), "~");
-      my_write(f, STR("! datadir %s\n"), p);
+      *stream << buf.printf(STR("! datadir %s\n"), p);
     } else if (conf.homedir && strstr(conf.datadir, conf.homedir)) { /* Could be an older homedir */
       p = replace(conf.datadir, conf.homedir, "~");
-      my_write(f, STR("! datadir %s\n"), p);
+      *stream << buf.printf(STR("! datadir %s\n"), p);
     } else
-      my_write(f, STR("! datadir %s\n"), conf.datadir);
+      *stream << buf.printf(STR("! datadir %s\n"), conf.datadir);
 
     comment("");
   }
 
   if (conf.portmin || conf.portmax) {
     comment("# portmin/max are for incoming connections (DCC) [0 for any] (These only make sense for HUBS)");
-    my_write(f, STR("! portmin %d\n"), conf.portmin);
-    my_write(f, STR("! portmax %d\n"), conf.portmax);
+    *stream << buf.printf(STR("! portmin %d\n"), conf.portmin);
+    *stream << buf.printf(STR("! portmax %d\n"), conf.portmax);
 
     comment("");
   }
@@ -910,14 +886,14 @@ writeconf(char *filename, FILE * stream, int bits)
 
   if (conf.autocron == 0) {
     comment("# Automatically add the bot to crontab?");
-    my_write(f, STR("! autocron %d\n"), conf.autocron);
+    *stream << buf.printf(STR("! autocron %d\n"), conf.autocron);
 
     comment("");
   }
 
   if (conf.autouname) {
     comment("# Automatically update 'uname' if it changes? (DANGEROUS)");
-    my_write(f, STR("! autouname %d\n"), conf.autouname);
+    *stream << buf.printf(STR("! autouname %d\n"), conf.autouname);
 
     comment("");
   }
@@ -935,17 +911,18 @@ writeconf(char *filename, FILE * stream, int bits)
 
 #endif /* CYGWIN_HACKS */
   for (bot = conf.bots; bot && bot->nick; bot = bot->next) {
-    my_write(f, STR("%s%s %s %s%s %s\n"), 
+    *stream << buf.printf(STR("%s%s %s %s%s %s\n"),
              bot->disabled ? "/" : "", bot->nick,
              bot->net.ip ? bot->net.ip : "*", bot->net.host6 ? "+" : "",
              bot->net.host ? bot->net.host : (bot->net.host6 ? bot->net.host6 : "*"), bot->net.ip6 ? bot->net.ip6 : "");
   }
 
-  fflush(f);
-
-  if (!stream)
-    fclose(f);
+  if (fd != -1)
+    stream->writeFile(fd);
+  else
+    stream->writeFile(filename);
 
+  delete stream;
   return autowrote;
 }
 

+ 2 - 2
src/conf.h

@@ -58,7 +58,7 @@ void spawnbot(const char *);
 void spawnbots(conf_bot *bots, bool rehashed = 0);
 int conf_killbot(conf_bot *, const char *, conf_bot *, int, bool = 0);
 void confedit() __attribute__((noreturn));
-void conf_addbot(char *, char *, char *, char *);
+void conf_addbot(const char*, const char*, const char*, const char*);
 int conf_delbot(char *, bool kill = 1);
 pid_t checkpid(const char *, conf_bot *);
 void init_conf();
@@ -67,7 +67,7 @@ void free_conf_bots(conf_bot *);
 void free_bot(conf_bot *bot);
 int readconf(const char *, int);
 int parseconf(bool);
-int writeconf(char *, FILE *, int);
+int writeconf(char *, int, int);
 void fill_conf_bot(bool fatal = 1);
 void bin_to_conf(bool error = 0);
 void conf_checkpids(conf_bot *bots, bool all = 1);

+ 12 - 118
src/crypt.c

@@ -14,6 +14,8 @@
 #include "src/crypto/crypto.h"
 #include <stdarg.h>
 #include <bdlib/src/String.h>
+#include <bdlib/src/Stream.h>
+#include "EncryptedStream.h"
 
 char *encrypt_string(const char *keydata, char *in)
 {
@@ -110,109 +112,26 @@ char *salted_sha1(const char *in, const char* saltin)
   return ret;
 }
 
-int lfprintf (FILE *stream, const char *format, ...)
-{
-  va_list va;
-  char buf[2048] = "", *ln = NULL, *nln = NULL, *tmp = NULL;
-  int res;
-
-  va_start(va, format);
-  egg_vsnprintf(buf, sizeof buf, format, va);
-  va_end(va);
-
-  ln = buf;
-  const char salt1[] = SALT1;
-  while (ln && *ln) {
-    if ((nln = strchr(ln, '\n')))
-      *nln++ = 0;
-
-    tmp = encrypt_string(salt1, ln);
-    res = fprintf(stream, "%s\n", tmp);
-    free(tmp);
-    if (res == EOF)
-      return EOF;
-    ln = nln;
-  }
-  return 0;
-}
-
 void Encrypt_File(char *infile, char *outfile)
 {
-  FILE *f = NULL, *f2 = NULL;
-  bool std = 0;
-
-  if (!strcmp(outfile, "STDOUT"))
-    std = 1;
-  f  = fopen(infile, "r");
-  if(!f)
-    return;
-  if (!std) {
-    f2 = fopen(outfile, "w");
-    if (!f2)
-      return;
-  } else {
-    printf(STR("----------------------------------START----------------------------------\n"));
-  }
-
-  char *buf = (char *) my_calloc(1, 1024);
   const char salt1[] = SALT1;
-  while (fgets(buf, 1024, f) != NULL) {
-    remove_crlf(buf);
-
-    if (std)
-      printf("%s\n", encrypt_string(salt1, buf));
-    else
-      lfprintf(f2, "%s\n", buf);
-    buf[0] = 0;
-  }
-  free(buf);
-  if (std)
-    printf(STR("-----------------------------------END-----------------------------------\n"));
+  bd::Stream stream_in;
+  EncryptedStream stream_out(salt1);
 
-  fclose(f);
-  if (f2)
-    fclose(f2);
+  stream_in.loadFile(infile);
+  stream_out << bd::String(stream_in);
+  stream_out.writeFile(outfile);
 }
 
 void Decrypt_File(char *infile, char *outfile)
 {
-  FILE *f = NULL, *f2 = NULL;
-  bool std = 0;
-
-  if (!strcmp(outfile, "STDOUT"))
-    std = 1;
-  f  = fopen(infile, "r");
-  if (!f)
-    return;
-  if (!std) {
-    f2 = fopen(outfile, "w");
-    if (!f2)
-      return;
-  } else {
-    printf(STR("----------------------------------START----------------------------------\n"));
-  }
-
-  char *buf = (char *) my_calloc(1, 2048);
   const char salt1[] = SALT1;
-  while (fgets(buf, 2048, f) != NULL) {
-    char *temps = NULL;
-
-    remove_crlf(buf);
-    temps = (char *) decrypt_string(salt1, buf);
-    if (!std)
-      fprintf(f2, "%s\n",temps);
-    else
-      printf("%s\n", temps);
-    free(temps);
-    buf[0] = 0;
-  }
-  free(buf);
-  if (std)
-    printf(STR("-----------------------------------END-----------------------------------\n"));
+  bd::Stream stream_out;
+  EncryptedStream stream_in(salt1);
 
-  fclose(f);
-  if (f2)
-    fclose(f2);
+  stream_in.loadFile(infile);
+  stream_out << bd::String(stream_in);
+  stream_out.writeFile(outfile);
 }
 
 
@@ -247,31 +166,6 @@ int md5cmp(const char *hash, const char *string) {
   return n;
 }
 
-char *
-MD5FILE(const char *bin)
-{
-  FILE *f = NULL;
-
-  if (!(f = fopen(bin, "rb")))
-    return "";
-
-  static char     md5string[MD5_HASH_LENGTH + 1] = "";
-  unsigned char   md5out[MD5_HASH_LENGTH + 1] = "", buffer[1024] = "";
-  MD5_CTX ctx;
-  size_t binsize = 0, len = 0;
-
-  MD5_Init(&ctx);
-  while ((len = fread(buffer, 1, sizeof buffer, f))) {
-    binsize += len;
-    MD5_Update(&ctx, buffer, len);
-  }
-  MD5_Final(md5out, &ctx);
-  btoh(md5out, MD5_DIGEST_LENGTH, md5string, sizeof(md5string));
-  OPENSSL_cleanse(&ctx, sizeof(ctx));
-
-  return md5string;
-}
-
 char *SHA1(const char *string)
 {
   static int n = 0;

+ 0 - 2
src/crypt.h

@@ -23,7 +23,6 @@ namespace bd {
 
 char *MD5(const char *);
 int md5cmp(const char *, const char*);
-char *MD5FILE(const char *);
 char *SHA1(const char *);
 int sha1cmp(const char *, const char*);
 
@@ -34,7 +33,6 @@ char *salted_sha1(const char *, const char* = NULL);
 bd::String decrypt_string(const bd::String&, const bd::String&);
 char *cryptit (char *);
 char *decryptit (char *);
-int lfprintf (FILE *, const char *, ...) __attribute__((format(printf, 2, 3)));
 void Encrypt_File(char *, char *);
 void Decrypt_File(char *, char *);
 void btoh(const unsigned char *md, size_t md_len, char *buf, const size_t buf_len);

+ 36 - 43
src/dccutil.c

@@ -51,6 +51,8 @@
 #include "egg_timer.h"
 #include "src/mod/server.mod/server.h"
 #include <stdarg.h>
+#include <bdlib/src/String.h>
+#include <bdlib/src/Stream.h>
 
 static struct portmap *root = NULL;
 
@@ -451,38 +453,30 @@ dcc_chatter(int idx)
 }
 
 int
-dcc_read(FILE *f, bool enc)
+dcc_read(bd::Stream& stream)
 {
-  char inbuf[1024] = "", *type = NULL, *buf = NULL, *buf_ptr = NULL;
   int idx = -1;
   bool isserv = 0;
-  const char salt1[] = SALT1;
+  bd::String buf, type;
 
-  while (fgets(inbuf, sizeof(inbuf), f) != NULL) {
-    remove_crlf(inbuf);
-    if (enc)
-      buf = buf_ptr = decrypt_string(salt1, inbuf);
-    else
-      buf = inbuf;
+  while (stream.tell() < stream.length()) {
+    buf = stream.getline().chomp();
 
-    if (!strcmp(buf, "+dcc")) {
-      if (enc)
-        free(buf_ptr);
+    if (buf == STR("+dcc"))
       return idx;
-    }
     
-    type = newsplit(&buf);
-    if (!strcmp(type, "type")) {
+    type = newsplit(buf);
+    if (type == STR("type")) {
       struct dcc_table *dcc_type = NULL;
       size_t dcc_size = 0;
 
-//      if (!strcmp(buf, "CHAT"))
+//      if (buf == STR("CHAT"))
 //        dcc_type = &DCC_CHAT;
-      if (!strcmp(buf, "SERVER")) {
+      if (buf == STR("SERVER")) {
         dcc_type = &SERVER_SOCKET;
         isserv = 1;
       }
-//      if (!strcmp(buf, "BOT"))
+//      if (buf == STR("BOT"))
 //        dcc_type = &DCC_BOT;
     
       if (dcc_type) {
@@ -493,49 +487,48 @@ dcc_read(FILE *f, bool enc)
     }
 
     if (idx >= 0) {
-      if (!strcmp(type, "addr"))
-        dcc[idx].addr = my_atoul(buf);
-      if (!strcmp(type, "sock")) {
-        dcc[idx].sock = atoi(buf);
+      if (type == STR("addr"))
+        dcc[idx].addr = my_atoul(buf.c_str());
+      if (type == STR("sock")) {
+        dcc[idx].sock = atoi(buf.c_str());
         if (isserv)
           serv = dcc[idx].sock;
       }
-      if (!strcmp(type, "port"))
-        dcc[idx].port = atoi(buf);
-      if (!strcmp(type, "nick"))
-        strlcpy(dcc[idx].nick, buf, NICKLEN);
-      if (!strcmp(type, "host")) {
-        strlcpy(dcc[idx].host, buf, UHOSTLEN);
-      }
+      if (type == STR("port"))
+        dcc[idx].port = atoi(buf.c_str());
+      if (type == STR("nick"))
+        strlcpy(dcc[idx].nick, buf.c_str(), NICKLEN);
+      if (type == STR("host"))
+        strlcpy(dcc[idx].host, buf.c_str(), UHOSTLEN);
     }
-    if (enc)
-      free(buf_ptr);
   }
   return -1;
 }
 
 void 
-dcc_write(FILE *f, int idx)
+dcc_write(bd::Stream &stream, int idx)
 {
   if (dcc[idx].sock > 0) {
-    lfprintf(f, "-dcc\n");
+    bd::String buf;
+
+    stream << buf.printf(STR("-dcc\n"));
     if (dcc[idx].type)
-      lfprintf(f, "type %s\n", dcc[idx].type->name);
+      stream << buf.printf(STR("type %s\n"), dcc[idx].type->name);
 //  if (user)
-//  lfprintf(f, "user %s\n", dcc[idx].user->handle);
+//  stream << buf.printf(STR("user %s\n"), dcc[idx].user->handle);
     if (dcc[idx].addr)
-      lfprintf(f, "addr %u\n", dcc[idx].addr);
+      stream << buf.printf(STR("addr %u\n"), dcc[idx].addr);
     if (dcc[idx].status)
-      lfprintf(f, "status %lu\n", dcc[idx].status);
-    lfprintf(f, "sock %d\n", dcc[idx].sock);
-//  lfprintf(f, "simul %d\n", dcc[idx].simul);
+      stream << buf.printf(STR("status %lu\n"), dcc[idx].status);
+    stream << buf.printf(STR("sock %d\n"), dcc[idx].sock);
+//  stream << buf.printf(STR("simul %d\n"), dcc[idx].simul);
     if (dcc[idx].port)
-      lfprintf(f, "port %d\n", dcc[idx].port);  
+      stream << buf.printf(STR("port %d\n"), dcc[idx].port);
     if (dcc[idx].nick[0])
-      lfprintf(f, "nick %s\n", dcc[idx].nick);
+      stream << buf.printf(STR("nick %s\n"), dcc[idx].nick);
     if (dcc[idx].host[0])
-      lfprintf(f, "host %s\n", dcc[idx].host);
-    lfprintf(f, "+dcc\n");
+      stream << buf.printf(STR("host %s\n"), dcc[idx].host);
+    stream << buf.printf(STR("+dcc\n"));
   }
 }
 

+ 6 - 2
src/dccutil.h

@@ -14,6 +14,10 @@ struct portmap {
   struct portmap *next;
 };
 
+namespace bd {
+  class Stream;
+}
+
 /* Fake idx's for dprintf - these should be ridiculously large +ve nums
  */
 #define DP_STDOUT       0x7FF1
@@ -55,8 +59,8 @@ void identd_open(const char * = NULL, const char * = NULL);
 void identd_close();
 int listen_all(port_t, bool);
 bool valid_idx(int);
-int dcc_read(FILE *, bool);
-void dcc_write(FILE *, int);
+int dcc_read(bd::Stream&);
+void dcc_write(bd::Stream&, int);
 int check_cmd_pass(const char *, char *);
 int has_cmd_pass(const char *);
 void set_cmd_pass(char *, int);

+ 48 - 59
src/misc.c

@@ -53,6 +53,9 @@
 #include "userrec.h"
 #include "stat.h"
 #include "net.h"
+#include "EncryptedStream.h"
+#include <bdlib/src/String.h>
+#include <bdlib/src/Stream.h>
 
 #include <sys/wait.h>
 #include <stdarg.h>
@@ -597,58 +600,41 @@ readsocks(const char *fname)
   if (!conf.bot->hub)
     restarting = 1;
 
-  FILE *f = NULL;
-
-  if (!(f = fopen(fname, "r"))) {
-    fatal(STR("CANT READ SOCKSFILE"), 0);
-  }
-
-  char buf[1024] = "", *nick = NULL, *jnick = NULL, *bufp = NULL, *type = NULL, *buf_ptr = NULL, *ip4 = NULL, *ip6 = NULL;
+  char *nick = NULL, *jnick = NULL, *ip4 = NULL, *ip6 = NULL;
   time_t old_buildts = 0;
 
-  bool enc = 0, first = 1, cached_005 = 0;
+  bool cached_005 = 0;
   const char salt1[] = SALT1;
-
-  while (fgets(buf, sizeof(buf), f) != NULL) {
-    remove_crlf(buf);
-
-    if (first) {
-      if (!strncmp(buf, STR("+enc"), 4))
-        enc = 1;
-      first = 0;
-    }
-
-    if (enc)
-      bufp = buf_ptr = decrypt_string(salt1, buf);
-    else
-      bufp = buf;
-
-//    dprintf(DP_STDOUT, "read line: %s\n", buf);
-    type = newsplit(&bufp);
-    if (!strcmp(type, STR("-dcc")))
-      dprintf(DP_STDOUT, STR("Added dcc: %d\n"), dcc_read(f, enc));
-    else if (!strcmp(type, STR("-sock")))
-      dprintf(DP_STDOUT, STR("Added fd: %d\n"), sock_read(f, enc));
-    else if (!strcmp(type, STR("+online_since")))
-      online_since = strtol(bufp, NULL, 10);
-    else if (!strcmp(type, STR("+server_floodless")))
+  EncryptedStream stream(salt1);
+  stream.loadFile(fname);
+  bd::String str, type;
+
+  while (stream.tell() < stream.length()) {
+    str = stream.getline().chomp();
+    type = newsplit(str);
+
+//    dprintf(DP_STDOUT, "read line: %s\n", buf.c_str());
+    if (type == STR("-dcc"))
+      dprintf(DP_STDOUT, STR("Added dcc: %d\n"), dcc_read(stream));
+    else if (type == STR("-sock"))
+      dprintf(DP_STDOUT, STR("Added fd: %d\n"), sock_read(stream));
+    else if (type == STR("+online_since"))
+      online_since = strtol(str.c_str(), NULL, 10);
+    else if (type == STR("+server_floodless"))
       floodless = 1;
-    else if (!strcmp(type, STR("+buildts")))
-      old_buildts = strtol(bufp, NULL, 10);
-    else if (!strcmp(type, STR("+botname")))
-      nick = strdup(bufp);
-    else if (!strcmp(type, STR("+ip4")))
-      ip4 = strdup(bufp);
-    else if (!strcmp(type, STR("+ip6")))
-      ip6 = strdup(bufp);
-    else if (!strcmp(type, STR("+serv_cache"))) {
-      if (!cached_005 && strstr(bufp, "005"))
+    else if (type == STR("+buildts"))
+      old_buildts = strtol(str.c_str(), NULL, 10);
+    else if (type == STR("+botname"))
+      nick = strdup(str.c_str());
+    else if (type == STR("+ip4"))
+      ip4 = strdup(str.c_str());
+    else if (type == STR("+ip6"))
+      ip6 = strdup(str.c_str());
+    else if (type == STR("+serv_cache")) {
+      if (!cached_005 && str.find(STR("005")))
         cached_005 = 1;
-      dprintf(DP_CACHE, "%s", bufp);
+      dprintf(DP_CACHE, "%s", str.c_str());
     }
-
-    if (enc)
-      free(buf_ptr);
   }
 
   restart_time = now;
@@ -659,7 +645,6 @@ readsocks(const char *fname)
   tell_netdebug(DP_STDOUT);
 
   unlink(fname);
-  fclose(f);
 
   if (servidx >= 0) {
     char nserv[50] = "";
@@ -721,31 +706,35 @@ restart(int idx)
     }
   }
 
-  fprintf(socks->f, STR("+enc\n"));
+  const char salt1[] = SALT1;
+  EncryptedStream stream(salt1);
 
   /* write out all leftover dcc[] entries */
   for (fd = 0; fd < dcc_total; fd++)
     if (dcc[fd].type && dcc[fd].sock != STDOUT)
-      dcc_write(socks->f, fd);
+      dcc_write(stream, fd);
 
   /* write out all leftover socklist[] entries */
   for (fd = 0; fd < MAXSOCKS; fd++)
     if (socklist[fd].sock != STDOUT)
-      sock_write(socks->f, fd);
+      sock_write(stream, fd);
+
+  bd::String buf;
 
   if (server_online) {
     if (botname[0])
-      lfprintf(socks->f, STR("+botname %s\n"), botname);
+      stream << buf.printf(STR("+botname %s\n"), botname);
   }
-  lfprintf(socks->f, STR("+online_since %li\n"), online_since);
+  stream << buf.printf(STR("+online_since %li\n"), online_since);
   if (floodless)
-    lfprintf(socks->f, STR("+server_floodless %d\n"), floodless);
-  lfprintf(socks->f, STR("+buildts %li\n"), buildts);
-  lfprintf(socks->f, STR("+ip4 %s\n"), myipstr(AF_INET));
-  lfprintf(socks->f, STR("+ip6 %s\n"), myipstr(AF_INET6));
-  replay_cache(-1, socks->f);
+    stream << buf.printf(STR("+server_floodless %d\n"), floodless);
+  stream << buf.printf(STR("+buildts %li\n"), buildts);
+  stream << buf.printf(STR("+ip4 %s\n"), myipstr(AF_INET));
+  stream << buf.printf(STR("+ip6 %s\n"), myipstr(AF_INET6));
+  replay_cache(-1, &stream);
+
+  stream.writeFile(socks->fd);
 
-  fflush(socks->f);
   socks->my_close();
 
   if (conf.bot->hub)
@@ -878,7 +867,7 @@ int updatebin(int idx, char *par, int secs)
 
   Tempfile *conffile = new Tempfile("conf");
 
-  if (writeconf(NULL, conffile->f, CONF_ENC)) {
+  if (writeconf(NULL, conffile->fd, CONF_ENC)) {
     putlog(LOG_MISC, "*", STR("Failed to write temporary config file for update."));
     delete conffile;
     return 1;

+ 7 - 4
src/mod/server.mod/server.c

@@ -46,6 +46,8 @@
 #include "src/mod/channels.mod/channels.h"
 #include "src/mod/ctcp.mod/ctcp.h"
 #include "src/mod/irc.mod/irc.h"
+#include <bdlib/src/Stream.h>
+#include <bdlib/src/String.h>
 #include "server.h"
 #include <stdarg.h>
 
@@ -372,7 +374,7 @@ char *splitnicks(char **rest)
   return r;
 }
 
-void replay_cache(int idx, FILE *f) {
+void replay_cache(int idx, bd::Stream* stream) {
   if (!cacheq.head) return;
 
   struct msgq *r = NULL;
@@ -381,9 +383,10 @@ void replay_cache(int idx, FILE *f) {
   replaying_cache = 1;
 
   for (r = cacheq.head; r; r = r->next) {
-    if (f)
-      lfprintf(f, STR("+serv_cache %s\n"), r->msg);
-    else {
+    if (stream) {
+      bd::String buf;
+      *stream << buf.printf(STR("+serv_cache %s\n"), r->msg);
+    } else {
       //Create temporary buffer since server_activity may squash the buffer
       p_ptr = p = strdup(r->msg);
       server_activity(idx, p, r->len);

+ 4 - 1
src/mod/server.mod/server.h

@@ -24,6 +24,9 @@
         tputs(serv, "\r\n", 2);                         \
 } while (0)
 
+namespace bd {
+  class Stream;
+}
 
 struct server_list {
   struct server_list	*next;
@@ -72,7 +75,7 @@ void clearq(struct server_list *);
 void nuke_server(const char *);
 bool match_my_nick(char *);
 void rehash_server(const char *, const char *);
-void replay_cache(int, FILE *);
+void replay_cache(int, bd::Stream*);
 void join_chans();
 void check_hostmask();
 void next_server(int *, char *, port_t *, char *);

+ 15 - 18
src/mod/share.mod/share.c

@@ -1244,23 +1244,6 @@ check_expired_tbufs()
   }
 }
 
-static bool
-write_tmp_userfile(char *fn, const struct userrec *bu, int idx)
-{
-  FILE *f = NULL;
-  int ok = 1;
-
-  if ((f = fopen(fn, "wb"))) {
-    if (real_writeuserfile(idx, bu, f))
-      ok = 0;
-    fclose(f);
-    fixmod(fn);
-  }
-  if (!ok)
-    putlog(LOG_MISC, "*", "ERROR writing user file to transfer.");
-  return ok;
-}
-
 /* Erase old user list, switch to new one.
  */
 void
@@ -1490,7 +1473,21 @@ start_sending_users(int idx)
   simple_snprintf(share_file, sizeof(share_file), "%s.share.%s", tempdir, rand);
   //mktemp(share_file); //Although safe here, g++ complains too much.
 
-  write_tmp_userfile(share_file, userlist, idx);
+/* FIXME: REMOVE AFTER 1.2.14 */
+  bool old = 0;
+
+  tand_t* bot = idx != -1 ? findbot(dcc[idx].nick) : NULL;
+  if (bot && bot->buildts < 1175102242) /* flood-* hacks */
+    old = 1;
+
+  const char salt1[] = SALT1;
+  EncryptedStream stream(salt1);
+  stream_writeuserfile(stream, userlist, idx, old);
+  stream.setFlags(ENC_KEEP_NEWLINES|ENC_AES_256_ECB|ENC_BASE64_BROKEN|ENC_NO_HEADER);
+  if (stream.writeFile(share_file)) {
+    putlog(LOG_MISC, "*", "ERROR writing user file to transfer.");
+    unlink(share_file);
+  }
 
 /* compress.mod
   if (!compress_file(share_file, compress_level)) {

+ 28 - 34
src/net.c

@@ -37,6 +37,9 @@
 #include "egg_timer.h"
 #include "traffic.h"
 #include "adns.h"
+#include <bdlib/src/String.h>
+#include <bdlib/src/Stream.h>
+
 #include <limits.h>
 #include <string.h>
 #include <netdb.h>
@@ -83,14 +86,14 @@ port_t firewallport = 1080;    /* Default port of Sock4/5 firewalls        */
 
 /* I need an UNSIGNED long for dcc type stuff
  */
-unsigned long my_atoul(char *s)
+unsigned long my_atoul(const char *s)
 {
   unsigned long ret = 0;
 
   while ((*s >= '0') && (*s <= '9')) {
     ret *= 10;
     ret += ((*s) - '0');
-    s++;
+    ++s;
   }
   return ret;
 }
@@ -290,63 +293,54 @@ int sockoptions(int sock, int operation, int sock_options)
 }
 
 int
-sock_read(FILE *f, bool enc)
+sock_read(bd::Stream& stream)
 {
-  char inbuf[1024] = "", *type = NULL, *buf = NULL, *buf_ptr = NULL;
   int fd = -1;
-  const char salt1[] = SALT1;
-
-  while (fgets(inbuf, sizeof(inbuf), f) != NULL) {
-    remove_crlf(inbuf);
+  bd::String buf, type;
 
-    if (enc)
-      buf = buf_ptr = decrypt_string(salt1, inbuf);
-    else
-      buf = inbuf;
+  while (stream.tell() < stream.length()) {
+    buf = stream.getline().chomp();
 
-    if (!strcmp(buf, "+sock")) {
-      if (enc)
-        free(buf_ptr);
+    if (buf == STR("+sock"))
       return fd;
-    }
 
-    type = newsplit(&buf);
-    if (!strcmp(type, "sock")) {
-      int sock = atoi(newsplit(&buf)), options = atoi(newsplit(&buf));
+    type = newsplit(buf);
+    if (type == STR("sock")) {
+      int sock = atoi(newsplit(buf).c_str()), options = atoi(newsplit(buf).c_str());
 
       fd = allocsock(sock, options);
     }
 
     if (fd >= 0) {
 #ifdef USE_IPV6
-      if (!strcmp(type, "af"))
-        socklist[fd].af = atoi(buf);
+      if (type == STR("af"))
+        socklist[fd].af = atoi(buf.c_str());
 #endif
-      if (!strcmp(type, "host"))
-        socklist[fd].host = strdup(buf);
-      if (!strcmp(type, "port"))
-        socklist[fd].port = atoi(buf);
+      if (type == STR("host"))
+        socklist[fd].host = strdup(buf.c_str());
+      if (type == STR("port"))
+        socklist[fd].port = atoi(buf.c_str());
     }
-    if (enc)
-      free(buf_ptr);
   }
   return -1;
 }
 
 void 
-sock_write(FILE *f, int fd)
+sock_write(bd::Stream &stream, int fd)
 {
   if (socklist[fd].sock > 0) {
-    lfprintf(f, "-sock\n");
-    lfprintf(f, "sock %d %d\n", socklist[fd].sock, socklist[fd].flags);
+    bd::String buf;
+
+    stream << buf.printf(STR("-sock\n"));
+    stream << buf.printf(STR("sock %d %d\n"), socklist[fd].sock, socklist[fd].flags);
 #ifdef USE_IPV6
-    lfprintf(f, "af %u\n", socklist[fd].af);
+    stream << buf.printf(STR("af %u\n"), socklist[fd].af);
 #endif
     if (socklist[fd].host)
-      lfprintf(f, "host %s\n", socklist[fd].host);
+      stream << buf.printf(STR("host %s\n"), socklist[fd].host);
     if (socklist[fd].port)
-      lfprintf(f, "port %d\n", socklist[fd].port);
-    lfprintf(f, "+sock\n");
+      stream << buf.printf(STR("port %d\n"), socklist[fd].port);
+    stream << buf.printf(STR("+sock\n"));
   }    
 }
 

+ 6 - 3
src/net.h

@@ -10,6 +10,9 @@
 #include <sys/socket.h>
 #include <setjmp.h>
 
+namespace bd {
+  class Stream;
+}
 
 #define ENC_KEY_LEN 32
 
@@ -92,7 +95,7 @@ typedef struct {
 
 # define killsock(x)     	real_killsock((x),__FILE__,__LINE__)
 
-unsigned long my_atoul(char *);
+unsigned long my_atoul(const char *);
 char *myipstr(int);
 in_addr_t getmyip();
 void cache_my_ip();
@@ -130,8 +133,8 @@ char *iptostr(in_addr_t);
 bool sock_has_data(int, int);
 int sockoptions(int sock, int operation, int sock_options);
 void init_net(void);
-int sock_read(FILE *, bool);
-void sock_write(FILE *, int);
+int sock_read(bd::Stream&);
+void sock_write(bd::Stream&, int);
 
 extern union sockaddr_union 		cached_myip4_so;
 #ifdef USE_IPV6

+ 16 - 38
src/userrec.c

@@ -485,49 +485,15 @@ int write_userfile(int idx)
   if (userlist == NULL || !conf.bot->hub)
     return 1;			/* No point in saving userfile */
 
-  FILE *f = NULL;
-  char *new_userfile = NULL;
-  size_t siz = strlen(userfile) + 4 + 1;
-
-  new_userfile = (char *) my_calloc(1, siz);
-  simple_snprintf(new_userfile, siz, "%s~new", userfile);
-
-  f = fopen(new_userfile, "w");
-  if (f == NULL) {
-    putlog(LOG_MISC, "*", "ERROR writing user file.");
-    free(new_userfile);
-    return 2;
-  }
-  fchmod(fileno(f), S_IRUSR | S_IWUSR);
-
-  char backup[DIRMAX] = "";
-
   if (idx >= 0)
     dprintf(idx, "Saving userfile...\n");
 
   if (sort_users)
     sort_userlist();
 
-
   putlog(LOG_DEBUG, "@", "Writing user entries.");
 
-  if (real_writeuserfile(idx, userlist, f)) {
-    putlog(LOG_MISC, "*", "ERROR writing user file. (%s)", strerror(ferror(f)));
-    fclose(f);
-    free(new_userfile);
-    return 3;
-  }
-  fclose(f);
-  putlog(LOG_DEBUG, "@", "Done writing userfile.");
-  simple_snprintf(backup, sizeof backup, "%s/%s~", conf.datadir, userfile);
-  copyfile(userfile, backup);
-  movefile(new_userfile, userfile);
-  free(new_userfile);
-  return 0;
-}
-
-/* Used by writeuserfile() and write_tmp_userfile() in share.c */
-int real_writeuserfile(int idx, const struct userrec *bu, FILE *f) {
+  Tempfile *new_userfile = new Tempfile("userfile");
 /* FIXME: REMOVE AFTER 1.2.14 */
   bool old = 0;
 
@@ -537,9 +503,21 @@ int real_writeuserfile(int idx, const struct userrec *bu, FILE *f) {
 
   const char salt1[] = SALT1;
   EncryptedStream stream(salt1);
-  stream_writeuserfile(stream, bu, idx, old);
-  if ((fwrite(bd::String(stream).data(), 1, stream.length(), f) != stream.length()) || (fflush(f)))
-    return 1;
+  stream_writeuserfile(stream, userlist, idx, old);
+  if (stream.writeFile(new_userfile->fd)) {
+    putlog(LOG_MISC, "*", "ERROR writing user file. (%s)", strerror(errno));
+    delete new_userfile;
+    return 3;
+  }
+  new_userfile->my_close();
+  putlog(LOG_DEBUG, "@", "Done writing userfile.");
+
+  char backup[DIRMAX] = "";
+
+  simple_snprintf(backup, sizeof backup, "%s/%s~", conf.datadir, userfile);
+  copyfile(userfile, backup);
+  movefile(new_userfile->file, userfile);
+  delete new_userfile;
   return 0;
 }
 

+ 0 - 1
src/userrec.h

@@ -17,7 +17,6 @@ int change_handle(struct userrec *, char *);
 void correct_handle(char *);
 void stream_writeuserfile(bd::Stream&, const struct userrec *, int, bool = 0);
 int write_userfile(int);
-int real_writeuserfile(int idx, const struct userrec *bu, FILE *f);
 void touch_laston(struct userrec *, char *, time_t);
 void user_del_chan(char *);
 struct userrec *host_conflicts(char *);

+ 3 - 3
src/users.c

@@ -589,7 +589,8 @@ int readuserfile(const char *file, struct userrec **ret)
 {
   const char salt1[] = SALT1;
   EncryptedStream stream(salt1);
-  stream.loadFile(file);
+  if (stream.loadFile(file))
+    return 1;
   return stream_readuserfile(stream, ret);
 }
 
@@ -625,9 +626,8 @@ int stream_readuserfile(bd::Stream& stream, struct userrec **ret)
   }
   while (stream.tell() < stream.length()) {
     s = buf;
-    str = stream.getline(sizeof(buf));
+    str = stream.getline(sizeof(buf)).chomp();
     strlcpy(s, str.c_str(), std::min(str.length() + 1, sizeof(buf)));
-    remove_crlf(s);
     if (1) {
       line++;
       if (s[0] != '#' && s[0] != ';' && s[0]) {