proftpd (and vsftpd too)

Jason Tishler jason@tishler.net
Wed Apr 23 15:47:00 GMT 2003


Gerrit,

On Tue, Apr 22, 2003 at 07:51:56AM -0400, Jason Tishler wrote:
> On Tue, Apr 22, 2003 at 07:18:11AM +0200, Gerrit P. Haase wrote:
> > Lets see what Jason figured out.
> 
> [snip]
>
> I very quickly got passed the NT authentication part thanks to
> leveraging off of Corinna's inetutils work.  Unfortunately, I had a
> *lot* of trouble and spent *way* too much time trying to get proftpd
> to function properly after switching users.
> 
> For some reason after proftpd switched users, operation like ls and
> get/put would fail with strange errors (e.g., socket operation on a
> non-socket).
> [snip]

I finally found the error of my ways -- I was using system (i.e., 18)
for root's gid instead of administrators (i.e., 544).  This caused all
kinds of problems after proftpd executed a setgid(ROOT_GID).

> I can post my proftpd "patch" from my very stale CVS working
> directory.  Do you want it?

See attached.  Note that you can ignore the mod_unixpw.c hunks since you
indicated that you have already completed this part of the port.

Jason

-- 
PGP/GPG Key: http://www.tishler.net/jason/pubkey.asc or key servers
Fingerprint: 7A73 1405 7F2B E669 C19D  8784 1AFD E4CC ECF4 8EF6
-------------- next part --------------
Index: include/privs.h
===================================================================
RCS file: /cvsroot/proftp/proftpd/include/privs.h,v
retrieving revision 1.11
diff -u -p -r1.11 privs.h
--- include/privs.h	28 Sep 2002 02:01:47 -0000	1.11
+++ include/privs.h	23 Apr 2003 11:40:52 -0000
@@ -45,6 +45,14 @@
  * doing this in here:
  */
 
+#ifdef __CYGWIN__
+#define ROOT_UID 18
+#define ROOT_GID 544
+#else
+#define ROOT_UID 0
+#define ROOT_GID 0
+#endif
+
 #ifdef __hpux
 #define setreuid(x,y) setresuid(x,y,0)
 #endif
