Bug 485380

Summary: sendmail applies MAXHOSTNAMELEN for FQDN.
Product: Red Hat Enterprise Linux 4 Reporter: Masayoshi Yamazaki <myamazak>
Component: sendmailAssignee: Jaroslav Škarvada <jskarvad>
Status: CLOSED ERRATA QA Contact: qe-baseos-daemons
Severity: medium Docs Contact:
Priority: low    
Version: 4.7CC: azelinka, jmarko, jskarvad, linux, rvokal
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: sendmail-8.13.1-4.el4 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
: 640232 640234 (view as bug list) Environment:
Last Closed: 2011-02-16 14:36:30 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 640232, 640234    
Attachments:
Description Flags
patch for FQDN length
none
MAXHOSTNAMELEN fix none

Description Masayoshi Yamazaki 2009-02-13 07:08:47 UTC
Description of problem:

sendmail use macro MAXHOSTNAMELEN as limit for host name length. It's
defined as '64' in /usr/include/asm/param.h.

MAXHOSTNAMELEN should be used against the dot('.') separated label
length only, but in some parts it be used against FQDN length. FQDN
max length is defined '255' by the RFC1035.

Therefore some problems occur.

Version-Release number of selected component (if applicable):

I checked the sendmail-8.13.1-3.3.el4 for RHEL4.7.  But it may be same
for RHEL5.3, I guess.

How reproducible:

always

Steps to Reproduce:

I confirmed 2 cases.

case 1)

1. setup DNS for 2 hosts, one's name length is less than 64
   (1.0.168...com), the other is more(128.128.128...com).

   # host 1.0.168.192.long.longlong.longlonglong.veryverylong.example.com
   1.0.168.192.long.longlong.longlonglong.veryverylong.example.com has address 127.0.0.64
   # host 128.128.168.192.long.longlong.longlonglong.veryverylong.example.com
   128.128.168.192.long.longlong.longlonglong.veryverylong.example.com has address 127.0.0.64

2. configure /etc/mail/sendmail.cf for dnsbl.

   # DNS based IP address spam list long.longlong.longlonglong.veryverylong.example.com
   R$*                     $: $&{client_addr}
   R$-.$-.$-.$-            $: <?> $(dnsbl $4.$3.$2.$1.long.longlong.longlonglong.veryverylong.example.com. $: OK $)
   R<?>OK                  $: OKSOFAR
   R<?>$+<TMP>             $: TMPOK
   R<?>$+                  $#error $@ 5.7.1 $:  "550 Mail from " $&{client_addr} " blocked using Email Reputation." 

3. test these addresses.

   # echo -e ".D{client_addr}192.168.0.1\ncheck_rcpt root@localhost" | sendmail -bt | tail
   A                  input: < 192 . 168 > < ? > < + Connect > < >
   A                  input: < 192 > < ? > < + Connect > < >
   A                returns: < ? > < >
   A                returns: < ? > < >
   A                returns: < ? > < >
   A                returns: < ? > < >
   Basic_check_rela returns: $# error $@ 5 . 7 . 1 $: "550 Mail from " 192 . 168 . 0 . 1 " blocked using Email Reputation."
   checkrelay       returns: $# error $@ 5 . 7 . 1 $: "550 Mail from " 192 . 168 . 0 . 1 " blocked using Email Reputation."
   check_rcpt       returns: $# error $@ 5 . 7 . 1 $: "550 Mail from " 192 . 168 . 0 . 1 " blocked using Email Reputation."
   > 
   # echo -e ".D{client_addr}192.168.128.128\ncheck_rcpt root@localhost" | sendmail -bt | tail
   A                  input: < 192 . 168 > < ? > < + Connect > < >
   A                  input: < 192 > < ? > < + Connect > < >
   A                returns: < ? > < >
   A                returns: < ? > < >
   A                returns: < ? > < >
   A                returns: < ? > < >
   Basic_check_rela returns: OKSOFAR
   checkrelay       returns: OKSOFAR
   check_rcpt       returns: < ? > root < @ localhost . example . com >

case 2)

1. setup DNS for 2 CNAME. One's name length is less than 64
   (long.verylong...com), the other is more(longhost.verylong...com).

   # host long.verylong.veryverylong.veryveryverylong.toolong.example.com
   long.verylong.veryverylong.veryveryverylong.toolong.example.com is an alias for server.example.com.
   server.example.com has address 192.168.0.1
   # host longhost.verylong.veryverylong.veryveryverylong.toolong.example.com
   longhost.verylong.veryverylong.veryveryverylong.toolong.example.com is an alias for server.example.com.
   server.example.com has address 192.168.0.1

2. test with '/canon'

   # echo '/canon long.verylong.veryverylong.veryveryverylong.toolong.example.com' | sendmail -bt 
   ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
   Enter <ruleset> <address>
   > getcanonname(long.verylong.veryverylong.veryveryverylong.toolong.example.com) returns server.example.com
   # echo '/canon longhost.verylong.veryverylong.veryveryverylong.toolong.example.com' | sendmail -bt 
   ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
   Enter <ruleset> <address>
   > Name too long
  
