Merge branch 'master' of ssh://git.samba.org/data/git/samba
authorJelmer Vernooij <jelmer@samba.org>
Mon, 26 Jan 2009 17:14:41 +0000 (18:14 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Mon, 26 Jan 2009 17:14:41 +0000 (18:14 +0100)
12 files changed:
docs-xml/manpages-3/vfs_shadow_copy2.8.xml [new file with mode: 0644]
docs-xml/smbdotconf/printing/printing.xml
source3/include/proto.h
source3/include/safe_string.h
source3/libsmb/cliconnect.c
source3/libsmb/clidfs.c
source3/libsmb/clifile.c
source3/libsmb/clifsinfo.c
source3/libsmb/clilist.c
source3/libsmb/clirap.c
source3/libsmb/clistr.c
source3/smbd/process.c

diff --git a/docs-xml/manpages-3/vfs_shadow_copy2.8.xml b/docs-xml/manpages-3/vfs_shadow_copy2.8.xml
new file mode 100644 (file)
index 0000000..364dd59
--- /dev/null
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
+<refentry id="vfs_shadow_copy2.8">
+
+<refmeta>
+       <refentrytitle>vfs_shadow_copy2</refentrytitle>
+       <manvolnum>8</manvolnum>
+       <refmiscinfo class="source">Samba</refmiscinfo>
+       <refmiscinfo class="manual">System Administration tools</refmiscinfo>
+       <refmiscinfo class="version">3.2</refmiscinfo>
+</refmeta>
+
+
+<refnamediv>
+       <refname>vfs_shadow_copy2</refname>
+       <refpurpose>Expose snapshots to Windows clients as shadow copies.</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+       <cmdsynopsis>
+               <command>vfs objects = shadow_copy2</command>
+       </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1>
+       <title>DESCRIPTION</title>
+
+       <para>This VFS module is part of the
+       <citerefentry><refentrytitle>samba</refentrytitle>
+       <manvolnum>7</manvolnum></citerefentry> suite.</para>
+
+       <para>The <command>vfs_shadow_copy2</command> VFS module functionality
+       that is similar to Microsoft Shadow Copy services. When setup properly,
+       this module allows Microsoft Shadow Copy clients to browse
+       "shadow copies" on Samba shares.
+       </para>
+
+       <para>This is a 2nd implementation of a shadow copy module. This
+       version has the following features:</para>
+       <orderedlist continuation="restarts" inheritnum="ignore" numeration="arabic">
+        <listitem><para>You don't need to populate your shares with symlinks to the
+       snapshots. This can be very important when you have thousands of
+       shares, or use [homes].</para></listitem>
+       <listitem><para>The inode number of the files is altered so it is different
+       from the original. This allows the 'restore' button to work
+       without a sharing violation.</para></listitem>
+       </orderedlist>
+
+       <para>This module is stackable.</para>
+
+</refsect1>
+
+<refsect1>
+       <title>CONFIGURATION</title>
+
+       <para><command>vfs_shadow_copy2</command> relies on a filesystem
+       snapshot implementation. Many common filesystems have native
+       support for this.
+       </para>
+
+       <para>Filesystem snapshots must be mounted on
+       specially named directories in order to be recognized by
+       <command>vfs_shadow_copy2</command>. The snapshot mount points must
+       be immediate children of a the directory being shared.</para>
+
+       <para>The snapshot naming convention is @GMT-YYYY.MM.DD-hh.mm.ss,
+       where:
+       <itemizedlist>
+               <listitem><para><command>YYYY</command> is the 4 digit year</para></listitem>
+               <listitem><para><command>MM</command> is the 2 digit month</para></listitem>
+               <listitem><para><command>DD</command> is the 2 digit day</para></listitem>
+               <listitem><para><command>hh</command> is the 2 digit hour</para></listitem>
+               <listitem><para><command>mm</command> is the 2 digit minute</para></listitem>
+               <listitem><para><command>ss</command> is the 2 digit second.</para></listitem>
+               </itemizedlist>
+       </para>
+
+       <para>The <command>vfs_shadow_copy2</command> snapshot naming convention can be
+       produced with the following <citerefentry><refentrytitle>date</refentrytitle>
+       <manvolnum>1</manvolnum></citerefentry> command:
+       <programlisting>
+       TZ=GMT date +@GMT-%Y.%m.%d-%H.%M.%S
+       </programlisting></para>
+
+</refsect1>
+
+<refsect1>
+        <title>OPTIONS</title>
+
+        <variablelist>
+               <varlistentry>
+                <term>shadow:snapdir = SNAPDIR
+                </term>
+                <listitem>
+                <para>Path to the directory where snapshots are kept.
+                </para>
+                </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                <term>shadow:basedir = BASEDIR
+               </term>
+                <listitem>
+                <para>Path to the base directory that snapshots are from.
+                </para>
+                </listitem>
+                </varlistentry>
+
+               <varlistentry>
+                <term>shadow:fixinodes = yes/no
+                </term>
+                <listitem>
+                <para>If you enable <command moreinfo="none">shadow:fixinodes
+               </command> then this module will modify the apparent inode
+               number of files in the snapshot directories using a hash of the
+               files path. This is needed for snapshot systems where the
+               snapshots have the same device:inode number as the original
+               files (such as happens with GPFS snapshots). If you don't set
+               this option then the 'restore' button in the shadow copy UI
+               will fail with a sharing violation.
+                </para>
+                </listitem>
+                </varlistentry>
+               </variablelist>
+</refsect1>
+
+<refsect1>
+       <title>EXAMPLES</title>
+
+       <para>Add shadow copy support to user home directories:</para>
+<programlisting>
+        <smbconfsection name="[homes]"/>
+       <smbconfoption name="vfs objects">shadow_copy2</smbconfoption>
+       <smbconfoption name="shadow:snapdir">/data/snaphots</smbconfoption>
+       <smbconfoption name="shadow:basedir">/data/home</smbconfoption>
+</programlisting>
+
+</refsect1>
+
+<refsect1>
+       <title>CAVEATS</title>
+
+       <para>This is not a backup, archival, or version control solution.
+       </para>
+
+       <para>With Samba or Windows servers,
+       <command>vfs_shadow_copy2</command> is designed to be an end-user
+       tool only. It does not replace or enhance your backup and
+       archival solutions and should in no way be considered as
+       such. Additionally, if you need version control, implement a
+       version control system.</para>
+
+</refsect1>
+
+
+
+<refsect1>
+       <title>VERSION</title>
+
+       <para>This man page is correct for version 3.2.7 of the Samba suite.
+       </para>
+</refsect1>
+
+<refsect1>
+       <title>AUTHOR</title>
+
+       <para>The original Samba software and related utilities
+       were created by Andrew Tridgell. Samba is now developed
+       by the Samba Team as an Open Source project similar
+       to the way the Linux kernel is developed.</para>
+
+</refsect1>
+
+</refentry>
index 3be0f429392e874c70ddc2f1586bbda6e20a16dd..c365594e1f12997e5838f90bb293b89173dd9450 100644 (file)
@@ -33,4 +33,6 @@
     <para>See also the discussion in the <link linkend="PRINTERSSECT">
     [printers]</link> section.</para>
 </description>
+<value type="default">Depends on the operating system, see
+<command moreinfo="none">testparm -v.</command></value>
 </samba:parameter>
index 1414ba89ecf118405b521523f6c65a375e0c698e..88384197055aa6bed2c05b6b3888d073f43eedf0 100644 (file)
@@ -2825,7 +2825,7 @@ size_t clistr_push_fn(const char *function,
                        int flags);
 size_t clistr_pull_fn(const char *function,
                        unsigned int line,
-                       struct cli_state *cli,
+                       const char *inbuf,
                        char *dest,
                        const void *src,
                        int dest_len,
@@ -2834,7 +2834,7 @@ size_t clistr_pull_fn(const char *function,
 size_t clistr_pull_talloc_fn(const char *function,
                                unsigned int line,
                                TALLOC_CTX *ctx,
-                               struct cli_state *cli,
+                               const char *inbuf,
                                char **pp_dest,
                                const void *src,
                                int src_len,
index c030acf8fdc2e152ae0d0b72c71e4b44935ac247..a7230964c9ce26a9881171fe96486ff91a357a75 100644 (file)
@@ -146,13 +146,13 @@ size_t __unsafe_string_function_usage_here_char__(void);
        clistr_push_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, \
                        cli, dest, src, dest_len, flags)
 
-#define clistr_pull(cli, dest, src, dest_len, src_len, flags) \
+#define clistr_pull(inbuf, dest, src, dest_len, src_len, flags) \
        clistr_pull_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, \
-                       cli, dest, src, dest_len, src_len, flags)
+                       inbuf, dest, src, dest_len, src_len, flags)
 
-#define clistr_pull_talloc(ctx, cli, pp_dest, src, src_len, flags) \
+#define clistr_pull_talloc(ctx, inbuf, pp_dest, src, src_len, flags) \
        clistr_pull_talloc_fn(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, \
-                       ctx, cli, pp_dest, src, src_len, flags)
+                       ctx, inbuf, pp_dest, src, src_len, flags)
 
 #define srvstr_push(base_ptr, smb_flags2, dest, src, dest_len, flags) \
        srvstr_push_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, \
