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