#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;
}
|