@@ -200,10 +200,10 @@ size_t __unsafe_string_function_usage_here_char__(void);
     ? __unsafe_string_function_usage_here_size_t__() \
     : clistr_push_fn(fn_name, fn_line, cli, dest, src, dest_len, flags))
 
-#define clistr_pull_fn2(fn_name, fn_line, cli, dest, src, dest_len, srclen, flags) \
+#define clistr_pull_fn2(fn_name, fn_line, inbuf, dest, src, dest_len, srclen, flags) \
     (CHECK_STRING_SIZE(dest, dest_len) \
     ? __unsafe_string_function_usage_here_size_t__() \
-    : clistr_pull_fn(fn_name, fn_line, cli, dest, src, dest_len, srclen, flags))
+    : clistr_pull_fn(fn_name, fn_line, inbuf, dest, src, dest_len, srclen, flags))
 
 #define srvstr_push_fn2(fn_name, fn_line, base_ptr, smb_flags2, dest, src, dest_len, flags) \
     (CHECK_STRING_SIZE(dest, dest_len) \
index 9e4266de5a5e27577a56650612416acb9bcb2025..bc690f2e02be44fdc1e4763f15b7db7a73f4211b 100644 (file)
@@ -199,9 +199,12 @@ static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
        cli->vuid = SVAL(cli->inbuf,smb_uid);
 
        p = smb_buf(cli->inbuf);
-       p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
-       p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
-       p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
 
        if (strstr(cli->server_type, "Samba")) {
                cli->is_samba = True;
@@ -276,9 +279,12 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
 
        cli->vuid = SVAL(cli->inbuf,smb_uid);
        p = smb_buf(cli->inbuf);
-       p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
-       p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
-       p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
        fstrcpy(cli->user_name, user);
 
        if (strstr(cli->server_type, "Samba")) {
@@ -426,9 +432,12 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
        cli->vuid = SVAL(cli->inbuf,smb_uid);
        
        p = smb_buf(cli->inbuf);
-       p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
-       p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
-       p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
 
        if (strstr(cli->server_type, "Samba")) {
                cli->is_samba = True;
@@ -512,11 +521,13 @@ static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
        blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
 
        p += blob2.length;
-       p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
+       p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
+                        -1, STR_TERMINATE);
 
        /* w2k with kerberos doesn't properly null terminate this field */
        len = smb_bufrem(cli->inbuf, p);
-       p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
+       p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
+                        len, 0);
 
        return blob2;
 }
@@ -1178,7 +1189,8 @@ bool cli_send_tconX(struct cli_state *cli,
        if (cli_is_error(cli))
                return False;
 
-       clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
+       clistr_pull(cli->inbuf, cli->dev, smb_buf(cli->inbuf), sizeof(fstring),
+                   -1, STR_TERMINATE|STR_ASCII);
 
        if (cli->protocol >= PROTOCOL_NT1 &&
            smb_buflen(cli->inbuf) == 3) {
@@ -1350,7 +1362,7 @@ NTSTATUS cli_negprot_recv(struct async_req *req)
                /* work out if they sent us a workgroup */
                if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
                    smb_buflen(cli->inbuf) > 8) {
-                       clistr_pull(cli, cli->server_domain,
+                       clistr_pull(cli->inbuf, cli->server_domain,
                                    bytes+8, sizeof(cli->server_domain),
                                    num_bytes-8,
                                    STR_UNICODE|STR_NOALIGN);
index d649c504b72ed5833ed6b549705eb9053745a063..f853e4e6701f6b062e1a90c6108d6b6902ec6d6f 100644 (file)
@@ -785,9 +785,10 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
                        if (p + node_offset > endp) {
                                goto out;
                        }
-                       clistr_pull_talloc(ctx, cli, &referrals[i].dfspath,
-                               p+node_offset, -1,
-                               STR_TERMINATE|STR_UNICODE );
+                       clistr_pull_talloc(ctx, cli->inbuf,
+                                          &referrals[i].dfspath,
+                                          p+node_offset, -1,
+                                          STR_TERMINATE|STR_UNICODE);
 
                        if (!referrals[i].dfspath) {
                                goto out;
index 7c75826414146248623b672a37c64fa1f470bd55..02cd2108bf2878af1a314720bb87617fa048860d 100644 (file)
@@ -783,10 +783,15 @@ int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess
 
 uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str)
 {
-       size_t buflen = talloc_get_size(buf);
+       size_t buflen;
        char *converted;
        size_t converted_size;
 
+       if (buf == NULL) {
+               return NULL;
+       }
+
+       buflen = talloc_get_size(buf);
        /*
         * We're pushing into an SMB buffer, align odd
         */
@@ -809,6 +814,7 @@ uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str)
        buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t,
                                   buflen + converted_size);
        if (buf == NULL) {
+               TALLOC_FREE(converted);
                return NULL;
        }
 
@@ -1745,7 +1751,7 @@ int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
                if (!path2) {
                        return -1;
                }
-               clistr_pull(cli, path2, p,
+               clistr_pull(cli->inbuf, path2, p,
                            len+1, len, STR_ASCII);
                *tmp_path = path2;
        }
index 5e73b61cd20e77435d5eaecb6e23521337a61435..77290d2df9b3c2c739264a8aa239756ff3c6fcf4 100644 (file)
@@ -229,7 +229,8 @@ bool cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint
                *pserial_number = IVAL(rdata,0);
        }
        nlen = CVAL(rdata,l2_vol_cch);
-       clistr_pull(cli, volume_name, rdata + l2_vol_szVolLabel, sizeof(fstring), nlen, STR_NOALIGN);
+       clistr_pull(cli->inbuf, volume_name, rdata + l2_vol_szVolLabel,
+                   sizeof(fstring), nlen, STR_NOALIGN);
 
        /* todo: but not yet needed
         *       return the other stuff
@@ -290,7 +291,8 @@ bool cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *
                *pserial_number = IVAL(rdata,8);
        }
        nlen = IVAL(rdata,12);
-       clistr_pull(cli, volume_name, rdata + 18, sizeof(fstring), nlen, STR_UNICODE);
+       clistr_pull(cli->inbuf, volume_name, rdata + 18, sizeof(fstring),
+                   nlen, STR_UNICODE);
 
        /* todo: but not yet needed
         *       return the other stuff
index 1431b804b040e0258670f79e24a171b3635bbb08..e6047254930a8adefcf76f9113922643758f2f30 100644 (file)
@@ -98,7 +98,7 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
                           between win2000 and win9x for this call
                           (tridge) */
                        ret = clistr_pull_talloc(ctx,
-                                               cli,
+                                               cli->inbuf,
                                                &finfo->name,
                                                p,
                                                len+2,
@@ -127,7 +127,7 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
                                return pdata_end - base;
                        }
                        ret = clistr_pull_talloc(ctx,
-                                               cli,
+                                               cli->inbuf,
                                                &finfo->name,
                                                p,
                                                len,
@@ -179,7 +179,7 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
                                /* stupid NT bugs. grr */
                                int flags = 0;
                                if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
-                               clistr_pull(cli, finfo->short_name, p,
+                               clistr_pull(cli->inbuf, finfo->short_name, p,
                                            sizeof(finfo->short_name),
                                            slen, flags);
                        }
@@ -188,7 +188,7 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
                                return pdata_end - base;
                        }
                        ret = clistr_pull_talloc(ctx,
-                                               cli,
+                                               cli->inbuf,
                                                &finfo->name,
                                                p,
                                                namelen,
@@ -514,7 +514,7 @@ static bool interpret_short_filename(TALLOC_CTX *ctx,
        finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0;
        finfo->size = IVAL(p,26);
        ret = clistr_pull_talloc(ctx,
-                       cli,
+                       cli->inbuf,
                        &finfo->name,
                        p+30,
                        12,
index 1656d9eb1cfef6e46980063e5471585603aafacb..3f95e77aeec31a0ff227f15321de17ddb9945241 100644 (file)
@@ -952,7 +952,8 @@ bool cli_qfilename(struct cli_state *cli, int fnum, char *name, size_t namelen)
                return False;
        }
 
-       clistr_pull(cli, name, rdata+4, namelen, IVAL(rdata, 0), STR_UNICODE);
+       clistr_pull(cli->inbuf, name, rdata+4, namelen, IVAL(rdata, 0),
+                   STR_UNICODE);
 
        SAFE_FREE(rparam);
        SAFE_FREE(rdata);
@@ -1232,7 +1233,8 @@ NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstrin
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
        }
 
-       clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
+       clistr_pull(cli->inbuf, alt_name, rdata+4, sizeof(fstring), len,
+                   STR_UNICODE);
 
        SAFE_FREE(rdata);
        SAFE_FREE(rparam);
index 5d20d632aad002b4d15a7fdcd1d9788f27896787..86857814043338df630c326d6a3b2007bf067338 100644 (file)
@@ -51,22 +51,22 @@ size_t clistr_push_fn(const char *function,
 
 size_t clistr_pull_fn(const char *function,
                        unsigned int line,
-                       struct cli_state *cli,
+                       const char *inbuf,
                        char *dest,
                        const void *src,
                        int dest_len,
                        int src_len,
                        int flags)
 {
-       return pull_string_fn(function, line, cli->inbuf,
-                             SVAL(cli->inbuf, smb_flg2), dest, src, dest_len,
+       return pull_string_fn(function, line, inbuf,
+                             SVAL(inbuf, smb_flg2), dest, src, dest_len,
                              src_len, flags);
 }
 
 size_t clistr_pull_talloc_fn(const char *function,
                                unsigned int line,
                                TALLOC_CTX *ctx,
-                               struct cli_state *cli,
+                               const char *inbuf,
                                char **pp_dest,
                                const void *src,
                                int src_len,
@@ -75,8 +75,8 @@ size_t clistr_pull_talloc_fn(const char *function,
        return pull_string_talloc_fn(function,
                                        line,
                                        ctx,
-                                       cli->inbuf,
-                                       SVAL(cli->inbuf, smb_flg2),
+                                       inbuf,
+                                       SVAL(inbuf, smb_flg2),
                                        pp_dest,
                                        src,
                                        src_len,
index dc038b6b95b3dca69dea51ea0cdfdfad8c031f7a..a025bb4197d2faff0c00ca21ffe4953702466a75 100644 (file)
@@ -1640,8 +1640,18 @@ void chain_reply(struct smb_request *req)
                /*
                 * In req->chain_outbuf we collect all the replies. Start the
                 * chain by copying in the first reply.
+                *
+                * We do the realloc because later on we depend on
+                * talloc_get_size to determine the length of
+                * chain_outbuf. The reply_xxx routines might have
+                * over-allocated (reply_pipe_read_and_X used to be such an
+                * example).
                 */
-               req->chain_outbuf = req->outbuf;
+               req->chain_outbuf = TALLOC_REALLOC_ARRAY(
+                       req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4);
+               if (req->chain_outbuf == NULL) {
+                       goto error;
+               }
                req->outbuf = NULL;
        } else {
                if (!smb_splice_chain(&req->chain_outbuf,