diff -uNr wget-1.9.1/src/ftp-basic.c wget-1.9.1.NEW/src/ftp-basic.c
--- wget-1.9.1/src/ftp-basic.c	2004-06-20 22:17:48.835120372 +0200
+++ wget-1.9.1.NEW/src/ftp-basic.c	2004-06-20 13:53:49.000000000 +0200
@@ -64,10 +64,98 @@
 #include "connect.h"
 #include "host.h"
 #include "ftp.h"
+#include "url.h"
+
+
+#define PROT_C 1 /* in the clear */
+#define PROT_S 2 /* safe */
+#define PROT_P 3 /* private */
+
+#define FTP_BUFSIZ 10240
+
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+
+
+gss_ctx_id_t gcontext;
+char *auth_type;
+int clevel = PROT_S;
+
 
 char ftp_last_respline[128];
 
-
+#define ftp_radix_decode(i,o,l) radix_encode((i),(o),(l),1)
+#define ftp_radix_encode(i,o,l) radix_encode((i),(o),(l),0)
+
+/*
+   Reads a single response line from a FTP control stream.
+
+   A response has the following fomat:
+   <code>[-]<blank><response message>\r\n
+
+   Where <code> is a three digit response code, with a well
+   defined meaning in the RFC, and <response message> is the
+   plain-text explanation or additional text. The response
+   may span additional lines, which must be read together to
+   form a complete response message. This is stated by appending
+   a "-" symbol to the numerical response code.
+
+   If the response spans additional lines, ftp_read_line must
+   be invoked in a loop until a line is read which does not
+   flag @slit.
+
+   @rbuf   - Control stream
+   @code   - Where <code> will be left
+   @obuf   - Where <response message> will be left
+   @bufsiz - Maximum allowable size for obuf
+   @i      - Number of characters of the response message
+   @split  - Whether this response spans additional lines
+*/
+uerr_t
+ftp_read_line (struct rbuf *rbuf, int *code, char *obuf,
+               size_t bufsiz, int *i, int *split)
+{
+  int res;
+  char c;
+
+  /* Extract the FTP three-digit result code */
+  res = RBUF_READCHAR (rbuf, &c);
+  *code = 0;
+  while (res ==1 && c != '\n' && ISDIGIT(c))
+  {
+	*code *= 10;
+	*code += c - '0';
+  	res = RBUF_READCHAR (rbuf, &c);
+  }
+
+  /* The result code could have a dash, noting this is a split
+     response, or a blank to delimit the plain-text additional
+     message. */
+  if (c != ' ' && c != '-')
+    return FTPRERR;
+
+  *split = (c == '-');
+  if(*split)
+	res = RBUF_READCHAR (rbuf, &c);
+
+  /* Parse the plain-text additional message, which must be
+     terminated by the "\r\n" character sequence. */
+  *i = 0;
+  res = RBUF_READCHAR (rbuf, &c);
+  while(res == 1 && c != '\n' && *i < bufsiz - 1)
+  {
+	if(c != '\r')
+        {
+		(*i)++;
+		*obuf++ = c;
+	}
+	res = RBUF_READCHAR (rbuf, &c);
+  }
+  *obuf = 0;
+  (*i)++;
+  return FTPOK;
+}   
+ 
 /* Get the response of FTP server and allocate enough room to handle
    it.  <CR> and <LF> characters are stripped from the line, and the
    line is 0-terminated.  All the response lines but the last one are
@@ -75,42 +163,66 @@
 uerr_t
 ftp_response (struct rbuf *rbuf, char **line)
 {
-  int i;
-  int bufsize = 40;
+  char c;
+  int res, i = 0, code = 0, split, dummy;
+  char obuf[FTP_BUFSIZ];
+
+  /* Read the response, taking care of splitted response messages
+     which may span several lines. */
+  res = ftp_read_line (rbuf, &code, obuf, sizeof(obuf), &i, &split);
+  while (res == FTPOK && split)
+    res = ftp_read_line (rbuf, &dummy, obuf, sizeof(obuf), &i, &split);
 