@@ -147,7 +155,7 @@
 #define PRIVS_SETUP(u, g) \
   { \
     log_debug(DEBUG8, "SETUP PRIVS at %s:%d", __FILE__, __LINE__); \
-    if (getuid()) { \
+    if (getuid() != ROOT_UID) { \
       session.ouid = session.uid = getuid(); \
       session.gid = getgid(); \
       if (setgid(session.gid)) \
@@ -163,7 +171,7 @@
       session.ouid = getuid(); \
       session.uid = (u); \
       session.gid = (g); \
-      if (setuid(0)) \
+      if (setuid(ROOT_UID)) \
         log_pri(LOG_ERR, "PRIVS_SETUP: unable to setuid(): %s", \
           strerror(errno)); \
       if (setgid((g))) \
@@ -180,7 +188,7 @@
 #define PRIVS_ROOT \
   if (!session.disable_id_switching) { \
     log_debug(DEBUG8, "ROOT PRIVS at %s:%d", __FILE__, __LINE__); \
-    if (seteuid(0)) \
+    if (seteuid(ROOT_UID)) \
       log_pri(LOG_ERR, "PRIVS_ROOT: unable to seteuid(): %s", \
         strerror(errno)); \
   }
@@ -189,14 +197,14 @@
  */
 #define PRIVS_USER \
   if (!session.disable_id_switching) { \
-    if (session.login_uid == 0) { \
+    if (session.login_uid == ROOT_UID) { \
       log_debug(DEBUG1, "Use of PRIVS_USER before session.login_uid set " \
         "in %s %d", __FILE__, __LINE__); \
     } else { \
       log_debug(DEBUG8, "USER PRIVS %d at %s:%d", (int) session.login_uid, \
         __FILE__, __LINE__); \
-      if (seteuid(0)) \
-        log_pri(LOG_ERR, "PRIVS_USER: unable to seteuid(0): %s", \
+      if (seteuid(ROOT_UID)) \
+        log_pri(LOG_ERR, "PRIVS_USER: unable to seteuid(ROOT_UID): %s", \
           strerror(errno)); \
       if (seteuid(session.login_uid)) \
         log_pri(LOG_ERR, "PRIVS_USER: unable to seteuid(session.login_uid): " \
@@ -208,9 +216,9 @@
  */
 #define PRIVS_RELINQUISH \
   if (!session.disable_id_switching) { \
-    if (geteuid() != 0) { \
-      if (seteuid(0)) \
-        log_pri(LOG_ERR, "PRIVS_RELINQUISH: unable to seteuid(0): %s", \
+    if (geteuid() != ROOT_UID) { \
+      if (seteuid(ROOT_UID)) \
+        log_pri(LOG_ERR, "PRIVS_RELINQUISH: unable to seteuid(ROOT_UID): %s", \
           strerror(errno)); \
     } \
     log_debug(DEBUG8, "RELINQUISH PRIVS at %s:%d", __FILE__, __LINE__); \
@@ -224,7 +232,7 @@
 #define PRIVS_REVOKE \
   { \
     log_debug(DEBUG8, "REVOKE PRIVS at %s:%d", __FILE__, __LINE__); \
-    if (seteuid(0)) \
+    if (seteuid(ROOT_UID)) \
       log_pri(LOG_ERR, "PRIVS_REVOKE: unable to seteuid(): %s", \
         strerror(errno)); \
     if (setgid(session.gid)) \
Index: modules/mod_auth.c
===================================================================
RCS file: /cvsroot/proftp/proftpd/modules/mod_auth.c,v
retrieving revision 1.101
diff -u -p -r1.101 mod_auth.c
--- modules/mod_auth.c	5 Nov 2002 19:06:57 -0000	1.101
+++ modules/mod_auth.c	23 Apr 2003 11:40:54 -0000
@@ -890,8 +890,8 @@ static int _setup_environment(pool *p, c
     setresuid(0,0,0);
     setresgid(0,0,0);
 #else
-    setuid(0);
-    setgid(0);
+    setuid(ROOT_UID);
+    setgid(ROOT_GID);
 #endif
     PRIVS_SETUP(pw->pw_uid, pw->pw_gid)
 
@@ -919,8 +919,8 @@ static int _setup_environment(pool *p, c
     setresuid(0,0,0);
     setresgid(0,0,0);
 #else
-    setuid(0);
-    setgid(0);
+    setuid(ROOT_UID);
+    setgid(ROOT_GID);
 #endif
     PRIVS_SETUP(daemon_uid, daemon_gid)
 
@@ -1113,8 +1113,8 @@ static int _setup_environment(pool *p, c
 
   PRIVS_ROOT
 
-  setuid(0);
-  setgid(0);
+  setuid(ROOT_UID);
+  setgid(ROOT_GID);
 
   PRIVS_SETUP(pw->pw_uid, pw->pw_gid)
 
Index: modules/mod_unixpw.c
===================================================================
RCS file: /cvsroot/proftp/proftpd/modules/Attic/mod_unixpw.c,v
retrieving revision 1.24
diff -u -p -r1.24 mod_unixpw.c
--- modules/mod_unixpw.c	21 Oct 2002 17:06:10 -0000	1.24
+++ modules/mod_unixpw.c	23 Apr 2003 11:40:54 -0000
@@ -38,6 +38,22 @@
 #include <crypt.h>
 #endif
 
+/* Cygwin specific typedefs, defines, and prototypes.
+ */
+
+#ifdef CYGWIN
+typedef void *HANDLE;
+typedef unsigned long DWORD;
+#define INVALID_HANDLE_VALUE (HANDLE)(-1)
+#define WINAPI __stdcall
+DWORD WINAPI GetVersion(void);
+extern HANDLE cygwin_logon_user (const struct passwd *, const char *);
+extern void cygwin_set_impersonation_token (const HANDLE);
+#define is_winnt (GetVersion() < 0x80000000)
+#else
+#define is_winnt (0)
+#endif
+
 #ifdef USE_SHADOW
 #include <shadow.h>
 #endif
@@ -608,8 +624,17 @@ MODRET pw_check(cmd_rec *cmd) {
   const char *cpw = cmd->argv[0];
   const char *pw = cmd->argv[2];
 
-  if(strcmp(crypt(pw,cpw),cpw) != 0)
-    return ERROR(cmd);
+  if (is_winnt) {
+    struct passwd *entry = p_getpwnam(cmd->argv[1]);
+    HANDLE token = cygwin_logon_user(entry, pw);
+    cygwin_set_impersonation_token(token);
+    if (token == INVALID_HANDLE_VALUE)
+      return ERROR(cmd);
+  }
+  else {
+    if(strcmp(crypt(pw,cpw),cpw) != 0)
+      return ERROR(cmd);
+  }
 
   return HANDLED(cmd);
 }
Index: src/main.c
===================================================================
RCS file: /cvsroot/proftp/proftpd/src/main.c,v
retrieving revision 1.128
diff -u -p -r1.128 main.c
--- src/main.c	28 Oct 2002 16:51:50 -0000	1.128
+++ src/main.c	23 Apr 2003 11:40:56 -0000
@@ -3058,15 +3058,15 @@ int main(int argc, char *argv[], char **
     if (uid)
       daemon_uid = *uid;
     else
-      daemon_uid = 0;
+      daemon_uid = ROOT_UID;
  
     if (gid)
       daemon_gid = *gid;
     else
-      daemon_gid = 0;
+      daemon_gid = ROOT_GID;
   }
 
-  if (daemon_uid) {
+  if (daemon_uid != ROOT_UID) {
     /* allocate space for daemon supplemental groups
      */
     daemon_gids = make_array(permanent_pool, 2, sizeof(gid_t));

-------------- next part --------------
--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


More information about the Cygwin mailing list