Subversion Repositories planix.SVN

Rev

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

Rev Author Line No. Line
2 - 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
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
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
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 *
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
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
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
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 *
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
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
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
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
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
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
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
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
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
}