File net-snmp-5.7.3-netgroups.patch of Package net-snmp.9069

diff -Nurp net-snmp-5.7.3.orig/configure.d/config_os_functions net-snmp-5.7.3/configure.d/config_os_functions
--- net-snmp-5.7.3.orig/configure.d/config_os_functions	2014-12-08 21:23:22.000000000 +0100
+++ net-snmp-5.7.3/configure.d/config_os_functions	2015-07-16 10:32:15.159643068 +0200
@@ -31,11 +31,12 @@ AC_CHECK_FUNCS([lrand48         rand
                [signal          sigset                  ] )
 
 #  Library:
-AC_CHECK_FUNCS([closedir        fgetc_unlocked  flockfile        ] dnl
-               [fork            funlockfile     getipnodebyname  ] dnl
-               [gettimeofday    if_nametoindex  mkstemp          ] dnl
-               [opendir         readdir         regcomp          ] dnl
-               [setenv          setitimer       setlocale        ] dnl
+AC_CHECK_FUNCS([closedir        endnetgrent     fgetc_unlocked   ] dnl
+               [flockfile       fork            funlockfile      ] dnl
+               [getipnodebyname getnetgrent     gettimeofday     ] dnl
+               [if_nametoindex  mkstemp         opendir          ] dnl
+               [readdir         regcomp         setenv           ] dnl
+               [setitimer       setlocale       setnetgrent      ] dnl
                [setsid          snprintf        strcasestr       ] dnl
                [strdup          strerror        strncasecmp      ] dnl
                [sysconf         times           vsnprintf        ] )
diff -Nurp net-snmp-5.7.3.orig/man/snmpd.conf.5.def net-snmp-5.7.3/man/snmpd.conf.5.def
--- net-snmp-5.7.3.orig/man/snmpd.conf.5.def	2014-12-08 21:23:22.000000000 +0100
+++ net-snmp-5.7.3/man/snmpd.conf.5.def	2015-07-16 10:41:34.337850287 +0200
@@ -389,7 +389,14 @@ map an SNMPv1 or SNMPv2c community strin
 a particular range of source addresses, or globally (\fI"default"\fR).
 A restricted source can either be a specific hostname (or address), or
 a subnet - represented as IP/MASK (e.g. 10.10.10.0/255.255.255.0), or
-IP/BITS (e.g. 10.10.10.0/24), or the IPv6 equivalents.
+IP/BITS (e.g. 10.10.10.0/24), or the IPv6 equivalents. It is also possible
+to reference a specific \fInetgroup\fR starting with an '@' character (e.g. 
+@adminhosts). The \fInetgroup\fR lookup is running through the NSS (Name
+Services Switch) making it possible to define the group locally or via
+NIS/LDAP.
+.IP
+Note: The hostname DNS lookup and \fInetgroup\fR resolution is done only
+during snmpd start or reload.
 .IP
 The same community string can be specified in several separate directives
 (presumably with different source tokens), and the first source/community
diff -Nurp net-snmp-5.7.3.orig/snmplib/transports/snmpUDPDomain.c net-snmp-5.7.3/snmplib/transports/snmpUDPDomain.c
--- net-snmp-5.7.3.orig/snmplib/transports/snmpUDPDomain.c	2014-12-08 21:23:22.000000000 +0100
+++ net-snmp-5.7.3/snmplib/transports/snmpUDPDomain.c	2015-07-16 10:32:15.160643078 +0200
@@ -88,6 +88,11 @@ void _netsnmp_udp_sockopt_set(int fd, in
 int
 netsnmp_sockaddr_in2(struct sockaddr_in *addr,
                      const char *inpeername, const char *default_target);
+static void
+netsnmp_udp_com2SecList_add(char *secName, size_t secNameLen,
+                            char *contextName, size_t contextNameLen,
+                            char *community, size_t communityLen,
+                            struct in_addr network, struct in_addr mask);
 
 /*
  * Return a string representing the address in data, or else the "far end"
@@ -100,6 +105,59 @@ netsnmp_udp_fmtaddr(netsnmp_transport *t
     return netsnmp_ipv4_fmtaddr("UDP", t, data, len);
 }
 
+static int
+netsnmp_udp_resolve_source(char *source, struct in_addr *network,
+        struct in_addr *mask)
+{
+    /* Split the source/netmask parts */
+    char *strmask = strchr(source, '/');
+    if (strmask != NULL)
+        /* Mask given. */
+        *strmask++ = '\0';
+
+    /* Try interpreting as a dotted quad. */
+   if (inet_pton(AF_INET, source, network) == 0) {
+        /* Nope, wasn't a dotted quad.  Must be a hostname. */
+        int ret = netsnmp_gethostbyname_v4(source, &(network->s_addr));
+        if (ret < 0) {
+            config_perror("cannot resolve source hostname");
+            return ret;
+        }
+    }
+
+    /* Now work out the mask. */
+    if (strmask == NULL || *strmask == '\0') {
+        /* No mask was given. Assume /32 */
+        mask->s_addr = (in_addr_t)(~0UL);
+    } else {
+        /* Try to interpret mask as a "number of 1 bits". */
+        char* cp;
+        long maskLen = strtol(strmask, &cp, 10);
+        if (*cp == '\0') {
+            if (0 < maskLen && maskLen <= 32)
+                mask->s_addr = htonl((in_addr_t)(~0UL << (32 - maskLen)));
+            else if (maskLen == 0)
+                mask->s_addr = 0;
+            else {
+                config_perror("bad mask length");
+                return -1;
+            }
+        }
+        /* Try to interpret mask as a dotted quad. */
+        else if (inet_pton(AF_INET, strmask, mask) == 0) {
+            config_perror("bad mask");
+            return -1;
+        }
+
+        /* Check that the network and mask are consistent. */
+        if (network->s_addr & ~mask->s_addr) {
+            config_perror("source/mask mismatch");
+            return -1;
+        }
+    }
+    return 0;
+}
+
 
 #if defined(HAVE_IP_PKTINFO) || defined(HAVE_IP_RECVDSTADDR)
 
@@ -259,102 +317,85 @@ netsnmp_udp_parse_security(const char *t
     if (strcmp(source, "default") == 0) {
         network.s_addr = 0;
         mask.s_addr = 0;
+        netsnmp_udp_com2SecList_add(secName, secNameLen, contextName,
+                contextNameLen, community, communityLen, network, mask);
     } else {
-        /* Split the source/netmask parts */
-        char *strmask = strchr(source, '/');
-        if (strmask != NULL)
-            /* Mask given. */
-            *strmask++ = '\0';
-
-        /* Try interpreting as a dotted quad. */
-        if (inet_pton(AF_INET, source, &network) == 0) {
-            /* Nope, wasn't a dotted quad.  Must be a hostname. */
-            int ret = netsnmp_gethostbyname_v4(source, &network.s_addr);
-            if (ret < 0) {
-                config_perror("cannot resolve source hostname");
-                return;
-            }
-        }
-
-        /* Now work out the mask. */
-        if (strmask == NULL || *strmask == '\0') {
-            /* No mask was given. Assume /32 */
-            mask.s_addr = (in_addr_t)(~0UL);
-        } else {
-            /* Try to interpret mask as a "number of 1 bits". */
-            char* cp;
-            long maskLen = strtol(strmask, &cp, 10);
-            if (*cp == '\0') {
-                if (0 < maskLen && maskLen <= 32)
-                    mask.s_addr = htonl((in_addr_t)(~0UL << (32 - maskLen)));
-                else if (maskLen == 0)
-                    mask.s_addr = 0;
-                else {
-                    config_perror("bad mask length");
-                    return;
+#if HAVE_ENDNETGRENT && HAVE_GETNETGRENT && HAVE_SETNETGRENT
+        /* Interpret as netgroup */
+        if (*source == '@') {
+            char *netgroup = source+1;
+            char *host, *user, *domain;
+            setnetgrent(netgroup);
+            while (getnetgrent(&host, &user, &domain)) {
+                if (netsnmp_udp_resolve_source(host, &network, &mask) == 0) {
+                    netsnmp_udp_com2SecList_add(secName, secNameLen, contextName,
+                            contextNameLen, community, communityLen, network, mask);
                 }
             }
-            /* Try to interpret mask as a dotted quad. */
-            else if (inet_pton(AF_INET, strmask, &mask) == 0) {
-                config_perror("bad mask");
-                return;
-            }
-
-            /* Check that the network and mask are consistent. */
-            if (network.s_addr & ~mask.s_addr) {
-                config_perror("source/mask mismatch");
-                return;
+            endnetgrent();
+        }
+        /* Without '@' it has to be an address or hostname */
+        else
+#endif
+        {
+            if (netsnmp_udp_resolve_source(source, &network, &mask) == 0) {
+                netsnmp_udp_com2SecList_add(secName, secNameLen, contextName,
+                    contextNameLen, community, communityLen, network, mask);
             }
         }
     }
+}
 
-    {
-        void* v = malloc(offsetof(com2SecEntry, community) + communityLen +
-                         secNameLen + contextNameLen);
-
-        com2SecEntry* e = (com2SecEntry*)v;
-        char* last = ((char*)v) + offsetof(com2SecEntry, community);
+static void
+netsnmp_udp_com2SecList_add(char *secName, size_t secNameLen, char *contextName,
+    size_t contextNameLen, char *community, size_t communityLen,
+    struct in_addr network, struct in_addr mask)
+{
+    void *v = malloc(offsetof(com2SecEntry, community) + communityLen +
+                     secNameLen + contextNameLen);
 
-        if (v == NULL) {
-            config_perror("memory error");
-            return;
-        }
+    com2SecEntry* e = (com2SecEntry*)v;
+    char* last = ((char*)v) + offsetof(com2SecEntry, community);
 
-        /*
-         * Everything is okay.  Copy the parameters to the structure allocated
-         * above and add it to END of the list.
-         */
+    if (v == NULL) {
+        config_perror("memory error");
+        return;
+    }
 
-        {
-          char buf1[INET_ADDRSTRLEN];
-          char buf2[INET_ADDRSTRLEN];
-          DEBUGMSGTL(("netsnmp_udp_parse_security",
-                      "<\"%s\", %s/%s> => \"%s\"\n", community,
-                      inet_ntop(AF_INET, &network, buf1, sizeof(buf1)),
-                      inet_ntop(AF_INET, &mask, buf2, sizeof(buf2)),
-                      secName));
-        }
+    /*
+     * Everything is okay.  Copy the parameters to the structure allocated
+     * above and add it to END of the list.
+     */
 
-        memcpy(last, community, communityLen);
-        last += communityLen;
-        memcpy(last, secName, secNameLen);
-        e->secName = last;
-        last += secNameLen;
-        if (contextNameLen) {
-            memcpy(last, contextName, contextNameLen);
-            e->contextName = last;
-        } else
-            e->contextName = last - 1;
-        e->network = network.s_addr;
-        e->mask = mask.s_addr;
-        e->next = NULL;
-
-        if (com2SecListLast != NULL) {
-            com2SecListLast->next = e;
-            com2SecListLast = e;
-        } else {
-            com2SecListLast = com2SecList = e;
-        }
+    {
+      char buf1[INET_ADDRSTRLEN];
+      char buf2[INET_ADDRSTRLEN];
+      DEBUGMSGTL(("netsnmp_udp_parse_security",
+                  "<\"%s\", %s/%s> => \"%s\"\n", community,
+                  inet_ntop(AF_INET, &network, buf1, sizeof(buf1)),
+                  inet_ntop(AF_INET, &mask, buf2, sizeof(buf2)),
+                  secName));
+    }
+
+    memcpy(last, community, communityLen);
+    last += communityLen;
+    memcpy(last, secName, secNameLen);
+    e->secName = last;
+    last += secNameLen;
+    if (contextNameLen) {
+        memcpy(last, contextName, contextNameLen);
+        e->contextName = last;
+    } else
+        e->contextName = last - 1;
+    e->network = network.s_addr;
+    e->mask = mask.s_addr;
+    e->next = NULL;
+
+    if (com2SecListLast != NULL) {
+        com2SecListLast->next = e;
+        com2SecListLast = e;
+    } else {
+        com2SecListLast = com2SecList = e;
     }
 }
openSUSE Build Service is sponsored by