]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/filedir.c
CNID/DID patch from Uwe Hees (moderately tested)
[netatalk.git] / etc / afpd / filedir.c
index ead729e7c52337e43b252b51b1fa9d9e4604681b..5d5e0b24d8e9ac0408ff0d1564eb7e21bdb0f40f 100644 (file)
@@ -1,11 +1,13 @@
 /*
+ * $Id: filedir.c,v 1.11 2001-08-14 14:00:10 rufustfirefly Exp $
+ *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
+#endif /* HAVE_CONFIG_H */
 
 #include <errno.h>
 #include <sys/syslog.h>
 #include <atalk/adouble.h>
 #include <atalk/afp.h>
 #include <atalk/util.h>
+#ifdef CNID_DB
 #include <atalk/cnid.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
+#ifdef HAVE_FCNTL_H
 #include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
 #include <dirent.h>
 #include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
 
 #include "directory.h"
 #include "desktop.h"
 #include "globals.h"
 #include "filedir.h"
 
+int matchfile2dirperms(upath, vol, did)
+                              /* Since it's kinda' big; I decided against an
+                              inline function */
+    char       *upath;
+    struct vol  *vol;
+    int                did;
+  /* The below code changes the way file ownership is determined in the name of
+  fixing dropboxes.  It has known security problem.  See the netatalk FAQ for
+  more information */
+{
+    struct stat        st, sb;
+    struct dir *dir;
+    char       adpath[50];
+    int                uid;
+
+#ifdef DEBUG
+    syslog (LOG_INFO, "begin matchfile2dirperms:");
+#endif /* DEBUG */
+
+    if (stat(upath, &st ) < 0)
+      syslog(LOG_ERR, "Could not stat %s: %m", upath);
+    strcpy (adpath, "./.AppleDouble/");
+    strcat (adpath, upath);
+    if (( dir = dirsearch( vol, did )) == NULL ) {
+      syslog (LOG_ERR, "matchfile2dirperms: Unable to get directory info.");
+      return( AFPERR_NOOBJ );
+    }
+    else if (stat(".", &sb) < 0) {
+        syslog (LOG_ERR, 
+          "matchfile2dirperms: Error checking directory \"%s\": %m", 
+          dir->d_name);
+        return(AFPERR_NOOBJ );
+      }
+    else {
+       uid=geteuid();
+       if ( uid != sb.st_uid )
+        {
+         seteuid(0);
+         if (lchown(upath, sb.st_uid, sb.st_gid) < 0)
+          {
+            syslog (LOG_ERR, 
+             "matchfile2dirperms: Error changing owner/gid of %s: %m", upath);
+            return (AFPERR_ACCESS);
+          }
+          if (chmod(upath,(st.st_mode&0x0FFFF)| S_IRGRP| S_IROTH) < 0)
+          {
+            syslog (LOG_ERR, 
+             "matchfile2dirperms:  Error adding file read permissions: %m");
+            return (AFPERR_ACCESS);
+          }
+#ifdef DEBUG
+          else 
+           syslog (LOG_INFO, 
+             "matchfile2dirperms:  Added S_IRGRP and S_IROTH: %m");
+#endif /* DEBUG */
+          if (lchown(adpath, sb.st_uid, sb.st_gid) < 0)
+          {
+           syslog (LOG_ERR, 
+             "matchfile2dirperms: Error changing AppleDouble owner/gid %s: %m",
+             adpath);
+            return (AFPERR_ACCESS);
+         }
+          if (chmod(adpath, (st.st_mode&0x0FFFF)| S_IRGRP| S_IROTH) < 0)
+          {
+            syslog (LOG_ERR, 
+             "matchfile2dirperms:  Error adding AD file read permissions: %m");
+            return (AFPERR_ACCESS);
+          }
+#ifdef DEBUG
+          else 
+           syslog (LOG_INFO, 
+             "matchfile2dirperms:  Added S_IRGRP and S_IROTH to AD: %m");
+#endif /* DEBUG */
+       }
+#ifdef DEBUG
+        else
+         syslog (LOG_INFO, 
+           "matchfile2dirperms: No ownership change necessary.");
+#endif /* DEBUG */
+    } /* end else if stat success */
+    seteuid(uid); /* Restore process ownership to normal */
+#ifdef DEBUG
+    syslog (LOG_INFO, "end matchfile2dirperms:");
+#endif /* DEBUG */
+
+    return (AFP_OK);
+
+}
+    
+
 int afp_getfildirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
     AFPObj      *obj;
     char       *ibuf, *rbuf;