-  *line = (char *)xmalloc (bufsize);
-  do
+  if(res != FTPOK)
+    return res;
+
+  if (!auth_type)
+  {
+    /* This is a simple response message */
+	  *line = (char *) xmalloc (i + 4);
+	  sprintf (*line, "%03d %s", code, obuf);
+  }
+  else
+  {
+    if (strcmp (auth_type, "GSSAPI") == 0)
     {
-      for (i = 0; 1; i++)
-        {
-          int res;
-          if (i > bufsize - 1)
-            *line = (char *)xrealloc (*line, (bufsize <<= 1));
-          res = RBUF_READCHAR (rbuf, *line + i);
-          /* RES is number of bytes read.  */
-          if (res == 1)
-            {
-              if ((*line)[i] == '\n')
-                {
-                  (*line)[i] = '\0';
-                  /* Get rid of \r.  */
-                  if (i > 0 && (*line)[i - 1] == '\r')
-                    (*line)[i - 1] = '\0';
-                  break;
-                }
-            }
-          else
-            return FTPRERR;
-        }
-      if (opt.server_response)
-        logprintf (LOG_ALWAYS, "%s\n", *line);
+      /* This is a GSSAPI-protected response message */
+      int conf_state;
+      char ibuf[FTP_BUFSIZ];
+      gss_buffer_desc xmit_buf, msg_buf;
+      gss_qop_t maj_stat, min_stat;
+
+      /* BASE64-decode the response */
+      res = ftp_radix_decode (obuf, ibuf, &i);
+      if (res)
+      {
+        printf("Can't base 64 decode reply %d (%s)\n\"%s\"\n", 
+               code, radix_error(res), obuf);
+        return FTPRERR;
+      }
+
+      /* Unseal the GSSAPI-protected response */
+      xmit_buf.value = ibuf;
+      xmit_buf.length = i;
+      conf_state = (code == 631);
+      maj_stat = gss_unseal(&min_stat, gcontext, &xmit_buf, &msg_buf,
+                            &conf_state, NULL);
+
+      if (maj_stat != GSS_S_COMPLETE)
+      {
+        printf("failed unsealing reply\n");
+        return FTPRERR;
+      }
       else
-        DEBUGP (("%s\n", *line));
+      {
+        *line = xmalloc (msg_buf.length + 3);
+        memcpy (*line, msg_buf.value, msg_buf.length);
+        strcpy (*line+msg_buf.length, "\r\n");
+        gss_release_buffer (&min_stat, &msg_buf);
+      }
     }
-  while (!(i >= 3 && ISDIGIT (**line) && ISDIGIT ((*line)[1]) &&
-           ISDIGIT ((*line)[2]) && (*line)[3] == ' '));
-  strncpy (ftp_last_respline, *line, sizeof (ftp_last_respline));
-  ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
+  }
+
   return FTPOK;
 }
 
