[2158] in Kerberos-V5-bugs

home help back first fref pref prev next nref lref last post

Re: gssftp secure.c bug

daemon@ATHENA.MIT.EDU (Sam Hartman)
Fri Aug 16 13:27:08 1996

To: Derrick J Brashear <shadow+@andrew.cmu.edu>
Cc: krb5-bugs@MIT.EDU
From: Sam Hartman <hartmans@MIT.EDU>
Date: 16 Aug 1996 13:26:46 -0400
In-Reply-To: Derrick J Brashear's message of Tue, 13 Aug 1996 15:03:50 -0400 (EDT)

>>>>> "Derrick" == Derrick J Brashear <shadow+@andrew.cmu.edu> writes:

    Derrick> Erk. I was looking at the wrong 2 files. so: (outbuf =
    Derrick> malloc((unsigned) (nbyte + FUDGE_FACTOR)))) { bufsize =
    Derrick> out_buf.length;

    Derrick> becomes (outbuf = malloc((unsigned) (nbyte +
    Derrick> FUDGE_FACTOR)))) { bufsize = (unsigned) (nbyte +
    Derrick> FUDGE_FACTOR);

	Done along with a few other bugs in the same code; see the
following patch.


    Derrick> -D


Index: ftp/ChangeLog
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftp/ChangeLog,v
retrieving revision 1.7
retrieving revision 1.11
diff -c -r1.7 -r1.11
*** ChangeLog	1996/05/01 00:21:05	1.7
--- ChangeLog	1996/08/05 18:11:28	1.11
***************
*** 1,3 ****
--- 1,36 ----
+ Tue Jul 30 19:45:45 1996  Samuel D Hartman  (hartmans@vorlon)
+ 
+ 	* ftp.c (empt resety): Use fd_set as a typedef not a struct.
+         Linux breaks.
+ 
+ Mon Jul 29 22:37:23 1996  Ezra Peisach  <epeisach@kangaroo.mit.edu>
+ 
+ 	* secure.c: Do not assume sizeof(long) = 4 for sending lengths OTW
+ 
+ 	* configure.in: Determine sizeof short, int, long for secure.c
+ 
+ Fri Jul 26 20:55:12 1996  Sam Hartman  <hartmans@tertius.mit.edu>
+ 
+ 	* secure.c (secure_putbyte): Reset nout to zero on errorso we
+         don't overflow our buffer.
+ 
+ 	* ftp.c (sendrequest): If there is an error in secure_write, break
+         out of the loop.
+ 
+ 	* secure.c(FUDGE_FACTOR): Define for GSSAPI so writes don't fail.
+         i chose a value of 64, which is larger than the apparent 52 bytes
+         of additional data but I'm not sure 52 is constant.
+ 
+ 	(secure_putbuf): Set bufsize to the size we actually allocate
+ 	     Also, write foure bytes for net_len no matter how long it
+ 	     actually is.  I would rather declare it a 32-bit type but am not
+ 	     sure whether to use the GSSAPI, krb4, or krb5 32-bit int.
+ 
+ Wed Jul 10 16:40:19 1996  Marc Horowitz  <marc@mit.edu>
+ 
+ 	* cmdtab.c (cmdtab[]), cmds.c (delete_file): rename delete() to
+  	delete_file() to avoid conflict with the dbm delete() function
+ 
  Thu Mar 28 21:07:40 1996  Ken Raeburn  <raeburn@cygnus.com>
  
  	* cmds.c (setpeer): Define unix for HP-UX.
***************
*** 13,19 ****
  Mon Mar 18 12:12:44 1996  Ezra Peisach  <epeisach@kangaroo.mit.edu>
  
  	* secure.c, ftp.c, ftp_var.h: Define STDARG if HAVE_STDARG_H is
! 		defined (in addition to the other tests)
  
  	* configure.in: Add AC_HEADER_STDARG
  
--- 46,52 ----
  Mon Mar 18 12:12:44 1996  Ezra Peisach  <epeisach@kangaroo.mit.edu>
  
  	* secure.c, ftp.c, ftp_var.h: Define STDARG if HAVE_STDARG_H is
!  		defined (in addition to the other tests)
  
  	* configure.in: Add AC_HEADER_STDARG
  
Index: ftp/cmds.c
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftp/cmds.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -c -r1.4 -r1.5
*** cmds.c	1996/04/09 22:40:12	1.4
--- cmds.c	1996/07/22 20:21:32	1.5
***************
*** 1243,1249 ****
  /*
   * Delete a single file.
   */
! delete(argc, argv)
  	int argc;
  	char *argv[];
  {
--- 1243,1249 ----
  /*
   * Delete a single file.
   */
! delete_file(argc, argv)
  	int argc;
  	char *argv[];
  {
Index: ftp/cmdtab.c
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftp/cmdtab.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** cmdtab.c	1996/01/14 08:32:41	1.1
--- cmdtab.c	1996/07/22 20:21:34	1.2
***************
*** 50,56 ****
  int	setprivate();
  #endif
  int	disconnect(), restart(), reget(), syst();
! int	cd(), lcd(), delete(), mdelete(), user();
  int	ls(), mls(), get(), mget(), help(), append(), put(), mput();
  int	quit(), renamefile(), status();
  int	quote(), rmthelp(), shell(), site();
--- 50,56 ----
  int	setprivate();
  #endif
  int	disconnect(), restart(), reget(), syst();
! int	cd(), lcd(), delete_file(), mdelete(), user();
  int	ls(), mls(), get(), mget(), help(), append(), put(), mput();
  int	quit(), renamefile(), status();
  int	quote(), rmthelp(), shell(), site();
***************
*** 154,160 ****
  	{ "clear",	clearhelp,	0,	1,	1,	setclear },
  	{ "close",	disconhelp,	0,	1,	1,	disconnect },
  	{ "cr",		crhelp,		0,	0,	0,	setcr },
! 	{ "delete",	deletehelp,	0,	1,	1,	delete },
  	{ "debug",	debughelp,	0,	0,	0,	setdebug },
  	{ "dir",	dirhelp,	1,	1,	1,	ls },
  	{ "disconnect",	disconhelp,	0,	1,	1,	disconnect },
--- 154,160 ----
  	{ "clear",	clearhelp,	0,	1,	1,	setclear },
  	{ "close",	disconhelp,	0,	1,	1,	disconnect },
  	{ "cr",		crhelp,		0,	0,	0,	setcr },
! 	{ "delete",	deletehelp,	0,	1,	1,	delete_file },
  	{ "debug",	debughelp,	0,	0,	0,	setdebug },
  	{ "dir",	dirhelp,	1,	1,	1,	ls },
  	{ "disconnect",	disconhelp,	0,	1,	1,	disconnect },
Index: ftp/configure.in
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftp/configure.in,v
retrieving revision 1.6
retrieving revision 1.7
diff -c -r1.6 -r1.7
*** configure.in	1996/03/19 02:09:58	1.6
--- configure.in	1996/07/30 02:39:18	1.7
***************
*** 7,12 ****
--- 7,15 ----
  CHECK_SIGPROCMASK
  CHECK_WAIT_TYPE
  DECLARE_SYS_ERRLIST
+ AC_CHECK_SIZEOF(short)
+ AC_CHECK_SIZEOF(int)
+ AC_CHECK_SIZEOF(long)
  AC_FUNC_VFORK
  AC_HAVE_FUNCS(getcwd getdtablesize)
  AC_HEADER_STDARG
Index: ftp/ftp.c
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftp/ftp.c,v
retrieving revision 1.8
retrieving revision 1.10
diff -c -r1.8 -r1.10
*** ftp.c	1996/03/19 02:10:00	1.8
--- ftp.c	1996/08/05 18:11:31	1.10
***************
*** 696,709 ****
  }
  
  empty(mask, sec)
! 	struct fd_set *mask;
  	int sec;
  {
  	struct timeval t;
  
  	t.tv_sec = (long) sec;
  	t.tv_usec = 0;
! 	return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
  }
  
  jmp_buf	sendabort;
--- 696,709 ----
  }
  
  empty(mask, sec)
!  fd_set *mask;
  	int sec;
  {
  	struct timeval t;
  
  	t.tv_sec = (long) sec;
  	t.tv_usec = 0;
! 	return(select(32, mask, (fd_set *) 0, (fd_set *) 0, &t));
  }
  
  jmp_buf	sendabort;
***************
*** 892,897 ****
--- 892,899 ----
  				}
  				(void) fflush(stdout);
  			}
