]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/cnid/cnid.c
Active Directory LDAP queries for ACL support
[netatalk.git] / libatalk / cnid / cnid.c
index 4e5f088d8630425d53ffd025d7272ab90940b253..7cf3af1618d19a6de2e0cecada09936aeab90508 100644 (file)
@@ -1,6 +1,4 @@
 /* 
- * $Id: cnid.c,v 1.2 2005-04-28 20:49:57 bfernhomberg Exp $
- *
  * Copyright (c) 2003 the Netatalk Team
  * Copyright (c) 2003 Rafal Lewczuk <rlewczuk@pronet.pl>
  * 
 #include <atalk/list.h>
 #include <atalk/logger.h>
 #include <atalk/util.h>
+#include <atalk/compat.h>
 
 /* List of all registered modules. */
 static struct list_head modules = ATALK_LIST_HEAD_INIT(modules);
 
 static sigset_t sigblockset;
 static const struct itimerval none = {{0, 0}, {0, 0}};
-static struct itimerval savetimer;
 
 /* Registers new CNID backend module. */
 
@@ -93,14 +91,15 @@ static int cnid_dir(const char *dir, mode_t mask)
 }
 
 /* Opens CNID database using particular back-end */
-struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags)
+struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags,
+                           const char *cnidsrv, const char *cnidport)
 {
     struct _cnid_db *db;
     cnid_module *mod = NULL;
     struct list_head *ptr;
-    uid_t uid;  /* uninitialized, OK 310105 */
-    gid_t gid;
-    
+    uid_t uid = -1;  
+    gid_t gid = -1;
+
     list_for_each(ptr, &modules) {
         if (0 == strcmp(list_entry(ptr, cnid_module, db_list)->name, type)) {
            mod = list_entry(ptr, cnid_module, db_list);
@@ -113,7 +112,7 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla
         return NULL;
     }
 
-    if ((mod->flags & CNID_FLAG_SETUID)) {
+    if ((mod->flags & CNID_FLAG_SETUID) && !(flags & CNID_FLAG_MEMORY)) {
         uid = geteuid();
         gid = getegid();
         if (seteuid(0)) {
@@ -129,9 +128,10 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla
         }
     }
 
-    db = mod->cnid_open(volpath, mask);
+    struct cnid_open_args args = {volpath, mask, flags, cnidsrv, cnidport};
+    db = mod->cnid_open(&args);
 
-    if ((mod->flags & CNID_FLAG_SETUID)) {
+    if ((mod->flags & CNID_FLAG_SETUID) && !(flags & CNID_FLAG_MEMORY)) {
         seteuid(0);
         if ( setegid(gid) < 0 || seteuid(uid) < 0) {
             LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno));
@@ -144,7 +144,7 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla
         return NULL;
     }
     /* FIXME should module know about it ? */
-    if (flags) {
+    if ((flags & CNID_FLAG_NODEV)) {
         db->flags |= CNID_FLAG_NODEV;
     }
     db->flags |= mod->flags;
@@ -154,6 +154,7 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla
         sigaddset(&sigblockset, SIGTERM);
         sigaddset(&sigblockset, SIGHUP);
         sigaddset(&sigblockset, SIGUSR1);
+        sigaddset(&sigblockset, SIGUSR2);
         sigaddset(&sigblockset, SIGALRM);
     }
 
@@ -161,27 +162,45 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla
 }
 
 /* ------------------- */
-static void block_signal( u_int32_t flags)
+static void block_signal(uint32_t flags)
 {
     if ((flags & CNID_FLAG_BLOCK)) {
-        sigprocmask(SIG_BLOCK, &sigblockset, NULL);
-        setitimer(ITIMER_REAL, &none, &savetimer);
+        pthread_sigmask(SIG_BLOCK, &sigblockset, NULL);
     }
 }
 
 /* ------------------- */
-static void unblock_signal(u_int32_t flags)
+static void unblock_signal(uint32_t flags)
 {
     if ((flags & CNID_FLAG_BLOCK)) {
-        setitimer(ITIMER_REAL, &savetimer, NULL);
-        sigprocmask(SIG_UNBLOCK, &sigblockset, NULL);
+        pthread_sigmask(SIG_UNBLOCK, &sigblockset, NULL);
+    }
+}
+
+/* ------------------- 
+  protect against bogus value from the DB.
+  adddir really doesn't like 2
+*/
+static cnid_t valide(cnid_t id)
+{
+  if (id == CNID_INVALID)
+      return id;
+      
+  if (id < CNID_START) {
+    static int err = 0;
+    if (!err) {
+        err = 1;
+        LOG(log_error, logtype_afpd, "Error: Invalid cnid, corrupted DB?");
     }
+    return CNID_INVALID;
+  }
+  return id;
 }
 
 /* Closes CNID database. Currently it's just a wrapper around db->cnid_close(). */
 void cnid_close(struct _cnid_db *db)
 {
-u_int32_t flags;
+    uint32_t flags;
 
     if (NULL == db) {
         LOG(log_error, logtype_afpd, "Error: cnid_close called with NULL argument !");
@@ -196,12 +215,15 @@ u_int32_t flags;
 
 /* --------------- */
 cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, 
-                       char *name, const int len, cnid_t hint)
+                const char *name, const size_t len, cnid_t hint)
 {
-cnid_t ret;
+    cnid_t ret;
+
+    if (len == 0)
+        return CNID_INVALID;
 
     block_signal(cdb->flags);
-    ret = cdb->cnid_add(cdb, st, did, name, len, hint);
+    ret = valide(cdb->cnid_add(cdb, st, did, name, len, hint));
     unblock_signal(cdb->flags);
     return ret;
 }
@@ -219,18 +241,18 @@ int ret;
 
 
 /* --------------- */
-cnid_t cnid_get(struct _cnid_db *cdb, const cnid_t did, char *name,const int len)
+cnid_t cnid_get(struct _cnid_db *cdb, const cnid_t did, char *name,const size_t len)
 {
 cnid_t ret;
 
     block_signal(cdb->flags);
-    ret = cdb->cnid_get(cdb, did, name, len);
+    ret = valide(cdb->cnid_get(cdb, did, name, len));
     unblock_signal(cdb->flags);
     return ret;
 }
 
 /* --------------- */
-int cnid_getstamp(struct _cnid_db *cdb,  void *buffer, const int len)
+int cnid_getstamp(struct _cnid_db *cdb,  void *buffer, const size_t len)
 {
 cnid_t ret;
 time_t t;
@@ -252,30 +274,50 @@ time_t t;
 
 /* --------------- */
 cnid_t cnid_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
-                       char *name, const int len)
+                   char *name, const size_t len)
 {
-cnid_t ret;
+    cnid_t ret;
 
     block_signal(cdb->flags);
-    ret = cdb->cnid_lookup(cdb, st, did, name, len);
+    ret = valide(cdb->cnid_lookup(cdb, st, did, name, len));
     unblock_signal(cdb->flags);
     return ret;
 }
 
 /* --------------- */
-char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, u_int32_t len)
+int cnid_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen)
+{
+    int ret;
+    
+    if (cdb->cnid_find == NULL) {
+        LOG(log_error, logtype_cnid, "cnid_find not supported by CNID backend");        
+        return -1;
+    }
+
+    block_signal(cdb->flags);
+    ret = cdb->cnid_find(cdb, name, namelen, buffer, buflen);
+    unblock_signal(cdb->flags);
+    return ret;
+}
+
+/* --------------- */
+char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len)
 {
 char *ret;
 
     block_signal(cdb->flags);
     ret = cdb->cnid_resolve(cdb, id, buffer, len);
     unblock_signal(cdb->flags);
+    if (ret && !strcmp(ret, "..")) {
+        LOG(log_error, logtype_afpd, "cnid_resolve: name is '..', corrupted db? ");
+        ret = NULL;
+    }
     return ret;
 }
 
 /* --------------- */
 int cnid_update   (struct _cnid_db *cdb, const cnid_t id, const struct stat *st, 
-                       const cnid_t did, char *name, const int len)
+                       const cnid_t did, char *name, const size_t len)
 {
 int ret;
 
@@ -287,7 +329,7 @@ int ret;
                        
 /* --------------- */
 cnid_t cnid_rebuild_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
-                       const char *name, const int len, cnid_t hint)
+                       char *name, const size_t len, cnid_t hint)
 {
 cnid_t ret;
 
@@ -296,3 +338,15 @@ cnid_t ret;
     unblock_signal(cdb->flags);
     return ret;
 }
+
+/* --------------- */
+int cnid_wipe(struct _cnid_db *cdb)
+{
+    int ret = 0;
+
+    block_signal(cdb->flags);
+    if (cdb->cnid_wipe)
+        ret = cdb->cnid_wipe(cdb);
+    unblock_signal(cdb->flags);
+    return ret;
+}