Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "headers.h"

SmbProcessResult
smbnegotiate(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *b)
{
        ushort index;
        int i;
        uchar bufferformat;

        if (!smbcheckwordcount("negotiate", h, 0))
                return SmbProcessResultFormat;
        if (s->state != SmbSessionNeedNegotiate) {
                /* this acts as a complete session reset */
                smblogprint(-1, "smbnegotiate: called when already negotiated\n");
                return SmbProcessResultUnimp;
        }
        i = 0;
        index = 0xffff;
        while (smbbuffergetb(b, &bufferformat)) {
                char *s;
                if (bufferformat != 0x02) {
                        smblogprint(-1, "smbnegotiate: unrecognised buffer format 0x%.2ux\n", bufferformat);
                        return SmbProcessResultFormat;
                }
                if (!smbbuffergetstr(b, 0, &s)) {
                        smblogprint(-1, "smbnegotiate: no null found\n");
                        return SmbProcessResultFormat;
                }
                smblogprint(h->command, "smbnegotiate: '%s'\n", s);
                if (index == 0xffff && strcmp(s, "NT LM 0.12") == 0)
                        index = i;
                i++;
                free(s);
        }
        if (index != 0xffff) {
                Tm *tm;
                ulong capabilities;
                ulong bytecountfixupoffset;

                h->wordcount = 17;
                if (!smbbufferputheader(s->response, h, nil)
                        || !smbbufferputs(s->response, index)
                        || !smbbufferputb(s->response, 3)                       /* user security, encrypted */
                        || !smbbufferputs(s->response, 1)                       /* max mux */
                        || !smbbufferputs(s->response, 1)                       /* max vc */
                        || !smbbufferputl(s->response, smbglobals.maxreceive)           /* max buffer size */
                        || !smbbufferputl(s->response, 0x10000)         /* max raw */
                        || !smbbufferputl(s->response, threadid()))     /* session key */
                        goto die;
                /* <= Win2k insist upon this being set to ensure that they observe the prototol (!) */
                capabilities = CAP_NT_SMBS;
                if (smbglobals.unicode)
                        capabilities |= CAP_UNICODE;
                tm = localtime(time(nil));
                s->tzoff = tm->tzoff;
                if (!smbbufferputl(s->response, capabilities)
                        || !smbbufferputv(s->response, nsec() / 100 + (vlong)10000000 * 11644473600LL)
                        || !smbbufferputs(s->response, -s->tzoff / 60)
                        || !smbbufferputb(s->response, 8))      /* crypt len */
                        goto die;
                bytecountfixupoffset = smbbufferwriteoffset(s->response);
                if (!smbbufferputs(s->response, 0))
                        goto die;
                s->cs = auth_challenge("proto=mschap role=server");
                if (s->cs == nil) {
                        smblogprint(h->command, "smbnegotiate: couldn't get mschap challenge\n");
                        return SmbProcessResultMisc;
                }
                if (s->cs->nchal != 8) {
                        smblogprint(h->command, "smbnegotiate: nchal %d\n", s->cs->nchal);
                        return SmbProcessResultMisc;
                }
                if (!smbbufferputbytes(s->response, s->cs->chal, s->cs->nchal)
                        || !smbbufferputstring(s->response, nil, SMB_STRING_UNICODE, smbglobals.primarydomain)
                        || !smbbufferfixuprelatives(s->response, bytecountfixupoffset))
                        goto die;
        }
        else {
                h->wordcount = 1;
                if (!smbbufferputheader(s->response, h, nil)
                        || !smbbufferputs(s->response, index)
                        || !smbbufferputs(s->response, 0))
                        goto die;
        }
        s->state = SmbSessionNeedSetup;
        return SmbProcessResultReply;
die:
        return SmbProcessResultDie;
}