Subject: Re: proftpd running on cygwin
From: Jason Tishler <[email-masked]>
To: TJ Saunders <[email-masked]>
Cc: Cygwin <[email-masked]>
Date: Thu, 24 Apr 2003 09:24:53 -0400

TJ,

On Wed, Apr 23, 2003 at 07:39:13PM -0700, TJ Saunders wrote:
> jason>The patch is in the following post:
> jason>
> jason>    http://cygwin.com/ml/cygwin/2003-04/msg01918.html
> jason>
> jason>Please test it and then try to get it accepted into proftp CVS.

I guess my posts to <[email-masked]> weren't rejected after
all... :,)

> Attached is your patch, updated for current CVS.  The patch is pretty
> much the same, with one minor addition (checking of uid 0 for
> RootLogin).  If this patch works for you, just let me know and I'll
> commit to CVS.

I checked out the latest proftpd CVS, applied your updated patch, built,
and tested proftpd.  The following are my observations:

1. proftpd functions properly when running under the LocalSystem user and
Administrators group

2. proftpd does not function properly running under a less privileged
user such as nobody by setting "User nobody" in proftpd.conf.  The
following error is displayed when a user attempts to log in:

          5 [win] conn 756 Winmain: Cannot create window
    c:\home\jt\src\proftp\proftpd.exe: *** WFSO failed, Win32 error 6

Unless someone is willing to debug and fix the above problem (if
possible), then my suggestion is to just document that Cygwin proftpd
must run under the LocalSystem user and Administrators group.

3. proftpd displays the following non-fatal error messages when a user
logs in:

    TISHLERJASON - error setting write fd IP_TOS: Invalid argument
    TISHLERJASON - error setting read fd IP_TOS: Invalid argument
    TISHLERJASON - error setting write fd TCP_NOPUSH: Protocol not available
    TISHLERJASON - error setting read fd TCP_NOPUSH: Protocol not available

4. proftpd complains about a world writable directory even in no daemon
mode:

    TISHLERJASON (127.0.0.1[127.0.0.1]) - error: /var/log is a world writeable directory

Note that Cygwin typically runs Unix daemons under a NT service wrapper
called cygrunsrv which exploits options such as "--nodaemon" and handles
logging.

Clearly, only 1 and 2 above are related to this patch, but I wanted to
log the other issues so that hopefully they can be addressed too.

Please commit your patch.

Thanks,
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

Subject: Re: proftpd running on cygwin
From: TJ Saunders <[email-masked]>
To: Jason Tishler <[email-masked]>
Date: Wed, 23 Apr 2003 19:39:13 -0700 (PDT)

jason>The patch is in the following post:
jason>
jason>    http://cygwin.com/ml/cygwin/2003-04/msg01918.html
jason>
jason>Please test it and then try to get it accepted into proftp CVS.

Attached is your patch, updated for current CVS.  The patch is pretty much
the same, with one minor addition (checking of uid 0 for RootLogin).  If
this patch works for you, just let me know and I'll commit to CVS.

Cheers,
TJ

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   To love is to place our happiness in the happiness of another.

   	-Gottfried Wilhelm von Leibniz

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Index: include/privs.h
===================================================================
RCS file: /cvsroot/proftp/proftpd/include/privs.h,v
retrieving revision 1.19
diff -u -r1.19 privs.h
--- include/privs.h	23 Apr 2003 06:53:22 -0000	1.19
+++ include/privs.h	24 Apr 2003 02:45:36 -0000
@@ -30,6 +30,18 @@
 #ifndef PR_PRIVS_H
 #define PR_PRIVS_H
 
