A good thing that the suggested patch was not pushed,
since it still relies on non-portable behaviour of
getsubopt(), a behaviour which is present in the
official code already.

In shishi_cfg() it is vital that "getsubopt(, , &value) == -1"
still leaves "value" with a valid content.  This is true for
glibc and Solaris libc, but is false for FreeBSD libc.
In consequence, FreeBSD has never been able to determine
"realm-kdc" configurations, much less "server-realm".

The new patch-suggestion has been verified for GNU/Linux,
OpenSolaris, and FreeBSD 8.2, providing full functionality
in shishi_realm_for_server(), in configuration as well as
using network lookup.

The portable remedy is to observe that

    getsubopt(&p, &table, &value)

returns the primary option content in "value"
and all suboptions as an untouched string in "p".
Thus the parser does better in accepting the duty
of parsing the contents in "p", as each of the
cases REALM_KDC_OPTION and SERVER_REALM_OPTION
dictate, not falling back on some trickery based
on a finite state automata in the catch-all case
at the very end of the rope.

Best regards,

  Mats Erik Andersson
>From c688c20e7df466a352f7263c3ec93e3e94c14e3a Mon Sep 17 00:00:00 2001
From: Mats Erik Andersson <g...@gisladisker.se>
Date: Thu, 23 Aug 2012 22:10:33 +0200
Subject: [PATCH] Configuration parsing of suboptions.

The library call getsubopt() is not portable
enough to rely on a catch all case `-1'.
In particular, FreeBSD was not able to parse
`kdc-realm=EX.ORG,localhost' at all.
---
 lib/cfg.c      |  109 ++++++++++++++++++++++++++++++++------------------------
 lib/init.c     |    5 ++-
 lib/realm.c    |   29 +++++++++++++++
 shishi.conf.in |    7 +++-
 4 files changed, 100 insertions(+), 50 deletions(-)

diff --git a/lib/cfg.c b/lib/cfg.c
index a0e39b3..9b9414e 100644
--- a/lib/cfg.c
+++ b/lib/cfg.c
@@ -117,7 +117,6 @@ shishi_cfg (Shishi * handle, const char *option)
   char *opt = option ? xstrdup (option) : NULL;
   char *p = opt;
   char *value;
-  char *realm = NULL;
   int res;
   size_t i;
 
@@ -182,6 +181,10 @@ shishi_cfg (Shishi * handle, const char *option)
 
 	case REALM_KDC_OPTION:
 	  {
+	    struct Shishi_realminfo *ri;
+	    char *realm = NULL;
+	    char *protstr;
+	    int transport = UDP;
 	    int add_realm = 1;
 
 	    realm = xstrdup (value);
@@ -194,6 +197,7 @@ shishi_cfg (Shishi * handle, const char *option)
 		      free (handle->realminfos[i].kdcaddresses);
 		      handle->realminfos[i].kdcaddresses = NULL;
 		      handle->realminfos[i].nkdcaddresses = 0;
+		      ri = &handle->realminfos[i];
 		      add_realm = 0;
 		    }
 		  break;
@@ -206,19 +210,71 @@ shishi_cfg (Shishi * handle, const char *option)
 		memset (&handle->realminfos[handle->nrealminfos], 0,
 			sizeof (handle->realminfos[handle->nrealminfos]));
 		handle->realminfos[handle->nrealminfos].name = realm;
+		ri = &handle->realminfos[handle->nrealminfos];
 		handle->nrealminfos++;
 	      }
+	    if ((protstr = strchr (p, '/')))
+	      {
+		*protstr = '\0';
+		protstr++;
+		if (strcasecmp (protstr, "udp") == 0)
+		  transport = UDP;
+		else if (strcasecmp (protstr, "tcp") == 0)
+		  transport = TCP;
+		else if (strcasecmp (protstr, "tls") == 0)
+		  transport = TLS;
+		else
+		  shishi_warn (handle,
+			       "Ignoring unknown KDC transport: %s",
+				   protstr);
+	      }
+
+	    ri->kdcaddresses = xrealloc (ri->kdcaddresses,
+					 (ri->nkdcaddresses + 1) *
+					   sizeof (*ri->kdcaddresses));
+	    ri->kdcaddresses[ri->nkdcaddresses].transport = transport;
+	    ri->kdcaddresses[ri->nkdcaddresses].hostname = xstrdup (p);
+	    if ((protstr = strchr (value, ':')))
+	      {
+		*protstr = '\0';
+		protstr++;
+		ri->kdcaddresses[ri->nkdcaddresses].port = protstr;
+	      }
+	    else
+	      ri->kdcaddresses[ri->nkdcaddresses].port = NULL;
+	    ri->nkdcaddresses++;
+
+	    p = NULL;	/* Done with suboptions.  */
 	  }
 	  break;
 
 	case SERVER_REALM_OPTION:
 	  {
 	    struct Shishi_realminfo *ri;
-	    ri = _shishi_realminfo_new (handle, value);
-	    ri->serverwildcards = xrealloc (ri->serverwildcards,
-					    ++ri->nserverwildcards *
-					    sizeof (*ri->serverwildcards));
-	    ri->serverwildcards[ri->nserverwildcards - 1] = xstrdup (value);
+	    char *subopts, *part, *next;
+
+	    if (!p || (*p == 0))
+	      {
+		shishi_warn (handle, "Empty server-realm for '%s'.", value);
+		break;
+	      }
+
+	    ri = _shishi_realminfo_new (handle, xstrdup (value));
+
+	    part = subopts = xstrdup (p);	/* List of patterns.  */
+	    while (part && *part)
+	      {
+		next = strchr (part, ',');
+		if (next)
+		  *(next++) = '\0';
+
+		ri->serverwildcards = xrealloc (ri->serverwildcards,
+						++ri->nserverwildcards *
+						sizeof (*ri->serverwildcards));
+		ri->serverwildcards[ri->nserverwildcards - 1] = xstrdup (part);
+		part = next;
+	      }
+	    p = NULL;	/* Done with suboptions.  */
 	  }
 	  break;
 