@@ -44,6 +143,10 @@ int afp_getfildirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
     char               *path;
     u_int16_t          fbitmap, dbitmap, vid;
 
+#ifdef DEBUG
+    syslog(LOG_INFO, "begin afp_getfildirparams:");
+#endif /* DEBUG */
+
     *rbuflen = 0;
     ibuf += 2;
 
@@ -100,6 +203,10 @@ int afp_getfildirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
     rbuf += sizeof( dbitmap ) + sizeof( u_char );
     *rbuf = 0;
 
+#ifdef DEBUG
+    syslog(LOG_INFO, "end afp_getfildirparams:");
+#endif /* DEBUG */
+
     return( AFP_OK );
 }
 
@@ -115,6 +222,10 @@ int afp_setfildirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
     u_int16_t  vid, bitmap;
     int                did, rc;
 
+#ifdef DEBUG
+    syslog(LOG_INFO, "begin afp_setfildirparams:");
+#endif /* DEBUG */
+
     *rbuflen = 0;
     ibuf += 2;
     memcpy( &vid, ibuf, sizeof(vid));
@@ -161,6 +272,11 @@ int afp_setfildirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
     if ( rc == AFP_OK ) {
        setvoltime(obj, vol );
     }
+
+#ifdef DEBUG
+    syslog(LOG_INFO, "end afp_setfildirparams:");
+#endif /* DEBUG */
+
     return( rc );
 }
 
@@ -178,9 +294,13 @@ int afp_rename(obj, ibuf, ibuflen, rbuf, rbuflen )
     u_int32_t          did;
     int                        plen;
     u_int16_t          vid;
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
     cnid_t              id;
-#endif
+#endif /* CNID_DB */
+
+#ifdef DEBUG
+    syslog(LOG_INFO, "begin afp_rename:");
+#endif /* DEBUG */
 
     *rbuflen = 0;
     ibuf += 2;
@@ -226,7 +346,7 @@ int afp_rename(obj, ibuf, ibuflen, rbuf, rbuflen )
     if ( strcasecmp( path, ibuf ) == 0 ) {
        return( AFP_OK );
     }
-#endif notdef
+#endif /* notdef */
 
     /* if a curdir/newname ofork exists, return busy */
     if (of_findname(vol, curdir, ibuf))
@@ -257,9 +377,9 @@ int afp_rename(obj, ibuf, ibuflen, rbuf, rbuflen )
 
     upath = mtoupath(vol, path);
 
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
     id = cnid_get(vol->v_db, curdir->d_did, upath, strlen(upath));
-#endif
+#endif /* CNID_DB */
 
     if ( rename( upath, newpath ) < 0 ) {
        switch ( errno ) {
@@ -272,11 +392,11 @@ int afp_rename(obj, ibuf, ibuflen, rbuf, rbuflen )
        }
     }
 
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
     if (stat(newpath, &st) < 0) /* this shouldn't fail */
       return AFPERR_MISC;
     cnid_update(vol->v_db, id, &st, curdir->d_did, newpath, strlen(newpath));
-#endif
+#endif /* CNID_DB */
 
     if ( !odir ) {
         newadpath = obj->newtmp;
@@ -332,6 +452,10 @@ out:
     if (of_rename(vol, curdir, path, curdir, ibuf) < 0)
        return AFPERR_MISC;
 
+#ifdef DEBUG
+    syslog(LOG_INFO, "end afp_rename:");
+#endif /* DEBUG */
+
     return( AFP_OK );
 }
 
