s4-winbindd: fixed handling of extra_data in s3 requests
authorAndrew Tridgell <tridge@samba.org>
Tue, 26 Jul 2011 00:51:31 +0000 (10:51 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 8 Sep 2011 13:09:54 +0000 (15:09 +0200)
extra_data in s3 winbind requests is appended to the end of the
request, but does not change the length header of the packet. Instead
you need to get it from the extra_len element of the request
structure.

Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>

source4/winbind/wb_samba3_protocol.c

index f0f803dac5df656ef848c11c89abb2f95757338f..6c89f340631cbe8427f7a4368a5742acf03b8fa1 100644 (file)
@@ -32,6 +32,8 @@
 NTSTATUS wbsrv_samba3_packet_full_request(void *private_data, DATA_BLOB blob, size_t *size)
 {
        uint32_t *len;
+       struct winbindd_request *req;
+
        if (blob.length < 4) {
                return STATUS_MORE_ENTRIES;
        }
@@ -40,13 +42,28 @@ NTSTATUS wbsrv_samba3_packet_full_request(void *private_data, DATA_BLOB blob, si
        if (*size > blob.length) {
                return STATUS_MORE_ENTRIES;
        }
+       if (*size < sizeof(req)) {
+               /* its not a valid winbind packet. We need to accept
+                  it here, and wbsrv_samba3_pull_request() will throw
+                  it away */
+               return NT_STATUS_OK;
+       }
+
+       /* now we need to cope with possible extra_data, which is
+          stuck on the end with no length prefix! This is a very very
+          stupid protocol */
+       req = (struct winbindd_request *)blob.data;
+       *size = (*len) + req->extra_len;
+       if (*size > blob.length) {
+               return STATUS_MORE_ENTRIES;
+       }
        return NT_STATUS_OK;
 }
 
 
 NTSTATUS wbsrv_samba3_pull_request(struct wbsrv_samba3_call *call)
 {
-       if (call->in.length != sizeof(*call->request)) {
+       if (call->in.length < sizeof(*call->request)) {
                DEBUG(0,("wbsrv_samba3_pull_request: invalid blob length %lu should be %lu\n"
                         " make sure you use the correct winbind client tools!\n",
                         (long)call->in.length, (long)sizeof(*call->request)));
@@ -59,6 +76,25 @@ NTSTATUS wbsrv_samba3_pull_request(struct wbsrv_samba3_call *call)
        /* the packet layout is the same as the in memory layout of the request, so just copy it */
        memcpy(call->request, call->in.data, sizeof(*call->request));
 
+       if (call->in.length != sizeof(*call->request) + call->request->extra_len) {
+               DEBUG(0,(__location__ " : invalid extra_len %u should be %u\n",
+                        call->request->extra_len, (unsigned)(call->in.length - sizeof(*call->request))));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* there may be extra data */
+       if (call->request->extra_len != 0) {
+               call->request->extra_data.data = talloc_size(call->request, call->request->extra_len+1);
+               NT_STATUS_HAVE_NO_MEMORY(call->request->extra_data.data);
+               /* guarantee a nul termination, as many of the uses of
+                  this field is for strings */
+               memcpy(call->request->extra_data.data, call->in.data + sizeof(*call->request),
+                      call->request->extra_len);
+               call->request->extra_data.data[call->request->extra_len] = 0;
+       } else {
+               call->request->extra_data.data = NULL;
+       }
+
        return NT_STATUS_OK;
 }