getnetgrent(3) fails to parse long netgroup entry if it is stored in NIS

From: Yasuhiro Kimura <yasu_at_FreeBSD.org>
Date: Tue, 15 Mar 2022 16:48:14 UTC
Hello,

I use netgroup stored in NIS database to control access to NFS server.
Recently I added some hosts to netgroup that access to NFS server is
permitted. And after that mountd(8) writes such messages as following
to syslog.

Mar 15 17:16:59 server mountd[4276]: can't get address info for host host34.nfs.
Mar 15 17:16:59 server mountd[4276]: bad host host34.nfs. in netgroup permitted_nfs_clients, skipping

The netgroup entry used to control access to NFS server includes a lot
of host such as following

----------------------------------------------------------------------
yasu@server[1002]% ypmatch -k permitted_nfs_clients  netgroup
permitted_nfs_clients: (host01.nfs.example.com,,)                       (host02.nfs.example.com,,)                    (host03.nfs.example.com,,)                       (host04.nfs.example.com,,)                      (host05.nfs.example.com,,)                     (host06.nfs.example.com,,)                      (host07.nfs.example.com,,)                    (host08.nfs.example.com,,)                       (host09.nfs.example.com,,)                      (host10.nfs.example.com,,)                     (host11.nfs.example.com,,)                      (host12.nfs.example.com,,)                    (host13.nfs.example.com,,)                       (host14.nfs.example.com,,)                      (host15.nfs.example.com,,)                     (host16.nfs.example.com,,)                      (host17.nfs.example.com,,)                    (host18.nfs.example.com,,)                       (host19.nfs.example.com,,)                      (host20.nfs.example.com,,)                     (host21.nfs.example.com,,)                      (host22.nfs.example.com,,)                    (host23.nfs.example.com,,)                       (host24.nfs.example.com,,)                      (host25.nfs.example.com,,)                     (host26.nfs.example.com,,)                      (host27.nfs.example.com,,)                    (host28.nfs.example.com,,)                       (host29.nfs.example.com,,)                      (host30.nfs.example.com,,)                     (host31.nfs.example.com,,)                      (host32.nfs.example.com,,)                    (host33.nfs.example.com,,)                       (host34.nfs.example.com,,)                      (host35.nfs.example.com,,)                     (host36.nfs.example.com,,)                      (host37.nfs.example.com,,)                    (host38.nfs.example.com,,)                       (host39.nfs.example.com,,)                      (host40.nfs.example.com,,)                     (host41.nfs.example.com,,)                      (host42.nfs.example.com,,)                    (host43.nfs.example.com,,)                       (host44.nfs.example.com,,)                      (host45.nfs.example.com,,)                     (host46.nfs.example.com,,)                      (host47.nfs.example.com,,)                    (host48.nfs.example.com,,)                       (host49.nfs.example.com,,)                      (host50.nfs.example.com,,)
yasu@server[1054]%
----------------------------------------------------------------------

And if I remove host34.nfs.example.com from permitted_nfs_clients,
then syslog messages of mountd(1) changes as following.

Mar 15 17:16:59 server mountd[4276]: can't get address info for host host35.nfs.
Mar 15 17:16:59 server mountd[4276]: bad host host35.nfs. in netgroup permitted_nfs_clients, skipping

It seems to stop parsing the value of the netgroup entry in its middle
if the length is longer than a certain value.

I checked usr.sbin/mountd/mountd.c and found it uses getnetgrent(3) to
parse the value of netgroup entry. So I wrote following program to
check its behavior.

----------------------------------------------------------------------
yasu@server[1152]% cat list_netgroup_entry.c
#include <stdio.h>
#include <libgen.h>
#include <netdb.h>

int
main(int argc, char **argv)
{
    if (argc != 2) {
        fprintf(stderr, "Usage: %s NameOfNetgroup\n", basename(argv[0]));
        return 1;
    }
    setnetgrent(argv[1]);
    printf("netgroup: %s\n", argv[1]);
    char *host, *user, *domain;
    while (getnetgrent(&host, &user, &domain))
        printf("\thost: %s, user: %s, domain: %s\n", host, user, domain);
    endnetgrent();
    return 0;
}
yasu@server[1152]%
----------------------------------------------------------------------

If netgroup entry is stored in /etc/netgroup, then the value is parsed
properly.

----------------------------------------------------------------------
yasu@server[1061]% cat /etc/netgroup
very_long_file_entry    (host1.long.long.long.example.com,,) \
                        (host2.long.long.long.example.com,,) \
                        (host3.long.long.long.example.com,,) \
                        (host4.long.long.long.example.com,,) \
                        (host5.long.long.long.example.com,,) \
                        (host6.long.long.long.example.com,,) \
                        (host7.long.long.long.example.com,,) \
                        (host8.long.long.long.example.com,,) \
                        (host9.long.long.long.example.com,,) \
                        (host10.long.long.long.example.com,,) \
                        (host11.long.long.long.example.com,,) \
                        (host12.long.long.long.example.com,,) \
                        (host13.long.long.long.example.com,,) \
                        (host14.long.long.long.example.com,,) \
                        (host15.long.long.long.example.com,,) \
                        (host16.long.long.long.example.com,,) \
                        (host17.long.long.long.example.com,,) \
                        (host18.long.long.long.example.com,,) \
                        (host19.long.long.long.example.com,,) \
                        (host20.long.long.long.example.com,,) \
                        (host21.long.long.long.example.com,,) \
                        (host22.long.long.long.example.com,,) \
                        (host23.long.long.long.example.com,,) \
                        (host24.long.long.long.example.com,,) \
                        (host25.long.long.long.example.com,,) \
                        (host26.long.long.long.example.com,,) \
                        (host27.long.long.long.example.com,,) \
                        (host28.long.long.long.example.com,,) \
                        (host29.long.long.long.example.com,,) \
                        (host30.long.long.long.example.com,,)