@@ -120,20 +232,75 @@
 static char *
 ftp_request (const char *command, const char *value)
 {
+  int length, conf_state;
+  char in[FTP_BUFSIZ];
+  char *out = NULL;
+  gss_buffer_desc in_buf, out_buf;
+  gss_qop_t maj_stat, min_stat;
   char *res = (char *)xmalloc (strlen (command)
                                + (value ? (1 + strlen (value)) : 0)
                                + 2 + 1);
   sprintf (res, "%s%s%s\r\n", command, value ? " " : "", value ? value : "");
   if (opt.server_response)
-    {
-      /* Hack: don't print out password.  */
-      if (strncmp (res, "PASS", 4) != 0)
-        logprintf (LOG_ALWAYS, "--> %s\n", res);
-      else
-        logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n");
-    }
+  {
+    /* Hack: don't print out password.  */
+    if (strncmp (res, "PASS", 4) != 0)
+      logprintf (LOG_ALWAYS, "--> %s\n", res);
+    else
+      logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n");
+  }
   else
     DEBUGP (("\n--> %s\n", res));
+
+  if (auth_type)
+  {
+    /* The session is protected */
+    DEBUGP(("Command before sealing is %s", res));
+    if (strcmp(auth_type, "GSSAPI") == 0)
+    {
+      /* The session is protected with GSSAPI, so the command
+         must be sealed properly */
+      in_buf.value = res;
+      in_buf.length = strlen (res) + 1;
+      maj_stat = gss_seal (&min_stat, gcontext, (clevel == PROT_P),
+                           GSS_C_QOP_DEFAULT, &in_buf, &conf_state, &out_buf);
+      xfree (res);
+      res = NULL;
+
+      if (maj_stat != GSS_S_COMPLETE)
+      {
+        printf ("Error sealing the command %s\n", res);
+        goto request_end;
+      }
+      else if ((clevel == PROT_P) && !conf_state)
+      {
+        printf("GSSAPI didn't encrypt the message\n");
+        goto request_end;
+      }
+      else
+      {
+        length = out_buf.length;
+        out = xmalloc (length);
+        memcpy (out, out_buf.value, length);
+        gss_release_buffer (&min_stat, &out_buf);
+      }
+    }
+
+    /* Encode the command in BASE64 */
+    int kerror = ftp_radix_encode (out, in, &length);
+    if (kerror)
+    {
+      printf("Error while base 64 decoding: %s\n", radix_error(kerror));
+      goto request_end;
+    }
+
+    res = xmalloc (4 + length + 2);
+    sprintf (res, "%s %s\r\n", (clevel == PROT_P) ? "ENC" : "MIC", in);
+  }
+
+  DEBUGP(("GSSAPI encoded command is: %s", res));
+
+request_end:
   return res;
 }
 
@@ -144,7 +311,7 @@
 /* Sends the USER and PASS commands to the server, to control
    connection socket csock.  */
 uerr_t
-ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
+ftp_login (struct rbuf *rbuf, const char *acc, const char *pass, struct url *u)
 {
   uerr_t err;
   char *request, *respline;
@@ -153,16 +320,166 @@
   /* Get greeting.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
-    {
-      xfree (respline);
-      return err;
-    }
+  {
+    xfree (respline);
+    return err;
+  }
+
   if (*respline != '2')
-    {
-      xfree (respline);
-      return FTPSRVERR;
-    }
+  {
+    xfree (respline);
+    return FTPSRVERR;
+  }
+
   xfree (respline);
+
+  /* Try to authenticate via the AUTH GSSAPI command */
+  auth_type = NULL;
+  request = ftp_request ("AUTH", "GSSAPI");
+  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  xfree (request);
+  if (nwritten < 0)
+      return WRITEFAILED;
+
+  err = ftp_response (rbuf, &respline);
+  if (err != FTPOK)
+  {
+    xfree (respline);
+    return err;
+  }
+
+  DEBUGP(("%s\n", respline));
+
+  /* If AUTH GSSAPI is not supported, proceed with plain-text login */
+  if (respline[0] != '3' || respline[1] != '3' || respline[2] != '4')
+    goto login_proceed;
+
+  int i, len, kerror;
+  char stbuf[FTP_BUFSIZ];
+  unsigned char out_buf[FTP_BUFSIZ];
+  char *reply_parse;
+  struct sockaddr_in hisctladdr;
+  struct sockaddr_in myctladdr;
+  struct gss_channel_bindings_struct chan;
+  gss_buffer_desc send_tok, recv_tok, *token_ptr;
+  gss_qop_t maj_stat, min_stat;
+  gss_name_t target_name;
+
+  /* Initialize the out-of-band GSSAPI channel */
+  memset (&hisctladdr, 0, sizeof (hisctladdr));
+  hisctladdr.sin_addr.s_addr = inet_addr (u->host);
+  len = sizeof (myctladdr);
+  if (getsockname( RBUF_FD (rbuf), &myctladdr, &len))
+    goto login_proceed;
+
+  chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32  */
+  chan.initiator_address.length = 4;
+  chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
+  chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
+  chan.acceptor_address.length = 4;
+  chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
+  chan.application_data.length = 0;
+  chan.application_data.value = 0;
+
+  /* Authenticate against the Kerberos "host@hostname" service.
+     GSSAPI will canonicalize the hostname automagically */
+  snprintf (stbuf, sizeof (stbuf), "host@%s", u->host);
+  send_tok.value = stbuf;
+  send_tok.length = strlen (stbuf) + 1;
+  maj_stat = gss_import_name (&min_stat, &send_tok, gss_nt_service_name,
+                              &target_name);
+
+  if (maj_stat != GSS_S_COMPLETE)
+  {
+    printf("gss_import_name failed!\n");
+    goto gssapi_end;
+  }
+
+  token_ptr = GSS_C_NO_BUFFER;
+  gcontext = GSS_C_NO_CONTEXT;
+
+  /* The GSSAPI authentication process usually needs to complete
+     in several stages, so we need to loop until all stages are
+     completed in turn. */
+  do
+  {
+    maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &gcontext,
+                                    target_name, GSS_C_NO_OID,
+                                    GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+                                    0, &chan, token_ptr, NULL, &send_tok,
+                                    NULL, NULL);
+
+    if (maj_stat == GSS_S_CONTINUE_NEEDED)
+      DEBUGP(("gss_init_sec_context needs to continue\n"));
+    else if (maj_stat == GSS_S_COMPLETE)
+      DEBUGP(("gss_init_sec_context is complete\n"));
+    else
+    {
+      printf("Error while initializing GSSAPI context\n");
+      goto gssapi_end;
+    }
+
+    if ((len = send_tok.length) != 0)
+    {
+      /* Encode the GSSAPI-generated token which will be sent
+         to the remote server in order to perform authentication. */
+      kerror = ftp_radix_encode(send_tok.value, out_buf, &len);
+      if(kerror)
+      {
+        printf("Error when base 64 encoding ADAT for server: %s\n",
+               radix_error(kerror));
+        goto gssapi_end;
+      }
+
+      /* Sent the BASE64-encoded, GSSAPI-generated authentication
+         token to the remote server via the ADAT command. */
+      DEBUGP(("GSSAPI ADAT= command is %s\n", out_buf));
+      request = ftp_request ("ADAT", out_buf);
+      nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+      if (nwritten < 0)
+      {
+        xfree(request);
+        return WRITEFAILED;
+      }
+
+      xfree(request);
+      err = ftp_response (rbuf, &respline);
+      if (err != FTPOK)
+      {
+        xfree (respline);
+        return err;
+      }
+
+      /* If the remote server does not support the ADAT command,
+         proceed with plain-text login. */
+      DEBUGP(("Response to ADAT= is %s\n", &respline[9]));
+      if(respline[0] != '2' || respline[1] != '3' || respline[2] != '5')
+        goto login_proceed;
+
+      kerror = ftp_radix_decode(respline + 9, out_buf, &i);
+      xfree(respline);
+      if (kerror)
+      {
+        printf("Error when base 64 decoding server reply\n");
+        goto gssapi_end;
+      }
+
+      token_ptr = &recv_tok;
+      recv_tok.value = out_buf;
+      recv_tok.length = i;
+    }
+  } while (maj_stat == GSS_S_CONTINUE_NEEDED);
+
+  DEBUGP(("GSSAPI authentication succeeded\n"));
+  auth_type = "GSSAPI";
+  acc = getenv("USER");
+
+gssapi_end:
+
+  gss_release_buffer(&min_stat, &send_tok);
+  gss_release_name(&min_stat, &target_name);
+
+login_proceed:
   /* Send USER username.  */
   request = ftp_request ("USER", acc);
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
@@ -252,6 +569,9 @@
       return FTPLOGINC;
     }
   xfree (respline);
