1 #include "headers.h"
2
3 SmbProcessResult
smbnegotiate(SmbSession * s,SmbHeader * h,uchar *,SmbBuffer * b)4 smbnegotiate(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *b)
5 {
6 ushort index;
7 int i;
8 uchar bufferformat;
9
10 if (!smbcheckwordcount("negotiate", h, 0))
11 return SmbProcessResultFormat;
12 if (s->state != SmbSessionNeedNegotiate) {
13 /* this acts as a complete session reset */
14 smblogprint(-1, "smbnegotiate: called when already negotiated\n");
15 return SmbProcessResultUnimp;
16 }
17 i = 0;
18 index = 0xffff;
19 while (smbbuffergetb(b, &bufferformat)) {
20 char *s;
21 if (bufferformat != 0x02) {
22 smblogprint(-1, "smbnegotiate: unrecognised buffer format 0x%.2ux\n", bufferformat);
23 return SmbProcessResultFormat;
24 }
25 if (!smbbuffergetstr(b, 0, &s)) {
26 smblogprint(-1, "smbnegotiate: no null found\n");
27 return SmbProcessResultFormat;
28 }
29 smblogprint(h->command, "smbnegotiate: '%s'\n", s);
30 if (index == 0xffff && strcmp(s, "NT LM 0.12") == 0)
31 index = i;
32 i++;
33 free(s);
34 }
35 if (index != 0xffff) {
36 Tm *tm;
37 ulong capabilities;
38 ulong bytecountfixupoffset;
39
40 h->wordcount = 17;
41 if (!smbbufferputheader(s->response, h, nil)
42 || !smbbufferputs(s->response, index)
43 || !smbbufferputb(s->response, 3) /* user security, encrypted */
44 || !smbbufferputs(s->response, 1) /* max mux */
45 || !smbbufferputs(s->response, 1) /* max vc */
46 || !smbbufferputl(s->response, smbglobals.maxreceive) /* max buffer size */
47 || !smbbufferputl(s->response, 0x10000) /* max raw */
48 || !smbbufferputl(s->response, threadid())) /* session key */
49 goto die;
50 /* <= Win2k insist upon this being set to ensure that they observe the prototol (!) */
51 capabilities = CAP_NT_SMBS;
52 if (smbglobals.unicode)
53 capabilities |= CAP_UNICODE;
54 tm = localtime(time(nil));
55 s->tzoff = tm->tzoff;
56 if (!smbbufferputl(s->response, capabilities)
57 || !smbbufferputv(s->response, nsec() / 100 + (vlong)10000000 * 11644473600LL)
58 || !smbbufferputs(s->response, -s->tzoff / 60)
59 || !smbbufferputb(s->response, 8)) /* crypt len */
60 goto die;
61 bytecountfixupoffset = smbbufferwriteoffset(s->response);
62 if (!smbbufferputs(s->response, 0))
63 goto die;
64 s->cs = auth_challenge("proto=mschap role=server");
65 if (s->cs == nil) {
66 smblogprint(h->command, "smbnegotiate: couldn't get mschap challenge\n");
67 return SmbProcessResultMisc;
68 }
69 if (s->cs->nchal != 8) {
70 smblogprint(h->command, "smbnegotiate: nchal %d\n", s->cs->nchal);
71 return SmbProcessResultMisc;
72 }
73 if (!smbbufferputbytes(s->response, s->cs->chal, s->cs->nchal)
74 || !smbbufferputstring(s->response, nil, SMB_STRING_UNICODE, smbglobals.primarydomain)
75 || !smbbufferfixuprelatives(s->response, bytecountfixupoffset))
76 goto die;
77 }
78 else {
79 h->wordcount = 1;
80 if (!smbbufferputheader(s->response, h, nil)
81 || !smbbufferputs(s->response, index)
82 || !smbbufferputs(s->response, 0))
83 goto die;
84 }
85 s->state = SmbSessionNeedSetup;
86 return SmbProcessResultReply;
87 die:
88 return SmbProcessResultDie;
89 }
90