1 #include "headers.h"
2
3 typedef struct RapTableEntry RapTableEntry;
4
5 struct RapTableEntry {
6 char *name;
7 SmbProcessResult (*procedure)(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata);
8 };
9
10 typedef int INFOSIZEFN(ushort level, void *data);
11 typedef int INFOPUTFN(SmbBuffer *b, ushort level, void *data);
12 typedef int INFOPUTSTRINGSFN(SmbBuffer *b, ushort level, int instance, void *data);
13 typedef void *INFOENUMERATEFN(void *magic, int i);
14
15 typedef struct InfoMethod {
16 INFOSIZEFN *size;
17 INFOPUTFN *put;
18 INFOPUTSTRINGSFN *putstrings;
19 INFOENUMERATEFN *enumerate;
20 } InfoMethod;
21
22 static int
serverinfosize(ushort level,void * data)23 serverinfosize(ushort level, void *data)
24 {
25 SmbServerInfo *si = data;
26 switch (level) {
27 case 0:
28 return 16;
29 case 1:
30 return 26 + smbstrlen(si->remark);
31 default:
32 return 0;
33 }
34 }
35
36 static int
serverinfoput(SmbBuffer * b,ushort level,void * data)37 serverinfoput(SmbBuffer *b, ushort level, void *data)
38 {
39 SmbServerInfo *si = data;
40 if (!smbbufferputstrn(b, si->name, 16, 1))
41 return 0;
42 if (level > 0) {
43 if (!smbbufferputb(b, si->vmaj)
44 || !smbbufferputb(b, si->vmin)
45 || !smbbufferputl(b, si->stype)
46 || !smbbufferputl(b, 0))
47 return 0;
48 }
49 if (level > 1)
50 return 0;
51 return 1;
52 }
53
54 static int
serverinfoputstrings(SmbBuffer * b,ushort level,int instance,void * data)55 serverinfoputstrings(SmbBuffer *b, ushort level, int instance, void *data)
56 {
57 SmbServerInfo *si = data;
58 if (level == 1) {
59 if (!smbbufferfixupabsolutel(b, instance * 26 + 22)
60 || !smbbufferputstring(b, nil, SMB_STRING_ASCII, si->remark))
61 return 0;
62 }
63 return 1;
64 }
65
66 static void *
serverinfoenumerate(void * magic,int i)67 serverinfoenumerate(void *magic, int i)
68 {
69 if (magic) {
70 SmbServerInfo **si = magic;
71 return si[i];
72 }
73 if (i == 0)
74 return &smbglobals.serverinfo;
75 return nil;
76 }
77
78 InfoMethod serverinfo = {
79 serverinfosize,
80 serverinfoput,
81 serverinfoputstrings,
82 serverinfoenumerate,
83 };
84
85 static int
shareinfosize(ushort level,void * data)86 shareinfosize(ushort level, void *data)
87 {
88 SmbService *serv = data;
89 switch (level) {
90 case 0:
91 return 13;
92 case 1:
93 return 20 + smbstrlen(serv->remark);
94 case 2:
95 return 40 + smbstrlen(serv->remark) + smbstrlen(serv->path);
96 default:
97 return 0;
98 }
99 }
100
101 static int
shareinfoput(SmbBuffer * b,ushort level,void * data)102 shareinfoput(SmbBuffer *b, ushort level, void *data)
103 {
104 SmbService *serv = data;
105 if (!smbbufferputstrn(b, serv->name, 13, 0))
106 return 0;
107 if (level > 0) {
108 if (!smbbufferputb(b, 0)
109 || !smbbufferputs(b, serv->stype)
110 || !smbbufferputl(b, 0))
111 return 0;
112 }
113 if (level > 1) {
114 if (!smbbufferputs(b, 7)
115 || !smbbufferputs(b, -1)
116 || !smbbufferputs(b, serv->ref)
117 || !smbbufferputl(b, 0)
118 || !smbbufferfill(b, 0, 10))
119 return 0;
120 }
121 if (level > 2)
122 return 0;
123 return 1;
124 }
125
126 static int
shareinfoputstrings(SmbBuffer * b,ushort level,int instance,void * data)127 shareinfoputstrings(SmbBuffer *b, ushort level, int instance, void *data)
128 {
129 SmbService *serv = data;
130 switch (level) {
131 case 0:
132 break;
133 case 1:
134 if (!smbbufferfixupabsolutel(b, instance * 20 + 16)
135 || !smbbufferputstring(b, nil, SMB_STRING_ASCII, serv->remark))
136 return 0;
137 break;
138 case 2:
139 if (!smbbufferfixupabsolutel(b, instance * 40 + 16)
140 || !smbbufferputstring(b, nil, SMB_STRING_ASCII, serv->remark)
141 || !smbbufferfixupabsolutel(b, instance * 40 + 26)
142 || !smbbufferputstring(b, nil, SMB_STRING_ASCII, serv->path))
143 return 0;
144 break;
145 default:
146 return 0;
147 }
148 return 1;
149 }
150
151 static void *
shareinfoenumerate(void *,int i)152 shareinfoenumerate(void *, int i)
153 {
154 SmbService *serv;
155 for (serv = smbservices; i-- > 0 && serv; serv = serv->next)
156 ;
157 return serv;
158 }
159
160 static InfoMethod shareinfo = {
161 shareinfosize,
162 shareinfoput,
163 shareinfoputstrings,
164 shareinfoenumerate,
165 };
166
167 static SmbProcessResult
thingfill(SmbBuffer * outparam,SmbBuffer * outdata,InfoMethod * m,ushort level,void * magic)168 thingfill(SmbBuffer *outparam, SmbBuffer *outdata, InfoMethod *m, ushort level, void *magic)
169 {
170 int sentthings, totalthings;
171 int i;
172 int totalbytes;
173
174 sentthings = 0;
175 totalbytes = 0;
176 for (i = 0; ; i++) {
177 int len;
178 void *thing = (*m->enumerate)(magic, i);
179 if (thing == nil)
180 break;
181 len = (*m->size)(level, thing);
182 if (totalbytes + len <= smbbufferspace(outdata)) {
183 assert((*m->put)(outdata, level, thing));
184 sentthings++;
185 }
186 totalbytes += len;
187 }
188 totalthings = i;
189 for (i = 0; i < sentthings; i++) {
190 void *thing = (*m->enumerate)(magic, i);
191 assert(thing);
192 assert((*m->putstrings)(outdata, level, i, thing));
193 }
194 if (!smbbufferputs(outparam, sentthings < totalthings ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
195 || !smbbufferputs(outparam, 0)
196 || !smbbufferputs(outparam, totalthings)
197 || !smbbufferputs(outparam, sentthings))
198 return SmbProcessResultFormat;
199 return SmbProcessResultReply;
200 }
201
202 static SmbProcessResult
onethingfill(SmbBuffer * outparam,SmbBuffer * outdata,InfoMethod * m,ushort level,void * thing)203 onethingfill(SmbBuffer *outparam, SmbBuffer *outdata, InfoMethod *m, ushort level, void *thing)
204 {
205 int moredata;
206 int totalbytes = (*m->size)(level, thing);
207 if (totalbytes <= smbbufferspace(outdata)) {
208 assert((*m->put)(outdata, level, thing));
209 assert((*m->putstrings)(outdata, level, 0, thing));
210 moredata = 0;
211 }
212 else
213 moredata = 1;
214 if (!smbbufferputs(outparam, moredata ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
215 || !smbbufferputs(outparam, 0)
216 || !smbbufferputs(outparam, totalbytes))
217 return SmbProcessResultFormat;
218 return SmbProcessResultReply;
219 }
220
221 static SmbProcessResult
netshareenum(SmbBuffer * inparam,SmbBuffer * outparam,SmbBuffer * outdata)222 netshareenum(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
223 {
224 ushort level;
225
226 /* WrLeh */
227 /* ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, ushort *pcTotalAvail */
228
229 if (!smbbuffergets(inparam, &level))
230 return SmbProcessResultFormat;
231
232 smblogprintif(smbglobals.log.rap2, "netshareenum(%lud, %lud)\n",
233 level, smbbufferwritespace(outdata));
234
235 if (level != 1)
236 return SmbProcessResultFormat;
237
238 return thingfill(outparam, outdata, &shareinfo, level, nil);
239 }
240
241 static SmbProcessResult
netserverenum2(SmbBuffer * inparam,SmbBuffer * outparam,SmbBuffer * outdata)242 netserverenum2(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
243 {
244 ushort level, rbl;
245 char *domain;
246 ulong servertype;
247 SmbProcessResult pr;
248 SmbServerInfo *si[3];
249 SmbServerInfo domainsi;
250 int entries;
251
252 /* WrLehDz
253 * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, ushort *pcTotalAvail,
254 * ulong fServerType, char *pszDomain
255 */
256
257 if (!smbbuffergets(inparam, &level)
258 || !smbbuffergets(inparam, &rbl)
259 || !smbbuffergetl(inparam, &servertype)
260 || !smbbuffergetstr(inparam, 0, &domain)) {
261 fmtfail:
262 pr = SmbProcessResultFormat;
263 goto done;
264 }
265
266 smblogprintif(smbglobals.log.rap2, "netserverenum2(%lud, %lud, 0x%.8lux, %s)\n",
267 level, smbbufferwritespace(outdata), servertype, domain);
268
269 if (level > 1)
270 goto fmtfail;
271
272 if (servertype == 0xffffffff)
273 servertype &= ~(SV_TYPE_DOMAIN_ENUM | SV_TYPE_LOCAL_LIST_ONLY);
274
275 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0 && (servertype & SV_TYPE_DOMAIN_ENUM) == 0)
276 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
277
278 entries = 0;
279
280 if ((servertype & SV_TYPE_SERVER) != 0
281 && (domain[0] == 0 || cistrcmp(domain, smbglobals.primarydomain) == 0)) {
282 si[entries++] = &smbglobals.serverinfo;
283 }
284
285 if ((servertype & SV_TYPE_DOMAIN_ENUM) != 0) {
286 /* there's only one that I know about */
287 memset(&domainsi, 0, sizeof(domainsi));
288 domainsi.name = smbglobals.primarydomain;
289 domainsi.stype = SV_TYPE_DOMAIN_ENUM;
290 si[entries++] = &domainsi;
291 }
292 si[entries] = 0;
293
294 pr = thingfill(outparam, outdata, &serverinfo, level, si);
295
296 done:
297 free(domain);
298 return pr;
299 }
300
301 static SmbProcessResult
netsharegetinfo(SmbBuffer * inparam,SmbBuffer * outparam,SmbBuffer * outdata)302 netsharegetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
303 {
304 char *netname;
305 ushort level;
306 SmbProcessResult pr;
307 SmbService *serv;
308
309 /*
310 * zWrLh
311 * char *pszNetName, ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
312 */
313
314 if (!smbbuffergetstrinline(inparam, &netname)
315 || !smbbuffergets(inparam, &level)) {
316 fmtfail:
317 pr = SmbProcessResultFormat;
318 goto done;
319 }
320
321 smblogprintif(smbglobals.log.rap2, "netsharegetinfo(%s, %lud, %lud)\n",
322 netname, level, smbbufferwritespace(outdata));
323
324 if (level > 2)
325 goto fmtfail;
326
327 for (serv = smbservices; serv; serv = serv->next)
328 if (cistrcmp(serv->name, netname) == 0)
329 break;
330
331 if (serv == nil) {
332 smblogprint(-1, "netsharegetinfo: service %s unimplemented\n", netname);
333 pr = SmbProcessResultUnimp;
334 goto done;
335 }
336
337 pr = onethingfill(outparam, outdata, &shareinfo, level, serv);
338
339 done:
340 return pr;
341 }
342
343 static SmbProcessResult
netservergetinfo(SmbBuffer * inparam,SmbBuffer * outparam,SmbBuffer * outdata)344 netservergetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
345 {
346 ushort level;
347 SmbProcessResult pr;
348
349 /* WrLh
350 * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
351 */
352
353 if (!smbbuffergets(inparam, &level)) {
354 fmtfail:
355 pr = SmbProcessResultFormat;
356 goto done;
357 }
358
359 smblogprintif(smbglobals.log.rap2, "netservergetinfo(%lud, %lud)\n",
360 level, smbbufferwritespace(outdata));
361
362 if (level > 1)
363 goto fmtfail;
364
365 pr = onethingfill(outparam, outdata, &shareinfo, level, &smbglobals.serverinfo);
366
367 done:
368 return pr;
369 }
370
371 static SmbProcessResult
netwkstagetinfo(SmbBuffer * inparam,SmbBuffer * outparam,SmbBuffer * outdata)372 netwkstagetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
373 {
374 ushort level;
375 ushort usefulbytes;
376 SmbProcessResult pr;
377 int moredata;
378
379 /* WrLh
380 * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
381 */
382
383 if (!smbbuffergets(inparam, &level)) {
384 fmtfail:
385 pr = SmbProcessResultFormat;
386 goto done;
387 }
388
389 smblogprintif(smbglobals.log.rap2, "netwkstagetinfo(%lud, %lud)\n",
390 level, smbbufferwritespace(outdata));
391
392 if (level != 10)
393 goto fmtfail;
394
395 usefulbytes = 22 + smbstrlen(smbglobals.serverinfo.name) + smbstrlen(getuser())
396 + 3 * smbstrlen(smbglobals.primarydomain);
397
398 moredata = usefulbytes > smbbufferwritespace(outdata);
399
400 assert(smbbufferputl(outdata, 0));
401 assert(smbbufferputl(outdata, 0));
402 assert(smbbufferputl(outdata, 0));
403 assert(smbbufferputb(outdata, smbglobals.serverinfo.vmaj));
404 assert(smbbufferputb(outdata, smbglobals.serverinfo.vmin));
405 assert(smbbufferputl(outdata, 0));
406 assert(smbbufferputl(outdata, 0));
407 assert(smbbufferfixupabsolutel(outdata, 0));
408 assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.serverinfo.name));
409 assert(smbbufferfixupabsolutel(outdata, 4));
410 assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, getuser()));
411 assert(smbbufferfixupabsolutel(outdata, 8));
412 assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
413 assert(smbbufferfixupabsolutel(outdata, 14));
414 assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
415 assert(smbbufferfixupabsolutel(outdata, 18));
416 assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
417
418 if (!smbbufferputs(outparam, moredata ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
419 || !smbbufferputs(outparam, 0)
420 || !smbbufferputs(outparam, usefulbytes)) {
421 pr = SmbProcessResultFormat;
422 goto done;
423 }
424
425 pr = SmbProcessResultReply;
426
427 done:
428 return pr;
429 }
430
431 static RapTableEntry raptable[] = {
432 [RapNetShareGetInfo] { "NetShareGetInfo", netsharegetinfo },
433 [RapNetShareEnum] { "NetShareEnum", netshareenum },
434 [RapNetServerGetInfo] {"NetServerGetInfo", netservergetinfo },
435 [RapNetWkstaGetInfo] { "NetWkstaGetInfo", netwkstagetinfo },
436 [RapNetServerEnum2] { "NetServerEnum2", netserverenum2 },
437 };
438
439 SmbProcessResult
smbrap2(SmbSession * s)440 smbrap2(SmbSession *s)
441 {
442 char *pstring;
443 char *dstring;
444 ushort pno;
445 RapTableEntry *e;
446 SmbProcessResult pr;
447 SmbBuffer *inparam;
448
449 inparam = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
450 if (!smbbuffergets(inparam, &pno)
451 || !smbbuffergetstrinline(inparam, &pstring)
452 || !smbbuffergetstrinline(inparam, &dstring)) {
453 smblogprintif(smbglobals.log.rap2, "smbrap2: not enough parameters\n");
454 pr = SmbProcessResultFormat;
455 goto done;
456 }
457 if (pno > nelem(raptable) || raptable[pno].name == nil) {
458 smblogprint(-1, "smbrap2: unsupported procedure %ud\n", pno);
459 pr = SmbProcessResultUnimp;
460 goto done;
461 }
462 e = raptable + pno;
463 pr = (*e->procedure)(inparam, s->transaction.out.parameters, s->transaction.out.data);
464 done:
465 smbbufferfree(&inparam);
466 return pr;
467 }
468