s3:smbd: allow status code in smbd_do_qfsinfo() to be set by information class handler
[metze/samba/wip.git] / source3 / smbd / trans2.c
index 7f0aaf982b2dde0803e983cd982c67ea6affb811..76176620800e2fcd06840e7f4ba87a1c77c7740d 100644 (file)
@@ -1253,6 +1253,20 @@ static void call_trans2open(connection_struct *conn,
                        reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
                        goto out;
                }
+
+               if (ea_list_has_invalid_name(ea_list)) {
+                       int param_len = 30;
+                       *pparams = (char *)SMB_REALLOC(*pparams, param_len);
+                       if(*pparams == NULL ) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               goto out;
+                       }
+                       params = *pparams;
+                       memset(params, '\0', param_len);
+                       send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
+                               params, param_len, NULL, 0, max_data_bytes);
+                       goto out;
+               }
        }
 
        status = SMB_VFS_CREATE_FILE(
@@ -2550,6 +2564,11 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                }
        }
 
+       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto out;
+       }
+
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
        if(*ppdata == NULL ) {
@@ -2879,6 +2898,11 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                }
        }
 
+       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
        if(*ppdata == NULL) {
@@ -3108,6 +3132,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
        uint32 additional_flags = 0;
        struct smb_filename smb_fname;
        SMB_STRUCT_STAT st;
+       NTSTATUS status = NT_STATUS_OK;
 
        if (fname == NULL || fname->base_name == NULL) {
                filename = ".";
@@ -3136,6 +3161,10 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
 
        st = smb_fname.st;
 
+       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
        if (*ppdata == NULL) {
@@ -3639,7 +3668,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
        }
 
        *ret_data_len = data_len;
-       return NT_STATUS_OK;
+       return status;
 }
 
 /****************************************************************************
@@ -4354,6 +4383,10 @@ static void call_trans2qpipeinfo(connection_struct *conn,
        }
        params = *pparams;
        SSVAL(params,0,0);
+       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
        data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
        *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
        if (*ppdata == NULL ) {
@@ -4435,6 +4468,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                nlink -= 1;
        }
 
+       if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
        data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
        *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
        if (*ppdata == NULL) {
@@ -8264,7 +8301,16 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
                        return;
                }
 
-               reply_nterror(req, status);
+               /*
+                * Invalid EA name needs to return 2 param bytes,
+                * not a zero-length error packet.
+                */
+               if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
+                       send_trans2_replies(conn, req, status, params, 2, NULL, 0,
+                                       max_data_bytes);
+               } else {
+                       reply_nterror(req, status);
+               }
                return;
        }