+
+login_end:
+
   /* All OK.  */
   return FTPOK;
 }
diff -uNr wget-1.9.1/src/ftp.c wget-1.9.1.NEW/src/ftp.c
--- wget-1.9.1/src/ftp.c	2004-06-20 22:17:48.790135746 +0200
+++ wget-1.9.1.NEW/src/ftp.c	2004-06-19 11:55:47.000000000 +0200
@@ -204,7 +204,7 @@
       logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
       if (opt.server_response)
 	logputs (LOG_ALWAYS, "\n");
-      err = ftp_login (&con->rbuf, logname, passwd);
+      err = ftp_login (&con->rbuf, logname, passwd, u);
 
       if (con->proxy)
 	xfree (logname);
diff -uNr wget-1.9.1/src/ftp.h wget-1.9.1.NEW/src/ftp.h
--- wget-1.9.1/src/ftp.h	2003-09-18 15:46:17.000000000 +0200
+++ wget-1.9.1.NEW/src/ftp.h	2004-06-19 11:56:10.000000000 +0200
@@ -47,7 +47,7 @@
 };
   
 uerr_t ftp_response PARAMS ((struct rbuf *, char **));
-uerr_t ftp_login PARAMS ((struct rbuf *, const char *, const char *));
+uerr_t ftp_login PARAMS ((struct rbuf *, const char *, const char *, struct url *));
 uerr_t ftp_port PARAMS ((struct rbuf *));
 uerr_t ftp_pasv PARAMS ((struct rbuf *, ip_address *, unsigned short *));
 #ifdef ENABLE_IPV6
diff -uNr wget-1.9.1/src/Makefile.in wget-1.9.1.NEW/src/Makefile.in
--- wget-1.9.1/src/Makefile.in	2003-10-08 01:53:31.000000000 +0200
+++ wget-1.9.1.NEW/src/Makefile.in	2004-06-20 22:18:49.740305456 +0200
@@ -77,7 +77,7 @@
       headers$o host$o html-parse$o html-url$o http$o init$o      \
       log$o main$o $(MD5_OBJ) netrc$o progress$o rbuf$o recur$o   \
       res$o retr$o safe-ctype$o snprintf$o $(SSL_OBJ) url$o       \
-      utils$o version$o
+      utils$o version$o radix$o
 
 .SUFFIXES:
 .SUFFIXES: .c .o ._c ._o