@@ -347,6 +471,10 @@ int afp_delete(obj, ibuf, ibuflen, rbuf, rbuflen )
     int                        did, rc;
     u_int16_t          vid;
 
+#ifdef DEBUG
+    syslog(LOG_INFO, "begin afp_delete:");
+#endif /* DEBUG */ 
+
     *rbuflen = 0;
     ibuf += 2;
 
@@ -374,14 +502,19 @@ int afp_delete(obj, ibuf, ibuflen, rbuf, rbuflen )
     } else if (of_findname(vol, curdir, path)) {
         rc = AFPERR_BUSY;
     } else if ((rc = deletefile( upath = mtoupath(vol, path ))) == AFP_OK) {
-#if AD_VERSION > AD_VERSION1 /* get rid of entry */
+#ifdef CNID_DB /* get rid of entry */
         cnid_t id = cnid_get(vol->v_db, curdir->d_did, upath, strlen(upath));
        cnid_delete(vol->v_db, id);
-#endif
+#endif /* CNID_DB */
     }
     if ( rc == AFP_OK ) {
        setvoltime(obj, vol );
     }
+
+#ifdef DEBUG
+    syslog(LOG_INFO, "end afp_delete:");
+#endif /* DEBUG */
+
     return( rc );
 }
 
@@ -430,9 +563,16 @@ int afp_moveandrename(obj, ibuf, ibuflen, rbuf, rbuflen )
     int                did, rc;
     int                plen;
     u_int16_t  vid;
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
     cnid_t      id;
-#endif
+#endif /* CNID_DB */
+#ifdef DROPKLUDGE
+    int                retvalue;
+#endif /* DROPKLUDGE */
+
+#ifdef DEBUG
+    syslog(LOG_INFO, "begin afp_moveandrename:");
+#endif /* DEBUG */
 
     *rbuflen = 0;
     ibuf += 2;
@@ -468,19 +608,19 @@ int afp_moveandrename(obj, ibuf, ibuflen, rbuf, rbuflen )
         /* not a directory */
        strcpy(newname, path);
        strcpy(oldname, path); /* an extra copy for of_rename */
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
        p = mtoupath(vol, path);
        id = cnid_get(vol->v_db, sdir->d_did, p, strlen(p));
-#endif
+#endif /* CNID_DB */
        p = ctoupath( vol, sdir, newname );
     } else {
        odir = curdir;
        strcpy( newname, odir->d_name );
-       strcpy(oldname, odir->d_name); 
+       strcpy(oldname, odir->d_name);
        p = ctoupath( vol, odir->d_parent, newname );
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
        id = curdir->d_did; /* we already have the CNID */
-#endif
+#endif /* CNID_DB */
     }
     /*
      * p now points to the full pathname of the source fs object.
@@ -544,17 +684,30 @@ int afp_moveandrename(obj, ibuf, ibuflen, rbuf, rbuflen )
        rc = renamedir(p, upath, odir, curdir, newname, vol_noadouble(vol));
     }
 
+#ifdef DROPKLUDGE
+    if (vol->v_flags & AFPVOL_DROPBOX) {
+        if (retvalue=matchfile2dirperms (newname, vol, did) != AFP_OK) {
+           return retvalue;
+        }
+    }
+#endif /* DROPKLUDGE */
+
     if ( rc == AFP_OK ) {
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
         /* renaming may have moved the file/dir across a filesystem */
-        if (stat(upath, &st) < 0) 
+        if (stat(upath, &st) < 0)
          return AFPERR_MISC;
-       
+
        /* fix up the catalog entry */
        cnid_update(vol->v_db, id, &st, curdir->d_did, upath, strlen(upath));
-#endif      
+#endif /* CNID_DB */
        setvoltime(obj, vol );
     }
+
+#ifdef DEBUG
+    syslog(LOG_INFO, "end afp_moveandrename:");
+#endif /* DEBUG */
+
     return( rc );
 }