1 /* cvm-vmailmgr.c - Direct file access vmailmgr CVM
2  * Copyright (C) 2010  Bruce Guenter <bruce@untroubled.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 #include <sys/types.h>
19 #include <errno.h>
20 #include <grp.h>
21 #include <pwd.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 
27 #include <bglibs/cdb.h>
28 #include <bglibs/cdb.h>
29 #include <bglibs/dict.h>
30 #include <bglibs/dict.h>
31 #include <bglibs/iobuf.h>
32 #include <bglibs/path.h>
33 #include <bglibs/str.h>
34 #include <vmailmgr/vpwentry.h>
35 
36 #include "module.h"
37 #include "qmail.h"
38 #include "cvm-vmailmgr.h"
39 
40 const char program[] = "cvm-vmailmgr";
41 
42 extern char* crypt(const char* key, const char* salt);
43 extern char* md5_crypt(const char* key, const char* salt);
44 
null_crypt(const char * pass)45 static const char* null_crypt(const char* pass)
46 {
47   static str buffer;
48   if (!str_copys(&buffer, "$0$")) return 0;
49   if (!str_cats(&buffer, pass)) return 0;
50   return buffer.s;
51 }
52 
53 str default_user = {0,0,0};
54 str domain = {0,0,0};
55 str virtuser = {0,0,0};
56 str vpwdata = {0,0,0};
57 
58 const char* pwfile = 0;
59 
60 static int lock_disabled;
61 static int do_autoconvert;
62 static vpwentry vpw;
63 
64 #define DEBUG(A,B,C) debug(__FUNCTION__, __LINE__, A, B, C)
65 static int show_debug = 0;
debug(const char * func,int line,const char * a,const char * b,const char * c)66 void debug(const char* func, int line,
67 	   const char* a, const char* b, const char* c)
68 {
69   if (!show_debug) return;
70   obuf_puts(&errbuf, func);
71   obuf_putc(&errbuf, '(');
72   obuf_puti(&errbuf, line);
73   obuf_puts(&errbuf, "): ");
74   if (a) obuf_puts(&errbuf, a);
75   if (b) obuf_puts(&errbuf, b);
76   if (c) obuf_puts(&errbuf, c);
77   obuf_putsflush(&errbuf, "\n");
78 }
79 
cvm_module_init(void)80 int cvm_module_init(void)
81 {
82   const char* tmp;
83   memset(&vpw, 0, sizeof vpw);
84   if ((pwfile = getenv("VMAILMGR_PWFILE")) == 0) pwfile = "passwd.cdb";
85   if ((tmp = getenv("VMAILMGR_DEFAULT")) == 0) tmp = "+";
86   lock_disabled = getenv("VMAILMGR_LOCK_DISABLED") != 0;
87   do_autoconvert = getenv("VMAILMGR_AUTOCONVERT") != 0;
88   if (!str_copys(&default_user, tmp)) return CVME_GENERAL;
89   if (getenv("DEBUG") != 0) show_debug = 1;
90   return lookup_init();
91 }
92 
93 static str directory;
94 
95 /* Account name is either "baseuser-virtuser" or "virtuser@domain" */
cvm_module_lookup(void)96 int cvm_module_lookup(void)
97 {
98   int err;
99 
100   if ((err = lookup_virtuser()) != 0) return err;
101 
102   if (!vpwentry_import(&vpw, &virtuser, &vpwdata)) {
103     DEBUG("Could not import virtual password data", 0, 0);
104     return CVME_IO;
105   }
106 
107   return 0;
108 }
109 
cvm_module_authenticate(void)110 int cvm_module_authenticate(void)
111 {
112   const char* stored;
113   const char* enc;
114   const char* pass;
115 
116   CVM_CRED_REQUIRED(PASSWORD);
117 
118   if (lock_disabled && !vpw.is_mailbox_enabled) {
119     DEBUG("Mailbox is disabled", 0, 0);
120     cvm_module_fact_uint(CVM_FACT_OUTOFSCOPE, 0);
121     return CVME_PERMFAIL;
122   }
123   if (vpw.pass.len < 3) {
124     DEBUG("Encoded password is too short", 0, 0);
125     cvm_module_fact_uint(CVM_FACT_OUTOFSCOPE, 0);
126     return CVME_PERMFAIL;
127   }
128   stored = vpw.pass.s;
129   pass = cvm_module_credentials[CVM_CRED_PASSWORD].s;
130   if (stored[0] == '$' && stored[2] == '$') {
131     switch (stored[1]) {
132     case '0':
133       enc = null_crypt(pass);
134       break;
135     case '1':
136       enc = md5_crypt(pass, stored);
137       break;
138     default:
139       enc = crypt(pass, stored);
140     }
141   }
142   else
143     enc = crypt(pass, stored);
144   if (strcmp(enc, stored) == 0) {
145     if (do_autoconvert
146 	&& (stored[0] != '$' || stored[1] != '0' || stored[2] != '$'))
147       return vmailmgr_autoconvert();
148     return 0;
149   }
150   DEBUG("authentication denied", 0, 0);
151   cvm_module_fact_uint(CVM_FACT_OUTOFSCOPE, 0);
152   return CVME_PERMFAIL;
153 }
154 
cvm_module_results(void)155 int cvm_module_results(void)
156 {
157   if (!str_copy(&directory, &vmuser.homedir)) return CVME_IO;
158   if (!path_merge(&directory, vpw.directory.s)) return CVME_IO;
159   cvm_fact_username = vpw.name.s;
160   cvm_fact_userid = vmuser.uid;
161   cvm_fact_groupid = vmuser.gid;
162   cvm_fact_realname = 0;
163   cvm_fact_directory = directory.s;
164   cvm_fact_shell = 0;
165   cvm_fact_sys_username = vmuser.user.s;
166   cvm_fact_sys_directory = vmuser.homedir.s;
167   cvm_fact_domain = domain.s;
168   cvm_fact_mailbox = directory.s;
169   return 0;
170 }
171 
cvm_module_stop(void)172 void cvm_module_stop(void)
173 {
174 }
175