smbd: Use talloc_pooled_object in cp_smb_filename
[amitay/samba.git] / source3 / lib / filename_util.c
index 90bb2b86274878c4635a8c741e604d6fd8d0cc4f..3ebf3112049d91f643e7dfe3c79b8bba140cb585 100644 (file)
@@ -50,14 +50,12 @@ NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
  * enumerate streams using the vfs_streaminfo interface and then want to
  * operate on each stream.
  */
-NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
-                                   const char *stream_name,
-                                   const SMB_STRUCT_STAT *psbuf,
-                                   struct smb_filename **smb_fname_out)
+struct smb_filename *synthetic_smb_fname(TALLOC_CTX *mem_ctx,
+                                        const char *base_name,
+                                        const char *stream_name,
+                                        const SMB_STRUCT_STAT *psbuf)
 {
-       struct smb_filename smb_fname_loc;
-
-       ZERO_STRUCT(smb_fname_loc);
+       struct smb_filename smb_fname_loc = { 0, };
 
        /* Setup the base_name/stream_name. */
        smb_fname_loc.base_name = discard_const_p(char, base_name);
@@ -67,22 +65,21 @@ NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
        if (psbuf)
                smb_fname_loc.st = *psbuf;
 
-       /* Let copy_smb_filename() do the heavy lifting. */
-       return copy_smb_filename(ctx, &smb_fname_loc, smb_fname_out);
+       /* Let cp_smb_filename() do the heavy lifting. */
+       return cp_smb_filename(mem_ctx, &smb_fname_loc);
 }
 
 /**
  * XXX: This is temporary and there should be no callers of this once
  * smb_filename is plumbed through all path based operations.
  */
-NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
-                                         const char *fname,
-                                         const SMB_STRUCT_STAT *psbuf,
-                                         struct smb_filename **smb_fname_out)
+struct smb_filename *synthetic_smb_fname_split(TALLOC_CTX *ctx,
+                                              const char *fname,
+                                              const SMB_STRUCT_STAT *psbuf)
 {
-       NTSTATUS status;
        const char *stream_name = NULL;
        char *base_name = NULL;
+       struct smb_filename *ret;
 
        if (!lp_posix_pathnames()) {
                stream_name = strchr_m(fname, ':');
@@ -97,13 +94,12 @@ NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
        }
 
        if (!base_name) {
-               return NT_STATUS_NO_MEMORY;
+               return NULL;
        }
 
-       status = create_synthetic_smb_fname(ctx, base_name, stream_name, psbuf,
-                                           smb_fname_out);
+       ret = synthetic_smb_fname(ctx, base_name, stream_name, psbuf);
        TALLOC_FREE(base_name);
-       return status;
+       return ret;
 }
 
 /**
@@ -165,50 +161,55 @@ struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
                                     const struct smb_filename *in)
 {
        struct smb_filename *out;
+       size_t base_len = 0;
+       size_t stream_len = 0;
+       size_t lcomp_len = 0;
+       int num = 0;
 
        /* stream_name must always be NULL if there is no stream. */
        if (in->stream_name) {
                SMB_ASSERT(in->stream_name[0] != '\0');
        }
 
-       out = talloc_zero(mem_ctx, struct smb_filename);
+       if (in->base_name != NULL) {
+               base_len = strlen(in->base_name) + 1;
+               num += 1;
+       }
+       if (in->stream_name != NULL) {
+               stream_len = strlen(in->stream_name) + 1;
+               num += 1;
+       }
+       if (in->original_lcomp != NULL) {
+               lcomp_len = strlen(in->original_lcomp) + 1;
+               num += 1;
+       }
+
+       out = talloc_pooled_object(mem_ctx, struct smb_filename,
+                               num, stream_len + base_len + lcomp_len);
        if (out == NULL) {
                return NULL;
        }
+       ZERO_STRUCTP(out);
+
+       /*
+        * The following allocations cannot fails as we
+        * pre-allocated space for them in the out pooled
+        * object.
+        */
        if (in->base_name != NULL) {
-               out->base_name = talloc_strdup(out, in->base_name);
-               if (out->base_name == NULL) {
-                       goto fail;
-               }
+               out->base_name = talloc_memdup(
+                               out, in->base_name, base_len);
        }
        if (in->stream_name != NULL) {
-               out->stream_name = talloc_strdup(out, in->stream_name);
-               if (out->stream_name == NULL) {
-                       goto fail;
-               }
+               out->stream_name = talloc_memdup(
+                               out, in->stream_name, stream_len);
        }
        if (in->original_lcomp != NULL) {
-               out->original_lcomp = talloc_strdup(out, in->original_lcomp);
-               if (out->original_lcomp == NULL) {
-                       goto fail;
-               }
+               out->original_lcomp = talloc_memdup(
+                               out, in->original_lcomp, lcomp_len);
        }
        out->st = in->st;
        return out;
-fail:
-       TALLOC_FREE(out);
-       return NULL;
-}
-
-NTSTATUS copy_smb_filename(TALLOC_CTX *ctx,
-                          const struct smb_filename *smb_fname_in,
-                          struct smb_filename **smb_fname_out)
-{
-       *smb_fname_out = cp_smb_filename(ctx, smb_fname_in);
-       if (*smb_fname_out == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -239,3 +240,37 @@ bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
 
        return strcasecmp_m(smb_fname->stream_name, "::$DATA") == 0;
 }
+
+/****************************************************************************
+ Filter out Windows invalid EA names (list probed from Windows 2012).
+****************************************************************************/
+
+static char bad_ea_name_chars[] = "\"*+,/:;<=>?[\\]|";
+
+bool is_invalid_windows_ea_name(const char *name)
+{
+       int i;
+       /* EA name is pulled as ascii so we can examine
+          individual bytes here. */
+       for (i = 0; name[i] != 0; i++) {
+               int val = (name[i] & 0xff);
+               if (val < ' ' || strchr(bad_ea_name_chars, val)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+bool ea_list_has_invalid_name(struct ea_list *ea_list)
+{
+       if (lp_posix_pathnames()) {
+               return false;
+       }
+
+       for (;ea_list; ea_list = ea_list->next) {
+               if (is_invalid_windows_ea_name(ea_list->ea.name)) {
+                       return true;
+               }
+       }
+       return false;
+}