krb5-appl/1059: gssftpd does not properly support multihomed hosts
benno@columbia.edu
benno at columbia.edu
Fri Feb 22 13:54:55 EST 2002
>Number: 1059
>Category: krb5-appl
>Synopsis: gssftpd does not properly support multihomed hosts
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: krb5-unassigned
>State: open
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Fri Feb 22 13:55:00 EST 2002
>Last-Modified:
>Originator: Benjamin Oshrin
>Organization:
Columbia University AcIS
>Release: krb5-1.2.3
>Environment:
System: SunOS starscream 5.8 Generic_108528-11 sun4u sparc SUNW,Ultra-5_10
Architecture: sun4
>Description:
We have a pool of servers fronted by "server load balancing" to
minimize user visible downtime. Each server is configured with
two interfaces: the real interface, known by the server's
hostname, and a virtual interface, which uses the address of the
pool slb vif. All of this is fronted by a DNS alias.
For example, the name "newcunix.cc.columbia.edu", the name that
is publicized to end users, is an alias for
"newcunixpool.cc.columbia.edu". "hazelnut.cc.columbia.edu" is
a member of the newcunix pool, and so listens on hme0 for hazelnut
and hme0:10 for newcunixpool. Our network hardware routes connections
to newcunixpool to an available host that is listening on that
address.
The problem arises when a user attempts to establish a kerberized
ftp session to these hosts, using either the ftp client included
with the distribution or other clients, such as MacOS Fetch.
The client correctly obtains a ticket for host/newcunixpool,
but upon connection the server expects a ticket for host/hazelnut
since that is the name returned by gethostname(3c).
>How-To-Repeat:
Set up a configuration similar to what is described aboved. It is
not necessary to use slb to test, the only requirement is a host
available via more than one hostname.
>Fix:
The following patch fixes the problem on Solaris by looking at
all /etc/hostname.* files for defined hostnames to try. This
is probably not a very portable patch.
*** ftpd.c Sat Dec 22 03:04:09 2001
--- ftpd.c.mh Fri Feb 22 13:45:56 2002
***************
*** 2351,2356 ****
--- 2351,2363 ----
char **service;
struct hostent *hp;
+ #if defined(COLUMBIA)
+ char **lhostnames = NULL;
+ int lhostlen = 0, x;
+ DIR *dirp = NULL;
+ struct dirent *dp;
+ #endif
+
chan.initiator_addrtype = GSS_C_AF_INET;
chan.initiator_address.length = 4;
chan.initiator_address.value = &his_addr.sin_addr.s_addr;
***************
*** 2370,2375 ****
--- 2377,2454 ----
tok.value = gout_buf;
tok.length = length;
+ #if defined(COLUMBIA)
+ /* Determine the possible set of hostnames to try by
+ looking in /etc/hostname.*
+ */
+
+ dirp = opendir("/etc");
+
+ if(dirp)
+ {
+ while((dp = readdir(dirp)) != NULL) {
+ if(strlen(dp->d_name) > 9 &&
+ (FILENAME_MAX - strlen(dp->d_name) > 10) &&
+ strncmp(dp->d_name, "hostname.", 9)==0)
+ {
+ /* Add the contents of this file to the array */
+
+ FILE *hfin = NULL;
+ char hfname[FILENAME_MAX];
+ char nhname[MAXHOSTNAMELEN];
+ char **newhostnames = NULL;
+
+ sprintf(hfname, "/etc/%s\0", dp->d_name);
+
+ hfin = fopen(hfname, "r");
+
+ if(hfin)
+ {
+ memset(nhname, 0, MAXHOSTNAMELEN);
+ fgets(nhname, MAXHOSTNAMELEN, hfin);
+ fclose(hfin);
+
+ for(x = 0;x < strlen(nhname);x++)
+ if(nhname[x] == '\r' || nhname[x] == '\n')
+ {
+ nhname[x] = '\0';
+ break;
+ }
+
+ if(!(hp = gethostbyname(nhname)))
+ {
+ reply(501, "couldn't canonicalize hostname\n");
+
+ /* We don't return, however, since there may be
+ * other names. Not worth syslogging this.
+ */
+ }
+ else
+ {
+ newhostnames = (char **)malloc((sizeof(char *)) *
+ (lhostlen + 1));
+
+ if(newhostnames)
+ {
+ for(x = 0;x < lhostlen;x++)
+ newhostnames[x] = lhostnames[x];
+
+ newhostnames[lhostlen] = strdup(hp->h_name);
+ lhostlen++;
+
+ if(lhostnames)
+ free(lhostnames);
+ lhostnames = newhostnames;
+ newhostnames = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ closedir(dirp);
+ }
+ #else /* COLUMBIA */
if (gethostname(localname, MAXHOSTNAMELEN)) {
reply(501, "couldn't get local hostname (%d)\n", errno);
syslog(LOG_ERR, "Couldn't get local hostname (%d)", errno);
***************
*** 2382,2390 ****
}
strncpy(localname, hp->h_name, sizeof(localname) - 1);
localname[sizeof(localname) - 1] = '\0';
for (service = gss_services; *service; service++) {
! sprintf(service_name, "%s@%s", *service, localname);
name_buf.value = service_name;
name_buf.length = strlen(name_buf.value) + 1;
if (debug)
--- 2461,2475 ----
}
strncpy(localname, hp->h_name, sizeof(localname) - 1);
localname[sizeof(localname) - 1] = '\0';
+ #endif /* COLUMBIA */
for (service = gss_services; *service; service++) {
! #if defined(COLUMBIA)
! for(x = 0;x < lhostlen;x++) {
! sprintf(service_name, "%s@%s", *service, lhostnames[x]);
! #else
! sprintf(service_name, "%s@%s", *service, localname);
! #endif
name_buf.value = service_name;
name_buf.length = strlen(name_buf.value) + 1;
if (debug)
***************
*** 2425,2431 ****
);
if (accept_maj==GSS_S_COMPLETE||accept_maj==GSS_S_CONTINUE_NEEDED)
break;
! }
if (found) {
if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
--- 2510,2519 ----
);
if (accept_maj==GSS_S_COMPLETE||accept_maj==GSS_S_CONTINUE_NEEDED)
break;
! #if defined(COLUMBIA)
! }
! #endif /* COLUMBIA */
! }
if (found) {
if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
>Audit-Trail:
>Unformatted:
More information about the krb5-bugs
mailing list