Actual results:

case 1) Error doesn't occur by the host '192.168.128.128...'.
case 2) The host 'longhost...' isn't resolved.

Expected results:

case 1) Error occurs by both hosts.
case 2) Both hosts are resolved.

Additional info:

case 1)
sendmail/sm_resolve.c::parse_dns_reply()
----------------------------------------------------------------------
 171         char host[MAXHOSTNAMELEN];
	:
 185         status = dn_expand(data, data + len, p, host, sizeof host);
 186         if (status < 0)
 187         {
 188                 dns_free_data(r);
 189                 return NULL;
----------------------------------------------------------------------

dn_expand() return '-1', if expanded host name length is more than
MAXHOSTNAMELEN as 64. Then expected error don't occur.

case 2)
./sendmail/main.c::testmodeline()
----------------------------------------------------------------------
4125       else if (sm_strcasecmp(&line[1], "canon") == 0)
4126       {
4127               char host[MAXHOSTNAMELEN];
	:
4135               else if (sm_strlcpy(host, p, sizeof host) >= sizeof host)
4136               {
4137                       (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
4138                                            "Name too long\n");
4139                       return;
----------------------------------------------------------------------

If /canon hostname length is more than MAXHOSTNAMELEN, it occurs "Name
too long".

case X)
MAXHOSTNAMELEN is used other parts, too. I don't check these, but they
might also have problems.

Comment 1 Masayoshi Yamazaki 2009-02-25 07:58:42 UTC
I tried to create a patch.

I've checked sources where MAXHOSTNAMELEN is used.  Unfortunately,
I couldn't verify some of them, enough.

Anyway, I report. The following are all of parts that MAXHOSTNAMELEN
is used by sendmail-8.13.1-3.3.el4.

| ./include/sm/conf.h:2718:# if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V)
| ./include/sm/conf.h:2719:#  define MAXHOSTNAMELEN   256
| ./include/sm/conf.h:2720:# endif /* !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V) */
I added new macro MAXFQDNLEN in my patch.

| ./sendmail/daemon.c:205:            char jbuf[MAXHOSTNAMELEN];
| ./sendmail/daemon.c:287:                    char jbuf[MAXHOSTNAMELEN];
Above codes are deleted by cpp, because macro XDEBUG is not defined.
Therefore, not include in the patch.

| ./sendmail/readcf.c:942:                    char jbuf[MAXHOSTNAMELEN];
jbuf is used for expanded $j, then I think it needs the size of MAXFQDNLEN.

| ./sendmail/sm_resolve.c:171:        char host[MAXHOSTNAMELEN];
This is related to case 1) of my first report.

| ./sendmail/mci.c:1207:              char host[MAXHOSTNAMELEN];
| ./sendmail/mci.c:1446:      char t_host[MAXHOSTNAMELEN];
These are related to MCI caching module. Without this patch, sendmail
can't cache information of hosts that has long FQDN name.

| ./sendmail/main.c:189:      char jbuf[MAXHOSTNAMELEN];      /* holds MyHostName */
jbuf is used to store a result of gethostname(). It needs the size of
MAXFQDNLEN, I think.

| ./sendmail/main.c:4127:                     char host[MAXHOSTNAMELEN];
This is related to case 2) of my first report.

| ./sendmail/map.c:1806:              char buf[MAXHOSTNAMELEN];
This part is deleted by cpp, because macro NDBM is not true.
Therefore, not include in the patch.

| ./sendmail/map.c:3741:                      char jbuf[MAXHOSTNAMELEN];
It seems jbuf is used for expaned $j.

| ./sendmail/conf.c:4542:     char hnb[MAXHOSTNAMELEN];
This is related to 'class w', I guess it needs MAXFQNDLEN.


Is this worthy?

Comment 2 Masayoshi Yamazaki 2009-02-25 08:01:01 UTC
Created attachment 333141 [details]
patch for FQDN length

Comment 3 Jaroslav Škarvada 2010-09-24 09:30:36 UTC
Thank you for report. The current implementation seems not to be against RFC as it states:

...the total length of a domain name ... is restricted to 255 octets or less... 

and most peoples probably don't care about this limitation. However the fix back-ported from sendmail-8.14.4 follows.

Comment 4 Jaroslav Škarvada 2010-09-24 09:32:39 UTC
Created attachment 449375 [details]
MAXHOSTNAMELEN fix

Comment 9 errata-xmlrpc 2011-02-16 14:36:30 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on therefore solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHSA-2011-0262.html

Comment 10 Chris Adams 2011-06-14 14:55:50 UTC
It appears this change was only made in sendmail in RHEL 4, but the same problem affects RHEL 5 and 6.  Can we please get an errata for those releases as well?

Comment 11 Jaroslav Škarvada 2011-06-20 07:38:51 UTC
Chris, it is tracked and it will be fixed in RHEL-5/6 in case of sendmail update, this bug alone is low prio.