diff -Naur inetutils-1.9.2-orig/ftpd/auth.c inetutils-1.9.2/ftpd/auth.c
--- inetutils-1.9.2-orig/ftpd/auth.c	2013-09-26 12:36:38.000000000 +0300
+++ inetutils-1.9.2/ftpd/auth.c	2014-12-12 11:55:12.478800000 +0300
@@ -19,6 +19,17 @@
 
 #include <config.h>
 
+#ifdef __CYGWIN__
+# undef ERROR
+# include <windows.h>
+# include <pwd.h>
+# include <sys/cygwin.h>
+# include <io.h>
+# define is_winnt      (GetVersion() < 0x80000000)
+#else
+# define is_winnt      (0)
+#endif
+
 #include <sys/types.h>
 #include <stdlib.h>
 #include <string.h>
@@ -44,6 +55,9 @@
    shell as returned by getusershell().  Disallow anyone mentioned in the file
    PATH_FTPUSERS to allow people such as root and uucp to be avoided.  */
 
+static int
+do_cygwin_auth (const char* passwd, struct credentials *pcred);
+
 int
 auth_user (const char *name, struct credentials *pcred)
 {
@@ -84,6 +98,12 @@
 	if (pcred->message == NULL)
 	  return -1;
 
+#ifdef __CYGWIN__
+	/* when running under WinNT, password is always required. */
+	if (!is_winnt)
+	{
+#endif /* __CYGWIN__ */
+
 	/* Check for anonymous log in.
 	 *
 	 * This code simulates part of `pam_ftp.so'
@@ -113,6 +133,9 @@
 	      }
 	    return err;
 	  }
+#ifdef __CYGWIN__
+	}
+#endif /* __CYGWIN__ */
 
 	if (sgetcred (name, pcred) == 0)
 	  {
@@ -184,18 +207,49 @@
     case AUTH_TYPE_PASSWD:
     default:
       {
+#ifdef __CYGWIN__
+	if (!is_winnt)
+	{
+#endif /* __CYGWIN__ */
 	char *xpasswd;
 	char *salt = pcred->passwd;
 	/* Try to authenticate the user.  */
 	if (pcred->passwd == NULL || *pcred->passwd == '\0')
 	  return 1;		/* Failed. */
-	xpasswd = crypt (passwd, salt);
+	xpasswd = (char*) crypt (passwd, salt);
 	return (!xpasswd || strcmp (xpasswd, pcred->passwd) != 0);
+#ifdef __CYGWIN__
+	} else {
+	  return  do_cygwin_auth (passwd, pcred);
+	}
+#endif /* __CYGWIN__ */
       }
     }				/* switch (auth_type) */
   return -1;
 }
 
+#ifdef __CYGWIN__
+static int
+do_cygwin_auth (const char* passwd, struct credentials *pcred)
+{
+  struct passwd *p;
+  if ((pcred == NULL) || (pcred->name == NULL) || (pcred->name[0] == '\0'))
+    return 1;
+
+  /* can't "recreate" p from contents of pcred, because
+     struct passwd might contain extension elements
+     unknown to us
+  */
+  p = getpwnam (pcred->name);
+  if (p == NULL)
+    return 1;
+
+  HANDLE hToken = (HANDLE) cygwin_logon_user (p, passwd);
+  cygwin_set_impersonation_token (hToken);
+  return (hToken == INVALID_HANDLE_VALUE); // non-zero on error
+}
+#endif /* __CYGWIN__ */
+
 int
 sgetcred (const char *name, struct credentials *pcred)
 {
diff -Naur inetutils-1.9.2-orig/ftpd/ftpcmd.y inetutils-1.9.2/ftpd/ftpcmd.y
--- inetutils-1.9.2-orig/ftpd/ftpcmd.y	2013-12-23 14:57:54.000000000 +0300
+++ inetutils-1.9.2/ftpd/ftpcmd.y	2014-12-12 11:55:12.478800000 +0300
@@ -592,7 +592,7 @@
 # endif /* BSD */
 #endif /* !HAVE_UNAME */
 
-#if defined unix || defined __unix || defined __unix__
+#if defined unix || defined __unix || defined __unix__ || defined __CYGWIN__
 			sys_type = "UNIX";
 #else
 			sys_type = "UNKNOWN";
diff -Naur inetutils-1.9.2-orig/ftpd/ftpd.c inetutils-1.9.2/ftpd/ftpd.c
--- inetutils-1.9.2-orig/ftpd/ftpd.c	2013-12-23 14:57:54.000000000 +0300
+++ inetutils-1.9.2/ftpd/ftpd.c	2014-12-12 11:55:12.478800000 +0300
@@ -113,6 +113,10 @@
 # define LOG_FTP LOG_DAEMON	/* Use generic facility.  */
 #endif
 
+#ifndef LARGE_TRANSFER_BLOCKSIZE
+# define LARGE_TRANSFER_BLOCKSIZE 4096
+#endif
+
 #ifndef MAP_FAILED
 # define MAP_FAILED (void*)-1
 #endif
@@ -445,11 +449,21 @@
   NULL
 };
 
+#if defined(WITH_WRAP) && defined(__CYGWIN__)
+extern int allow_severity; /* set value in main() */
+extern int deny_severity;  /* set value in main() */
+#endif
+
 int
 main (int argc, char *argv[], char **envp)
 {
   int index;
 
+#if defined(WITH_WRAP) && defined(__CYGWIN__)
+  allow_severity = LOG_INFO;
+  deny_severity = LOG_NOTICE;
+#endif
+
   set_program_name (argv[0]);
 
 #ifdef HAVE_TZSET
@@ -560,7 +574,7 @@
   }
 #endif
 
-#ifdef	F_SETOWN
+#if defined(F_SETOWN) && !defined(__CYGWIN__)
   if (fcntl (STDIN_FILENO, F_SETOWN, getpid ()) == -1)
     syslog (LOG_ERR, "fcntl F_SETOWN: %m");
 #endif
@@ -684,19 +698,29 @@
       /* We MUST do a chdir () after the chroot. Otherwise
          the old current directory will be accessible as "."
          outside the new root!  */
-      if (chroot (pcred->rootdir) < 0 || chdir (pcred->homedir) < 0)
+      if (chroot (pcred->rootdir) < 0)
 	{
 	  reply (550, "Can't set guest privileges.");
 	  goto bad;
 	}
+      if (chdir (pcred->homedir) < 0)
+	{
+	  reply(550, "Can't access home directory.");
+	  goto bad;
+	}
     }
   else if (pcred->dochroot)
     {
-      if (chroot (pcred->rootdir) < 0 || chdir (pcred->homedir) < 0)
+      if (chroot (pcred->rootdir) < 0)
 	{
 	  reply (550, "Can't change root.");
 	  goto bad;
 	}
+      if (chdir (pcred->homedir) < 0)
+	{
+	  reply(550, "Can't access home directory.");
+	  goto bad;
+	}
     }
 
   if (seteuid ((uid_t) pcred->uid) < 0)