+ 			if (d <= 0 ) 
+   break;
  		}
  		if (hash && bytes > 0) {
  			if (bytes < HASHBYTES)
***************
*** 1640,1646 ****
  	int secndflag = 0, prox_type, nfnd;
  	extern jmp_buf ptabort;
  	char *cmd2;
! 	struct fd_set mask;
  	sigtype abortpt();
  
  	if (strcmp(cmd, "RETR"))
--- 1642,1648 ----
  	int secndflag = 0, prox_type, nfnd;
  	extern jmp_buf ptabort;
  	char *cmd2;
! 	 fd_set mask;
  	sigtype abortpt();
  
  	if (strcmp(cmd, "RETR"))
***************
*** 1755,1761 ****
  
  reset()
  {
! 	struct fd_set mask;
  	int nfnd = 1;
  
  	FD_ZERO(&mask);
--- 1757,1763 ----
  
  reset()
  {
!    fd_set mask;
  	int nfnd = 1;
  
  	FD_ZERO(&mask);
***************
*** 2077,2083 ****
  {
  	char buf[FTP_BUFSIZ];
  	int nfnd;
! 	struct fd_set mask;
  
  	/*
  	 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
--- 2079,2085 ----
  {
  	char buf[FTP_BUFSIZ];
  	int nfnd;
! 	fd_set mask;
  
  	/*
  	 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
Index: ftp/secure.c
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftp/secure.c,v
retrieving revision 1.5
retrieving revision 1.7
diff -c -r1.5 -r1.7
*** secure.c	1996/04/09 22:40:14	1.5
--- secure.c	1996/07/30 02:39:19	1.7
***************
*** 35,40 ****
--- 35,52 ----
  extern char *sys_errlist[];
  #endif
  
+ #if (SIZEOF_SHORT == 4)
+ typedef unsigned short ftp_uint32;
+ typedef short ftp_int32;
+ #elif (SIZEOF_INT == 4)
+ typedef unsigned int ftp_uint32;
+ typedef int ftp_int32;
+ #elif (SIZEOF_LONG == 4)
+ typedef unsigned long ftp_uint32;
+ typedef long ftp_int32;
+ #endif
+ 
+ 
  extern struct	sockaddr_in hisaddr;
  extern struct	sockaddr_in myaddr;
  extern int	level;
***************
*** 54,59 ****
--- 66,75 ----
  				 */
  #endif /* KERBEROS */
  
+ #ifdef GSSAPI
+ #define FUDGE_FACTOR 64 /*It appears to add 52 byts, but I'm not usre it is a constant--hartmans*/
+ #endif /*GSSAPI*/
+ 
  #ifndef FUDGE_FACTOR		/* In case no auth types define it. */
  #define FUDGE_FACTOR 0
  #endif
***************
*** 136,146 ****
  	int ret;
  
  	ucbuf[nout++] = c;
! 	if (nout == MAX - FUDGE_FACTOR)
! 		if (ret = secure_putbuf(fd, ucbuf, nout))
! 			return(ret);
! 		else	nout = 0;
! 	return(c);
  }
  
  /* returns:
--- 152,163 ----
  	int ret;
  
  	ucbuf[nout++] = c;
! 	if (nout == MAX - FUDGE_FACTOR) {
! 	  ret = secure_putbuf(fd, ucbuf, nout);
! 	  nout = 0;
! 	  return(ret?ret:c);
! 	}
! return (c);
  }
  
  /* returns:
***************
*** 202,215 ****
   *	-2  on security error
   */
  secure_putbuf(fd, buf, nbyte)
! int fd;
  unsigned char *buf;
  unsigned int nbyte;
  {
! 	static char *outbuf;		/* output ciphertext */
  	static unsigned int bufsize;	/* size of outbuf */
! 	long length;
! 	u_long net_len;
  
  	/* Other auth types go here ... */
  #ifdef KERBEROS
--- 219,232 ----
   *	-2  on security error
   */
  secure_putbuf(fd, buf, nbyte)
!   int fd;
  unsigned char *buf;
  unsigned int nbyte;
  {
!   static char *outbuf;		/* output ciphertext */
  	static unsigned int bufsize;	/* size of outbuf */
! 	ftp_int32 length;
! 	ftp_uint32 net_len;
  
  	/* Other auth types go here ... */
  #ifdef KERBEROS
***************
*** 217,223 ****
  		if (outbuf?
  		    (outbuf = realloc(outbuf, (unsigned) (nbyte + FUDGE_FACTOR))):
  		    (outbuf = malloc((unsigned) (nbyte + FUDGE_FACTOR)))) {
! 			bufsize = nbyte + FUDGE_FACTOR;
  		} else {
  			bufsize = 0;
  			secure_error("%s (in malloc of PROT buffer)",
--- 234,240 ----
  		if (outbuf?
  		    (outbuf = realloc(outbuf, (unsigned) (nbyte + FUDGE_FACTOR))):
  		    (outbuf = malloc((unsigned) (nbyte + FUDGE_FACTOR)))) {
! 		  			bufsize = out_buf.length;
  		} else {
  			bufsize = 0;
  			secure_error("%s (in malloc of PROT buffer)",
***************
*** 278,284 ****
  	}
  #endif /* GSSAPI */
  	net_len = htonl((u_long) length);
! 	if (looping_write(fd, &net_len, sizeof(net_len)) == -1) return(-1);
  	if (looping_write(fd, outbuf, length) != length) return(-1);
  	return(0);
  }
--- 295,301 ----
  	}
  #endif /* GSSAPI */
  	net_len = htonl((u_long) length);
! 	if (looping_write(fd, &net_len, 4) == -1) return(-1);
  	if (looping_write(fd, outbuf, length) != length) return(-1);
  	return(0);
  }
***************
*** 290,296 ****
  	/* number of chars in ucbuf, pointer into ucbuf */
  	static unsigned int nin, bufp;
  	int kerror;
! 	u_long length;
  
  	if (nin == 0) {
  		if ((kerror = looping_read(fd, &length, sizeof(length)))
--- 307,313 ----
  	/* number of chars in ucbuf, pointer into ucbuf */
  	static unsigned int nin, bufp;
  	int kerror;
! 	ftp_uint32 length;
  
  	if (nin == 0) {
  		if ((kerror = looping_read(fd, &length, sizeof(length)))
Index: ftpd/ChangeLog
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftpd/ChangeLog,v
retrieving revision 1.11
retrieving revision 1.15
diff -c -r1.11 -r1.15
*** ChangeLog	1996/06/03 20:16:56	1.11
--- ChangeLog	1996/07/30 02:40:08	1.15
***************
*** 1,3 ****
--- 1,25 ----
+ Mon Jul 29 22:37:05 1996  Ezra Peisach  <epeisach@kangaroo.mit.edu>
+ 
+ 	* configure.in: Determine sizeof short, int, long for secure.c
+ 
+ Tue Jul 23 23:13:07 1996  Marc Horowitz  <marc@mit.edu>
+ 
+ 	* ftpd.c (auth_data): the logic which dealt with multiple acceptor
+  	names and fallback was just broken.
+ 
+ Wed Jul 10 16:38:01 1996  Marc Horowitz  <marc@mit.edu>
+ 
+ 	* ftpd.c (store), ftpcmd.y (STOR, APPE, STOU): rename store() to
+  	store_file() to avoid conflict with dbm store() function
+ 	* ftpd.c (delete), ftpcmd.y (DELE): rename delete() to
+  	delete_file() to avoid conflict with the dbm delete() function
+ 
+ Thu Jun 13 18:35:19 1996  Kevin L Mitchell  <klmitch@mit.edu>
+ 
+ 	* ftpd.c (authdata): misplaced braces caused server to not be able to
+ 		use ftp principle if it was present.  Client looks for ftp
+ 		first, then tries host; ftpd was looking only for host.
+ 
  Mon Jun  3 16:12:59 1996  Tom Yu  <tlyu@mit.edu>
  
  	* Makefile.in, configure.in: back out previous changes and use
Index: ftpd/configure.in
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftpd/configure.in,v
retrieving revision 1.8
retrieving revision 1.9
diff -c -r1.8 -r1.9
*** configure.in	1996/06/03 20:17:01	1.8
--- configure.in	1996/07/30 02:40:10	1.9
***************
*** 7,12 ****
--- 7,15 ----
  CHECK_UTMP
  CHECK_SIGPROCMASK
  CHECK_WAIT_TYPE
+ AC_CHECK_SIZEOF(short)
+ AC_CHECK_SIZEOF(int)
+ AC_CHECK_SIZEOF(long)
  DECLARE_SYS_ERRLIST
  AC_FUNC_VFORK
  AC_HEADER_STDARG
Index: ftpd/ftpcmd.y
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftpd/ftpcmd.y,v
retrieving revision 1.4
retrieving revision 1.5
diff -c -r1.4 -r1.5
*** ftpcmd.y	1996/05/01 01:50:53	1.4
--- ftpcmd.y	1996/07/22 20:21:40	1.5
***************
*** 338,351 ****
  	|	STOR check_login SP pathname CRLF
  		= {
  			if ($2 && $4 != NULL)
! 				store((char *) $4, "w", 0);
  			if ($4 != NULL)
  				free((char *) $4);
  		}
  	|	APPE check_login SP pathname CRLF
  		= {
  			if ($2 && $4 != NULL)
! 				store((char *) $4, "a", 0);
  			if ($4 != NULL)
  				free((char *) $4);
  		}
--- 338,351 ----
  	|	STOR check_login SP pathname CRLF
  		= {
  			if ($2 && $4 != NULL)
! 				store_file((char *) $4, "w", 0);
  			if ($4 != NULL)
  				free((char *) $4);
  		}
  	|	APPE check_login SP pathname CRLF
  		= {
  			if ($2 && $4 != NULL)
! 				store_file((char *) $4, "a", 0);
  			if ($4 != NULL)
  				free((char *) $4);
  		}
***************
*** 387,393 ****
  	|	DELE check_login SP pathname CRLF
  		= {
  			if ($2 && $4 != NULL)
! 				delete((char *) $4);
  			if ($4 != NULL)
  				free((char *) $4);
  		}
--- 387,393 ----
  	|	DELE check_login SP pathname CRLF
  		= {
  			if ($2 && $4 != NULL)
! 				delete_file((char *) $4);
  			if ($4 != NULL)
  				free((char *) $4);
  		}
***************
*** 535,541 ****
  	|	STOU check_login SP pathname CRLF
  		= {
  			if ($2 && $4 != NULL)
! 				store((char *) $4, "w", 1);
  			if ($4 != NULL)
  				free((char *) $4);
  		}
--- 535,541 ----
  	|	STOU check_login SP pathname CRLF
  		= {
  			if ($2 && $4 != NULL)
! 				store_file((char *) $4, "w", 1);
  			if ($4 != NULL)
  				free((char *) $4);
  		}
Index: ftpd/ftpd.c
===================================================================
RCS file: /mit/krbdev/.cvsroot/src/appl/gssftp/ftpd/ftpd.c,v
retrieving revision 1.9
retrieving revision 1.12
diff -c -r1.9 -r1.12
*** ftpd.c	1996/04/09 22:40:18	1.9
--- ftpd.c	1996/07/24 03:15:05	1.12
***************
*** 923,929 ****
  	(*closefunc)(fin);
  }
  
! store(name, mode, unique)
  	char *name, *mode;
  	int unique;
  {
--- 923,929 ----
  	(*closefunc)(fin);
  }
  
! store_file(name, mode, unique)
  	char *name, *mode;
  	int unique;
  {
***************
*** 1549,1555 ****
  	reply(500, "'%s': command not understood.", cbuf);
  }
  
! delete(name)
  	char *name;
  {
  	struct stat st;
--- 1549,1555 ----
  	reply(500, "'%s': command not understood.", cbuf);
  }
  
! delete_file(name)
  	char *name;
  {
  	struct stat st;
***************
*** 1832,1844 ****
  	char buf[FTP_BUFSIZ];
  	u_char out_buf[sizeof(buf)];
  #endif /* KERBEROS */
- #ifdef GSSAPI
- 	OM_uint32 maj_stat, min_stat;
- 	gss_OID mechid;
- 	gss_buffer_desc tok, out_tok;
- 	char gbuf[FTP_BUFSIZ];
- 	u_char gout_buf[sizeof(gbuf)];
- #endif
  
  	if (auth_type) {
  		reply(503, "Authentication already established");
--- 1832,1837 ----
***************
*** 1849,2070 ****
  		return(0);
  	}
  #ifdef KERBEROS
!     if (strcmp(temp_auth_type, "KERBEROS_V4") == 0) {
! 	if (kerror = radix_encode(data, out_buf, &length, 1)) {
! 		reply(501, "Couldn't decode ADAT (%s)",
! 				radix_error(kerror));
! 		syslog(LOG_ERR, "Couldn't decode ADAT (%s)",
! 				radix_error(kerror));
! 		return(0);
! 	}
! 	(void) memcpy((char *)ticket.dat, (char *)out_buf, ticket.length = length);
! 	strcpy(instance, "*");
! 	if (!service) {
! 		char realm[REALM_SZ];
! 		des_cblock key;
! 
! 		service = "ftp";
! 		if (krb_get_lrealm(realm, 1) == KSUCCESS &&
! 		    read_service_key(service, instance, realm, 0, keyfile, key))
! 			service = "rcmd";
! 		else	(void) memset(key, 0, sizeof(key));
! 	}
! 	if (kerror = krb_rd_req(&ticket, service, instance,
! 		his_addr.sin_addr.s_addr, &kdata, keyfile)) {
! 		secure_error("ADAT: Kerberos V4 krb_rd_req: %s",
! 				krb_get_err_text(kerror));
! 		return(0);
! 	}
! 	/* add one to the (formerly) sealed checksum, and re-seal it */
! 	cksum = kdata.checksum + 1;
! 	cksum = htonl(cksum);
! 	key_sched(kdata.session,schedule);
! 	if ((length = krb_mk_safe((u_char *)&cksum, out_buf, sizeof(cksum),
! 			&kdata.session,&ctrl_addr, &his_addr)) == -1) {
! 		secure_error("ADAT: krb_mk_safe failed");
! 		return(0);
! 	}
! 	if (kerror = radix_encode(out_buf, buf, &length, 0)) {
! 		secure_error("Couldn't encode ADAT reply (%s)",
! 				radix_error(kerror));
! 		return(0);
  	}
- 	reply(235, "ADAT=%s", buf);
- 	/* Kerberos V4 authentication succeeded */
- 	auth_type = temp_auth_type;
- 	temp_auth_type = NULL;
- 	return(1);
-     }
  #endif /* KERBEROS */
  #ifdef GSSAPI
!     if (strcmp(temp_auth_type, "GSSAPI") == 0) {
!         int replied = 0;
! 	int found = 0;
!         gss_cred_id_t server_creds;     
! 	gss_name_t client;
! 	int ret_flags;
! 	struct gss_channel_bindings_struct chan;
! 	gss_buffer_desc name_buf;
! 	gss_name_t server_name;
! 	OM_uint32 maj_stat, min_stat, save_stat;
! 	char localname[MAXHOSTNAMELEN];
! 	char service_name[MAXHOSTNAMELEN+10];
! 	char **service;
! 	struct hostent *hp;
! 
! 	chan.initiator_addrtype = GSS_C_AF_INET;
! 	chan.initiator_address.length = 4;
! 	chan.initiator_address.value = &his_addr.sin_addr.s_addr;
! 	chan.acceptor_addrtype = GSS_C_AF_INET;
! 	chan.acceptor_address.length = 4;
! 	chan.acceptor_address.value = &ctrl_addr.sin_addr.s_addr;
! 	chan.application_data.length = 0;
! 	chan.application_data.value = 0;
! 
! 	if (kerror = radix_encode(data, gout_buf, &length, 1)) {
! 		reply(501, "Couldn't decode ADAT (%s)",
! 				radix_error(kerror));
! 		syslog(LOG_ERR, "Couldn't decode ADAT (%s)",
! 				radix_error(kerror));
! 		return(0);
! 	}
! 	tok.value = gout_buf;
! 	tok.length = length;
! 	
! 	if (gethostname(localname, MAXHOSTNAMELEN)) {
! 		reply(501, "couldn't get local hostname (%d)\n", errno);
! 		syslog(LOG_ERR, "Couldn't get local hostname (%d)", errno);
! 		return 0;
! 	}
! 	if (!(hp = gethostbyname(localname))) {
! 		extern int h_errno;
! 		reply(501, "couldn't canonicalize local hostname (%d)\n", h_errno);
! 		syslog(LOG_ERR, "Couldn't canonicalize local hostname (%d)", h_errno);
! 		return 0;
! 	}
! 	strcpy(localname, hp->h_name);
! 
! 	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) syslog(LOG_INFO, "importing <%s>", service_name);
! 		maj_stat = gss_import_name(&min_stat, &name_buf, 
! 					   gss_nt_service_name,
! 					   &server_name);
! 		if (maj_stat != GSS_S_COMPLETE) {
! 			reply_gss_error(501, maj_stat, min_stat,
! 					"importing name");
! 			syslog(LOG_ERR, "gssapi error importing name");
  			return 0;
  		}
  
! 		maj_stat = gss_acquire_cred(&min_stat, server_name, 0,
! 					    GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
! 					    &server_creds, NULL, NULL);
! 		save_stat = min_stat;
! 		(void) gss_release_name(&min_stat, &server_name);
! 		if (maj_stat != GSS_S_COMPLETE)
! 		  continue;
! 		found++;
! 	}
  
! 		if (!found && (maj_stat != GSS_S_COMPLETE))
! 		{
! 			min_stat = save_stat;
! 			reply_gss_error(501, maj_stat, min_stat,
  					"acquiring credentials");
  			syslog(LOG_ERR, "gssapi error acquiring credentials");
  			return 0;
  		}
- 		if (server_creds == GSS_C_NO_CREDENTIAL) {
- 			syslog(LOG_ERR, "acquire return GSS_C_NO_CREDENTIAL");
- 		}
- 
  
! 	gcontext = GSS_C_NO_CONTEXT;
! 
! 	maj_stat = gss_accept_sec_context(&min_stat,
! 					  &gcontext, /* context_handle */
! 					  server_creds, /* verifier_cred_handle */
! 					  &tok, /* input_token */
! 					  &chan, /* channel bindings */
! 					  &client, /* src_name */
! 					  &mechid, /* mech_type */
! 					  &out_tok, /* output_token */
! 					  &ret_flags,
! 					  NULL, 	/* ignore time_rec */
! 					  NULL   /* ignore del_cred_handle */
! 					  );
! 	if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
! 		reply_gss_error(535, maj_stat, min_stat,
! 				"accepting context");
! 		syslog(LOG_ERR, "failed accepting context");
! 		(void) gss_release_cred(&min_stat, &server_creds);
! 		return 0;
! 	}
! 
! 	if (out_tok.length) {
! 		if (kerror = radix_encode(out_tok.value, gbuf, &out_tok.length, 0)) {
! 			secure_error("Couldn't encode ADAT reply (%s)",
! 				     radix_error(kerror));
! 			syslog(LOG_ERR, "couldn't encode ADAT reply");
! 			return(0);
  		}
! 		if (maj_stat == GSS_S_COMPLETE) {
! 		  reply(235, "ADAT=%s", gbuf);
! 		  replied = 1;
  		} else {
- 		  /* If the server accepts the security data, and
- 		     requires additional data, it should respond with
- 		     reply code 335. */
- 		  reply(335, "ADAT=%s", gbuf);
- 		}
- 		(void) gss_release_buffer(&min_stat, &out_tok);
- 	}
- 	if (maj_stat == GSS_S_COMPLETE) {
- 		/* GSSAPI authentication succeeded */
- 		maj_stat = gss_display_name(&min_stat, client, &client_name, 
- 					    &mechid);
- 		if (maj_stat != GSS_S_COMPLETE) {
  			/* "If the server rejects the security data (if 
! 			   a checksum fails, for instance), it should 
! 			   respond with reply code 535." */
! 			reply_gss_error(535, maj_stat, min_stat,
! 					"extracting GSSAPI identity name");
! 			syslog(LOG_ERR, "gssapi error extracting identity");
! 			(void) gss_release_cred(&min_stat, &server_creds);
! 			return 0;
  		}
- 		/* If the server accepts the security data, but does
- 		   not require any additional data (i.e., the security
- 		   data exchange has completed successfully), it must
- 		   respond with reply code 235. */
- 		if (!replied) reply(235, "GSSAPI Authentication succeeded");
- 
- 		auth_type = temp_auth_type;
- 		temp_auth_type = NULL;
- 
- 		(void) gss_release_cred(&min_stat, &server_creds);
- 		return(1);
- 	} else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
- 		/* If the server accepts the security data, and
- 		   requires additional data, it should respond with
- 		   reply code 335. */
- 		reply(335, "more data needed");
- 		(void) gss_release_cred(&min_stat, &server_creds);
- 		return(0);
- 	} else {
- 		/* "If the server rejects the security data (if 
- 		   a checksum fails, for instance), it should 
- 		   respond with reply code 535." */
- 		reply_gss_error(535, maj_stat, min_stat, 
- 				"GSSAPI failed processing ADAT");
- 		syslog(LOG_ERR, "GSSAPI failed processing ADAT");
- 		(void) gss_release_cred(&min_stat, &server_creds);
- 		return(0);
  	}
-     }
  #endif /* GSSAPI */
  	/* Other auth types go here ... */
  	/* Also need to check authorization, but that is done in user() */
--- 1842,2068 ----
  		return(0);
  	}
  #ifdef KERBEROS
! 	if (strcmp(temp_auth_type, "KERBEROS_V4") == 0) {
! 		if (kerror = radix_encode(data, out_buf, &length, 1)) {
! 			reply(501, "Couldn't decode ADAT (%s)",
! 			      radix_error(kerror));
! 			syslog(LOG_ERR, "Couldn't decode ADAT (%s)",
! 			       radix_error(kerror));
! 			return(0);
! 		}
! 		(void) memcpy((char *)ticket.dat, (char *)out_buf, ticket.length = length);
! 		strcpy(instance, "*");
! 		if (!service) {
! 			char realm[REALM_SZ];
! 			des_cblock key;
! 			
! 			service = "ftp";
! 			if (krb_get_lrealm(realm, 1) == KSUCCESS &&
! 			    read_service_key(service, instance, realm, 0, keyfile, key))
! 				service = "rcmd";
! 			else
! 				(void) memset(key, 0, sizeof(key));
! 		}
! 		if (kerror = krb_rd_req(&ticket, service, instance,
! 					his_addr.sin_addr.s_addr, &kdata, keyfile)) {
! 			secure_error("ADAT: Kerberos V4 krb_rd_req: %s",
! 				     krb_get_err_text(kerror));
! 			return(0);
! 		}
! 		/* add one to the (formerly) sealed checksum, and re-seal it */
! 		cksum = kdata.checksum + 1;
! 		cksum = htonl(cksum);
! 		key_sched(kdata.session,schedule);
! 		if ((length = krb_mk_safe((u_char *)&cksum, out_buf, sizeof(cksum),
! 					  &kdata.session,&ctrl_addr, &his_addr)) == -1) {
! 			secure_error("ADAT: krb_mk_safe failed");
! 			return(0);
! 		}
! 		if (kerror = radix_encode(out_buf, buf, &length, 0)) {
! 			secure_error("Couldn't encode ADAT reply (%s)",
! 				     radix_error(kerror));
! 			return(0);
! 		}
! 		reply(235, "ADAT=%s", buf);
! 		/* Kerberos V4 authentication succeeded */
! 		auth_type = temp_auth_type;
! 		temp_auth_type = NULL;
! 		return(1);
  	}
  #endif /* KERBEROS */
  #ifdef GSSAPI
! 	if (strcmp(temp_auth_type, "GSSAPI") == 0) {
! 		int replied = 0;
! 		int found = 0;
! 		gss_cred_id_t server_creds;     
! 		gss_name_t client;
! 		int ret_flags;
! 		struct gss_channel_bindings_struct chan;
! 		gss_buffer_desc name_buf;
! 		gss_name_t server_name;
! 		OM_uint32 acquire_maj, acquire_min, accept_maj, accept_min,
! 				stat_maj, stat_min;
! 		gss_OID mechid;
! 		gss_buffer_desc tok, out_tok;
! 		char gbuf[FTP_BUFSIZ];
! 		u_char gout_buf[FTP_BUFSIZ];
! 		char localname[MAXHOSTNAMELEN];
! 		char service_name[MAXHOSTNAMELEN+10];
! 		char **service;
! 		struct hostent *hp;
! 
! 		chan.initiator_addrtype = GSS_C_AF_INET;
! 		chan.initiator_address.length = 4;
! 		chan.initiator_address.value = &his_addr.sin_addr.s_addr;
! 		chan.acceptor_addrtype = GSS_C_AF_INET;
! 		chan.acceptor_address.length = 4;
! 		chan.acceptor_address.value = &ctrl_addr.sin_addr.s_addr;
! 		chan.application_data.length = 0;
! 		chan.application_data.value = 0;
! 
! 		if (kerror = radix_encode(data, gout_buf, &length, 1)) {
! 			reply(501, "Couldn't decode ADAT (%s)",
! 			      radix_error(kerror));
! 			syslog(LOG_ERR, "Couldn't decode ADAT (%s)",
! 			       radix_error(kerror));
! 			return(0);
! 		}
! 		tok.value = gout_buf;
! 		tok.length = length;
! 
! 		if (gethostname(localname, MAXHOSTNAMELEN)) {
! 			reply(501, "couldn't get local hostname (%d)\n", errno);
! 			syslog(LOG_ERR, "Couldn't get local hostname (%d)", errno);
! 			return 0;
! 		}
! 		if (!(hp = gethostbyname(localname))) {
! 			extern int h_errno;
! 			reply(501, "couldn't canonicalize local hostname (%d)\n", h_errno);
! 			syslog(LOG_ERR, "Couldn't canonicalize local hostname (%d)", h_errno);
  			return 0;
  		}
+ 		strcpy(localname, hp->h_name);
  
! 		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)
! 				syslog(LOG_INFO, "importing <%s>", service_name);
! 			stat_maj = gss_import_name(&stat_min, &name_buf, 
! 						   gss_nt_service_name,
! 						   &server_name);
! 			if (stat_maj != GSS_S_COMPLETE) {
! 				reply_gss_error(501, stat_maj, stat_min,
! 						"importing name");
! 				syslog(LOG_ERR, "gssapi error importing name");
! 				return 0;
! 			}
! 			
! 			acquire_maj = gss_acquire_cred(&acquire_min, server_name, 0,
! 						       GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
! 						       &server_creds, NULL, NULL);
! 			(void) gss_release_name(&stat_min, &server_name);
! 
! 			if (acquire_maj != GSS_S_COMPLETE)
! 				continue;
! 
! 			found++;
! 
! 			gcontext = GSS_C_NO_CONTEXT;
! 
! 			accept_maj = gss_accept_sec_context(&accept_min,
! 							    &gcontext, /* context_handle */
! 							    server_creds, /* verifier_cred_handle */
! 							    &tok, /* input_token */
! 							    &chan, /* channel bindings */
! 							    &client, /* src_name */
! 							    &mechid, /* mech_type */
! 							    &out_tok, /* output_token */
! 							    &ret_flags,
! 							    NULL, 	/* ignore time_rec */
! 							    NULL   /* ignore del_cred_handle */
! 							    );
! 			if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED)
! 				continue;
! 		}
  
! 		if (found) {
! 			if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
! 				reply_gss_error(535, accept_maj, accept_min,
! 						"accepting context");
! 				syslog(LOG_ERR, "failed accepting context");
! 				(void) gss_release_cred(&stat_min, &server_creds);
! 				return 0;
! 			}
! 		} else {
! 			reply_gss_error(501, stat_maj, stat_min,
  					"acquiring credentials");
  			syslog(LOG_ERR, "gssapi error acquiring credentials");
  			return 0;
  		}
  
! 		if (out_tok.length) {
! 			if (kerror = radix_encode(out_tok.value, gbuf, &out_tok.length, 0)) {
! 				secure_error("Couldn't encode ADAT reply (%s)",
! 					     radix_error(kerror));
! 				syslog(LOG_ERR, "couldn't encode ADAT reply");
! 				return(0);
! 			}
! 			if (stat_maj == GSS_S_COMPLETE) {
! 				reply(235, "ADAT=%s", gbuf);
! 				replied = 1;
! 			} else {
! 				/* If the server accepts the security data, and
! 				   requires additional data, it should respond with
! 				   reply code 335. */
! 				reply(335, "ADAT=%s", gbuf);
! 			}
! 			(void) gss_release_buffer(&stat_min, &out_tok);
  		}
! 		if (stat_maj == GSS_S_COMPLETE) {
! 			/* GSSAPI authentication succeeded */
! 			stat_maj = gss_display_name(&stat_min, client, &client_name, 
! 						    &mechid);
! 			if (stat_maj != GSS_S_COMPLETE) {
! 				/* "If the server rejects the security data (if 
! 				   a checksum fails, for instance), it should 
! 				   respond with reply code 535." */
! 				reply_gss_error(535, stat_maj, stat_min,
! 						"extracting GSSAPI identity name");
! 				syslog(LOG_ERR, "gssapi error extracting identity");
! 				(void) gss_release_cred(&stat_min, &server_creds);
! 				return 0;
! 			}
! 			/* If the server accepts the security data, but does
! 				   not require any additional data (i.e., the security
! 				   data exchange has completed successfully), it must
! 				   respond with reply code 235. */
! 			if (!replied) reply(235, "GSSAPI Authentication succeeded");
! 				
! 			auth_type = temp_auth_type;
! 			temp_auth_type = NULL;
! 				
! 			(void) gss_release_cred(&stat_min, &server_creds);
! 			return(1);
! 		} else if (stat_maj == GSS_S_CONTINUE_NEEDED) {
! 			/* If the server accepts the security data, and
! 				   requires additional data, it should respond with
! 				   reply code 335. */
! 			reply(335, "more data needed");
! 			(void) gss_release_cred(&stat_min, &server_creds);
! 			return(0);
  		} else {
  			/* "If the server rejects the security data (if 
! 				   a checksum fails, for instance), it should 
! 				   respond with reply code 535." */
! 			reply_gss_error(535, stat_maj, stat_min, 
! 					"GSSAPI failed processing ADAT");
! 			syslog(LOG_ERR, "GSSAPI failed processing ADAT");
! 			(void) gss_release_cred(&stat_min, &server_creds);
! 			return(0);
  		}
  	}
  #endif /* GSSAPI */
  	/* Other auth types go here ... */
  	/* Also need to check authorization, but that is done in user() */

home help back first fref pref prev next nref lref last post