INN commit: branches/2.6 (8 files)

INN Commit rra at isc.org
Sun Dec 2 14:05:50 UTC 2018


    Date: Sunday, December 2, 2018 @ 06:05:50
  Author: iulius
Revision: 10304

Rewrite GetFQDN and rename to inn_getfqdn

Use getaddrinfo with AI_CANONNAME instead of the tedious code to
find an FQDN in gethostbyname results. Return a newly-allocated
string instead of using a static buffer, since this function isn't
performance-critical, avoiding buffer management complexity. Adjust
call sites to do proper memory allocation handling of the return
value.

Remove some old disabled code to try to force canonicalization by
adding a period to the end of the DNS query.

Patch from Russ Allbery (backported from CURRENT).

Modified:
  branches/2.6/doc/man/libinn.3
  branches/2.6/doc/pod/inn.conf.pod
  branches/2.6/frontends/inews.c
  branches/2.6/include/inn/libinn.h
  branches/2.6/lib/getfqdn.c
  branches/2.6/lib/innconf.c
  branches/2.6/lib/messageid.c
  branches/2.6/nnrpd/post.c

----------------------+
 doc/man/libinn.3     |   12 +++--
 doc/pod/inn.conf.pod |    4 -
 frontends/inews.c    |    6 +-
 include/inn/libinn.h |   11 +++-
 lib/getfqdn.c        |  110 +++++++++++++++----------------------------------
 lib/innconf.c        |    9 ++--
 lib/messageid.c      |    8 ++-
 nnrpd/post.c         |   11 +++-
 8 files changed, 75 insertions(+), 96 deletions(-)

Modified: doc/man/libinn.3
===================================================================
--- doc/man/libinn.3	2018-11-11 14:43:41 UTC (rev 10303)
+++ doc/man/libinn.3	2018-12-02 14:05:50 UTC (rev 10304)
@@ -61,8 +61,8 @@
 .B "    bool	block;"
 
 .B "char *"
-.B "GetFQDN(domain)"
-.B "    char    *domain;"
+.B "inn_getfqdn(domain)"
+.B "    const char *domain;"
 
 .B "char *"
 .B "GetModeratorAddress(FromServer, ToServer, group, moderatormailer)"
@@ -276,11 +276,13 @@
 is one of: INN_LOCK_READ, INN_LOCK_WRITE, or INN_LOCK_UNLOCK.
 It returns false on failure or true on success.
 .PP
-.I GetFQDN
+.I inn_getfqdn
 returns the fully qualified domain name of the local host.
 .I Domain
-is used if local host can not be resolved.
-The returned value points to static space that is reused on subsequent calls,
+is used to qualify the local host name if local host can not be resolved
+in DNS.
+The returned value points to newly-allocated memory that the caller is
+responsible for freeing,
 or NULL on error.
 .PP
 .I GetModeratorAddress

Modified: doc/pod/inn.conf.pod
===================================================================
--- doc/pod/inn.conf.pod	2018-11-11 14:43:41 UTC (rev 10303)
+++ doc/pod/inn.conf.pod	2018-12-02 14:05:50 UTC (rev 10304)
@@ -60,8 +60,8 @@
 
 This should be the domain name of the local host.  It should not have a
 leading period, and it should not be a full host address.  It is used only
-if the GetFQDN() routine in libinn(3) cannot get the fully qualified
-domain name by using either the gethostname(3) or gethostbyname(3) calls.
+if the inn_getfqdn() routine in libinn(3) cannot get the fully qualified
+domain name by using either the gethostname(3) or getaddrinfo(3) calls.
 The check is very simple; if either routine returns a name with a period
 in it, then it is assumed to have the full domain name.  As this parameter
 is rarely used, do not use it to affect the righthand side of

Modified: frontends/inews.c
===================================================================
--- frontends/inews.c	2018-11-11 14:43:41 UTC (rev 10303)
+++ frontends/inews.c	2018-12-02 14:05:50 UTC (rev 10304)
@@ -608,9 +608,11 @@
                 HDR(_path) = concat(Exclusions, PATHFLUFF, (char *) 0);
 	}
 	else if (innconf->server != NULL) {
-	    if ((p = GetFQDN(innconf->domain)) == NULL)
-                sysdie("cannot get hostname");
+	    p = inn_getfqdn(innconf->domain);
+	    if (p == NULL)
+		sysdie("cannot get hostname");
 	    HDR(_path) = concat(Exclusions, p, "!", PATHFLUFF, (char *) 0);
+	    free(p);
 	}
 	else {
 	    HDR(_path) = concat(Exclusions, PATHFLUFF, (char *) 0);

Modified: include/inn/libinn.h
===================================================================
--- include/inn/libinn.h	2018-11-11 14:43:41 UTC (rev 10303)
+++ include/inn/libinn.h	2018-12-02 14:05:50 UTC (rev 10304)
@@ -137,10 +137,15 @@
 			    const char *request);
 extern void     CAclose(void);
 
