Allow a new file to inherit the Windows ACL from its parent.
authorJeremy Allison <jra@samba.org>
Wed, 29 Oct 2008 20:27:14 +0000 (13:27 -0700)
committerJeremy Allison <jra@samba.org>
Wed, 29 Oct 2008 20:27:14 +0000 (13:27 -0700)
Now to do the same for directories.
Jeremy.

source3/include/proto.h
source3/lib/secdesc.c
source3/modules/vfs_acl_xattr.c
source3/printing/nt_printing.c

index e4a445bcd0a7c0bb539d231f20dc0c516240abee..b227a30f00570479227ee6acc253dc617e065284 100644 (file)
@@ -758,8 +758,17 @@ SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src);
 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size);
 NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask);
 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size);
-SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
-                                     bool child_container);
+NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
+                                        SEC_DESC **ppsd,
+                                       size_t *psize,
+                                        const SEC_DESC *parent_ctr,
+                                        const DOM_SID *owner_sid,
+                                        const DOM_SID *group_sid,
+                                        bool container);
+NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
+                                       SEC_DESC_BUF **ppsdb,
+                                       const SEC_DESC *parent_ctr,
+                                       bool container);
 
 /* The following definitions come from lib/select.c  */
 
index 52ff067d6ab358936319e729adae33cfef77fd59..6afc165c0f6a86f76840277c2871586952c51491 100644 (file)
@@ -429,19 +429,47 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t
        return NT_STATUS_OK;
 }
 
+/*
+ * Determine if an ACE is inheritable
+ */
+
+static bool is_inheritable_ace(const SEC_ACE *ace,
+                               bool container)
+{
+       if (!container) {
+               return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
+       }
+
+       if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
+               return true;
+       }
+
+       if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
+                       !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
+               return true;
+       }
+
+       return false;
+}
+
 /* Create a child security descriptor using another security descriptor as
    the parent container.  This child object can either be a container or
    non-container object. */
 
-SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
-                                     bool child_container)
+NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
+                                       SEC_DESC **ppsd,
+                                       size_t *psize,
+                                       const SEC_DESC *parent_ctr,
+                                       const DOM_SID *owner_sid,
+                                       const DOM_SID *group_sid,
+                                       bool container)
 {
-       SEC_DESC_BUF *sdb;
-       SEC_DESC *sd;
-       SEC_ACL *new_dacl, *the_acl;
+       SEC_ACL *new_dacl = NULL, *the_acl = NULL;
        SEC_ACE *new_ace_list = NULL;
        unsigned int new_ace_list_ndx = 0, i;
-       size_t size;
+
+       *ppsd = NULL;
+       *psize = 0;
 
        /* Currently we only process the dacl when creating the child.  The
           sacl should also be processed but this is left out as sacls are
@@ -450,71 +478,78 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
        the_acl = parent_ctr->dacl;
 
        if (the_acl->num_aces) {
-               if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE, the_acl->num_aces))) 
-                       return NULL;
+               if (2*the_acl->num_aces < the_acl->num_aces) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE,
+                                               2*the_acl->num_aces))) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        } else {
                new_ace_list = NULL;
        }
 
        for (i = 0; i < the_acl->num_aces; i++) {
-               SEC_ACE *ace = &the_acl->aces[i];
+               const SEC_ACE *ace = &the_acl->aces[i];
                SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
-               uint8 new_flags = 0;
-               bool inherit = False;
+               const DOM_SID *ptrustee = &ace->trustee;
+               const DOM_SID *creator = NULL;
+               uint8 new_flags = ace->flags;
 
-               /* The OBJECT_INHERIT_ACE flag causes the ACE to be
-                  inherited by non-container children objects.  Container
-                  children objects will inherit it as an INHERIT_ONLY
-                  ACE. */
+               if (!is_inheritable_ace(ace, container)) {
+                       continue;
+               }
 
-               if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
+               /* see the RAW-ACLS inheritance test for details on these rules */
+               if (!container) {
+                       new_flags = 0;
+               } else {
+                       new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
 
-                       if (!child_container) {
-                               new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
-                       } else {
+                       if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
                                new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
                        }
-
-                       inherit = True;
+                       if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
+                               new_flags = 0;
+                       }
                }
 
-               /* The CONAINER_INHERIT_ACE flag means all child container
-                  objects will inherit and use the ACE. */
-
-               if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
-                       if (!child_container) {
-                               inherit = False;
-                       } else {
-                               new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
-                       }
+               /* The CREATOR sids are special when inherited */
+               if (sid_equal(ptrustee, &global_sid_Creator_Owner)) {
+                       creator = &global_sid_Creator_Owner;
+                       ptrustee = owner_sid;
+               } else if (sid_equal(ptrustee, &global_sid_Creator_Group)) {
+                       creator = &global_sid_Creator_Group;
+                       ptrustee = group_sid;
                }
 