@@ -275,47 +331,6 @@ shishi_cfg (Shishi * handle, const char *option)
 	case -1:
 	  if (!value)
 	    break;
-	  for (i = 0; i < handle->nrealminfos; i++)
-	    if (realm && strcmp (handle->realminfos[i].name, realm) == 0)
-	      {
-		struct Shishi_realminfo *ri = &handle->realminfos[i];
-		char *protstr;
-		int transport = UDP;
-
-		if ((protstr = strchr (value, '/')))
-		  {
-		    *protstr = '\0';
-		    protstr++;
-		    if (strcasecmp (protstr, "udp") == 0)
-		      transport = UDP;
-		    else if (strcasecmp (protstr, "tcp") == 0)
-		      transport = TCP;
-		    else if (strcasecmp (protstr, "tls") == 0)
-		      transport = TLS;
-		    else
-		      shishi_warn (handle,
-				   "Ignoring unknown KDC transport: %s",
-				   protstr);
-		  }
-
-		ri->kdcaddresses = xrealloc (ri->kdcaddresses,
-					     (ri->nkdcaddresses + 1) *
-					     sizeof (*ri->kdcaddresses));
-		ri->kdcaddresses[ri->nkdcaddresses].transport = transport;
-		ri->kdcaddresses[ri->nkdcaddresses].hostname =
-		  xstrdup (value);
-		if ((protstr = strchr (value, ':')))
-		  {
-		    *protstr = '\0';
-		    protstr++;
-		    ri->kdcaddresses[ri->nkdcaddresses].port = protstr;
-		  }
-		else
-		  ri->kdcaddresses[ri->nkdcaddresses].port = NULL;
-		ri->nkdcaddresses++;
-	      }
-	  if (realm)
-	    break;
 	  /* fall through */
 
 	default:
diff --git a/lib/init.c b/lib/init.c
index 7fb349c..8c61001 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -175,7 +175,7 @@ shishi_done (Shishi * handle)
 
   if (handle->realminfos)
     {
-      size_t i;
+      size_t i, j;
 
       for (i = 0; i < handle->nrealminfos; i++)
 	{
@@ -183,6 +183,9 @@ shishi_done (Shishi * handle)
 
 	  free (handle->realminfos[i].kdcaddresses);
 	  free (handle->realminfos[i].name);
+
+	  for (j = 0; j < handle->realminfos[i].nserverwildcards; j++)
+	    free (handle->realminfos[i].serverwildcards[j]);
 	}
     }
 
diff --git a/lib/realm.c b/lib/realm.c
index b17010d..1b7c005 100644
--- a/lib/realm.c
+++ b/lib/realm.c
@@ -111,6 +111,35 @@ shishi_realm_default_set (Shishi * handle, const char *realm)
 char *
 shishi_realm_for_server_file (Shishi * handle, char *server)
 {
+  struct Shishi_realminfo *ri;
+  size_t i, j;
+  char *p;
+
+  for (i = 0; i < handle->nrealminfos; i++)
+    {
+      ri = &handle->realminfos[i];
+
+      if (!ri->nserverwildcards)
+	continue;
+
+      for (j = 0; j < ri->nserverwildcards; j++)
+	{
+	  /* Exact server name match.  */
+	  if (strcmp (server, ri->serverwildcards[j]) == 0)
+	    return ri->name;
+
+	  /* Is this a tail pattern?  */
+	  if (*(ri->serverwildcards[j]) != '.')
+	    continue;
+
+	  /* Domain part matching.  */
+	  p = server;
+	  while (p = strchr (p, '.'))
+	    if (strcmp (p++, ri->serverwildcards[j]) == 0)
+	      return ri->name;
+	}
+    }
+
   return NULL;
 }
 
diff --git a/shishi.conf.in b/shishi.conf.in
index 98db22b..2d2c285 100644
--- a/shishi.conf.in
+++ b/shishi.conf.in
@@ -70,8 +70,11 @@
 
 # Specify realm for servers.
 # Value is REALM,SERVERREGEXP[,SERVERREGEXP...]
-# SERVERREGEXP is a regular expression matching servers in the realm.
-# The first match is used.
+# SERVERREGEXP is a pattern used to establish membership in the
+# given realm.  The pattern is either the exact name of a server,
+# or a trailing domain part expected in a qualified server name,
+# whenever the pattern commences with a period.  The first match
+# found will be used in library calls.
 #server-realm=JOSEFSSON.ORG,.josefsson.org
 
 # How long shishi waits for a response from a KDC before continuing
-- 
1.7.2.5

_______________________________________________
Help-shishi mailing list
Help-shishi@gnu.org
https://lists.gnu.org/mailman/listinfo/help-shishi

Reply via email to