-extern char *    GetFQDN(char *domain);
-extern char *    GetModeratorAddress(FILE *FromServer, FILE *ToServer,
-                                     char *group, char *moderatormailer); 
+/* Return the fully-qualified domain name of the local system in
+   newly-allocated memory, or NULL if it cannot be discovered.  The caller is
+   responsible for freeing.  If the host's domain cannot be found in DNS, use
+   the domain argument as a fallback. */
+extern char *   inn_getfqdn(const char *domain);
 
+extern char *   GetModeratorAddress(FILE *FromServer, FILE *ToServer,
+                                    char *group, char *moderatormailer); 
+
 #define TEMPORARYOPEN   0
 #define INND_HISTORY    1
 #define INND_HISLOG     2

Modified: lib/getfqdn.c
===================================================================
--- lib/getfqdn.c	2018-11-11 14:43:41 UTC (rev 10303)
+++ lib/getfqdn.c	2018-12-02 14:05:50 UTC (rev 10304)
@@ -1,96 +1,54 @@
 /*  $Id$
 **
+**  Discover the fully-qualified domain name of the local host.
 */
 
 #include "config.h"
 #include "clibrary.h"
-#include <netdb.h>
+#include "portable/socket.h"
 
 #include "inn/libinn.h"
-#include "inn/paths.h"
+#include "inn/xmalloc.h"
 
 
 /*
-**  Get the fully qualified domain name for this host, as reported
-**  by the system.
+**  Return the fully-qualified domain name of the local system in
+**  newly-allocated memory, or NULL if it cannot be discovered.  The caller is
+**  responsible for freeing.  If the host's domain cannot be found in DNS, use
+**  the domain argument as a fallback.
 */
