]> andersk Git - moira.git/blob - clients/lib/pobox.c
Fix impressively unimportant whitespace issues
[moira.git] / clients / lib / pobox.c
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
20 RCSID("$Header$");
21
22 enum { POTYPE_ERROR, POTYPE_POP, POTYPE_LOCAL, POTYPE_MAILHUB, POTYPE_SMTP, POTYPE_IMAP };
23 static int potype(char *machine);
24 static int save_sloc_machine(int argc, char **argv, void *sq);
25 static int save_alias_value(int argc, char **argv, void *sq);
26
27 extern char *whoami;
28
29 #ifdef _WIN32
30 #define strtok_r(s, tokens, resume) strtok(s, tokens)
31 #endif /* _WIN32 */
32
33 int 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
63       if (strlen(m) > 0)
64         {
65           machine = canonicalize_hostname(strdup(m));
66         }
67       else
68         {
69           com_err(whoami, 0, "No hostname in address \"%s@\".", p);
70           status = MRCL_REJECT;
71           goto cleanup;
72         }
73       
74       switch (potype(machine))
75         {
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
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
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.  
155  */
156 static 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;
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
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
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
288 static 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
294 static 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.061533 seconds and 5 git commands to generate.