@@ -862,7 +886,7 @@
   char *remotehost = pcred->remotehost;
   int atype = pcred->auth_type;
 
-  seteuid ((uid_t) 0);
+  seteuid (getuid ());
   if (pcred->logged_in)
     {
       logwtmp_keep_open (ttyline, "", "");
@@ -972,7 +996,13 @@
 
   if (cmd == 0)
     {
+#ifdef __CYGWIN__
+      if (type != TYPE_A)
+	fin = fopen (name, "rb"), closefunc = fclose;
+      else
+#else
       fin = fopen (name, "r"), closefunc = fclose;
+#endif /* __CYGWIN__ */
       st.st_size = 0;
     }
   else
@@ -1059,6 +1089,13 @@
   FILE *fout, *din;
   struct stat st;
   int (*closefunc) (FILE *);
+  char nmode[8];
+
+  strcpy (nmode, mode);
+#ifdef __CYGWIN__
+  if (type != TYPE_A)
+    strcat (nmode, "b");
+#endif
 
   if (unique && stat (name, &st) == 0)
     {
@@ -1074,8 +1111,16 @@
     }
 
   if (restart_point)
-    mode = "r+";
-  fout = fopen (name, mode);
+    {
+#ifdef __CYGWIN__
+      if (type != TYPE_A)
+	mode = "rb+";
+      else
+#endif
+	mode = "r+";
+      strcpy (nmode, mode);
+    }
+  fout = fopen (name, nmode);
   closefunc = fclose;
   if (fout == NULL || fstat (fileno (fout), &st) < 0)
     {
@@ -1151,7 +1196,7 @@
 
   if (data >= 0)
     return fdopen (data, mode);
-  seteuid ((uid_t) 0);
+  seteuid (getuid ());
   s = socket (ctrl_addr.ss_family, SOCK_STREAM, 0);
   if (s < 0)
     goto bad;
@@ -1414,7 +1459,14 @@
 	  len = filesize;
 	  do
 	    {
+#ifdef __CYGWIN__
+	      cnt = write (netfd, bp,
+		(len < LARGE_TRANSFER_BLOCKSIZE ?
+		 len : LARGE_TRANSFER_BLOCKSIZE));
+#else
 	      cnt = write (netfd, bp, len);
+#endif /* __CYGWIN__ */
+
 	      len -= cnt;
 	      bp += cnt;
 	      if (cnt > 0)
@@ -1439,6 +1491,9 @@
 	    syslog (LOG_DEBUG, "Starting at position %jd.", curpos);
 	}
 
+      if (blksize <= 0)
+	blksize = LARGE_TRANSFER_BLOCKSIZE;
+
       buf = malloc ((u_int) blksize);
       if (buf == NULL)
 	{
@@ -1978,7 +2033,7 @@
   else	/* !AF_INET6 */
     ((struct sockaddr_in *) &pasv_addr)->sin_port = 0;
 
-  seteuid ((uid_t) 0);
+  seteuid (getuid ());
   if (bind (pdata, (struct sockaddr *) &pasv_addr, pasv_addrlen) < 0)
     {
       if (seteuid ((uid_t) cred.uid))
diff -Naur inetutils-1.9.2-orig/ftpd/server_mode.c inetutils-1.9.2/ftpd/server_mode.c
--- inetutils-1.9.2-orig/ftpd/server_mode.c	2013-09-26 12:36:38.000000000 +0300
+++ inetutils-1.9.2/ftpd/server_mode.c	2014-12-12 11:55:12.478800000 +0300
@@ -58,8 +58,14 @@
 extern int hosts_ctl (char *, char *, char *, char *);
 # endif
 
+#ifdef __CYGWIN__
+/* provided by library (e.g. extern, here) on cygwin */
+extern int allow_severity; /* set value in main() */
+extern int deny_severity;  /* set value in main() */
+#else
 int allow_severity = LOG_INFO;
 int deny_severity = LOG_NOTICE;
+#endif
 
 static int
 check_host (struct sockaddr *sa, socklen_t len)
