1 /* vmautoconvert.c - Automatically convert passwords for vmailmgr.
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 <bglibs/sysdeps.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23
24 #include <bglibs/cdb.h>
25 #include <bglibs/iobuf.h>
26 #include <bglibs/path.h>
27 #include <bglibs/str.h>
28 #include <vmailmgr/vpwentry.h>
29 #include <bglibs/uint32.h>
30
31 #include "module.h"
32 #include "qmail.h"
33 #include "cvm-vmailmgr.h"
34
read_start(ibuf * in,uint32 * end)35 static int read_start(ibuf* in, uint32* end)
36 {
37 unsigned char buf[2048];
38 if (!ibuf_read(in, (char*)buf, sizeof buf))
39 return 0;
40 *end = uint32_get_lsb(buf);
41 return 1;
42 }
43
read_cdb_pair(ibuf * in,str * key,str * data)44 static int read_cdb_pair(ibuf* in, str* key, str* data)
45 {
46 unsigned char buf[8];
47 uint32 keylen;
48 uint32 datalen;
49 if (!ibuf_read(in, (char*)buf, sizeof buf))
50 return 0;
51 keylen = uint32_get_lsb(buf);
52 datalen = uint32_get_lsb(buf+4);
53 if (!str_ready(key, keylen)
54 || !str_ready(data, datalen)
55 || !ibuf_read(in, key->s, keylen)
56 || !ibuf_read(in, data->s, datalen))
57 return 0;
58 key->s[key->len = keylen] = 0;
59 data->s[data->len = datalen] = 0;
60 return 1;
61 }
62
63 static str tmppwfile;
64 static str key;
65 static str data;
66
convert_data(void)67 static int convert_data(void)
68 {
69 struct vpwentry vpw;
70 int status = 1;
71 memset(&vpw, 0, sizeof vpw);
72 if (!vpwentry_import(&vpw, &virtuser, &data))
73 return 0;
74 status = str_copyb(&vpw.pass, "$0$", 3)
75 && str_cat(&vpw.pass, &cvm_module_credentials[CVM_CRED_PASSWORD])
76 && vpwentry_export(&vpw, &data);
77 vpwentry_free(&vpw);
78 return status;
79 }
80
vmailmgr_autoconvert(void)81 int vmailmgr_autoconvert(void)
82 {
83 int writefd = -1;
84 ibuf reader;
85 struct cdb_make writer;
86 int error = 0;
87 int readall = 0;
88 int writerr = 0;
89 if ((writefd = path_mktemp(pwfile, &tmppwfile)) != -1) {
90
91 if (cdb_make_start(&writer, writefd) != 0)
92 error = CVME_IO | CVME_FATAL;
93 else {
94
95 if (ibuf_open(&reader, pwfile, 0)) {
96
97 uint32 end;
98 struct stat st;
99 if (fstat(reader.io.fd, &st) == 0
100 && fchmod(writefd, st.st_mode) == 0
101 && fchown(writefd, st.st_uid, st.st_gid) == 0
102 && read_start(&reader, &end)) {
103 while (ibuf_tell(&reader) < end) {
104 if (!read_cdb_pair(&reader, &key, &data))
105 break;
106 if (str_diff(&key, &virtuser) == 0)
107 if (!convert_data()) {
108 writerr = 1;
109 break;
110 }
111 if (cdb_make_add(&writer, key.s, key.len, data.s, data.len) != 0) {
112 writerr = 1;
113 break;
114 }
115 }
116 readall = ibuf_tell(&reader) == end;
117 }
118 ibuf_close(&reader);
119 }
120 if (cdb_make_finish(&writer) != 0)
121 error |= CVME_FATAL;
122 else
123 if (readall && !writerr)
124 rename(tmppwfile.s, pwfile);
125 }
126 close(writefd);
127 unlink(tmppwfile.s);
128 }
129 return error;
130 }
131