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