1 /* cvm-qmail.c - qmail lookup-only 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 <bglibs/sysdeps.h>
19 #include <ctype.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include <bglibs/ibuf.h>
26 #include <bglibs/striter.h>
27
28 #include "module.h"
29 #include "qmail.h"
30
31 const char program[] = "cvm-qmail";
32
33 static struct qmail_user user;
34 static str domain;
35 static str username;
36 static str ext;
37 static str programs;
38 static int check_perms = 0;
39 static uid_t saved_uid;
40 static gid_t saved_gid;
41
cvm_module_init(void)42 int cvm_module_init(void)
43 {
44 const char* tmp;
45 if (qmail_lookup_init() == -1)
46 return CVME_IO;
47 if ((tmp = getenv("CVM_QMAIL_LOOKASIDE")) != 0) {
48 if (!str_copys(&programs, tmp))
49 return CVME_IO | CVME_FATAL;
50 str_subst(&programs, ' ', 0);
51 }
52
53 if ((tmp = getenv("CVM_QMAIL_CHECK_PERMS")) != 0 && tmp[0] != 0) {
54 check_perms = (tmp[0] == '-') ? CVME_PERMFAIL : CVME_IO;
55 saved_uid = getuid();
56 saved_gid = getgid();
57 }
58
59 return 0;
60 }
61
lookup_programs(const str * path)62 static int lookup_programs(const str* path)
63 {
64 static str dotqmail;
65 striter line;
66 striter progname;
67 const char* start;
68 const char* end;
69 unsigned long left;
70
71 if (!ibuf_openreadclose(path->s, &dotqmail))
72 return -1;
73 striter_loop(&line, &dotqmail, '\n') {
74 /* skip over spaces preceding '|' */
75 for (start = line.startptr, left = line.len;
76 left > 0 && isspace(*start);
77 --left, ++start)
78 ;
79 if (left > 0 && *start == '|') {
80 /* skip spaces preceding the program name */
81 for (++start, --left;
82 left > 0 && isspace(*start);
83 --left, ++start)
84 ;
85 /* the program name ends at the first space */
86 for (end = start;
87 left > 0 && !isspace(*end);
88 --left, ++end)
89 ;
90 if (end > start) {
91 striter_loop(&progname, &programs, 0) {
92 if ((unsigned long)(end - start) == progname.len
93 && memcmp(progname.startptr, start, progname.len) == 0)
94 return 1;
95 }
96 }
97 }
98 }
99 return 0;
100 }
101
102 /* Account name is either "baseuser-virtuser" or "virtuser@domain" */
cvm_module_lookup(void)103 int cvm_module_lookup(void)
104 {
105 static str path;
106 int r;
107
108 switch (qmail_lookup_cvm(&user, &domain, &username, &ext)) {
109 case -1:
110 return CVME_IO;
111 case 0:
112 break;
113 case 1:
114 cvm_module_fact_uint(CVM_FACT_OUTOFSCOPE, 1);
115 return CVME_PERMFAIL;
116 default:
117 cvm_module_fact_uint(CVM_FACT_OUTOFSCOPE, 0);
118 return CVME_PERMFAIL;
119 }
120
121 if (check_perms) {
122 setegid(user.gid);
123 seteuid(user.uid);
124 }
125 r = qmail_dotfile_exists(&user, ext.s, &path);
126 if (check_perms) {
127 seteuid(saved_uid);
128 setegid(saved_gid);
129 }
130 switch (r) {
131 case -1:
132 if (errno == EACCES && check_perms == CVME_PERMFAIL) {
133 cvm_module_fact_uint(CVM_FACT_OUTOFSCOPE, 0);
134 return CVME_PERMFAIL;
135 }
136 return CVME_IO;
137 case 0:
138 cvm_module_fact_uint(CVM_FACT_OUTOFSCOPE, 0);
139 return CVME_PERMFAIL;
140 }
141
142 if (programs.len > 0) {
143 switch (lookup_programs(&path)) {
144 case -1:
145 return CVME_IO;
146 case 0:
147 break;
148 default:
149 cvm_module_fact_uint(CVM_FACT_OUTOFSCOPE, 1);
150 return CVME_PERMFAIL;
151 }
152 }
153
154 return 0;
155 }
156
cvm_module_authenticate(void)157 int cvm_module_authenticate(void)
158 {
159 return CVME_CONFIG;
160 }
161
cvm_module_results(void)162 int cvm_module_results(void)
163 {
164 cvm_fact_username = user.user.s;
165 cvm_fact_userid = user.uid;
166 cvm_fact_groupid = user.gid;
167 cvm_fact_realname = 0;
168 cvm_fact_directory = user.homedir.s;
169 cvm_fact_shell = 0;
170 cvm_fact_sys_username = user.user.s;
171 cvm_fact_sys_directory = user.homedir.s;
172 cvm_fact_domain = domain.s;
173 cvm_fact_mailbox = user.homedir.s;
174 return 0;
175 }
176
cvm_module_stop(void)177 void cvm_module_stop(void)
178 {
179 }
180