1 #include "headers.h"
2 #include <mp.h>
3 #include <libsec.h>
4
5 SmbProcessResult
smbcomsessionsetupandx(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)6 smbcomsessionsetupandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
7 {
8 uchar andxcommand;
9 ushort andxoffset;
10 ulong andxfixupoffset;
11 ushort vcnumber;
12 ulong sessionkey;
13 ushort caseinsensitivepasswordlength;
14 ushort casesensitivepasswordlength;
15 ushort bytecountfixup, offset;
16 uchar *mschapreply;
17 AuthInfo *ai;
18 char *sp;
19 SmbProcessResult pr;
20 char *accountname = nil;
21 char *primarydomain = nil;
22 char *nativeos = nil;
23 char *nativelanman = nil;
24
25 if (!smbcheckwordcount("comsessionsetupandx", h, 13)) {
26 fmtfail:
27 pr = SmbProcessResultFormat;
28 goto done;
29 }
30
31 andxcommand = *pdata++;
32 switch (andxcommand) {
33 case SMB_COM_TREE_CONNECT_ANDX:
34 case SMB_COM_OPEN_ANDX:
35 case SMB_COM_CREATE_NEW:
36 case SMB_COM_DELETE:
37 case SMB_COM_FIND:
38 case SMB_COM_COPY:
39 case SMB_COM_NT_RENAME:
40 case SMB_COM_QUERY_INFORMATION:
41 case SMB_COM_NO_ANDX_COMMAND:
42 case SMB_COM_OPEN:
43 case SMB_COM_CREATE:
44 case SMB_COM_CREATE_DIRECTORY:
45 case SMB_COM_DELETE_DIRECTORY:
46 case SMB_COM_FIND_UNIQUE:
47 case SMB_COM_RENAME:
48 case SMB_COM_CHECK_DIRECTORY:
49 case SMB_COM_SET_INFORMATION:
50 case SMB_COM_OPEN_PRINT_FILE:
51 break;
52 default:
53 smblogprint(h->command, "smbcomsessionsetupandx: invalid andxcommand %s (0x%.2ux)\n",
54 smboptable[andxcommand].name, andxcommand);
55 goto fmtfail;
56 }
57 pdata++;
58 andxoffset = smbnhgets(pdata); pdata += 2;
59 s->peerinfo.maxlen = smbnhgets(pdata); pdata += 2;
60 smbresponseinit(s, s->peerinfo.maxlen);
61 s->client.maxmpxcount = smbnhgets(pdata); pdata += 2;
62 vcnumber = smbnhgets(pdata); pdata += 2;
63 sessionkey = smbnhgetl(pdata); pdata += 4;
64 caseinsensitivepasswordlength = smbnhgets(pdata); pdata += 2;
65 casesensitivepasswordlength = smbnhgets(pdata); pdata += 2;
66 pdata += 4;
67 s->peerinfo.capabilities = smbnhgetl(pdata); /*pdata += 4;*/
68 smbloglock();
69 smblogprint(h->command, "andxcommand: %s offset %ud\n", smboptable[andxcommand].name, andxoffset);
70 smblogprint(h->command, "client.maxbuffersize: %ud\n", s->peerinfo.maxlen);
71 smblogprint(h->command, "client.maxmpxcount: %ud\n", s->client.maxmpxcount);
72 smblogprint(h->command, "vcnumber: %ud\n", vcnumber);
73 smblogprint(h->command, "sessionkey: 0x%.8lux\n", sessionkey);
74 smblogprint(h->command, "caseinsensitivepasswordlength: %ud\n", caseinsensitivepasswordlength);
75 smblogprint(h->command, "casesensitivepasswordlength: %ud\n", casesensitivepasswordlength);
76 smblogprint(h->command, "clientcapabilities: 0x%.8lux\n", s->peerinfo.capabilities);
77 smblogunlock();
78
79 mschapreply = smbbufferreadpointer(b);
80
81 if (!smbbuffergetbytes(b, nil, caseinsensitivepasswordlength + casesensitivepasswordlength)) {
82 smblogprint(h->command, "smbcomsessionsetupandx: not enough bdata for passwords\n");
83 goto fmtfail;
84 }
85 if (!smbbuffergetstring(b, h, 0, &accountname)
86 || !smbbuffergetstring(b, h, 0, &primarydomain)
87 || !smbbuffergetstring(b, h, 0, &nativeos)
88 || !smbbuffergetstring(b, h, 0, &nativelanman)) {
89 smblogprint(h->command, "smbcomsessionsetupandx: not enough bytes for strings\n");
90 goto fmtfail;
91 }
92
93 for (sp = accountname; *sp; sp++)
94 *sp = tolower(*sp);
95
96 smblogprint(h->command, "account: %s\n", accountname);
97 smblogprint(h->command, "primarydomain: %s\n", primarydomain);
98 smblogprint(h->command, "nativeos: %s\n", nativeos);
99 smblogprint(h->command, "nativelanman: %s\n", nativelanman);
100
101 if (s->client.accountname && accountname[0] && strcmp(s->client.accountname, accountname) != 0) {
102 smblogprint(h->command, "smbcomsessionsetupandx: more than one user on VC (before %s, now %s)\n",
103 s->client.accountname, accountname);
104 smbseterror(s, ERRSRV, ERRtoomanyuids);
105 errordone:
106 pr = SmbProcessResultError;
107 goto done;
108 }
109
110 if (s->client.accountname == nil) {
111 /* first time */
112 if (accountname[0] == 0) {
113 smbseterror(s, ERRSRV, ERRbaduid);
114 goto errordone;
115 }
116 if ((casesensitivepasswordlength != 24 || caseinsensitivepasswordlength != 24)) {
117 smblogprint(h->command,
118 "smbcomsessionsetupandx: case sensitive/insensitive password length not 24\n");
119 smbseterror(s, ERRSRV, ERRbadpw);
120 goto errordone;
121 }
122 memcpy(&s->client.mschapreply, mschapreply, sizeof(s->client.mschapreply));
123 if(s->cs == nil){
124 smbseterror(s, ERRSRV, ERRerror);
125 goto errordone;
126 }
127 s->cs->user = accountname;
128 s->cs->resp = &s->client.mschapreply;
129 s->cs->nresp = sizeof(MSchapreply);
130 ai = auth_response(s->cs);
131 if (ai == nil) {
132 smblogprint(h->command, "authentication failed\n");
133 smbseterror(s, ERRSRV, ERRbadpw);
134 goto errordone;
135 }
136 smblogprint(h->command, "authentication succeeded\n");
137 if (auth_chuid(ai, nil) < 0) {
138 smblogprint(h->command, "smbcomsessionsetupandx: chuid failed: %r\n");
139 auth_freeAI(ai);
140 miscerror:
141 pr = SmbProcessResultMisc;
142 goto done;
143 }
144 auth_freeAI(ai);
145 h->uid = 1;
146 s->client.accountname = accountname;
147 s->client.primarydomain = primarydomain;
148 s->client.nativeos = nativeos;
149 s->client.nativelanman = nativelanman;
150 accountname = nil;
151 primarydomain = nil;
152 nativeos = nil;
153 nativelanman = nil;
154 }
155 else {
156 if (caseinsensitivepasswordlength == 24 && casesensitivepasswordlength == 24
157 && memcmp(&s->client.mschapreply, mschapreply, sizeof(MSchapreply)) != 0) {
158 smblogprint(h->command, "second time authentication failed\n");
159 smbseterror(s, ERRSRV, ERRbadpw);
160 goto errordone;
161 }
162 }
163
164 /* CIFS says 4 with or without extended security, samba/ms says 3 without */
165 h->wordcount = 3;
166 if (!smbresponseputandxheader(s, h, andxcommand, &andxfixupoffset))
167 goto miscerror;
168 if (!smbresponseputs(s, 0))
169 goto miscerror;
170 bytecountfixup = smbresponseoffset(s);
171 if (!smbresponseputs(s, 0))
172 goto miscerror;
173 if (!smbresponseputstring(s, 1, smbglobals.nativeos)
174 || !smbresponseputstring(s, 1, smbglobals.serverinfo.nativelanman)
175 || !smbresponseputstring(s, 1, smbglobals.primarydomain))
176 goto miscerror;
177 offset = smbresponseoffset(s);
178 smbresponseoffsetputs(s, bytecountfixup, offset - bytecountfixup - 2);
179 s->state = SmbSessionEstablished;
180 if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
181 pr = smbchaincommand(s, h, andxfixupoffset, andxcommand, andxoffset, b);
182 else
183 pr = SmbProcessResultReply;
184 done:
185 free(accountname);
186 free(primarydomain);
187 free(nativeos);
188 free(nativelanman);
189 return pr;
190 }
191