summaryrefslogtreecommitdiffstats
path: root/mcop/md5auth.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mcop/md5auth.cpp')
-rw-r--r--mcop/md5auth.cpp213
1 files changed, 213 insertions, 0 deletions
diff --git a/mcop/md5auth.cpp b/mcop/md5auth.cpp
new file mode 100644
index 0000000..5278870
--- /dev/null
+++ b/mcop/md5auth.cpp
@@ -0,0 +1,213 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ */
+
+#include <config.h>
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#elif HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+
+#include "md5.h"
+#include "md5auth.h"
+#include "debug.h"
+
+// MD5_BINARY_LEN is defined in md5.h
+#define MD5_COOKIE_LEN (MD5_BINARY_LEN*2)
+#define MD5_MANGLE_LEN (MD5_COOKIE_LEN*2)
+
+
+
+struct random_info {
+ struct timeval tv;
+ int pid;
+ struct utsname un;
+ char dev_urandom[MD5_BINARY_LEN];
+ char seed[MD5_COOKIE_LEN+1];
+ int number;
+};
+
+static char md5_seed[MD5_COOKIE_LEN+1];
+static char md5_cookie[MD5_COOKIE_LEN+1];
+static int md5_init = 0;
+static int md5_random_cookie_number = 0;
+
+static char *md5_to_ascii_overwrite(char *md5)
+{
+ char outascii[MD5_COOKIE_LEN+1];
+ char *result;
+ int i;
+
+ // convert to readable text
+ for(i = 0; i < MD5_BINARY_LEN; i++) {
+ sprintf(&outascii[i*2],"%02x",md5[i] & 0xff);
+ }
+ outascii[MD5_COOKIE_LEN] = 0;
+ result = strdup(outascii);
+
+ // try to zero out traces
+ memset(md5,0,MD5_BINARY_LEN);
+ memset(outascii,0,MD5_COOKIE_LEN);
+
+ // well, here it is
+ return result;
+}
+
+char *arts_md5_auth_mangle(const char *cookie)
+{
+ char mangle[MD5_MANGLE_LEN+1];
+ char out[MD5_BINARY_LEN];
+ assert(md5_init);
+
+ // concat the two cookies and mangle them to a new one
+ strncpy(mangle,md5_cookie, MD5_COOKIE_LEN);
+ mangle[MD5_COOKIE_LEN] = 0;
+ strncat(mangle,cookie, MD5_COOKIE_LEN);
+ mangle[MD5_MANGLE_LEN] = 0;
+ arts_md5sum((unsigned char *)mangle,MD5_MANGLE_LEN,out);
+
+ // try to zero out traces
+ memset(mangle,0,MD5_MANGLE_LEN);
+
+ return md5_to_ascii_overwrite(out);
+}
+
+char *arts_md5_auth_mkcookie()
+{
+ struct random_info r;
+ char out[MD5_BINARY_LEN];
+ int rndfd;
+
+ memset(&r,0,sizeof(struct random_info));
+
+ // collect some "random" system information
+ gettimeofday(&r.tv,0);
+ r.pid = getpid();
+ uname(&r.un);
+
+ // linux random device ; if that works, we have good random anyway, the
+ // above are just helpers for the case that it doesn't
+ rndfd = open("/dev/urandom",O_RDONLY);
+ if(rndfd != -1)
+ {
+ read(rndfd,r.dev_urandom,MD5_BINARY_LEN);
+ close(rndfd);
+ }
+
+ // ensure that two cookies that are requested very shortly after each
+ // other (so that it looks like "at the same time") won't be the same
+ r.number = ++md5_random_cookie_number;
+
+ // this is some seed from a file which is updated sometimes with a
+ // new "arts_md5_auth_mkcookie()" after initialization
+ strncpy(r.seed,md5_seed,MD5_COOKIE_LEN);
+
+ // build hash value of all information
+ arts_md5sum((unsigned char *)&r,sizeof(struct random_info),out);
+
+ // zero out traces and return
+ memset(&r,0,sizeof(struct random_info));
+ return md5_to_ascii_overwrite(out);
+}
+
+const char *arts_md5_auth_cookie()
+{
+ assert(md5_init);
+ return md5_cookie;
+}
+
+static int md5_load_cookie(const char *filename, char *cookie)
+{
+ int fd = open(filename,O_RDONLY);
+ int i;
+
+ if(fd != -1) {
+ struct stat st;
+ for(i=0;i<5;i++) {
+ fstat(fd,&st);
+ if(st.st_size == MD5_COOKIE_LEN) {
+ lseek(fd, 0, SEEK_SET);
+ if(read(fd,cookie,MD5_COOKIE_LEN) == MD5_COOKIE_LEN)
+ {
+ cookie[MD5_COOKIE_LEN] = 0;
+ close(fd);
+ return 1;
+ }
+ }
+ arts_warning("MCOP: "
+ "authority file has wrong size (just being written?)");
+ sleep(1);
+ }
+ }
+ return 0;
+}
+
+void arts_md5_auth_init_seed(const char *seedname)
+{
+ // don't care if it works - no harm is being done if it doesn't
+ md5_load_cookie(seedname,md5_seed);
+
+ /*
+ * maxage ensures that not everybody will try to update the seed
+ * at the same time, while it will take at most 5 hours between
+ * updates (if there are any initialization calls)
+ */
+ struct stat st;
+ int maxage = 300 + (getpid() & 0xfff)*4;
+ int lstat_result = lstat(seedname,&st);
+ if(lstat_result != 0 || (time(0) - st.st_mtime) > maxage)
+ {
+ int fd = open(seedname,O_TRUNC|O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR);
+ if(fd != -1) {
+ char *cookie = arts_md5_auth_mkcookie();
+ write(fd,cookie,strlen(cookie));
+ memset(cookie,0,strlen(cookie));
+ free(cookie);
+ close(fd);
+ }
+ }
+}
+
+bool arts_md5_auth_set_cookie(const char *cookie)
+{
+ if(strlen(cookie) != MD5_COOKIE_LEN)
+ return false;
+
+ strncpy(md5_cookie,cookie,MD5_COOKIE_LEN);
+ md5_cookie[MD5_COOKIE_LEN] = 0;
+ md5_init = 1;
+ return true;
+}