diff -uNr wget-1.9.1/src/radix.c wget-1.9.1.NEW/src/radix.c
--- wget-1.9.1/src/radix.c	1970-01-01 01:00:00.000000000 +0100
+++ wget-1.9.1.NEW/src/radix.c	2004-06-19 12:30:23.000000000 +0200
@@ -0,0 +1,164 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+static char *radixN =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static char pad = '=';
+
+int radix_encode(inbuf, outbuf, len, decode)
+unsigned char inbuf[], outbuf[];
+int *len, decode;
+{
+	int i,j,D = 0;
+	char *p;
+	unsigned char c = 0;
+
+	if (decode) {
+		for (i=0,j=0; inbuf[i] && inbuf[i] != pad; i++) {
+		    if ((p = strchr(radixN, inbuf[i])) == NULL) return(1);
+		    D = p - radixN;
+		    switch (i&3) {
+			case 0:
+			    c = D<<2;
+			    break;
+			case 1:
+			    outbuf[j++] = c | D>>4;
+			    c = (D&15)<<4;
+			    break;
+			case 2:
+			    outbuf[j++] = c | D>>2;
+			    c = (D&3)<<6;
+			    break;
+			case 3:
+			    outbuf[j++] = c | D;
+		    }
+		}
+		switch (i&3) {
+			case 1: return(3);
+			case 2: if (D&15) return(3);
+				if (strcmp((char *)&inbuf[i], "==")) return(2);
+				break;
+			case 3: if (D&3) return(3);
+				if (strcmp((char *)&inbuf[i], "="))  return(2);
+		}
+		*len = j;
+	} else {
+		for (i=0,j=0; i < *len; i++)
+		    switch (i%3) {
+			case 0:
+			    outbuf[j++] = radixN[inbuf[i]>>2];
+			    c = (inbuf[i]&3)<<4;
+			    break;
+			case 1:
+			    outbuf[j++] = radixN[c|inbuf[i]>>4];
+			    c = (inbuf[i]&15)<<2;
+			    break;
+			case 2:
+			    outbuf[j++] = radixN[c|inbuf[i]>>6];
+			    outbuf[j++] = radixN[inbuf[i]&63];
+			    c = 0;
+		    }
+		if (i%3) outbuf[j++] = radixN[c];
+		switch (i%3) {
+			case 1: outbuf[j++] = pad;
+			case 2: outbuf[j++] = pad;
+		}
+		outbuf[*len = j] = '\0';
+	}
+	return(0);
+}
+
+char *
+radix_error(e)
+int e;
+{
+	switch (e) {
+	    case 0:  return("Success");
+	    case 1:  return("Bad character in encoding");
+	    case 2:  return("Encoding not properly padded");
+	    case 3:  return("Decoded # of bits not a multiple of 8");
+	    default: return("Unknown error");
+	}
+}
+
+#ifdef STANDALONE
+usage(s)
+char *s;
+{
+	fprintf(stderr, "Usage: %s [ -d ] [ string ]\n", s);
+	exit(2);
+}
+
+static int n;
+
+putbuf(inbuf, outbuf, len, decode)
+unsigned char inbuf[], outbuf[];
+int len, decode;
+{
+	int c;
+
+	if (c = radix_encode(inbuf, outbuf, &len, decode)) {
+		fprintf(stderr, "Couldn't %scode input: %s\n",
+				decode ? "de" : "en", radix_error(c));
+		exit(1);
+	}
+	if (decode)
+		write(1, outbuf, len);
+	else
+		for (c = 0; c < len;) {
+			putchar(outbuf[c++]);
+			if (++n%76 == 0) putchar('\n');
+		}
+}
+
+main(argc,argv)
+int argc;
+char *argv[];
+{
+	unsigned char *inbuf, *outbuf;
+	int c, len = 0, decode = 0;
+	extern int optind;
+
+	while ((c = getopt(argc, argv, "d")) != -1)
+		switch(c) {
+			default:
+				usage(argv[0]);
+			case 'd':
+				decode++;
+		}
+
+	switch (argc - optind) {
+		case 0:
+			inbuf  = (unsigned char *) malloc(5);
+			outbuf = (unsigned char *) malloc(5);
+			while ((c = getchar()) != EOF)
+			    if (c != '\n') {
+				inbuf[len++] = c;
+				if (len == (decode ? 4 : 3)) {
+					inbuf[len] = '\0';
+					putbuf(inbuf, outbuf, len, decode);
+					len=0;
+				}
+			    }
+			if (len) {
+				inbuf[len] = '\0';
+				putbuf(inbuf, outbuf, len, decode);
+			}
+			break;
+		case 1:
+			inbuf = (unsigned char *)argv[optind];
+			len = strlen(inbuf);
+			outbuf = (unsigned char *)
+				malloc((len * (decode?3:4)) / (decode?4:3) + 1);
+			putbuf(inbuf, outbuf, len, decode);
+			break;
+		default:
+			fprintf(stderr, "Only one argument allowed\n");
+			usage(argv[0]);
+	}
+	if (n%76) putchar('\n');
+	exit(0);
+}
+#endif /* STANDALONE */