-               /* The INHERIT_ONLY_ACE is not used by the se_access_check()
-                  function for the parent container, but is inherited by
-                  all child objects as a normal ACE. */
+               if (creator && container &&
+                               (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
 
-               if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
-                       /* Move along, nothing to see here */
-               }
+                       /* First add the regular ACE entry with flags = 0. */
+                       init_sec_ace(new_ace, ptrustee, ace->type,
+                               ace->access_mask, 0);
 
-               /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
-                  is inherited by child objects but not grandchildren
-                  objects.  We clear the object inherit and container
-                  inherit flags in the inherited ACE. */
+                       DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
+                               " inherited as %s:%d/0x%02x/0x%08x\n",
+                               sid_string_dbg(&ace->trustee),
+                               ace->type, ace->flags, ace->access_mask,
+                               sid_string_dbg(&new_ace->trustee),
+                               new_ace->type, new_ace->flags,
+                               new_ace->access_mask));
 
-               if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
-                       new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
-                                      SEC_ACE_FLAG_CONTAINER_INHERIT);
-               }
+                       new_ace_list_ndx++;
 
-               /* Add ACE to ACE list */
+                       /* Now add the extra creator ACE. */
+                       new_ace = &new_ace_list[new_ace_list_ndx];
 
-               if (!inherit)
-                       continue;
+                       ptrustee = creator;
+                       new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
+               }
 
-               new_ace->access_mask = ace->access_mask;
-               init_sec_ace(new_ace, &ace->trustee, ace->type,
-                            new_ace->access_mask, new_flags);
+               init_sec_ace(new_ace, ptrustee, ace->type,
+                            ace->access_mask, new_flags);
 
                DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
                          " inherited as %s:%d/0x%02x/0x%08x\n",
@@ -528,21 +563,54 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
        }
 
        /* Create child security descriptor to return */
-       
-       new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
 
-       /* Use the existing user and group sids.  I don't think this is
-          correct.  Perhaps the user and group should be passed in as
-          parameters by the caller? */
+       new_dacl = make_sec_acl(ctx,
+                               ACL_REVISION,
+                               new_ace_list_ndx,
+                               new_ace_list);
 
-       sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
-                          SEC_DESC_SELF_RELATIVE,
-                          parent_ctr->owner_sid,
-                          parent_ctr->group_sid,
-                          parent_ctr->sacl,
-                          new_dacl, &size);
+       if (!new_dacl) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       *ppsd = make_sec_desc(ctx,
+                       SECURITY_DESCRIPTOR_REVISION_1,
+                       SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
+                               SEC_DESC_DACL_DEFAULTED,
+                       owner_sid,
+                       group_sid,
+                       NULL,
+                       new_dacl,
+                       psize);
+       if (!*ppsd) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return NT_STATUS_OK;
+}
 
-       sdb = make_sec_desc_buf(ctx, size, sd);
+NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
+                                       SEC_DESC_BUF **ppsdb,
+                                       const SEC_DESC *parent_ctr,
+                                       bool container)
+{
+       NTSTATUS status;
+       size_t size = 0;
+       SEC_DESC *sd = NULL;
+
+       *ppsdb = NULL;
+       status = se_create_child_secdesc(ctx,
+                                       &sd,
+                                       &size,
+                                       parent_ctr,
+                                       parent_ctr->owner_sid,
+                                       parent_ctr->group_sid,
+                                       container);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-       return sdb;
+       *ppsdb = make_sec_desc_buf(ctx, size, sd);
+       if (!*ppsdb) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return NT_STATUS_OK;
 }
index 241751c6a6f8a8d4f6bffdc9ccbb6c802708a958..a802dac554b0bcba1ca9ddbfc56b5d3158dd282d 100644 (file)
@@ -36,7 +36,6 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
        struct xattr_NTACL xacl;
        enum ndr_err_code ndr_err;
        size_t sd_size;
-       struct timespec ts;
 
        ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
                        (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
@@ -51,17 +50,29 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
                return NT_STATUS_REVISION_MISMATCH;
        }
 
