>From c688c20e7df466a352f7263c3ec93e3e94c14e3a Mon Sep 17 00:00:00 2001 From: Mats Erik Andersson 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