diff options
-rw-r--r-- | source4/winbind/wb_samba3_protocol.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/source4/winbind/wb_samba3_protocol.c b/source4/winbind/wb_samba3_protocol.c index f0f803dac5d..6c89f340631 100644 --- a/source4/winbind/wb_samba3_protocol.c +++ b/source4/winbind/wb_samba3_protocol.c @@ -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; } |