-       /*
-        * Check that the ctime timestamp is ealier
-        * than the stored timestamp.
-        */
-
-       ts = nt_time_to_unix_timespec(&xacl.info.sd_ts->last_changed);
-
-       if (timespec_compare(&cts, &ts) > 0) {
-               DEBUG(5, ("parse_acl_blob: stored ACL out of date.\n"));
-               return NT_STATUS_EA_CORRUPT_ERROR;
+#if 0
+       {
+               struct timespec ts;
+               /* Arg. This doesn't work. Too many activities
+                * change the ctime. May have to roll back to
+                * version 1.
+                */
+               /*
+                * Check that the ctime timestamp is ealier
+                * than the stored timestamp.
+                */
+
+               ts = nt_time_to_unix_timespec(&xacl.info.sd_ts->last_changed);
+
+               if (timespec_compare(&cts, &ts) > 0) {
+                       DEBUG(5, ("parse_acl_blob: stored ACL out of date "
+                               "(%s > %s.\n",
+                               timestring(ctx, cts.tv_sec),
+                               timestring(ctx, ts.tv_sec)));
+                       return NT_STATUS_EA_CORRUPT_ERROR;
+               }
        }
+#endif
 
        *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
                        (security_info & OWNER_SECURITY_INFORMATION)
@@ -133,6 +144,78 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
        return NT_STATUS_OK;
 }
 
+static NTSTATUS create_acl_blob(const SEC_DESC *psd, DATA_BLOB *pblob)
+{
+       struct xattr_NTACL xacl;
+       struct security_descriptor_timestamp sd_ts;
+       enum ndr_err_code ndr_err;
+       TALLOC_CTX *ctx = talloc_tos();
+       struct timespec curr = timespec_current();
+
+       ZERO_STRUCT(xacl);
+       ZERO_STRUCT(sd_ts);
+
+       /* Horrid hack as setting an xattr changes the ctime
+        * on Linux. This gives a race of 1 second during
+        * which we would not see a POSIX ACL set.
+        */
+       curr.tv_sec += 1;
+
+       xacl.version = 2;
+       xacl.info.sd_ts = &sd_ts;
+       xacl.info.sd_ts->sd = CONST_DISCARD(SEC_DESC *, psd);
+       unix_timespec_to_nt_time(&xacl.info.sd_ts->last_changed, curr);
+
+       DEBUG(10, ("create_acl_blob: timestamp stored as %s\n",
+               timestring(ctx, curr.tv_sec) ));
+
+       ndr_err = ndr_push_struct_blob(
+                       pblob, ctx, NULL, &xacl,
+                       (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
+
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
+                       ndr_errstr(ndr_err)));
+               return ndr_map_error2ntstatus(ndr_err);;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS store_acl_blob(files_struct *fsp,
+                               DATA_BLOB *pblob)
+{
+       int ret;
+       int saved_errno = 0;
+
+       DEBUG(10,("store_acl_blob: storing blob length %u on file %s\n",
+                       (unsigned int)pblob->length, fsp->fsp_name));
+
+       become_root();
+       if (fsp->fh->fd != -1) {
+               ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME,
+                       pblob->data, pblob->length, 0);
+       } else {
+               ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name,
+                               XATTR_NTACL_NAME,
+                               pblob->data, pblob->length, 0);
+       }
+       if (ret) {
+               saved_errno = errno;
+       }
+       unbecome_root();
+       if (ret) {
+               errno = saved_errno;
+               DEBUG(5, ("store_acl_blob: setting attr failed for file %s"
+                       "with error %s\n",
+                       fsp->fsp_name,
+                       strerror(errno) ));
+               return map_nt_error_from_unix(errno);
+       }
+       return NT_STATUS_OK;
+}
+
+
 static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
                                        files_struct *fsp,
                                        const char *name,
@@ -188,10 +271,72 @@ static int mkdir_acl_xattr(vfs_handle_struct *handle,  const char *path, mode_t
  * inheritance for new files.
 *********************************************************************/
 
-static int open_acl_xattr(vfs_handle_struct *handle,  const char *fname, files_struct *fsp, int flags, mode_t mode)
+static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
+                                       const char *fname,
+                                       files_struct *fsp)
+{
+       TALLOC_CTX *ctx = talloc_tos();
+       NTSTATUS status;
+       SEC_DESC *parent_desc = NULL;
+       SEC_DESC *psd = NULL;
+       DATA_BLOB blob;
+       size_t size;
+       char *parent_name;
+
+       if (!parent_dirname_talloc(ctx,
+                               fname,
+                               &parent_name,
+                               NULL)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       DEBUG(10,("inherit_new_acl: check directory %s\n",
+                       parent_name));
+
+       status = get_nt_acl_xattr_internal(handle,
+                                       NULL,
+                                       parent_name,
+                                       DACL_SECURITY_INFORMATION,
+                                       &parent_desc);
+        if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10,("inherit_new_acl: directory %s failed "
+                       "to get acl %s\n",
+                       parent_name,
+                       nt_errstr(status) ));
+               return status;
+       }
+
+       /* Create an inherited descriptor from the parent. */
+       status = se_create_child_secdesc(ctx,
+                               &psd,
+                               &size,
+                               parent_desc,
+                               &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
+                               &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
+                               false);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       status = create_acl_blob(psd, &blob);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       return store_acl_blob(fsp, &blob);
+}
+
+/*********************************************************************
+ Check ACL on open. For new files inherit from parent directory.
+*********************************************************************/
+
+static int open_acl_xattr(vfs_handle_struct *handle,
+                                       const char *fname,
+                                       files_struct *fsp,
+                                       int flags,
+                                       mode_t mode)
 {
        uint32_t access_granted = 0;
        SEC_DESC *pdesc = NULL;
+       bool file_existed = true;
        NTSTATUS status = get_nt_acl_xattr_internal(handle,
                                        NULL,
                                        fname,
@@ -209,9 +354,24 @@ static int open_acl_xattr(vfs_handle_struct *handle,  const char *fname, files_s
                        errno = map_errno_from_nt_status(status);
                        return -1;
                }
-        }
+        } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               file_existed = false;
+       }
+
+       DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
+               "file %s returned %s\n",
+               fname,
+               nt_errstr(status) ));
+
+       fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+
+       if (!file_existed && fsp->fh->fd != -1) {
+               /* File was created. Inherit from parent directory. */
+               string_set(&fsp->fsp_name, fname);
+               inherit_new_acl(handle, fname, fsp);
+       }
 
-       return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       return fsp->fh->fd;
 }
 
 static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
@@ -238,74 +398,6 @@ static NTSTATUS get_nt_acl_xattr(vfs_handle_struct *handle,
                        security_info, ppdesc);
 }
 
-static NTSTATUS create_acl_blob(const SEC_DESC *psd, DATA_BLOB *pblob)
-{
-       struct xattr_NTACL xacl;
-       struct security_descriptor_timestamp sd_ts;
-       enum ndr_err_code ndr_err;
-       TALLOC_CTX *ctx = talloc_tos();
-       struct timespec curr = timespec_current();
-
-       ZERO_STRUCT(xacl);
-       ZERO_STRUCT(sd_ts);
-
-       /* Horrid hack as setting an xattr changes the ctime
-        * on Linux. This gives a race of 1 second during
-        * which we would not see a POSIX ACL set.
-        */
-       curr.tv_sec += 1;
-
-       xacl.version = 2;
-       xacl.info.sd_ts = &sd_ts;
-       xacl.info.sd_ts->sd = CONST_DISCARD(SEC_DESC *, psd);
-       unix_timespec_to_nt_time(&xacl.info.sd_ts->last_changed, curr);
-
-       ndr_err = ndr_push_struct_blob(
-                       pblob, ctx, NULL, &xacl,
-                       (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
-
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
-                       ndr_errstr(ndr_err)));
-               return ndr_map_error2ntstatus(ndr_err);;
-       }
-
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS store_acl_blob(files_struct *fsp,
-                               DATA_BLOB *pblob)
-{
-       int ret;
-       int saved_errno = 0;
-
-       DEBUG(10,("store_acl_blob: storing blob length %u on file %s\n",
-                       (unsigned int)pblob->length, fsp->fsp_name));
-
-       become_root();
-       if (fsp->fh->fd != -1) {
-               ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME,
-                       pblob->data, pblob->length, 0);
-       } else {
-               ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name,
-                               XATTR_NTACL_NAME,
-                               pblob->data, pblob->length, 0);
-       }
-       if (ret) {
-               saved_errno = errno;
-       }
-       unbecome_root();
-       if (ret) {
-               errno = saved_errno;
-               DEBUG(5, ("store_acl_blob: setting attr failed for file %s"
-                       "with error %s\n",
-                       fsp->fsp_name,
-                       strerror(errno) ));
-               return map_nt_error_from_unix(errno);
-       }
-       return NT_STATUS_OK;
-}
-
 static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
         uint32 security_info_sent, const SEC_DESC *psd)
 {
index 1826fa88ed3b2f3f6e852de457dfabc41427c1db..5ec0e1e9f3eab85c422dc78f46a01d2292877d65 100644 (file)
@@ -5811,11 +5811,11 @@ bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
                   against.  This is because print jobs are child objects
                   objects of a printer. */
 
-               secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
+               status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
 
-               if (!secdesc) {
+               if (!NT_STATUS_IS_OK(status)) {
                        talloc_destroy(mem_ctx);
-                       errno = ENOMEM;
+                       errno = map_errno_from_nt_status(status);
                        return False;
                }