s4:ntvfs Don't attempt to follow NULL in unixuid_setup_security()
[ira/wip.git] / source4 / ntvfs / unixuid / vfs_unixuid.c
index 542b011c67d616031d39a58514724a88b8fc29bc..70ad6ee253411b15d4f8a91ca337982232ddd022 100644 (file)
@@ -8,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "system/filesys.h"
+#include "system/passwd.h"
+#include "auth/auth.h"
+#include "ntvfs/ntvfs.h"
+#include "libcli/wbclient/wbclient.h"
+#define TEVENT_DEPRECATED
+#include <tevent.h>
 
 struct unixuid_private {
-       void *samctx;
+       struct wbc_context *wbc_ctx;
        struct unix_sec_ctx *last_sec_ctx;
-       struct nt_user_token *last_token;
+       struct security_token *last_token;
 };
 
 
-/*
-  map a sid to a unix uid
-*/
-static NTSTATUS sid_to_unixuid(struct ntvfs_module_context *ntvfs,
-                              struct smbsrv_request *req, struct dom_sid *sid, uid_t *uid)
-{
-       struct unixuid_private *private = ntvfs->private_data;
-       const char *attrs[] = { "sAMAccountName", "unixID", "unixName", "sAMAccountType", NULL };
-       int ret;
-       const char *s;
-       void *ctx;
-       struct ldb_message **res;
-       const char *sidstr;
-       uint_t atype;
-
-       ctx = talloc(req, 0);
-       sidstr = dom_sid_string(ctx, sid);
-
-       ret = samdb_search(private->samctx, ctx, NULL, &res, attrs, "objectSid=%s", sidstr);
-       if (ret != 1) {
-               DEBUG(0,("sid_to_unixuid: unable to find sam record for sid %s\n", sidstr));
-               talloc_free(ctx);
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       /* make sure its a user, not a group */
-       atype = samdb_result_uint(res[0], "sAMAccountType", 0);
-       if (atype && atype != ATYPE_NORMAL_ACCOUNT) {
-               DEBUG(0,("sid_to_unixuid: sid %s is not ATYPE_NORMAL_ACCOUNT\n", sidstr));
-               talloc_free(ctx);
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       /* first try to get the uid directly */
-       s = samdb_result_string(res[0], "unixID", NULL);
-       if (s != NULL) {
-               *uid = strtoul(s, NULL, 0);
-               talloc_free(ctx);
-               return NT_STATUS_OK;
-       }
-
-       /* next try via the UnixName attribute */
-       s = samdb_result_string(res[0], "unixName", NULL);
-       if (s != NULL) {
-               struct passwd *pwd = getpwnam(s);
-               if (!pwd) {
-                       DEBUG(0,("unixName %s for sid %s does not exist as a local user\n", s, sidstr));
-                       talloc_free(ctx);
-                       return NT_STATUS_ACCESS_DENIED;
-               }
-               *uid = pwd->pw_uid;
-               talloc_free(ctx);
-               return NT_STATUS_OK;
-       }
-
-       /* finally try via the sAMAccountName attribute */
-       s = samdb_result_string(res[0], "sAMAccountName", NULL);
-       if (s != NULL) {
-               struct passwd *pwd = getpwnam(s);
-               if (!pwd) {
-                       DEBUG(0,("sAMAccountName '%s' for sid %s does not exist as a local user\n", s, sidstr));
-                       talloc_free(ctx);
-                       return NT_STATUS_ACCESS_DENIED;
-               }
-               *uid = pwd->pw_uid;
-               talloc_free(ctx);
-               return NT_STATUS_OK;
-       }
-
-       DEBUG(0,("sid_to_unixuid: no unixID, unixName or sAMAccountName for sid %s\n", sidstr));
-
-       talloc_free(ctx);
-       return NT_STATUS_ACCESS_DENIED;
-}
-
-
-/*
-  map a sid to a unix gid
-*/
-static NTSTATUS sid_to_unixgid(struct ntvfs_module_context *ntvfs,
-                              struct smbsrv_request *req, struct dom_sid *sid, gid_t *gid)
-{
-       struct unixuid_private *private = ntvfs->private_data;
-       const char *attrs[] = { "sAMAccountName", "unixID", "unixName", "sAMAccountType", NULL };
-       int ret;
-       const char *s;
-       void *ctx;
-       struct ldb_message **res;
-       const char *sidstr;
-       uint_t atype;
-
-       ctx = talloc(req, 0);
-       sidstr = dom_sid_string(ctx, sid);
-
-       ret = samdb_search(private->samctx, ctx, NULL, &res, attrs, "objectSid=%s", sidstr);
-       if (ret != 1) {
-               DEBUG(0,("sid_to_unixgid: unable to find sam record for sid %s\n", sidstr));
-               talloc_free(ctx);
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       /* make sure its not a user */
-       atype = samdb_result_uint(res[0], "sAMAccountType", 0);
-       if (atype && atype == ATYPE_NORMAL_ACCOUNT) {
-               DEBUG(0,("sid_to_unixgid: sid %s is a ATYPE_NORMAL_ACCOUNT\n", sidstr));
-               talloc_free(ctx);
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       /* first try to get the gid directly */
-       s = samdb_result_string(res[0], "unixID", NULL);
-       if (s != NULL) {
-               *gid = strtoul(s, NULL, 0);
-               talloc_free(ctx);
-               return NT_STATUS_OK;
-       }
-
-       /* next try via the UnixName attribute */
-       s = samdb_result_string(res[0], "unixName", NULL);
-       if (s != NULL) {
-               struct group *grp = getgrnam(s);
-               if (!grp) {
-                       DEBUG(0,("unixName '%s' for sid %s does not exist as a local group\n", s, sidstr));
-                       talloc_free(ctx);
-                       return NT_STATUS_ACCESS_DENIED;
-               }
-               *gid = grp->gr_gid;
-               talloc_free(ctx);
-               return NT_STATUS_OK;
-       }
-
-       /* finally try via the sAMAccountName attribute */
-       s = samdb_result_string(res[0], "sAMAccountName", NULL);
-       if (s != NULL) {
-               struct group *grp = getgrnam(s);
-               if (!grp) {
-                       DEBUG(0,("sAMAccountName '%s' for sid %s does not exist as a local group\n", s, sidstr));
-                       talloc_free(ctx);
-                       return NT_STATUS_ACCESS_DENIED;
-               }
-               *gid = grp->gr_gid;
-               talloc_free(ctx);
-               return NT_STATUS_OK;
-       }
-
-       DEBUG(0,("sid_to_unixgid: no unixID, unixName or sAMAccountName for sid %s\n", sidstr));
-
-       talloc_free(ctx);
-       return NT_STATUS_ACCESS_DENIED;
-}
 
 struct unix_sec_ctx {
        uid_t uid;
@@ -193,7 +49,7 @@ struct unix_sec_ctx {
 */
 static struct unix_sec_ctx *save_unix_security(TALLOC_CTX *mem_ctx)
 {
-       struct unix_sec_ctx *sec = talloc_p(mem_ctx, struct unix_sec_ctx);
+       struct unix_sec_ctx *sec = talloc(mem_ctx, struct unix_sec_ctx);
        if (sec == NULL) {
                return NULL;
        }
@@ -204,7 +60,7 @@ static struct unix_sec_ctx *save_unix_security(TALLOC_CTX *mem_ctx)
                talloc_free(sec);
                return NULL;
        }
-       sec->groups = talloc_array_p(sec, gid_t, sec->ngroups);
+       sec->groups = talloc_array(sec, gid_t, sec->ngroups);
        if (sec->groups == NULL) {
                talloc_free(sec);
                return NULL;
@@ -237,43 +93,131 @@ static NTSTATUS set_unix_security(struct unix_sec_ctx *sec)
        return NT_STATUS_OK;
 }
 
+static int unixuid_nesting_level;
+
+/*
+  called at the start and end of a tevent nesting loop. Needs to save/restore
+  unix security context
+ */
+static int unixuid_event_nesting_hook(struct tevent_context *ev,
+                                     void *private_data,
+                                     uint32_t level,
+                                     bool begin,
+                                     void *stack_ptr,
+                                     const char *location)
+{
+       struct unix_sec_ctx *sec_ctx;
+
+       if (unixuid_nesting_level == 0) {
+               /* we don't need to do anything unless we are nested
+                  inside of a call in this module */
+               return 0;
+       }
+
+       if (begin) {
+               sec_ctx = save_unix_security(ev);
+               if (sec_ctx == NULL) {
+                       DEBUG(0,("%s: Failed to save security context\n", location));
+                       return -1;
+               }
+               *(struct unix_sec_ctx **)stack_ptr = sec_ctx;
+               if (seteuid(0) != 0 || setegid(0) != 0) {
+                       DEBUG(0,("%s: Failed to change to root\n", location));
+                       return -1;                      
+               }
+       } else {
+               /* called when we come out of a nesting level */
+               NTSTATUS status;
+
+               sec_ctx = *(struct unix_sec_ctx **)stack_ptr;
+               if (sec_ctx == NULL) {
+                       /* this happens the first time this function
+                          is called, as we install the hook while
+                          inside an event in unixuid_connect() */
+                       return 0;
+               }
+
+               sec_ctx = talloc_get_type_abort(sec_ctx, struct unix_sec_ctx);
+               status = set_unix_security(sec_ctx);
+               talloc_free(sec_ctx);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0,("%s: Failed to revert security context (%s)\n", 
+                                location, nt_errstr(status)));
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+
 /*
-  form a unix_sec_ctx from the current nt_user_token
+  form a unix_sec_ctx from the current security_token
 */
 static NTSTATUS nt_token_to_unix_security(struct ntvfs_module_context *ntvfs,
-                                         struct smbsrv_request *req,
-                                         struct nt_user_token *token,
+                                         struct ntvfs_request *req,
+                                         struct security_token *token,
                                          struct unix_sec_ctx **sec)
 {
+       struct unixuid_private *priv = ntvfs->private_data;
        int i;
        NTSTATUS status;
-       *sec = talloc_p(req, struct unix_sec_ctx);
+       struct id_mapping *ids;
+       struct composite_context *ctx;
+       *sec = talloc(req, struct unix_sec_ctx);
 
        /* we can't do unix security without a user and group */
        if (token->num_sids < 2) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       status = sid_to_unixuid(ntvfs, req, token->user_sids[0], &(*sec)->uid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
+       ids = talloc_array(req, struct id_mapping, token->num_sids);
+       NT_STATUS_HAVE_NO_MEMORY(ids);
+
+       ids[0].unixid = NULL;
+       ids[0].sid = token->user_sid;
+       ids[0].status = NT_STATUS_NONE_MAPPED;
+
+       ids[1].unixid = NULL;
+       ids[1].sid = token->group_sid;
+       ids[1].status = NT_STATUS_NONE_MAPPED;
+
+       (*sec)->ngroups = token->num_sids - 2;
+       (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups);
+       NT_STATUS_HAVE_NO_MEMORY((*sec)->groups);
+
+       for (i=0;i<(*sec)->ngroups;i++) {
+               ids[i+2].unixid = NULL;
+               ids[i+2].sid = token->sids[i+2];
+               ids[i+2].status = NT_STATUS_NONE_MAPPED;
        }
 
-       status = sid_to_unixgid(ntvfs, req, token->user_sids[1], &(*sec)->gid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
+       ctx = wbc_sids_to_xids_send(priv->wbc_ctx, ids, token->num_sids, ids);
+       NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+       status = wbc_sids_to_xids_recv(ctx, &ids);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       if (ids[0].unixid->type == ID_TYPE_BOTH ||
+           ids[0].unixid->type == ID_TYPE_UID) {
+               (*sec)->uid = ids[0].unixid->id;
+       } else {
+               return NT_STATUS_INVALID_SID;
        }
 
-       (*sec)->ngroups = token->num_sids - 2;
-       (*sec)->groups = talloc_array_p(*sec, gid_t, (*sec)->ngroups);
-       if ((*sec)->groups == NULL) {
-               return NT_STATUS_NO_MEMORY;
+       if (ids[1].unixid->type == ID_TYPE_BOTH ||
+           ids[1].unixid->type == ID_TYPE_GID) {
+               (*sec)->gid = ids[1].unixid->id;
+       } else {
+               return NT_STATUS_INVALID_SID;
        }
 
        for (i=0;i<(*sec)->ngroups;i++) {
-               status = sid_to_unixgid(ntvfs, req, token->user_sids[i+2], &(*sec)->groups[i]);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
+               if (ids[i+2].unixid->type == ID_TYPE_BOTH ||
+                   ids[i+2].unixid->type == ID_TYPE_GID) {
+                       (*sec)->groups[i] = ids[i+2].unixid->id;
+               } else {
+                       return NT_STATUS_INVALID_SID;
                }
        }
 
@@ -284,43 +228,49 @@ static NTSTATUS nt_token_to_unix_security(struct ntvfs_module_context *ntvfs,
   setup our unix security context according to the session authentication info
 */
 static NTSTATUS unixuid_setup_security(struct ntvfs_module_context *ntvfs,
-                                      struct smbsrv_request *req, struct unix_sec_ctx **sec)
+                                      struct ntvfs_request *req, struct unix_sec_ctx **sec)
 {
-       struct unixuid_private *private = ntvfs->private_data;
-       struct nt_user_token *token = req->session->session_info->nt_user_token;
-       void *ctx = talloc(req, 0);
+       struct unixuid_private *priv = ntvfs->private_data;
+       struct security_token *token;
        struct unix_sec_ctx *newsec;
        NTSTATUS status;
 
-       *sec = save_unix_security(req);
+       /* If we are asked to set up, but have not had a successful
+        * session setup or tree connect, then these may not be filled
+        * in.  ACCESS_DENIED is the right error code here */
+       if (req->session_info == NULL || priv == NULL) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       token = req->session_info->security_token;
+
+       *sec = save_unix_security(ntvfs);
        if (*sec == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (req->session->session_info->nt_user_token == private->last_token) {
-               newsec = private->last_sec_ctx;
+       if (token == priv->last_token) {
+               newsec = priv->last_sec_ctx;
        } else {
                status = nt_token_to_unix_security(ntvfs, req, token, &newsec);
                if (!NT_STATUS_IS_OK(status)) {
-                       talloc_free(ctx);
+                       talloc_free(*sec);
                        return status;
                }
-               if (private->last_sec_ctx) {
-                       talloc_free(private->last_sec_ctx);
+               if (priv->last_sec_ctx) {
+                       talloc_free(priv->last_sec_ctx);
                }
-               private->last_sec_ctx = newsec;
-               private->last_token = req->session->session_info->nt_user_token;
-               talloc_steal(private, newsec);
+               priv->last_sec_ctx = newsec;
+               priv->last_token = token;
+               talloc_steal(priv, newsec);
        }
 
        status = set_unix_security(newsec);
        if (!NT_STATUS_IS_OK(status)) {
-               talloc_free(ctx);
+               talloc_free(*sec);
                return status;
        }
 
-       talloc_free(ctx);
-
        return NT_STATUS_OK;
 }
 
@@ -331,8 +281,12 @@ static NTSTATUS unixuid_setup_security(struct ntvfs_module_context *ntvfs,
        NTSTATUS status2; \
        struct unix_sec_ctx *sec; \
        status = unixuid_setup_security(ntvfs, req, &sec); \
-       if (NT_STATUS_IS_OK(status)) status = ntvfs_next_##op args; \
+       NT_STATUS_NOT_OK_RETURN(status); \
+       unixuid_nesting_level++; \
+       status = ntvfs_next_##op args; \
+       unixuid_nesting_level--; \
        status2 = set_unix_security(sec); \
+       talloc_free(sec); \
        if (!NT_STATUS_IS_OK(status2)) smb_panic("Unable to reset security context"); \
 } while (0)
 
@@ -342,29 +296,35 @@ static NTSTATUS unixuid_setup_security(struct ntvfs_module_context *ntvfs,
   connect to a share - used when a tree_connect operation comes in.
 */
 static NTSTATUS unixuid_connect(struct ntvfs_module_context *ntvfs,
-                               struct smbsrv_request *req, const char *sharename)
+                               struct ntvfs_request *req, union smb_tcon *tcon)
 {
-       struct unixuid_private *private;
+       struct unixuid_private *priv;
        NTSTATUS status;
 
-       private = talloc_p(req->tcon, struct unixuid_private);
-       if (!private) {
+       priv = talloc(ntvfs, struct unixuid_private);
+       if (!priv) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       private->samctx = samdb_connect(private);
-       if (private->samctx == NULL) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       priv->wbc_ctx = wbc_init(priv, ntvfs->ctx->msg_ctx,
+                                   ntvfs->ctx->event_ctx);
+       if (priv->wbc_ctx == NULL) {
+               talloc_free(priv);
+               return NT_STATUS_INTERNAL_ERROR;
        }
 
-       ntvfs->private_data = private;
-       private->last_sec_ctx = NULL;
-       private->last_token = NULL;
+       priv->last_sec_ctx = NULL;
+       priv->last_token = NULL;
+       ntvfs->private_data = priv;
+
+       tevent_loop_set_nesting_hook(ntvfs->ctx->event_ctx, 
+                                    unixuid_event_nesting_hook,
+                                    &unixuid_nesting_level);
 
        /* we don't use PASS_THRU_REQ here, as the connect operation runs with 
           root privileges. This allows the backends to setup any database
           links they might need during the connect. */
-       status = ntvfs_next_connect(ntvfs, req, sharename);
+       status = ntvfs_next_connect(ntvfs, req, tcon);
 
        return status;
 }
@@ -372,15 +332,15 @@ static NTSTATUS unixuid_connect(struct ntvfs_module_context *ntvfs,
 /*
   disconnect from a share
 */
-static NTSTATUS unixuid_disconnect(struct ntvfs_module_context *ntvfs,
-                                  struct smbsrv_tcon *tcon)
+static NTSTATUS unixuid_disconnect(struct ntvfs_module_context *ntvfs)
 {
-       struct unixuid_private *private = ntvfs->private_data;
+       struct unixuid_private *priv = ntvfs->private_data;
        NTSTATUS status;
 
-       talloc_free(private);
+       talloc_free(priv);
+       ntvfs->private_data = NULL;
 
-       status = ntvfs_next_disconnect(ntvfs, tcon);
+       status = ntvfs_next_disconnect(ntvfs);
  
        return status;
 }
@@ -390,7 +350,8 @@ static NTSTATUS unixuid_disconnect(struct ntvfs_module_context *ntvfs,
   delete a file
 */
 static NTSTATUS unixuid_unlink(struct ntvfs_module_context *ntvfs,
-                             struct smbsrv_request *req, struct smb_unlink *unl)
+                             struct ntvfs_request *req,
+                             union smb_unlink *unl)
 {
        NTSTATUS status;
 
@@ -403,7 +364,7 @@ static NTSTATUS unixuid_unlink(struct ntvfs_module_context *ntvfs,
   ioctl interface
 */
 static NTSTATUS unixuid_ioctl(struct ntvfs_module_context *ntvfs,
-                            struct smbsrv_request *req, union smb_ioctl *io)
+                            struct ntvfs_request *req, union smb_ioctl *io)
 {
        NTSTATUS status;
 
@@ -416,7 +377,8 @@ static NTSTATUS unixuid_ioctl(struct ntvfs_module_context *ntvfs,
   check if a directory exists
 */
 static NTSTATUS unixuid_chkpath(struct ntvfs_module_context *ntvfs,
-                              struct smbsrv_request *req, struct smb_chkpath *cp)
+                               struct ntvfs_request *req,
+                               union smb_chkpath *cp)
 {
        NTSTATUS status;
 
@@ -429,7 +391,7 @@ static NTSTATUS unixuid_chkpath(struct ntvfs_module_context *ntvfs,
   return info on a pathname
 */
 static NTSTATUS unixuid_qpathinfo(struct ntvfs_module_context *ntvfs,
-                                struct smbsrv_request *req, union smb_fileinfo *info)
+                                struct ntvfs_request *req, union smb_fileinfo *info)
 {
        NTSTATUS status;
 
@@ -442,7 +404,7 @@ static NTSTATUS unixuid_qpathinfo(struct ntvfs_module_context *ntvfs,
   query info on a open file
 */
 static NTSTATUS unixuid_qfileinfo(struct ntvfs_module_context *ntvfs,
-                                struct smbsrv_request *req, union smb_fileinfo *info)
+                                struct ntvfs_request *req, union smb_fileinfo *info)
 {
        NTSTATUS status;
 
@@ -456,7 +418,7 @@ static NTSTATUS unixuid_qfileinfo(struct ntvfs_module_context *ntvfs,
   set info on a pathname
 */
 static NTSTATUS unixuid_setpathinfo(struct ntvfs_module_context *ntvfs,
-                                  struct smbsrv_request *req, union smb_setfileinfo *st)
+                                  struct ntvfs_request *req, union smb_setfileinfo *st)
 {
        NTSTATUS status;
 
@@ -469,7 +431,7 @@ static NTSTATUS unixuid_setpathinfo(struct ntvfs_module_context *ntvfs,
   open a file
 */
 static NTSTATUS unixuid_open(struct ntvfs_module_context *ntvfs,
-                           struct smbsrv_request *req, union smb_open *io)
+                            struct ntvfs_request *req, union smb_open *io)
 {
        NTSTATUS status;
 
@@ -482,7 +444,7 @@ static NTSTATUS unixuid_open(struct ntvfs_module_context *ntvfs,
   create a directory
 */
 static NTSTATUS unixuid_mkdir(struct ntvfs_module_context *ntvfs,
-                            struct smbsrv_request *req, union smb_mkdir *md)
+                            struct ntvfs_request *req, union smb_mkdir *md)
 {
        NTSTATUS status;
 
@@ -495,7 +457,7 @@ static NTSTATUS unixuid_mkdir(struct ntvfs_module_context *ntvfs,
   remove a directory
 */
 static NTSTATUS unixuid_rmdir(struct ntvfs_module_context *ntvfs,
-                            struct smbsrv_request *req, struct smb_rmdir *rd)
+                            struct ntvfs_request *req, struct smb_rmdir *rd)
 {
        NTSTATUS status;
 
@@ -508,7 +470,7 @@ static NTSTATUS unixuid_rmdir(struct ntvfs_module_context *ntvfs,
   rename a set of files
 */
 static NTSTATUS unixuid_rename(struct ntvfs_module_context *ntvfs,
-                             struct smbsrv_request *req, union smb_rename *ren)
+                             struct ntvfs_request *req, union smb_rename *ren)
 {
        NTSTATUS status;
 
@@ -521,7 +483,7 @@ static NTSTATUS unixuid_rename(struct ntvfs_module_context *ntvfs,
   copy a set of files
 */
 static NTSTATUS unixuid_copy(struct ntvfs_module_context *ntvfs,
-                           struct smbsrv_request *req, struct smb_copy *cp)
+                           struct ntvfs_request *req, struct smb_copy *cp)
 {
        NTSTATUS status;
 
@@ -534,7 +496,7 @@ static NTSTATUS unixuid_copy(struct ntvfs_module_context *ntvfs,
   read from a file
 */
 static NTSTATUS unixuid_read(struct ntvfs_module_context *ntvfs,
-                           struct smbsrv_request *req, union smb_read *rd)
+                           struct ntvfs_request *req, union smb_read *rd)
 {
        NTSTATUS status;
 
@@ -547,7 +509,7 @@ static NTSTATUS unixuid_read(struct ntvfs_module_context *ntvfs,
   write to a file
 */
 static NTSTATUS unixuid_write(struct ntvfs_module_context *ntvfs,
-                            struct smbsrv_request *req, union smb_write *wr)
+                            struct ntvfs_request *req, union smb_write *wr)
 {
        NTSTATUS status;
 
@@ -560,7 +522,8 @@ static NTSTATUS unixuid_write(struct ntvfs_module_context *ntvfs,
   seek in a file
 */
 static NTSTATUS unixuid_seek(struct ntvfs_module_context *ntvfs,
-                           struct smbsrv_request *req, struct smb_seek *io)
+                            struct ntvfs_request *req,
+                            union smb_seek *io)
 {
        NTSTATUS status;
 
@@ -573,7 +536,8 @@ static NTSTATUS unixuid_seek(struct ntvfs_module_context *ntvfs,
   flush a file
 */
 static NTSTATUS unixuid_flush(struct ntvfs_module_context *ntvfs,
-                            struct smbsrv_request *req, struct smb_flush *io)
+                             struct ntvfs_request *req,
+                             union smb_flush *io)
 {
        NTSTATUS status;
 
@@ -586,7 +550,7 @@ static NTSTATUS unixuid_flush(struct ntvfs_module_context *ntvfs,
   close a file
 */
 static NTSTATUS unixuid_close(struct ntvfs_module_context *ntvfs,
-                            struct smbsrv_request *req, union smb_close *io)
+                            struct ntvfs_request *req, union smb_close *io)
 {
        NTSTATUS status;
 
@@ -599,7 +563,7 @@ static NTSTATUS unixuid_close(struct ntvfs_module_context *ntvfs,
   exit - closing files
 */
 static NTSTATUS unixuid_exit(struct ntvfs_module_context *ntvfs,
-                           struct smbsrv_request *req)
+                           struct ntvfs_request *req)
 {
        NTSTATUS status;
 
@@ -612,14 +576,54 @@ static NTSTATUS unixuid_exit(struct ntvfs_module_context *ntvfs,
   logoff - closing files
 */
 static NTSTATUS unixuid_logoff(struct ntvfs_module_context *ntvfs,
-                             struct smbsrv_request *req)
+                             struct ntvfs_request *req)
 {
-       struct unixuid_private *private = ntvfs->private_data;
+       struct unixuid_private *priv = ntvfs->private_data;
        NTSTATUS status;
 
        PASS_THRU_REQ(ntvfs, req, logoff, (ntvfs, req));
 
-       private->last_token = NULL;
+       priv->last_token = NULL;
+
+       return status;
+}
+
+/*
+  async setup
+*/
+static NTSTATUS unixuid_async_setup(struct ntvfs_module_context *ntvfs,
+                                   struct ntvfs_request *req, 
+                                   void *private_data)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, async_setup, (ntvfs, req, private_data));
+
+       return status;
+}
+
+/*
+  cancel an async request
+*/
+static NTSTATUS unixuid_cancel(struct ntvfs_module_context *ntvfs,
+                              struct ntvfs_request *req)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, cancel, (ntvfs, req));
+
+       return status;
+}
+
+/*
+  change notify
+*/
+static NTSTATUS unixuid_notify(struct ntvfs_module_context *ntvfs,
+                              struct ntvfs_request *req, union smb_notify *info)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, notify, (ntvfs, req, info));
 
        return status;
 }
@@ -628,7 +632,7 @@ static NTSTATUS unixuid_logoff(struct ntvfs_module_context *ntvfs,
   lock a byte range
 */
 static NTSTATUS unixuid_lock(struct ntvfs_module_context *ntvfs,
-                           struct smbsrv_request *req, union smb_lock *lck)
+                           struct ntvfs_request *req, union smb_lock *lck)
 {
        NTSTATUS status;
 
@@ -641,7 +645,7 @@ static NTSTATUS unixuid_lock(struct ntvfs_module_context *ntvfs,
   set info on a open file
 */
 static NTSTATUS unixuid_setfileinfo(struct ntvfs_module_context *ntvfs,
-                                  struct smbsrv_request *req, 
+                                  struct ntvfs_request *req, 
                                   union smb_setfileinfo *info)
 {
        NTSTATUS status;
@@ -656,7 +660,7 @@ static NTSTATUS unixuid_setfileinfo(struct ntvfs_module_context *ntvfs,
   return filesystem space info
 */
 static NTSTATUS unixuid_fsinfo(struct ntvfs_module_context *ntvfs,
-                             struct smbsrv_request *req, union smb_fsinfo *fs)
+                             struct ntvfs_request *req, union smb_fsinfo *fs)
 {
        NTSTATUS status;
 
@@ -669,7 +673,7 @@ static NTSTATUS unixuid_fsinfo(struct ntvfs_module_context *ntvfs,
   return print queue info
 */
 static NTSTATUS unixuid_lpq(struct ntvfs_module_context *ntvfs,
-                          struct smbsrv_request *req, union smb_lpq *lpq)
+                          struct ntvfs_request *req, union smb_lpq *lpq)
 {
        NTSTATUS status;
 
@@ -682,9 +686,9 @@ static NTSTATUS unixuid_lpq(struct ntvfs_module_context *ntvfs,
    list files in a directory matching a wildcard pattern
 */
 static NTSTATUS unixuid_search_first(struct ntvfs_module_context *ntvfs,
-                                   struct smbsrv_request *req, union smb_search_first *io, 
+                                   struct ntvfs_request *req, union smb_search_first *io, 
                                    void *search_private, 
-                                   BOOL (*callback)(void *, union smb_search_data *))
+                                   bool (*callback)(void *, const union smb_search_data *))
 {
        NTSTATUS status;
 
@@ -695,9 +699,9 @@ static NTSTATUS unixuid_search_first(struct ntvfs_module_context *ntvfs,
 
 /* continue a search */
 static NTSTATUS unixuid_search_next(struct ntvfs_module_context *ntvfs,
-                                  struct smbsrv_request *req, union smb_search_next *io, 
+                                  struct ntvfs_request *req, union smb_search_next *io, 
                                   void *search_private, 
-                                  BOOL (*callback)(void *, union smb_search_data *))
+                                  bool (*callback)(void *, const union smb_search_data *))
 {
        NTSTATUS status;
 
@@ -708,7 +712,7 @@ static NTSTATUS unixuid_search_next(struct ntvfs_module_context *ntvfs,
 
 /* close a search */
 static NTSTATUS unixuid_search_close(struct ntvfs_module_context *ntvfs,
-                                   struct smbsrv_request *req, union smb_search_close *io)
+                                   struct ntvfs_request *req, union smb_search_close *io)
 {
        NTSTATUS status;
 
@@ -719,7 +723,7 @@ static NTSTATUS unixuid_search_close(struct ntvfs_module_context *ntvfs,
 
 /* SMBtrans - not used on file shares */
 static NTSTATUS unixuid_trans(struct ntvfs_module_context *ntvfs,
-                            struct smbsrv_request *req, struct smb_trans2 *trans2)
+                            struct ntvfs_request *req, struct smb_trans2 *trans2)
 {
        NTSTATUS status;
 
@@ -735,6 +739,7 @@ NTSTATUS ntvfs_unixuid_init(void)
 {
        NTSTATUS ret;
        struct ntvfs_ops ops;
+       NTVFS_CURRENT_CRITICAL_SIZES(vers);
 
        ZERO_STRUCT(ops);
 
@@ -767,20 +772,23 @@ NTSTATUS ntvfs_unixuid_init(void)
        ops.search_close = unixuid_search_close;
        ops.trans = unixuid_trans;
        ops.logoff = unixuid_logoff;
+       ops.async_setup = unixuid_async_setup;
+       ops.cancel = unixuid_cancel;
+       ops.notify = unixuid_notify;
 
        ops.name = "unixuid";
 
        /* we register under all 3 backend types, as we are not type specific */
        ops.type = NTVFS_DISK;  
-       ret = register_backend("ntvfs", &ops);
+       ret = ntvfs_register(&ops, &vers);
        if (!NT_STATUS_IS_OK(ret)) goto failed;
 
        ops.type = NTVFS_PRINT; 
-       ret = register_backend("ntvfs", &ops);
+       ret = ntvfs_register(&ops, &vers);
        if (!NT_STATUS_IS_OK(ret)) goto failed;
 
        ops.type = NTVFS_IPC;   
-       ret = register_backend("ntvfs", &ops);
+       ret = ntvfs_register(&ops, &vers);
        if (!NT_STATUS_IS_OK(ret)) goto failed;
        
 failed: