Read beyond end of buffer in init_id_info2()

Martin Buck at
Tue Feb 22 13:44:32 GMT 2005


I'm still struggling with my "Samba can't authenticate XP clients with
lmcompatibilitylevel=3 against NT4 SP6a PDC" problem (see ).

While debugging this, I had a closer look at init_id_info2(). In my case,
this gets called with nt_chal_resp_len = 164, which will cause a read
beyond the end of a buffer on the stack. Annotated source code follows:

void init_id_info2(NET_ID_INFO_2 * id, const char *domain_name,
                   uint32 param_ctrl,
                   uint32 log_id_low, uint32 log_id_high,
                   const char *user_name, const char *wksta_name,
                   const uchar lm_challenge[8],
                   const uchar * lm_chal_resp, size_t lm_chal_resp_len,
                   const uchar * nt_chal_resp, size_t nt_chal_resp_len)
        unsigned char lm_owf[24]; 
        unsigned char nt_owf[128];

        DEBUG(5,("init_id_info2: %d\n", __LINE__));

        id->ptr_id_info2 = 1;

        id->param_ctrl = param_ctrl;
        init_logon_id(&id->logon_id, log_id_low, log_id_high);

        if (nt_chal_resp) {
                /* oops.  can only send what-ever-it-is direct */
                memcpy(nt_owf, nt_chal_resp, MIN(sizeof(nt_owf), nt_chal_resp_len));
                nt_chal_resp = nt_owf;
        if (lm_chal_resp) {
                /* oops.  can only send what-ever-it-is direct */
                memcpy(lm_owf, lm_chal_resp, MIN(sizeof(lm_owf), lm_chal_resp_len));

*** This copy will truncate nt_chal_resp, because sizeof lm_owf is only 128
*** bytes. Note that even when truncating, lm_chal_resp_len isn't adjusted.

                lm_chal_resp = lm_owf;

        memcpy(id->lm_chal, lm_challenge, sizeof(id->lm_chal));
        init_str_hdr(&id->hdr_nt_chal_resp, nt_chal_resp_len, nt_chal_resp_len, (nt_chal_resp != NULL) ? 1 : 0);
        init_str_hdr(&id->hdr_lm_chal_resp, lm_chal_resp_len, lm_chal_resp_len, (lm_chal_resp != NULL) ? 1 : 0);

        init_unistr2(&id->uni_domain_name, domain_name, UNI_FLAGS_NONE);
        init_uni_hdr(&id->hdr_domain_name, &id->uni_domain_name);
        init_unistr2(&id->uni_user_name, user_name, UNI_FLAGS_NONE);
        init_uni_hdr(&id->hdr_user_name, &id->uni_user_name);
        init_unistr2(&id->uni_wksta_name, wksta_name, UNI_FLAGS_NONE);
        init_uni_hdr(&id->hdr_wksta_name, &id->uni_wksta_name);

        init_string2(&id->nt_chal_resp, (const char *)nt_chal_resp, nt_chal_resp_len, nt_chal_resp_len);
        init_string2(&id->lm_chal_resp, (const char *)lm_chal_resp, lm_chal_resp_len, lm_chal_resp_len);

*** Since lm_chal_resp now points to lm_owf, we use the 128 byte buffer,
*** but the original lm_chal_resp_len value of 164. init_string2() will
*** do a memcpy() with the length we passed to it. Bad.


Can anyone confirm that this is a bug and I'm not missing something

What's the use of lm_owf and nt_owf anyway? We never seem to modify them
after the initial memcpy(), so we could simply use the original buffers.

Is nobody using Samba with NTLMv2, which seems to be the reason for
nt_chal_resp_len = 164? Even if the read beyond the buffer doesn't cause a
crash, memcpy() will copy random memory, so this should should kill the
challenge/response, causing authentication to fail.

BTW, I've tried increasing nt_owf's size to 164, but Samba still can't
authenticate my XP clients. Any suggestions concerning this issue?


More information about the samba-technical mailing list