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