winbindd: Do not use group_list->out.resume_index after free
[samba.git] / source4 / winbind / wb_samba3_protocol.c
index f0f803dac5df656ef848c11c89abb2f95757338f..1b78c99c1f942b1cb405490a4b639f0805d00e45 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;
 }
 
@@ -178,13 +214,15 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_samba3_call *s3call)
        case WINBINDD_PAM_LOGOFF:
                return wbsrv_samba3_pam_logoff(s3call);
 
+       case WINBINDD_SIDS_TO_XIDS:
+               return wbsrv_samba3_sids2xids(s3call);
+
        /* Unimplemented commands */
        case WINBINDD_GETPWSID:
        case WINBINDD_PAM_CHAUTHTOK:
        case WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP:
        case WINBINDD_LOOKUPRIDS:
        case WINBINDD_LOOKUPSIDS:
-       case WINBINDD_SIDS_TO_XIDS:
        case WINBINDD_ALLOCATE_UID:
        case WINBINDD_ALLOCATE_GID:
        case WINBINDD_SHOW_SEQUENCE:
@@ -259,6 +297,8 @@ NTSTATUS wbsrv_samba3_send_reply(struct wbsrv_samba3_call *call)
        struct tevent_req *subreq;
        NTSTATUS status;
 
+       call->wbconn->pending_calls--;
+
        status = wbsrv_samba3_push_reply(call);
        NT_STATUS_NOT_OK_RETURN(status);
 
@@ -317,9 +357,12 @@ NTSTATUS wbsrv_samba3_process(struct wbsrv_samba3_call *call)
                return status;
        }
 
+       call->wbconn->pending_calls++;
+
        status = wbsrv_samba3_handle_call(call);
 
        if (!NT_STATUS_IS_OK(status)) {
+               call->wbconn->pending_calls--;
                talloc_free(call);
                return status;
        }