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 +#ifdef __CYGWIN__ +# undef ERROR +# include +# include +# include +# include +# define is_winnt (GetVersion() < 0x80000000) +#else +# define is_winnt (0) +#endif + #include #include #include @@ -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)