authenticate/checkvpw.cc
changeset 0 6f7a81934006
child 2 b3afb9f1e801
equal deleted inserted replaced
-1:000000000000 0:6f7a81934006
       
     1 // Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
       
     2 //
       
     3 // This program is free software; you can redistribute it and/or modify
       
     4 // it under the terms of the GNU General Public License as published by
       
     5 // the Free Software Foundation; either version 2 of the License, or
       
     6 // (at your option) any later version.
       
     7 //
       
     8 // This program is distributed in the hope that it will be useful,
       
     9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    11 // GNU General Public License for more details.
       
    12 //
       
    13 // You should have received a copy of the GNU General Public License
       
    14 // along with this program; if not, write to the Free Software
       
    15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    16 
       
    17 #include <config.h>
       
    18 #include <errno.h>
       
    19 #include <string.h>
       
    20 #include <sys/types.h>
       
    21 #include "config/configrc.h"
       
    22 #include "misc/exec.h"
       
    23 #include "misc/stat_fns.h"
       
    24 #include "authvlib.h"
       
    25 
       
    26 const mystring exec_presetuid = "checkvpw-presetuid";
       
    27 const mystring exec_postsetuid = "checkvpw-postsetuid";
       
    28 
       
    29 void fail(const char* msg, const char* execfile, int code)
       
    30 {
       
    31   presetenv("CHECKVPW_ERROR=", msg);
       
    32   execute(execfile);
       
    33   exit(code);
       
    34 }
       
    35 
       
    36 void fail_login(const char* msg)
       
    37 {
       
    38   fail(msg, "checkvpw-loginfail", 1);
       
    39 }
       
    40 
       
    41 void fail_baddata(const char* msg)
       
    42 {
       
    43   fail(msg, "checkvpw-error", 2);
       
    44 }
       
    45 
       
    46 void fail_temporary(const char* msg)
       
    47 {
       
    48   fail(msg, "checkvpw-error", 111);
       
    49 }
       
    50 
       
    51 struct auth_data 
       
    52 {
       
    53   mystring name;
       
    54   mystring pass;
       
    55   mystring stamp;
       
    56 
       
    57   auth_data(mystring n, mystring p, mystring s)
       
    58     : name(n), pass(p), stamp(s)
       
    59   {
       
    60     name = name.lower();
       
    61   }
       
    62   ~auth_data() { }
       
    63 };
       
    64 
       
    65 auth_data* getdata()
       
    66 {
       
    67   char buf[513];
       
    68   unsigned buflen = 0;
       
    69   while(buflen < sizeof(buf)) {
       
    70     int r;
       
    71     do
       
    72       r = read(3, buf+buflen, sizeof(buf) - buflen);
       
    73     while ((r == -1) && (errno == EINTR));
       
    74     if (r == -1) fail_baddata("Read error");
       
    75     if (r == 0) break;
       
    76     buflen += r;
       
    77   }
       
    78   if(buflen >= sizeof(buf))
       
    79     fail_baddata("Read buffer too long");
       
    80 
       
    81   char *name = buf;
       
    82   char *pass = 0;
       
    83   char *stamp = 0;
       
    84   bool has_end = false;
       
    85   
       
    86   char* bufend = buf+sizeof(buf);
       
    87 
       
    88   for(char* ptr = buf; ptr < bufend; ptr++)
       
    89     if(*ptr == 0) {
       
    90       ++ptr;
       
    91       if(!pass)
       
    92 	pass = ptr;
       
    93       else if(!stamp)
       
    94 	stamp = ptr;
       
    95       else {
       
    96 	has_end = true;
       
    97 	break;
       
    98       }
       
    99     }
       
   100   if(!has_end)
       
   101     fail_baddata("Invalid data");
       
   102   
       
   103   close(3);
       
   104   return new auth_data(name, pass, stamp);
       
   105 }
       
   106 
       
   107 char* strcasestr(const char* haystack, const char* needle)
       
   108 {
       
   109   for(size_t hlength = strlen(haystack), nlength = strlen(needle);
       
   110       hlength >= nlength; hlength--, haystack++)
       
   111     if(!strncasecmp(haystack, needle, nlength))
       
   112       return (char*)haystack;
       
   113   return 0;
       
   114 }
       
   115 
       
   116 unsigned find_maildir(int argc, const char* args[])
       
   117 {
       
   118   for(int arg = 0; arg < argc; arg++) {
       
   119     if(strcasestr(args[arg], config->maildir_arg_str().c_str()))
       
   120       return arg;
       
   121   }
       
   122   return argc-1;
       
   123 }
       
   124 
       
   125 void set_maildirarg(int argc, const char* argv[], user_data* udata)
       
   126 {
       
   127   unsigned maildirarg = find_maildir(argc-1, argv+1) + 1;
       
   128   if(!udata->maildir)
       
   129     udata->maildir = argv[maildirarg];
       
   130   if(!is_dir(udata->maildir.c_str()))
       
   131     udata->maildir = config->error_maildir();
       
   132   presetenv("MAILDIR=", udata->maildir);
       
   133 
       
   134   char* str = new char[udata->maildir.length()+1];
       
   135   memcpy(str, udata->maildir.c_str(), udata->maildir.length()+1);
       
   136   argv[maildirarg] = str;
       
   137 }
       
   138 
       
   139 int main(int argc, const char* argv[])
       
   140 {
       
   141   if(argc <= 1)
       
   142     fail_baddata("No subprogram given to execute");
       
   143   
       
   144   auth_data* auth = getdata();
       
   145 
       
   146   mystring hostname;
       
   147   set_domain(auth->name, hostname);
       
   148 
       
   149   user_data* udata = authenticate(auth->name, auth->pass, hostname);
       
   150 
       
   151   set_maildirarg(argc, argv, udata);
       
   152   
       
   153   if(execute_one(argv+1))
       
   154     fail_temporary("Execution of command line arguments failed");
       
   155 
       
   156   execute("checkvpw-postexec");
       
   157   return 0;
       
   158 }