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