+
yasu@server[1062]% ./list_netgroup_entry very_long_file_entry
netgroup: very_long_file_entry
        host: host30.long.long.long.example.com, user: , domain: 
        host: host29.long.long.long.example.com, user: , domain: 
        host: host28.long.long.long.example.com, user: , domain: 
        host: host27.long.long.long.example.com, user: , domain: 
        host: host26.long.long.long.example.com, user: , domain: 
        host: host25.long.long.long.example.com, user: , domain: 
        host: host24.long.long.long.example.com, user: , domain: 
        host: host23.long.long.long.example.com, user: , domain: 
        host: host22.long.long.long.example.com, user: , domain: 
        host: host21.long.long.long.example.com, user: , domain: 
        host: host20.long.long.long.example.com, user: , domain: 
        host: host19.long.long.long.example.com, user: , domain: 
        host: host18.long.long.long.example.com, user: , domain: 
        host: host17.long.long.long.example.com, user: , domain: 
        host: host16.long.long.long.example.com, user: , domain: 
        host: host15.long.long.long.example.com, user: , domain: 
        host: host14.long.long.long.example.com, user: , domain: 
        host: host13.long.long.long.example.com, user: , domain: 
        host: host12.long.long.long.example.com, user: , domain: 
        host: host11.long.long.long.example.com, user: , domain: 
        host: host10.long.long.long.example.com, user: , domain: 
        host: host9.long.long.long.example.com, user: , domain: 
        host: host8.long.long.long.example.com, user: , domain: 
        host: host7.long.long.long.example.com, user: , domain: 
        host: host6.long.long.long.example.com, user: , domain: 
        host: host5.long.long.long.example.com, user: , domain: 
        host: host4.long.long.long.example.com, user: , domain: 
        host: host3.long.long.long.example.com, user: , domain: 
        host: host2.long.long.long.example.com, user: , domain: 
        host: host1.long.long.long.example.com, user: , domain: 
yasu@server[1063]%
----------------------------------------------------------------------

But if it is stored in NIS database, then parsing stops at the middle
of it.

----------------------------------------------------------------------
yasu@server[1063]% ypmatch -k very_long_nis_entry netgroup
very_long_nis_entry: (host1.long.long.long.example.com,,)                       (host2.long.long.long.example.com,,)  (host3.long.long.long.example.com,,)                     (host4.long.long.long.example.com,,)                    (host5.long.long.long.example.com,,)                   (host6.long.long.long.example.com,,)                    (host7.long.long.long.example.com,,)                   (host8.long.long.long.example.com,,)                    (host9.long.long.long.example.com,,)                   (host10.long.long.long.example.com,,)                   (host11.long.long.long.example.com,,)                  (host12.long.long.long.example.com,,)                   (host13.long.long.long.example.com,,) (host14.long.long.long.example.com,,)                    (host15.long.long.long.example.com,,)                   (host16.long.long.long.example.com,,)                  (host17.long.long.long.example.com,,)                   (host18.long.long.long.example.com,,)                  (host19.long.long.long.example.com,,)                   (host20.long.long.long.example.com,,)                  (host21.long.long.long.example.com,,)                   (host22.long.long.long.example.com,,)                  (host23.long.long.long.example.com,,)                   (host24.long.long.long.example.com,,) (host25.long.long.long.example.com,,)                    (host26.long.long.long.example.com,,)                   (host27.long.long.long.example.com,,)                  (host28.long.long.long.example.com,,)                   (host29.long.long.long.example.com,,)                  (host30.long.long.long.example.com,,)
yasu@server[1064]% ./list_netgroup_entry very_long_nis_entry
netgroup: very_long_nis_entry
        host: host25.long.long.long.examp, user: , domain: 
        host: host24.long.long.long.example.com, user: , domain: 
        host: host23.long.long.long.example.com, user: , domain: 
        host: host22.long.long.long.example.com, user: , domain: 
        host: host21.long.long.long.example.com, user: , domain: 
        host: host20.long.long.long.example.com, user: , domain: 
        host: host19.long.long.long.example.com, user: , domain: 
        host: host18.long.long.long.example.com, user: , domain: 
        host: host17.long.long.long.example.com, user: , domain: 
        host: host16.long.long.long.example.com, user: , domain: 
        host: host15.long.long.long.example.com, user: , domain: 
        host: host14.long.long.long.example.com, user: , domain: 
        host: host13.long.long.long.example.com, user: , domain: 
        host: host12.long.long.long.example.com, user: , domain: 
        host: host11.long.long.long.example.com, user: , domain: 
        host: host10.long.long.long.example.com, user: , domain: 
        host: host9.long.long.long.example.com, user: , domain: 
        host: host8.long.long.long.example.com, user: , domain: 
        host: host7.long.long.long.example.com, user: , domain: 
        host: host6.long.long.long.example.com, user: , domain: 
        host: host5.long.long.long.example.com, user: , domain: 
        host: host4.long.long.long.example.com, user: , domain: 
        host: host3.long.long.long.example.com, user: , domain: 
        host: host2.long.long.long.example.com, user: , domain: 
        host: host1.long.long.long.example.com, user: , domain: 
yasu@server[1065]%
----------------------------------------------------------------------

So it seems getnetgrent(3) fails to parse long netgroup entry if it is
stored in NIS.

---
Yasuhiro Kimura