authenticate/checkvpw.cc
changeset 0 6f7a81934006
child 2 b3afb9f1e801
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticate/checkvpw.cc	Wed Jan 16 22:39:43 2008 +0100
@@ -0,0 +1,158 @@
+// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include <config.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include "config/configrc.h"
+#include "misc/exec.h"
+#include "misc/stat_fns.h"
+#include "authvlib.h"
+
+const mystring exec_presetuid = "checkvpw-presetuid";
+const mystring exec_postsetuid = "checkvpw-postsetuid";
+
+void fail(const char* msg, const char* execfile, int code)
+{
+  presetenv("CHECKVPW_ERROR=", msg);
+  execute(execfile);
+  exit(code);
+}
+
+void fail_login(const char* msg)
+{
+  fail(msg, "checkvpw-loginfail", 1);
+}
+
+void fail_baddata(const char* msg)
+{
+  fail(msg, "checkvpw-error", 2);
+}
+
+void fail_temporary(const char* msg)
+{
+  fail(msg, "checkvpw-error", 111);
+}
+
+struct auth_data 
+{
+  mystring name;
+  mystring pass;
+  mystring stamp;
+
+  auth_data(mystring n, mystring p, mystring s)
+    : name(n), pass(p), stamp(s)
+  {
+    name = name.lower();
+  }
+  ~auth_data() { }
+};
+
+auth_data* getdata()
+{
+  char buf[513];
+  unsigned buflen = 0;
+  while(buflen < sizeof(buf)) {
+    int r;
+    do
+      r = read(3, buf+buflen, sizeof(buf) - buflen);
+    while ((r == -1) && (errno == EINTR));
+    if (r == -1) fail_baddata("Read error");
+    if (r == 0) break;
+    buflen += r;
+  }
+  if(buflen >= sizeof(buf))
+    fail_baddata("Read buffer too long");
+
+  char *name = buf;
+  char *pass = 0;
+  char *stamp = 0;
+  bool has_end = false;
+  
+  char* bufend = buf+sizeof(buf);
+
+  for(char* ptr = buf; ptr < bufend; ptr++)
+    if(*ptr == 0) {
+      ++ptr;
+      if(!pass)
+	pass = ptr;
+      else if(!stamp)
+	stamp = ptr;
+      else {
+	has_end = true;
+	break;
+      }
+    }
+  if(!has_end)
+    fail_baddata("Invalid data");
+  
+  close(3);
+  return new auth_data(name, pass, stamp);
+}
+
+char* strcasestr(const char* haystack, const char* needle)
+{
+  for(size_t hlength = strlen(haystack), nlength = strlen(needle);
+      hlength >= nlength; hlength--, haystack++)
+    if(!strncasecmp(haystack, needle, nlength))
+      return (char*)haystack;
+  return 0;
+}
+
+unsigned find_maildir(int argc, const char* args[])
+{
+  for(int arg = 0; arg < argc; arg++) {
+    if(strcasestr(args[arg], config->maildir_arg_str().c_str()))
+      return arg;
+  }
+  return argc-1;
+}
+
+void set_maildirarg(int argc, const char* argv[], user_data* udata)
+{
+  unsigned maildirarg = find_maildir(argc-1, argv+1) + 1;
+  if(!udata->maildir)
+    udata->maildir = argv[maildirarg];
+  if(!is_dir(udata->maildir.c_str()))
+    udata->maildir = config->error_maildir();
+  presetenv("MAILDIR=", udata->maildir);
+
+  char* str = new char[udata->maildir.length()+1];
+  memcpy(str, udata->maildir.c_str(), udata->maildir.length()+1);
+  argv[maildirarg] = str;
+}
+
+int main(int argc, const char* argv[])
+{
+  if(argc <= 1)
+    fail_baddata("No subprogram given to execute");
+  
+  auth_data* auth = getdata();
+
+  mystring hostname;
+  set_domain(auth->name, hostname);
+
+  user_data* udata = authenticate(auth->name, auth->pass, hostname);
+
+  set_maildirarg(argc, argv, udata);
+  
+  if(execute_one(argv+1))
+    fail_temporary("Execution of command line arguments failed");
+
+  execute("checkvpw-postexec");
+  return 0;
+}