+/* Definition of root user/group IDs (non-Unix platforms may have these as
+ * different from 0/0).
+ */
+
+#ifdef __CYGWIN__
+# define PR_ROOT_UID    18
+# define PR_ROOT_GID    544
+#else
+# define PR_ROOT_UID    0
+# define PR_ROOT_GID    0
+#endif /* __CYGWIN__ */
+
 /* Macros for manipulating saved, real and effective uid for easy
  * switching from/to root.
  *
@@ -75,7 +87,7 @@
 
 #  define PRIVS_SETUP(u, g) { \
     log_debug(DEBUG9, "SETUP PRIVS at %s:%d", __FILE__, __LINE__); \
-    if (getuid()) { \
+    if (getuid() != PR_ROOT_UID) { \
       session.ouid = session.uid = getuid(); \
       session.gid = getgid(); \
       if (setgid(session.gid)) \
@@ -91,7 +103,7 @@
       if (setgid(session.gid)) \
         log_pri(PR_LOG_ERR, "PRIVS_SETUP: unable to setgid(): %s", \
           strerror(errno)); \
-      if (setreuid(0, session.uid)) \
+      if (setreuid(PR_ROOT_UID, session.uid)) \
         log_pri(PR_LOG_ERR, "PRIVS_SETUP: unable to setreuid(): %s", \
           strerror(errno)); \
     } \
@@ -100,10 +112,10 @@
 #  define PRIVS_ROOT { \
     log_debug(DEBUG9, "ROOT PRIVS at %s:%d", __FILE__, __LINE__); \
     if (!session.disable_id_switching) { \
-      if (setregid(session.gid,0)) \
+      if (setregid(session.gid, PR_ROOT_GID)) \
         log_pri(PR_LOG_ERR, "PRIVS_ROOT: unable to setregid(): %s", \
           strerror(errno)); \
-      if (setreuid(session.uid, 0)) \
+      if (setreuid(session.uid, PR_ROOT_UID)) \
         log_pri(PR_LOG_ERR, "PRIVS_ROOT: unable to setreuid(): %s", \
           strerror(errno)); \
     } else \
@@ -114,8 +126,8 @@
     log_debug(DEBUG9, "USER PRIVS %d at %s:%d", (int) session.login_uid, \
       __FILE__, __LINE__); \
     if (!session.disable_id_switching) { \
-      if (setreuid(session.uid,0)) \
-        log_pri(PR_LOG_ERR, "PRIVS_USER: unable to setreuid(session.uid, 0): %s", \
+      if (setreuid(session.uid, PR_ROOT_UID)) \
+        log_pri(PR_LOG_ERR, "PRIVS_USER: unable to setreuid(session.uid, PR_ROOT_UID): %s", \
           strerror(errno)); \
       if (setreuid(session.uid, session.login_uid)) \
         log_pri(PR_LOG_ERR, "PRIVS_USER: unable to setreuid(session.uid, " \
@@ -127,18 +139,18 @@
 #  define PRIVS_RELINQUISH  { \
     log_debug(DEBUG9, "RELINQUISH PRIVS at %s:%d", __FILE__, __LINE__); \
     if (!session.disable_id_switching) { \
-      if (getegid() != 0) { \
-        if (setregid(session.gid, 0)) \
+      if (getegid() != PR_ROOT_GID) { \
+        if (setregid(session.gid, PR_ROOT_GID)) \
           log_pri(PR_LOG_ERR, "PRIVS_RELINQUISH: unable to " \
-            "setregid(session.gid, 0): %s", strerror(errno)); \
+            "setregid(session.gid, PR_ROOT_GID): %s", strerror(errno)); \
       } \
       if (setregid(session.gid, session.gid)) \
         log_pri(PR_LOG_ERR, "PRIVS_RELINQUISH: unable to setregid(session.jid, " \
           "session.gid): %s", strerror(errno)); \
-      if (geteuid() != 0) { \
-        if (setreuid(session.uid, 0)) \
+      if (geteuid() != PR_ROOT_UID) { \
+        if (setreuid(session.uid, PR_ROOT_UID)) \
           log_pri(PR_LOG_ERR, "PRIVS_RELINQUISH: unable to " \
-            "setreuid(session.uid, 0): %s", strerror(errno)); \
+            "setreuid(session.uid, PR_ROOT_UID): %s", strerror(errno)); \
       } \
       if (setreuid(session.uid, session.uid)) \
         log_pri(PR_LOG_ERR, "PRIVS_RELINQUISH: unable to setreuid(session.uid, " \
@@ -149,8 +161,8 @@
 
 #  define PRIVS_REVOKE { \
     log_debug(DEBUG9, "REVOKE PRIVS at %s:%d", __FILE__, __LINE__); \
-    if (setreuid(0, 0)) \
-      log_pri(PR_LOG_ERR, "PRIVS_REVOKE: unable to setreuid(0, 0): %s", \
+    if (setreuid(PR_ROOT_UID, PR_ROOT_UID)) \
+      log_pri(PR_LOG_ERR, "PRIVS_REVOKE: unable to setreuid(PR_ROOT_UID, PR_ROOT_UID): %s", \
         strerror(errno)); \
     if (setgid(session.gid)) \
       log_pri(PR_LOG_ERR, "PRIVS_REVOKE: unable to setgid(): %s", \
@@ -174,7 +186,7 @@
 
 #  define PRIVS_SETUP(u, g) { \
     log_debug(DEBUG9, "SETUP PRIVS at %s:%d", __FILE__, __LINE__); \
-    if (getuid()) { \
+    if (getuid() != PR_ROOT_UID) { \
       session.ouid = session.uid = getuid(); \
       session.gid = getgid(); \
       if (setgid(session.gid)) \
@@ -190,7 +202,7 @@
       session.ouid = getuid(); \
       session.uid = (u); \
       session.gid = (g); \
-      if (setuid(0)) \
+      if (setuid(PR_ROOT_UID)) \
         log_pri(PR_LOG_ERR, "PRIVS_SETUP: unable to setuid(): %s", \
           strerror(errno)); \
       if (setgid((g))) \
@@ -207,10 +219,10 @@
 #  define PRIVS_ROOT \
   if (!session.disable_id_switching) { \
     log_debug(DEBUG9, "ROOT PRIVS at %s:%d", __FILE__, __LINE__); \
-    if (seteuid(0)) \
+    if (seteuid(PR_ROOT_UID)) \
       log_pri(PR_LOG_ERR, "PRIVS_ROOT: unable to seteuid(): %s", \
         strerror(errno)); \
-    if (setegid(0)) \
+    if (setegid(PR_ROOT_UID)) \
       log_pri(PR_LOG_ERR, "PRIVS_ROOT: unable to setegid(): %s", \
         strerror(errno)); \
   } else \
@@ -220,14 +232,14 @@
  */
 #  define PRIVS_USER \
   if (!session.disable_id_switching) { \
-    if (session.login_uid == 0) { \
+    if (session.login_uid == PR_ROOT_UID) { \
       log_debug(DEBUG1, "Use of PRIVS_USER before session.login_uid set " \
         "in %s %d", __FILE__, __LINE__); \
     } else { \
       log_debug(DEBUG9, "USER PRIVS %d at %s:%d", (int) session.login_uid, \
         __FILE__, __LINE__); \
-      if (seteuid(0)) \
-        log_pri(PR_LOG_ERR, "PRIVS_USER: unable to seteuid(0): %s", \
+      if (seteuid(PR_ROOT_UID)) \
+        log_pri(PR_LOG_ERR, "PRIVS_USER: unable to seteuid(PR_ROOT_UID): %s", \
           strerror(errno)); \
       if (seteuid(session.login_uid)) \
         log_pri(PR_LOG_ERR, "PRIVS_USER: unable to seteuid(session.login_uid): " \
@@ -240,9 +252,9 @@
  */
 #  define PRIVS_RELINQUISH \
   if (!session.disable_id_switching) { \
-    if (geteuid() != 0) { \
-      if (seteuid(0)) \
-        log_pri(PR_LOG_ERR, "PRIVS_RELINQUISH: unable to seteuid(0): %s", \
+    if (geteuid() != PR_ROOT_UID) { \
+      if (seteuid(PR_ROOT_UID)) \
+        log_pri(PR_LOG_ERR, "PRIVS_RELINQUISH: unable to seteuid(PR_ROOT_UID): %s", \
           strerror(errno)); \
     } \
     log_debug(DEBUG9, "RELINQUISH PRIVS at %s:%d", __FILE__, __LINE__); \
@@ -259,7 +271,7 @@
  */
 #  define PRIVS_REVOKE { \
     log_debug(DEBUG9, "REVOKE PRIVS at %s:%d", __FILE__, __LINE__); \
-    if (seteuid(0)) \
+    if (seteuid(PR_ROOT_UID)) \
       log_pri(PR_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.148
diff -u -r1.148 mod_auth.c
--- modules/mod_auth.c	23 Apr 2003 06:53:23 -0000	1.148
+++ modules/mod_auth.c	24 Apr 2003 02:45:36 -0000
@@ -763,7 +763,7 @@
    */
   pw = passwd_dup(p, pw);
 
-  if (pw->pw_uid == 0) {
+  if (pw->pw_uid == PR_ROOT_UID) {
     unsigned char *root_allow = NULL;
 
     /* If RootLogin is set to true, we allow this... even though we
@@ -1012,8 +1012,8 @@
     setresuid(0, 0, 0);
     setresgid(0, 0, 0);
 # else
-    setuid(0);
-    setgid(0);
+    setuid(PR_ROOT_UID);
+    setgid(PR_ROOT_GID);
 # endif /* __hpux */
 #endif /* PR_DEVEL_COREDUMP */
 
@@ -1044,8 +1044,8 @@
     setresuid(0, 0, 0);
     setresgid(0, 0, 0);
 # else
-    setuid(0);
-    setgid(0);
+    setuid(PR_ROOT_UID);
+    setgid(PR_ROOT_GID);
 # endif /* __hpux */
 #endif /* PR_DEVEL_COREDUMP */
 
@@ -1249,8 +1249,8 @@
   PRIVS_ROOT
 
 # ifndef PR_DEVEL_COREDUMP
-  setuid(0);
-  setgid(0);
+  setuid(PR_ROOT_UID);
+  setgid(PR_ROOT_GID);
 # endif /* PR_DEVEL_COREDUMP */
 
   PRIVS_SETUP(pw->pw_uid, pw->pw_gid)
Index: src/main.c
===================================================================
RCS file: /cvsroot/proftp/proftpd/src/main.c,v
retrieving revision 1.178
diff -u -r1.178 main.c
--- src/main.c	23 Apr 2003 06:53:23 -0000	1.178
+++ src/main.c	24 Apr 2003 02:45:36 -0000
@@ -2615,17 +2615,16 @@
     if (uid)
       daemon_uid = *uid;
     else
-      daemon_uid = 0;
+      daemon_uid = PR_ROOT_UID;
 
     if (gid)
       daemon_gid = *gid;
     else
-      daemon_gid = 0;
+      daemon_gid = PR_ROOT_GID;
   }
 
-  if (daemon_uid) {
-    /* allocate space for daemon supplemental groups
-     */
+  if (daemon_uid != PR_ROOT_UID) {
+    /* Allocate space for daemon supplemental groups. */
     daemon_gids = make_array(permanent_pool, 2, sizeof(gid_t));
 
     if (auth_getgroups(permanent_pool, (const char *) get_param_ptr(
--
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/