1 /*:ts=8*/
2 /*****************************************************************************
3 * FIDOGATE --- Gateway software UNIX <-> FIDO
4 *
5 * $Id: address.c,v 4.19 2004/08/22 20:19:11 n0ll Exp $
6 *
7 * Parsing and conversion for FIDO and RFC addresses
8 *
9 *****************************************************************************
10 * Copyright (C) 1990-2004
11 * _____ _____
12 * | |___ | Martin Junius
13 * | | | | | | Radiumstr. 18 Internet: mj.at.n0ll.dot.net
14 * |_|_|_|@home| D-51069 Koeln, Germany
15 *
16 * This file is part of FIDOGATE.
17 *
18 * FIDOGATE is free software; you can redistribute it and/or modify it
19 * under the terms of the GNU General Public License as published by the
20 * Free Software Foundation; either version 2, or (at your option) any
21 * later version.
22 *
23 * FIDOGATE is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with FIDOGATE; see the file COPYING. If not, write to the Free
30 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31 *****************************************************************************/
32
33 #include "fidogate.h"
34
35
36
37 /*
38 * Local prototypes
39 */
40 static int try_pfnz (Node *, char *, char *, char *);
41
42
43
44 /*
45 * HostsRestricted mode: bounce mails to/from unknown FTN addresses
46 * (not registered in HOSTS)
47 */
48 static int hosts_restricted = FALSE;
49
50
51
52 #ifdef AI_6
53 static char **addr_is_local_pats = NULL;
54 #endif
55
56 /*
57 * Set/get HostsRestricted mode
58 */
addr_restricted(int f)59 void addr_restricted(int f)
60 {
61 hosts_restricted = f;
62 }
63
addr_is_restricted(void)64 int addr_is_restricted(void)
65 {
66 return hosts_restricted;
67 }
68
69
70
71 /*
72 * str_ftn_to_inet(): convert FTN address to Internet address
73 *
74 * force==TRUE: generate `pX.' point address even if `-p' is not
75 * specified in HOSTS.
76 */
str_ftn_to_inet(char * buf,size_t len,Node * node,int force)77 char *str_ftn_to_inet(char *buf, size_t len, Node *node, int force)
78 {
79 Host *h;
80 int point;
81
82 h = hosts_lookup(node, NULL);
83
84 if(h) /* Address found in HOSTS */
85 {
86 point = h->flags & HOST_POINT ? TRUE : force;
87 if(h->name)
88 {
89 if(point && node->point && !h->node.point)
90 str_printf(buf, len, "p%d.%s", node->point, h->name);
91 else
92 str_printf(buf, len, "%s", h->name);
93 }
94 else
95 str_printf(buf, len, "%s%s", node_to_pfnz(node, FALSE),
96 cf_hostsdomain());
97 }
98 else
99 str_printf(buf, len, "%s%s", node_to_pfnz(node, FALSE),
100 cf_zones_inet_domain(node->zone));
101
102 return buf;
103 }
104
105
106
107 /*
108 * s_ftn_to_inet(): convert FTN address to Internet address
109 */
s_ftn_to_inet(Node * node,int force)110 char *s_ftn_to_inet(Node *node, int force)
111 {
112 TmpS *s;
113
114 s = tmps_alloc(MAXINETADDR);
115 str_ftn_to_inet(s->s, s->len, node, force);
116 return s->s;
117 }
118
119
120
121 /*
122 * s_ftn_to_inet_pfnz(): convert FTN address to p.f.n.z Internet address
123 */
s_ftn_to_inet_pfnz(Node * node)124 char *s_ftn_to_inet_pfnz(Node *node)
125 {
126 TmpS *s;
127
128 s = tmps_alloc(MAXINETADDR);
129 str_copy (s->s, s->len, node_to_pfnz(node, FALSE));
130 str_append(s->s, s->len, cf_zones_inet_domain(node->zone));
131 tmps_stripsize(s);
132
133 return s->s;
134 }
135
136
137 #ifdef AI_1
138 /*
139 * verify_host_flag(): Verify FTN host flag
140 *
141 */
verify_host_flag(Node * node,int flag)142 int verify_host_flag(Node *node, int flag)
143 {
144 Host *h;
145
146 h = hosts_lookup(node, NULL);
147 if(h) /* Address found in HOSTS */
148 {
149 return h->flags & flag ? TRUE : FALSE;
150 }
151 return FALSE;
152 }
153 #endif
154
155 /*
156 * inet_to_ftn(): convert Internet address to FTN address
157 */
try_pfnz(Node * node,char * addr,char * dot,char * domain)158 static int try_pfnz(Node *node, char *addr, char *dot, char *domain)
159 {
160 char dom[MAXINETADDR];
161 char adr[MAXINETADDR];
162
163 int len = strlen(addr);
164 int dlen = strlen(dot) + strlen(domain);
165
166 BUF_COPY(adr, addr);
167 BUF_COPY(dom, dot);
168 BUF_APPEND(dom, domain);
169
170 if(len > dlen && !stricmp(adr+len-dlen, dom))
171 {
172 adr[len - dlen] = 0;
173 if(pfnz_to_node(adr, node, FALSE) == OK)
174 return TRUE;
175 }
176
177 return FALSE;
178 }
179
180
inet_to_ftn(char * addr)181 Node *inet_to_ftn(char *addr)
182 {
183 char buf[MAXINETADDR];
184 static Node node;
185 Host *host;
186 char *p, *pn;
187 int point = -1;
188
189 /*
190 * Look for optional point addressing in front of host name
191 */
192 p = addr;
193 if(*p=='p' || *p=='P') {
194 p++;
195 pn = p;
196 while(*p && is_digit(*p))
197 p++;
198 if(*p == '.') { /* Must end with '.' */
199 p++;
200 point = atoi(pn); /* Point number */
201 }
202 else
203 p = addr; /* No pX. */
204 }
205
206 /*
207 * 1. Lookup in HOSTS
208 */
209 if( (host = hosts_lookup(NULL, p)) )
210 {
211 node = host->node;
212 if(!node.point && point!=-1)
213 node.point = point;
214 return &node;
215 }
216
217 /*
218 * 2. Add domainname and lookup in HOSTS
219 */
220 BUF_COPY(buf, p);
221 BUF_APPEND(buf, cf_domainname());
222 if( (host = hosts_lookup(NULL, buf)) )
223 {
224 node = host->node;
225 if(!node.point && point!=-1)
226 node.point = point;
227 return &node;
228 }
229
230 /*
231 * 2a. Add hosts domainname and lookup in HOSTS
232 */
233 BUF_COPY(buf, p);
234 BUF_APPEND(buf, cf_hostsdomain());
235 if( (host = hosts_lookup(NULL, buf)) )
236 {
237 node = host->node;
238 if(!node.point && point!=-1)
239 node.point = point;
240 return &node;
241 }
242
243 BUF_COPY(buf, addr);
244
245 /*
246 * 3. Try p.f.n.z
247 */
248 if( try_pfnz(&node, buf, "", "") )
249 return &node;
250
251 /*
252 * 4. Try p.f.n.z.HOSTNAME
253 */
254 if( try_pfnz(&node, buf, ".", cf_hostname()) )
255 return &node;
256
257 /*
258 * 5. Try p.f.n.z.HOSTNAME.DOMAIN
259 */
260 if( try_pfnz(&node, buf, ".", cf_fqdn()) )
261 return &node;
262
263 /*
264 * 6. Try p.f.n.z.DOMAIN
265 */
266 if( try_pfnz(&node, buf, "", cf_domainname()) )
267 return &node;
268
269 /*
270 * 6a. Try p.f.n.z.HOSTSDOMAIN
271 */
272 if( try_pfnz(&node, buf, "", cf_hostsdomain()) )
273 return &node;
274
275 /*
276 * 7. Try FTN domains from CONFIG
277 */
278 for (p=cf_zones_trav(TRUE); p; p=cf_zones_trav(FALSE))
279 if( try_pfnz(&node, buf, "", p) )
280 return &node;
281
282 /*
283 * Everything failed - not an FTN address
284 */
285 return NULL;
286 }
287
288
289
290 /*
291 * Check for local RFC address, i.e. "user@HOSTNAME.DOMAIN (Full Name)"
292 * or "user (Full Name)"
293 */
addr_is_local(char * addr)294 int addr_is_local(char *addr)
295 {
296 RFCAddr rfc;
297
298 if(!addr)
299 return FALSE;
300
301 rfc = rfcaddr_from_rfc(addr);
302
303 debug(7, "addr_is_local(): From=%s FQDN=%s",
304 s_rfcaddr_to_asc(&rfc, TRUE), cf_fqdn());
305 return rfc.addr[0] == '\0' || stricmp(rfc.addr, cf_fqdn()) == 0;
306 }
307
308 #ifdef AI_6
addr_is_local_xpost_init(char * addr)309 void addr_is_local_xpost_init(char *addr)
310 {
311 list_init(&addr_is_local_pats, addr);
312 }
313
314
addr_is_local_xpost(char * addr)315 int addr_is_local_xpost(char *addr)
316 {
317 RFCAddr rfc;
318 int ailx;
319 static char **addr_list = NULL;
320
321 if(!addr)
322 return FALSE;
323
324 rfc = rfcaddr_from_rfc(addr);
325
326 debug(7, "addr_is_local_xpost(): From=%s FQDN=%s",
327 s_rfcaddr_to_asc(&rfc, TRUE), cf_fqdn());
328 ailx = rfc.addr[0] == '\0' || stricmp(rfc.addr, cf_fqdn()) == 0;
329 if (!ailx) {
330 list_init(&addr_list, addr);
331 ailx = list_match(FALSE, addr_is_local_pats, addr_list);
332 }
333 return ailx;
334 }
335 #endif
336
337
338 /*
339 * Check for address in local domain, i.e. "user@*DOMAIN (Full Name)"
340 * or "user (Full Name)"
341 */
addr_is_domain(char * addr)342 int addr_is_domain(char *addr)
343 {
344 RFCAddr rfc;
345 char *d;
346 int l, ld;
347
348 if(!addr)
349 return FALSE;
350
351 rfc = rfcaddr_from_rfc(addr);
352
353 d = cf_domainname();
354 ld = strlen(d);
355 l = strlen(rfc.addr);
356
357 debug(7, "addr_is_domain(): From=%s domain=%s",
358 s_rfcaddr_to_asc(&rfc, TRUE), d );
359
360 if(rfc.addr[0] == '\0')
361 return TRUE;
362
363 /* user@DOMAIN */
364 if(*d == '.' && stricmp(rfc.addr, d+1) == 0)
365 return TRUE;
366 else if(stricmp(rfc.addr, d) == 0)
367 return TRUE;
368 /* user@*.DOMAIN */
369 if(ld > l)
370 return FALSE;
371 return stricmp(rfc.addr + l - ld, d) == 0;
372 }
373