]> andersk Git - moira.git/blame - clients/lib/pobox.c
Fix impressively unimportant whitespace issues
[moira.git] / clients / lib / pobox.c
CommitLineData
013096e5 1/* $Id$
2 *
3 * Shared routines for pobox changing.
4 *
5 * Copyright (C) 1999 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
8 */
9
10#include <mit-copyright.h>
11#include <moira.h>
12#include <mrclient.h>
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include <com_err.h>
19
20RCSID("$Header$");
21
798e9c7a 22enum { POTYPE_ERROR, POTYPE_POP, POTYPE_LOCAL, POTYPE_MAILHUB, POTYPE_SMTP, POTYPE_IMAP };
013096e5 23static int potype(char *machine);
24static int save_sloc_machine(int argc, char **argv, void *sq);
25static int save_alias_value(int argc, char **argv, void *sq);
26
27extern char *whoami;
28
533bacb3 29#ifdef _WIN32
30#define strtok_r(s, tokens, resume) strtok(s, tokens)
31#endif /* _WIN32 */
32
013096e5 33int mrcl_validate_pobox_smtp(char *user, char *address, char **ret)
34{
35 char *addr, *retaddr, *p, *lasts = NULL;
36 char *machine = NULL, *m;
37 int oldlen, len, status = MRCL_SUCCESS;
38
39 /* Make a private copy of address that we can mangle. */
40 addr = strdup(address);
41
42 retaddr = strdup("");
43 len = 1;
44
45 /* For each comma-delimited address, canonicalize the hostname and
46 * verify that the address won't cause mail problems.
47 */
48 for (p = strtok_r(addr, ", ", &lasts); p; p = strtok_r(NULL, ",", &lasts))
49 {
50 m = strchr(p, '@');
51 if (m)
52 {
53 *m++ = '\0'; /* get rid of the @ sign */
54 m = strtrim(m); /* get rid of whitespace */
55 }
56 else
57 {
58 com_err(whoami, 0, "No at sign (@) in address \"%s\".", p);
59 status = MRCL_REJECT;
60 goto cleanup;
61 }
62
16ed72d4 63 if (strlen(m) > 0)
64 {
65 machine = canonicalize_hostname(strdup(m));
66 }
67 else
68 {
f49ccd46 69 com_err(whoami, 0, "No hostname in address \"%s@\".", p);
16ed72d4 70 status = MRCL_REJECT;
71 goto cleanup;
72 }
73
013096e5 74 switch (potype(machine))
75 {
798e9c7a 76 case POTYPE_IMAP:
77 com_err(whoami, 0, "Cannot forward mail to IMAP server %s",
78 machine);
79 com_err(NULL, 0, "Use \"chpobox -p\" if you are trying to unset "
80 "your mail forwarding.");
81 status = MRCL_REJECT;
82 goto cleanup;
83
013096e5 84 case POTYPE_POP:
85 if (strcmp(p, user))
86 {
87 com_err(whoami, 0, "The name on the POP box (%s) must match "
88 "the username (%s).", p, user);
89 status = MRCL_REJECT;
90 goto cleanup;
91 }
92 /* Fall through */
93
94 case POTYPE_LOCAL:
95 if ((m = strchr(machine, '.')))
96 *m = '\0';
97 machine = realloc(machine, strlen(machine) + 6);
98 strcat(machine, ".LOCAL");
99 break;
100
101 case POTYPE_MAILHUB:
102 if (!strcmp(p, user))
103 {
104 com_err(whoami, 0, "The address \"%s@%s\" would create a mail "
105 "loop.", p, machine);
106 com_err(NULL, 0, "Set a POP pobox if you want local mail "
107 "delivery.");
108 status = MRCL_REJECT;
109 goto cleanup;
110 }
111 else
112 {
113 com_err(whoami, 0, "Cannot forward mail to a local mailing "
114 "address (%s@%s).", p, machine);
115 status = MRCL_REJECT;
116 goto cleanup;
117 }
118
119 case POTYPE_SMTP:
120 if (*m != '"' && strcasecmp(m, machine))
121 {
122 com_err(whoami, 0, "Warning: hostname %s canonicalized to %s\n",
123 m, machine);
124 }
125 break;
126
127 default:
128 status = MRCL_MOIRA_ERROR;
129 goto cleanup;
130 }
131
132 oldlen = len;
133 len += (oldlen > 1 ? 2 : 0) + strlen(p) + strlen(machine) + 1;
134 retaddr = realloc(retaddr, len);
135 sprintf(retaddr + oldlen - 1, "%s%s@%s", oldlen > 1 ? ", " : "",
136 p, machine);
137 free(machine);
138 machine = NULL; /* Make sure it doesn't get freed again later. */
139 }
140
141 cleanup:
142 free(addr);
143 if (status == MRCL_SUCCESS)
144 *ret = retaddr;
145 else
146 free(retaddr);
147 free(machine);
148
149 return status;
150}
151
798e9c7a 152/* Given a canonicalized machine name, ask the Moira server if it is
153 * of type IMAP, POP, LOCAL, or MAILHUB -- if none of those, we assume
154 * it's foreign.
013096e5 155 */
156static int potype(char *machine)
157{
158 char *name;
159 int status, match = 0;
160 static struct save_queue *pop = NULL, *local = NULL;
161 static struct save_queue *mailhub = NULL, *mailhub_name = NULL;
798e9c7a 162 static struct save_queue *imap = NULL;
163
164 /* 0. Check if the machine is an IMAP server. */
165 if (!imap)
166 {
167 char *service = "POSTOFFICE";
168 imap = sq_create();
169 status = mr_query("get_server_locations", 1, &service,
170 save_sloc_machine, imap);
171 if (status && (status != MR_NO_MATCH))
172 {
173 com_err(whoami, status, "while reading list of IMAP servers");
174 return POTYPE_ERROR;
175 }
176 }
177
178 /* Because of how sq_get_data works, we need to go through the entire
179 * queue even if we find a match, so that it gets reset for the next
180 * call.
181 */
182 while (sq_get_data(imap, &name))
183 {
184 if (!match && !strcasecmp(name, machine))
185 match = 1;
186 }
187
188 if (match)
189 return POTYPE_IMAP;
190
013096e5 191
192 /* 1. Check if the machine is a POP server. */
193 if (!pop)
194 {
195 char *service = "POP";
196 pop = sq_create();
197 status = mr_query("get_server_locations", 1, &service,
198 save_sloc_machine, pop);
199 if (status && (status != MR_NO_MATCH))
200 {
201 com_err(whoami, status, "while reading list of POP servers");
202 return POTYPE_ERROR;
203 }
204 }
205
013096e5 206 while (sq_get_data(pop, &name))
207 {
208 if (!match && !strcasecmp(name, machine))
209 match = 1;
210 }
211 if (match)
212 return POTYPE_POP;
213
214
215 /* 2. Check if the machine is "LOCAL". */
216 if (!local)
217 {
218 char *service = "LOCAL";
219 local = sq_create();
220 status = mr_query("get_server_locations", 1, &service,
221 save_sloc_machine, local);
222 if (status && (status != MR_NO_MATCH))
223 {
224 com_err(whoami, status, "while reading list of LOCAL servers");
225 return POTYPE_ERROR;
226 }
227 }
228
229 while (sq_get_data(local, &name))
230 {
231 if (!match && !strcasecmp(name, machine))
232 match = 1;
233 }
234 if (match)
235 return POTYPE_LOCAL;
236
237
238 /* 3. Check if the machine is one of the mailhubs. */
239 if (!mailhub)
240 {
241 char *service = "MAILHUB";
242 mailhub = sq_create();
243 status = mr_query("get_server_locations", 1, &service,
244 save_sloc_machine, mailhub);
245 if (status && (status != MR_NO_MATCH))
246 {
247 com_err(whoami, status, "while reading list of MAILHUB servers");
248 return POTYPE_ERROR;
249 }
250 }
251
252 while (sq_get_data(mailhub, &name))
253 {
254 if (!match && !strcasecmp(name, machine))
255 match = 1;
256 }
257 if (match)
258 return POTYPE_MAILHUB;
259
260
261 /* 4. Check if the machine is one of the external names of the mailhubs. */
262 if (!mailhub_name)
263 {
264 char *argv[3];
265 mailhub_name = sq_create();
266 argv[0] = "mailhub";
267 argv[1] = "TYPE";
268 argv[2] = "*";
269 status = mr_query("get_alias", 3, argv, save_alias_value, mailhub_name);
270 if (status && (status != MR_NO_MATCH))
271 {
272 com_err(whoami, status, "while reading list of mailhub names");
273 return POTYPE_ERROR;
274 }
275 }
276
277 while (sq_get_data(mailhub_name, &name))
278 {
279 if (!match && !strcasecmp(name, machine))
280 match = 1;
281 }
282 if (match)
283 return POTYPE_MAILHUB;
284
285 return POTYPE_SMTP;
286}
287
288static int save_sloc_machine(int argc, char **argv, void *sq)
289{
290 sq_save_data(sq, strdup(argv[1]));
291 return MR_CONT;
292}
293
294static int save_alias_value(int argc, char **argv, void *sq)
295{
296 sq_save_data(sq, strdup(argv[2]));
297 return MR_CONT;
298}
This page took 0.098962 seconds and 5 git commands to generate.