-char *GetFQDN(char *domain)
+char *
+inn_getfqdn(const char *domain)
 {
-    static char		buff[SMBUF];
-    struct hostent	*hp;
-    char		*p;
-    char		**ap;
-#if	0
-    /* See comments below. */
-    char		temp[SMBUF + 2];
-#endif	/* 0 */
+    char hostname[BUFSIZ];
+    struct addrinfo hints, *res;
+    char *fqdn, *canon;
 
-    /* Return any old results. */
-    if (buff[0])
-	return buff;
+    /* If gethostname fails, there's nothing we can do. */
+    if (gethostname(hostname, sizeof(hostname)) < 0)
+        return NULL;
 
-    /* Try gethostname. */
-    if (gethostname(buff, (int)sizeof buff) < 0)
-	return NULL;
-    if (strchr(buff, '.') != NULL)
-	return buff;
+    /* If the local hostname is already fully qualified, just return it. */
+    if (strchr(hostname, '.') != NULL)
+        return xstrdup(hostname);
 
-    /*
-    ** See if DNS (or /etc/hosts) gives us a full domain name.  If the host
-    ** doesn't exist in DNS at all but we were given a domain name, use the
-    ** fallback of appending that domain to the hostname.
-    */
-    if ((hp = gethostbyname(buff)) == NULL)
-	goto fallback;
-#if	0
-    /* This code is a "feature" that allows multiple domains (NIS or
-     * DNS, I'm not sure) to work with a single INN server.  However,
-     * it turns out to cause more problems for people, and they have to
-     * use hacks like __switch_gethostbyname, etc.  So if you need this,
-     * turn it on, but don't complain to me. */
-    if (strchr(hp->h_name, '.') == NULL) {
-	/* Try to force DNS lookup if NIS/whatever gets in the way. */
-        strlcpy(temp, buff, sizeof(temp));
-        strlcat(temp, ".", sizeof(temp));
-	hp = gethostbyname(temp);
-    }
-    if (hp == NULL) {
-        return NULL;
-    }
-#endif	/* 0 */
-
-    /* First, see if the main name is a FQDN.  It should be. */
-    if (strchr(hp->h_name, '.') != NULL) {
-	if (strlen(hp->h_name) < sizeof buff - 1) {
-	    strlcpy(buff, hp->h_name, sizeof(buff));
-            return buff;
+    /* Attempt to canonicalize with DNS. */
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_flags = AI_CANONNAME;
+    if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
+        canon = res->ai_canonname;
+        if (canon != NULL && strchr(canon, '.') != NULL) {
+            fqdn = xstrdup(canon);
+            freeaddrinfo(res);
+            return fqdn;
         }
-	/* Doesn't fit; make sure we don't return bad data next time. */
-	buff[0] = '\0';
-	return hp->h_name;
+        freeaddrinfo(res);
     }
 
-    /* Second, see if any aliases are. */
-    if ((ap = hp->h_aliases) != NULL)
-	while ((p = *ap++) != NULL)
-	    if (strchr(p, '.') != NULL) {
-		/* Deja-vous all over again. */
-		if (strlen(p) < sizeof buff - 1) {
-		    strlcpy(buff, p, sizeof(buff));
-                    return buff;
-                }
-		buff[0] = '\0';
-		return p ;
-	    }
-
-    /* Give up:  Get the domain config param and append it. */
-fallback:
-    if ((p = domain) == NULL || *p == '\0')
-	return NULL;
-    if (strlen(buff) + 1 + strlen(p) > sizeof buff - 1)
-	/* Doesn't fit. */
-	return NULL;
-    strlcat(buff, ".", sizeof(buff));
-    strlcat(buff, p, sizeof(buff));
-    return buff;
+    /* Fall back on canonicalizing with a provided domain. */
+    if (domain == NULL || domain[0] == '\0')
+        return NULL;
+    xasprintf(&fqdn, "%s.%s", hostname, domain);
+    return fqdn;
 }

Modified: lib/innconf.c
===================================================================
--- lib/innconf.c	2018-11-11 14:43:41 UTC (rev 10303)
+++ lib/innconf.c	2018-12-02 14:05:50 UTC (rev 10304)
@@ -332,9 +332,9 @@
 
     /* Some parameters have defaults that depend on other parameters. */
     if (innconf->fromhost == NULL)
-        innconf->fromhost = xstrdup(GetFQDN(innconf->domain));
+        innconf->fromhost = inn_getfqdn(innconf->domain);
     if (innconf->pathhost == NULL)
-        innconf->pathhost = xstrdup(GetFQDN(innconf->domain));
+        innconf->pathhost = inn_getfqdn(innconf->domain);
     if (innconf->pathtmp == NULL)
         innconf->pathtmp = xstrdup(INN_PATH_TMP);
 
@@ -472,11 +472,14 @@
 innconf_validate(struct config_group *group)
 {
     bool okay = true;
+    char *fqdn;
 
-    if (GetFQDN(innconf->domain) == NULL) {
+    fqdn = inn_getfqdn(innconf->domain);
+    if (fqdn == NULL) {
         warn("hostname does not resolve or domain not set in inn.conf");
         okay = false;
     }
+    free(fqdn);
     if (innconf->mta == NULL) {
         warn("must set mta in inn.conf");
         okay = false;

Modified: lib/messageid.c
===================================================================
--- lib/messageid.c	2018-11-11 14:43:41 UTC (rev 10303)
+++ lib/messageid.c	2018-12-02 14:05:50 UTC (rev 10304)
@@ -30,6 +30,7 @@
     static char		buff[SMBUF];
     static int		count;
     char		*p;
+    char		*fqdn = NULL;
     char		sec32[10];
     char		pid32[10];
     time_t		now;
@@ -42,10 +43,13 @@
          && strcmp(domain, innconf->domain) != 0)) {
 	p = domain;
     } else {
-	if ((p = GetFQDN(domain)) == NULL)
-	    return NULL;
+        fqdn = inn_getfqdn(domain);
+        if (fqdn == NULL)
+            return NULL;
+        p = fqdn;
     }
     snprintf(buff, sizeof(buff), "<%s$%s$%d@%s>", sec32, pid32, ++count, p);
+    free(fqdn);
     return buff;
 }
 

Modified: nnrpd/post.c
===================================================================
--- nnrpd/post.c	2018-11-11 14:43:41 UTC (rev 10303)
+++ nnrpd/post.c	2018-12-02 14:05:50 UTC (rev 10304)
@@ -348,6 +348,7 @@
     static char		*newpath = NULL;
     HEADER		*hp;
     char		*p;
+    char		*fqdn = NULL;
     time_t		t, now;
     const char          *error;
     pid_t               pid;
@@ -561,11 +562,15 @@
     if (VirtualPathlen > 0) {
         p = PERMaccessconf->domain;
     } else {
-        if ((p = GetFQDN(PERMaccessconf->domain)) == NULL) {
-            p = (char *) "unknown";
-        }
+	fqdn = inn_getfqdn(PERMaccessconf->domain);
+	if (fqdn == NULL)
+	    p = (char *) "unknown";
+	else
+	    p = fqdn;
     }
     snprintf(pathidentitybuff, sizeof(pathidentitybuff), "%s", p);
+    free(fqdn);
+    p = NULL;
 
     /* Set the posting-account value. */
      if (PERMaccessconf->addinjectionpostingaccount && PERMuser[0] != '\0') {



More information about the inn-committers mailing list