2 |
- |
1 |
#include "headers.h"
|
|
|
2 |
|
|
|
3 |
static void
|
|
|
4 |
smblogprintattr(int cmd, ushort attr)
|
|
|
5 |
{
|
|
|
6 |
if (attr & SMB_ATTR_READ_ONLY)
|
|
|
7 |
smblogprint(cmd, " readonly");
|
|
|
8 |
if (attr & SMB_ATTR_HIDDEN)
|
|
|
9 |
smblogprint(cmd, " hidden");
|
|
|
10 |
if (attr & SMB_ATTR_SYSTEM)
|
|
|
11 |
smblogprint(cmd, " system");
|
|
|
12 |
if (attr & SMB_ATTR_DIRECTORY)
|
|
|
13 |
smblogprint(cmd, " directory");
|
|
|
14 |
if (attr & SMB_ATTR_ARCHIVE)
|
|
|
15 |
smblogprint(cmd, " archive");
|
|
|
16 |
}
|
|
|
17 |
|
|
|
18 |
static SmbFile *
|
|
|
19 |
openfile(SmbSession *s, SmbTree *t, char *path, ushort mode, ushort attr, ushort ofun, ulong createoptions, uvlong createsize,
|
|
|
20 |
ushort *fidp, Dir **dp, ushort *actionp)
|
|
|
21 |
{
|
|
|
22 |
int p9mode;
|
|
|
23 |
int share;
|
|
|
24 |
Dir *d = nil;
|
|
|
25 |
int fd = -1;
|
|
|
26 |
ushort action;
|
|
|
27 |
SmbFile *f = nil;
|
|
|
28 |
SmbSharedFile *sf = nil;
|
|
|
29 |
char *fullpath = nil;
|
|
|
30 |
int diropen = 0;
|
|
|
31 |
|
|
|
32 |
//smblogprint(-1, "%s A %r", path);
|
|
|
33 |
p9mode = (mode >> SMB_OPEN_MODE_ACCESS_SHIFT) & SMB_OPEN_MODE_ACCESS_MASK;
|
|
|
34 |
share = (mode >> SMB_OPEN_MODE_SHARE_SHIFT) & SMB_OPEN_MODE_SHARE_MASK;
|
|
|
35 |
if (share == SMB_OPEN_MODE_SHARE_COMPATIBILITY) {
|
|
|
36 |
badshare:
|
|
|
37 |
//smblogprint(-1, "%s SMB_OPEN_MODE_SHARE_COMPATIBILITY", path);
|
|
|
38 |
smbseterror(s, ERRDOS, ERRbadshare);
|
|
|
39 |
goto done;
|
|
|
40 |
}
|
|
|
41 |
smbstringprint(&fullpath, "%s%s", t->serv->path, path);
|
|
|
42 |
d = dirstat(fullpath);
|
|
|
43 |
if (d) {
|
|
|
44 |
/* file exists */
|
|
|
45 |
int ofunexist;
|
|
|
46 |
if (d->mode & DMDIR) {
|
|
|
47 |
if (createoptions & SMB_CO_FILE) {
|
|
|
48 |
smbseterror(s, ERRDOS, ERRnoaccess);
|
|
|
49 |
goto done;
|
|
|
50 |
}
|
|
|
51 |
}
|
|
|
52 |
else if (createoptions & SMB_CO_DIRECTORY) {
|
|
|
53 |
smbseterror(s, ERRDOS, ERRnoaccess);
|
|
|
54 |
goto done;
|
|
|
55 |
}
|
|
|
56 |
|
|
|
57 |
sf = smbsharedfileget(d, p9mode, &share);
|
|
|
58 |
if (sf == nil)
|
|
|
59 |
goto badshare;
|
|
|
60 |
action = 1;
|
|
|
61 |
ofunexist = (ofun >> SMB_OFUN_EXIST_SHIFT) & SMB_OFUN_EXIST_MASK;
|
|
|
62 |
if (ofunexist == SMB_OFUN_EXIST_FAIL) {
|
|
|
63 |
smbseterror(s, ERRDOS, ERRfilexists);
|
|
|
64 |
goto done;
|
|
|
65 |
}
|
|
|
66 |
else if (ofunexist == SMB_OFUN_EXIST_TRUNCATE) {
|
|
|
67 |
if ((d->mode & DMDIR) || (p9mode != OWRITE && p9mode != ORDWR)) {
|
|
|
68 |
smbseterror(s, ERRDOS, ERRbadaccess);
|
|
|
69 |
goto done;
|
|
|
70 |
}
|
|
|
71 |
p9mode |= OTRUNC;
|
|
|
72 |
action = 3;
|
|
|
73 |
}
|
|
|
74 |
else if (ofunexist != SMB_OFUN_EXIST_OPEN) {
|
|
|
75 |
smbseterror(s, ERRDOS, ERRbadaccess);
|
|
|
76 |
goto done;
|
|
|
77 |
}
|
|
|
78 |
if (d->mode & DMDIR)
|
|
|
79 |
diropen = 1;
|
|
|
80 |
else
|
|
|
81 |
fd = open(fullpath, p9mode);
|
|
|
82 |
}
|
|
|
83 |
else {
|
|
|
84 |
/* file does not exist */
|
|
|
85 |
ulong p9attr;
|
|
|
86 |
action = 3;
|
|
|
87 |
if ((ofun & SMB_OFUN_NOEXIST_CREATE) == 0) {
|
|
|
88 |
smbseterror(s, ERRDOS, ERRbadfile);
|
|
|
89 |
goto done;
|
|
|
90 |
}
|
|
|
91 |
if (createsize != 0) {
|
|
|
92 |
smbseterror(s, ERRDOS, ERRunsup);
|
|
|
93 |
goto done;
|
|
|
94 |
}
|
|
|
95 |
//smblogprint(-1, "creating: attr 0x%.4ux co 0x%.8lux\n", attr, createoptions);
|
|
|
96 |
if (createoptions & SMB_CO_FILE) {
|
|
|
97 |
attr &= SMB_ATTR_DIRECTORY;
|
|
|
98 |
if (attr == 0)
|
|
|
99 |
attr = SMB_ATTR_NORMAL;
|
|
|
100 |
}
|
|
|
101 |
else if (createoptions & SMB_CO_DIRECTORY) {
|
|
|
102 |
attr &= ~SMB_ATTR_NORMAL;
|
|
|
103 |
attr |= SMB_ATTR_DIRECTORY;
|
|
|
104 |
p9mode = OREAD;
|
|
|
105 |
}
|
|
|
106 |
//smblogprint(-1, "creating: before conversion attr 0x%.4ux\n", attr);
|
|
|
107 |
p9attr = smbdosattr2plan9mode(attr);
|
|
|
108 |
//smblogprint(-1, "creating: after conversion p9attr 0%.uo\n", p9attr);
|
|
|
109 |
fd = create(fullpath, p9mode, p9attr);
|
|
|
110 |
if (fd >= 0) {
|
|
|
111 |
d = dirfstat(fd);
|
|
|
112 |
sf = smbsharedfileget(d, p9mode, &share);
|
|
|
113 |
if (sf == nil) {
|
|
|
114 |
close(fd);
|
|
|
115 |
remove(path);
|
|
|
116 |
goto badshare;
|
|
|
117 |
}
|
|
|
118 |
}
|
|
|
119 |
}
|
|
|
120 |
//smblogprint(-1, "%s D %r", fullpath);
|
|
|
121 |
if (!diropen && fd < 0) {
|
|
|
122 |
smbseterror(s, ERRSRV, ERRaccess);
|
|
|
123 |
goto done;
|
|
|
124 |
}
|
|
|
125 |
f = smbemalloc(sizeof(SmbFile));
|
|
|
126 |
if (diropen) {
|
|
|
127 |
f->ioallowed = 0;
|
|
|
128 |
f->fd = -1;
|
|
|
129 |
}
|
|
|
130 |
else {
|
|
|
131 |
f->ioallowed = 1;
|
|
|
132 |
f->fd = fd;
|
|
|
133 |
}
|
|
|
134 |
f->name = smbestrdup(path);
|
|
|
135 |
f->sf = sf;
|
|
|
136 |
sf = nil;
|
|
|
137 |
f->share = share;
|
|
|
138 |
f->p9mode = p9mode;
|
|
|
139 |
f->t = t;
|
|
|
140 |
if (s->fidmap == nil)
|
|
|
141 |
s->fidmap = smbidmapnew();
|
|
|
142 |
*fidp = smbidmapadd(s->fidmap, f);
|
|
|
143 |
//smblogprint(h->command, "REPLY:\n t->id=0x%ux fid=%d path=%s\n", t->id, *fidp, path);
|
|
|
144 |
smblogprintif(smbglobals.log.fids, "openfile: 0x%.4ux/0x%.4ux %s\n", t->id, *fidp, path);
|
|
|
145 |
if (actionp)
|
|
|
146 |
*actionp = action;
|
|
|
147 |
if (dp) {
|
|
|
148 |
*dp = d;
|
|
|
149 |
d = nil;
|
|
|
150 |
}
|
|
|
151 |
done:
|
|
|
152 |
if (sf)
|
|
|
153 |
smbsharedfileput(nil, sf, share);
|
|
|
154 |
free(d);
|
|
|
155 |
free(fullpath);
|
|
|
156 |
return f;
|
|
|
157 |
}
|
|
|
158 |
|
|
|
159 |
SmbProcessResult
|
|
|
160 |
smbcomopenandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
|
|
|
161 |
{
|
|
|
162 |
uchar andxcommand;
|
|
|
163 |
ushort andxoffset, flags, mode, sattr, attr;
|
|
|
164 |
ulong createtime;
|
|
|
165 |
ushort ofun;
|
|
|
166 |
ulong createsize, timeout;
|
|
|
167 |
char *path = nil;
|
|
|
168 |
ulong andxoffsetfixupoffset;
|
|
|
169 |
SmbProcessResult pr;
|
|
|
170 |
ushort action;
|
|
|
171 |
Dir *d = nil;
|
|
|
172 |
SmbFile *f;
|
|
|
173 |
SmbTree *t;
|
|
|
174 |
ushort fid;
|
|
|
175 |
|
|
|
176 |
if (!smbcheckwordcount("comopenandx", h, 15))
|
|
|
177 |
return SmbProcessResultFormat;
|
|
|
178 |
|
|
|
179 |
andxcommand = *pdata++;
|
|
|
180 |
pdata++;
|
|
|
181 |
andxoffset = smbnhgets(pdata); pdata += 2;
|
|
|
182 |
flags = smbnhgets(pdata); pdata += 2;
|
|
|
183 |
mode = smbnhgets(pdata); pdata += 2;
|
|
|
184 |
sattr = smbnhgets(pdata); pdata += 2;
|
|
|
185 |
attr = smbnhgets(pdata); pdata += 2;
|
|
|
186 |
createtime = smbnhgetl(pdata); pdata += 4;
|
|
|
187 |
ofun = smbnhgets(pdata); pdata += 2;
|
|
|
188 |
createsize = smbnhgetl(pdata); pdata += 4;
|
|
|
189 |
timeout = smbnhgetl(pdata); pdata += 4;
|
|
|
190 |
pdata += 4;
|
|
|
191 |
USED(pdata);
|
|
|
192 |
if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
|
|
|
193 |
pr = SmbProcessResultFormat;
|
|
|
194 |
goto done;
|
|
|
195 |
}
|
|
|
196 |
|
|
|
197 |
smbloglock();
|
|
|
198 |
smblogprint(h->command, "flags 0x%.4ux", flags);
|
|
|
199 |
if (flags & SMB_OPEN_FLAGS_ADDITIONAL)
|
|
|
200 |
smblogprint(h->command, " additional");
|
|
|
201 |
if (flags & SMB_OPEN_FLAGS_OPLOCK)
|
|
|
202 |
smblogprint(h->command, " oplock");
|
|
|
203 |
if (flags & SMB_OPEN_FLAGS_OPBATCH)
|
|
|
204 |
smblogprint(h->command, " opbatch");
|
|
|
205 |
smblogprint(h->command, "\n");
|
|
|
206 |
smblogprint(h->command, "mode 0x%.4ux", mode);
|
|
|
207 |
switch ((mode >> SMB_OPEN_MODE_ACCESS_SHIFT) & SMB_OPEN_MODE_ACCESS_MASK) {
|
|
|
208 |
case OREAD:
|
|
|
209 |
smblogprint(h->command, " OREAD");
|
|
|
210 |
break;
|
|
|
211 |
case OWRITE:
|
|
|
212 |
smblogprint(h->command, " OWRITE");
|
|
|
213 |
break;
|
|
|
214 |
case ORDWR:
|
|
|
215 |
smblogprint(h->command, " ORDWR");
|
|
|
216 |
break;
|
|
|
217 |
case OEXEC:
|
|
|
218 |
smblogprint(h->command, " OEXEC");
|
|
|
219 |
break;
|
|
|
220 |
}
|
|
|
221 |
switch ((mode >> SMB_OPEN_MODE_SHARE_SHIFT) & SMB_OPEN_MODE_SHARE_MASK) {
|
|
|
222 |
case SMB_OPEN_MODE_SHARE_COMPATIBILITY:
|
|
|
223 |
smblogprint(h->command, " compatinility");
|
|
|
224 |
break;
|
|
|
225 |
case SMB_OPEN_MODE_SHARE_EXCLUSIVE:
|
|
|
226 |
smblogprint(h->command, " exclusive");
|
|
|
227 |
break;
|
|
|
228 |
case SMB_OPEN_MODE_SHARE_DENY_WRITE:
|
|
|
229 |
smblogprint(h->command, " deny write");
|
|
|
230 |
break;
|
|
|
231 |
case SMB_OPEN_MODE_SHARE_DENY_READOREXEC:
|
|
|
232 |
smblogprint(h->command, " deny readorxec");
|
|
|
233 |
break;
|
|
|
234 |
case SMB_OPEN_MODE_SHARE_DENY_NONE:
|
|
|
235 |
smblogprint(h->command, " deny none");
|
|
|
236 |
break;
|
|
|
237 |
}
|
|
|
238 |
if (mode & SMB_OPEN_MODE_WRITE_THROUGH)
|
|
|
239 |
smblogprint(h->command, " write through");
|
|
|
240 |
smblogprint(h->command, "\n");
|
|
|
241 |
smblogprint(h->command, "sattr 0x%.4ux", sattr);
|
|
|
242 |
smblogprintattr(h->command, sattr);
|
|
|
243 |
smblogprint(h->command, "\n");
|
|
|
244 |
smblogprint(h->command, "attr 0x%.4ux", attr);
|
|
|
245 |
smblogprintattr(h->command, attr);
|
|
|
246 |
smblogprint(h->command, "\n");
|
|
|
247 |
smblogprint(h->command, "createtime 0x%.8lux\n", createtime);
|
|
|
248 |
smblogprint(h->command, "ofun 0x%.4ux", ofun);
|
|
|
249 |
if (ofun & SMB_OFUN_NOEXIST_CREATE)
|
|
|
250 |
smblogprint(h->command, " noexistscreate");
|
|
|
251 |
else
|
|
|
252 |
smblogprint(h->command, " noexistfail");
|
|
|
253 |
switch ((ofun >> SMB_OFUN_EXIST_SHIFT) & SMB_OFUN_EXIST_MASK) {
|
|
|
254 |
case SMB_OFUN_EXIST_FAIL:
|
|
|
255 |
smblogprint(h->command, " existfail");
|
|
|
256 |
break;
|
|
|
257 |
case SMB_OFUN_EXIST_OPEN:
|
|
|
258 |
smblogprint(h->command, " existopen");
|
|
|
259 |
break;
|
|
|
260 |
case SMB_OFUN_EXIST_TRUNCATE:
|
|
|
261 |
smblogprint(h->command, " existtruncate");
|
|
|
262 |
break;
|
|
|
263 |
}
|
|
|
264 |
smblogprint(h->command, "\n");
|
|
|
265 |
smblogprint(h->command, "createsize 0x%.8lux\n", createsize);
|
|
|
266 |
smblogprint(h->command, "timeout 0x%.8lux\n", timeout);
|
|
|
267 |
smblogprint(h->command, "path %s\n", path);
|
|
|
268 |
smblogunlock();
|
|
|
269 |
|
|
|
270 |
t = smbidmapfind(s->tidmap, h->tid);
|
|
|
271 |
if (t == nil) {
|
|
|
272 |
smbseterror(s, ERRSRV, ERRinvtid);
|
|
|
273 |
goto errordone;
|
|
|
274 |
}
|
|
|
275 |
|
|
|
276 |
f = openfile(s, t, path, mode, attr, ofun, 0, createsize, &fid, &d, &action);
|
|
|
277 |
if (f == nil) {
|
|
|
278 |
pr = SmbProcessResultError;
|
|
|
279 |
goto done;
|
|
|
280 |
}
|
|
|
281 |
h->wordcount = 15;
|
|
|
282 |
if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixupoffset)
|
|
|
283 |
|| !smbbufferputs(s->response, fid)
|
|
|
284 |
|| !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode))
|
|
|
285 |
|| !smbbufferputl(s->response, smbplan9time2utime(d->mtime, s->tzoff))
|
|
|
286 |
|| !smbbufferputl(s->response, smbplan9length2size32(d->length))
|
|
|
287 |
|| !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode)) // probbaly bogus
|
|
|
288 |
|| !smbbufferputs(s->response, 0) // all files are files
|
|
|
289 |
|| !smbbufferputs(s->response, 0) // pipe state
|
|
|
290 |
|| !smbbufferputs(s->response, action)
|
|
|
291 |
|| !smbbufferputl(s->response, 0) // fileID
|
|
|
292 |
|| !smbbufferputs(s->response, 0)
|
|
|
293 |
|| !smbbufferputs(s->response, 0)) { // bytecount 0
|
|
|
294 |
smbfileclose(s, f);
|
|
|
295 |
pr = SmbProcessResultMisc;
|
|
|
296 |
goto done;
|
|
|
297 |
}
|
|
|
298 |
if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
|
|
|
299 |
pr = smbchaincommand(s, h, andxoffsetfixupoffset, andxcommand, andxoffset, b);
|
|
|
300 |
else
|
|
|
301 |
pr = SmbProcessResultReply;
|
|
|
302 |
goto done;
|
|
|
303 |
errordone:
|
|
|
304 |
pr = SmbProcessResultError;
|
|
|
305 |
done:
|
|
|
306 |
free(path);
|
|
|
307 |
free(d);
|
|
|
308 |
return pr;
|
|
|
309 |
}
|
|
|
310 |
|
|
|
311 |
SmbProcessResult
|
|
|
312 |
smbcomopen(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
|
|
|
313 |
{
|
|
|
314 |
uchar fmt;
|
|
|
315 |
char *path;
|
|
|
316 |
ushort mode, attr;
|
|
|
317 |
SmbTree *t;
|
|
|
318 |
ushort fid;
|
|
|
319 |
Dir *d = nil;
|
|
|
320 |
SmbFile *f;
|
|
|
321 |
SmbProcessResult pr;
|
|
|
322 |
|
|
|
323 |
if (!smbcheckwordcount("comopen", h, 2))
|
|
|
324 |
return SmbProcessResultFormat;
|
|
|
325 |
mode = smbnhgets(pdata);
|
|
|
326 |
attr = smbnhgets(pdata + 2);
|
|
|
327 |
if (!smbbuffergetb(b, &fmt)
|
|
|
328 |
|| fmt != 4
|
|
|
329 |
|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
|
|
|
330 |
pr = SmbProcessResultFormat;
|
|
|
331 |
goto done;
|
|
|
332 |
}
|
|
|
333 |
t = smbidmapfind(s->tidmap, h->tid);
|
|
|
334 |
if (t == nil) {
|
|
|
335 |
smbseterror(s, ERRSRV, ERRinvtid);
|
|
|
336 |
error:
|
|
|
337 |
pr = SmbProcessResultError;
|
|
|
338 |
goto done;
|
|
|
339 |
}
|
|
|
340 |
f = openfile(s, t, path, mode, attr,
|
|
|
341 |
SMB_OFUN_EXIST_OPEN << SMB_OFUN_EXIST_SHIFT,
|
|
|
342 |
0, 0, &fid, &d, nil);
|
|
|
343 |
if (f == nil)
|
|
|
344 |
goto error;
|
|
|
345 |
h->wordcount = 7;
|
|
|
346 |
if (!smbbufferputheader(s->response, h, &s->peerinfo)
|
|
|
347 |
|| !smbbufferputs(s->response, fid)
|
|
|
348 |
|| !smbbufferputs(s->response, smbplan9mode2dosattr(d->mode))
|
|
|
349 |
|| !smbbufferputl(s->response, smbplan9time2utime(d->mtime, s->tzoff))
|
|
|
350 |
|| !smbbufferputl(s->response, smbplan9length2size32(d->length))
|
|
|
351 |
|| !smbbufferputs(s->response, 2) // lies - this should be the actual access allowed
|
|
|
352 |
|| !smbbufferputs(s->response, 0))
|
|
|
353 |
pr = SmbProcessResultMisc;
|
|
|
354 |
else
|
|
|
355 |
pr = SmbProcessResultReply;
|
|
|
356 |
done:
|
|
|
357 |
free(path);
|
|
|
358 |
free(d);
|
|
|
359 |
return pr;
|
|
|
360 |
}
|
|
|
361 |
|
|
|
362 |
|
|
|
363 |
/*
|
|
|
364 |
smb_com SMBcreate smb_com SMBcreate
|
|
|
365 |
smb_wct 3 smb_wct 1
|
|
|
366 |
smb_vwv[0] attribute smb_vwv[0] file handle
|
|
|
367 |
smb_vwv[1] time low smb_bcc 0
|
|
|
368 |
smb_vwv[2] time high
|
|
|
369 |
smb_bcc min = 2
|
|
|
370 |
smb_buf[] ASCII -- 04
|
|
|
371 |
file pathname
|
|
|
372 |
*/
|
|
|
373 |
|
|
|
374 |
SmbProcessResult
|
|
|
375 |
smbcomcreate(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
|
|
|
376 |
{
|
|
|
377 |
int ofun, attr, mode;
|
|
|
378 |
long createtime;
|
|
|
379 |
char *path;
|
|
|
380 |
uchar fmt;
|
|
|
381 |
SmbFile *f;
|
|
|
382 |
SmbTree *t;
|
|
|
383 |
ushort fid;
|
|
|
384 |
SmbProcessResult pr;
|
|
|
385 |
|
|
|
386 |
path = nil;
|
|
|
387 |
if (!smbcheckwordcount("comcreate", h, 3))
|
|
|
388 |
return SmbProcessResultFormat;
|
|
|
389 |
|
|
|
390 |
smblogprint(h->command, "tid=%d\n", h->tid);
|
|
|
391 |
attr = smbnhgets(pdata); pdata += 2;
|
|
|
392 |
createtime = smbnhgetl(pdata);
|
|
|
393 |
if (!smbbuffergetb(b, &fmt) || fmt != 0x04 ||
|
|
|
394 |
!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)){
|
|
|
395 |
pr = SmbProcessResultError;
|
|
|
396 |
goto done;
|
|
|
397 |
}
|
|
|
398 |
|
|
|
399 |
smbloglock();
|
|
|
400 |
smblogprint(h->command, "path %s\n", path);
|
|
|
401 |
smblogprint(h->command, "attr 0x%.4ux", attr);
|
|
|
402 |
smblogprintattr(h->command, attr);
|
|
|
403 |
smblogprint(h->command, "\n");
|
|
|
404 |
smblogprint(h->command, "createtime 0x%.8lux\n", createtime);
|
|
|
405 |
smblogunlock();
|
|
|
406 |
|
|
|
407 |
t = smbidmapfind(s->tidmap, h->tid);
|
|
|
408 |
if (t == nil) {
|
|
|
409 |
pr = SmbProcessResultError;
|
|
|
410 |
goto done;
|
|
|
411 |
}
|
|
|
412 |
|
|
|
413 |
mode = (ORDWR<<SMB_OPEN_MODE_ACCESS_SHIFT) | // SFS: FIXME: should be OWRITE?
|
|
|
414 |
(SMB_OPEN_MODE_SHARE_EXCLUSIVE<<SMB_OPEN_MODE_SHARE_SHIFT);
|
|
|
415 |
ofun = SMB_OFUN_NOEXIST_CREATE|(SMB_OFUN_EXIST_FAIL<<SMB_OFUN_EXIST_SHIFT);
|
|
|
416 |
f = openfile(s, t, path, mode, attr, ofun, SMB_CO_FILE, 0, &fid, nil, nil);
|
|
|
417 |
if (f == nil) {
|
|
|
418 |
pr = SmbProcessResultError;
|
|
|
419 |
goto done;
|
|
|
420 |
}
|
|
|
421 |
|
|
|
422 |
h->wordcount = 1; // SFS: FIXME: unsure of this constant, maybe should be 3
|
|
|
423 |
if (!smbbufferputheader(s->response, h, &s->peerinfo)
|
|
|
424 |
|| !smbbufferputs(s->response, fid)
|
|
|
425 |
|| !smbbufferputs(s->response, 0)){ // bytecount 0
|
|
|
426 |
pr = SmbProcessResultMisc;
|
|
|
427 |
goto done;
|
|
|
428 |
}
|
|
|
429 |
pr = SmbProcessResultReply;
|
|
|
430 |
goto done;
|
|
|
431 |
|
|
|
432 |
done:
|
|
|
433 |
free(path);
|
|
|
434 |
return pr;
|
|
|
435 |
}
|
|
|
436 |
|
|
|
437 |
|
|
|
438 |
typedef struct SmbSblut {
|
|
|
439 |
char *s;
|
|
|
440 |
ulong mask;
|
|
|
441 |
} SmbSblut;
|
|
|
442 |
|
|
|
443 |
static SmbSblut dasblut[] = {
|
|
|
444 |
{ "SMB_DA_SPECIFIC_READ_DATA", SMB_DA_SPECIFIC_READ_DATA },
|
|
|
445 |
{ "SMB_DA_SPECIFIC_WRITE_DATA", SMB_DA_SPECIFIC_WRITE_DATA },
|
|
|
446 |
{ "SMB_DA_SPECIFIC_APPEND_DATA", SMB_DA_SPECIFIC_APPEND_DATA },
|
|
|
447 |
{ "SMB_DA_SPECIFIC_READ_EA", SMB_DA_SPECIFIC_READ_EA },
|
|
|
448 |
{ "SMB_DA_SPECIFIC_WRITE_EA", SMB_DA_SPECIFIC_WRITE_EA },
|
|
|
449 |
{ "SMB_DA_SPECIFIC_EXECUTE", SMB_DA_SPECIFIC_EXECUTE },
|
|
|
450 |
{ "SMB_DA_SPECIFIC_DELETE_CHILD", SMB_DA_SPECIFIC_DELETE_CHILD },
|
|
|
451 |
{ "SMB_DA_SPECIFIC_READ_ATTRIBUTES", SMB_DA_SPECIFIC_READ_ATTRIBUTES },
|
|
|
452 |
{ "SMB_DA_SPECIFIC_WRITE_ATTRIBUTES", SMB_DA_SPECIFIC_WRITE_ATTRIBUTES },
|
|
|
453 |
{ "SMB_DA_STANDARD_DELETE_ACCESS", SMB_DA_STANDARD_DELETE_ACCESS },
|
|
|
454 |
{ "SMB_DA_STANDARD_READ_CONTROL_ACCESS", SMB_DA_STANDARD_READ_CONTROL_ACCESS },
|
|
|
455 |
{ "SMB_DA_STANDARD_WRITE_DAC_ACCESS", SMB_DA_STANDARD_WRITE_DAC_ACCESS },
|
|
|
456 |
{ "SMB_DA_STANDARD_WRITE_OWNER_ACCESS", SMB_DA_STANDARD_WRITE_OWNER_ACCESS },
|
|
|
457 |
{ "SMB_DA_STANDARD_SYNCHRONIZE_ACCESS", SMB_DA_STANDARD_SYNCHRONIZE_ACCESS },
|
|
|
458 |
{ "SMB_DA_GENERIC_ALL_ACCESS", SMB_DA_GENERIC_ALL_ACCESS },
|
|
|
459 |
{ "SMB_DA_GENERIC_EXECUTE_ACCESS", SMB_DA_GENERIC_EXECUTE_ACCESS },
|
|
|
460 |
{ "SMB_DA_GENERIC_WRITE_ACCESS", SMB_DA_GENERIC_WRITE_ACCESS },
|
|
|
461 |
{ "SMB_DA_GENERIC_READ_ACCESS", SMB_DA_GENERIC_READ_ACCESS },
|
|
|
462 |
{ 0 }
|
|
|
463 |
};
|
|
|
464 |
|
|
|
465 |
static SmbSblut efasblut[] = {
|
|
|
466 |
{ "SMB_ATTR_READ_ONLY", SMB_ATTR_READ_ONLY },
|
|
|
467 |
{ "SMB_ATTR_HIDDEN", SMB_ATTR_HIDDEN },
|
|
|
468 |
{ "SMB_ATTR_SYSTEM", SMB_ATTR_SYSTEM },
|
|
|
469 |
{ "SMB_ATTR_DIRECTORY", SMB_ATTR_DIRECTORY },
|
|
|
470 |
{ "SMB_ATTR_ARCHIVE", SMB_ATTR_ARCHIVE },
|
|
|
471 |
{ "SMB_ATTR_NORMAL", SMB_ATTR_NORMAL },
|
|
|
472 |
{ "SMB_ATTR_COMPRESSED", SMB_ATTR_COMPRESSED },
|
|
|
473 |
{ "SMB_ATTR_TEMPORARY", SMB_ATTR_TEMPORARY },
|
|
|
474 |
{ "SMB_ATTR_WRITETHROUGH", SMB_ATTR_WRITETHROUGH },
|
|
|
475 |
{ "SMB_ATTR_NO_BUFFERING", SMB_ATTR_NO_BUFFERING },
|
|
|
476 |
{ "SMB_ATTR_RANDOM_ACCESS", SMB_ATTR_RANDOM_ACCESS },
|
|
|
477 |
{ 0 }
|
|
|
478 |
};
|
|
|
479 |
|
|
|
480 |
static SmbSblut sasblut[] = {
|
|
|
481 |
{ "SMB_SA_SHARE_READ", SMB_SA_SHARE_READ },
|
|
|
482 |
{ "SMB_SA_SHARE_WRITE", SMB_SA_SHARE_WRITE },
|
|
|
483 |
{ "SMB_SA_SHARE_DELETE", SMB_SA_SHARE_DELETE },
|
|
|
484 |
{ "SMB_SA_NO_SHARE", SMB_SA_NO_SHARE },
|
|
|
485 |
{ 0 }
|
|
|
486 |
};
|
|
|
487 |
|
|
|
488 |
static SmbSblut cosblut[] = {
|
|
|
489 |
{ "SMB_CO_DIRECTORY", SMB_CO_DIRECTORY },
|
|
|
490 |
{ "SMB_CO_WRITETHROUGH", SMB_CO_WRITETHROUGH },
|
|
|
491 |
{ "SMB_CO_SEQUENTIAL_ONLY", SMB_CO_SEQUENTIAL_ONLY },
|
|
|
492 |
{ "SMB_CO_FILE", SMB_CO_FILE },
|
|
|
493 |
{ "SMB_CO_NO_EA_KNOWLEDGE", SMB_CO_NO_EA_KNOWLEDGE },
|
|
|
494 |
{ "SMB_CO_EIGHT_DOT_THREE_ONLY", SMB_CO_EIGHT_DOT_THREE_ONLY },
|
|
|
495 |
{ "SMB_CO_RANDOM_ACCESS", SMB_CO_RANDOM_ACCESS },
|
|
|
496 |
{ "SMB_CO_DELETE_ON_CLOSE", SMB_CO_DELETE_ON_CLOSE },
|
|
|
497 |
{ 0 }
|
|
|
498 |
};
|
|
|
499 |
|
|
|
500 |
static SmbSlut cdslut[] = {
|
|
|
501 |
{ "SMB_CD_SUPERCEDE", SMB_CD_SUPERCEDE },
|
|
|
502 |
{ "SMB_CD_OPEN", SMB_CD_OPEN },
|
|
|
503 |
{ "SMB_CD_CREATE", SMB_CD_CREATE },
|
|
|
504 |
{ "SMB_CD_OPEN_IF", SMB_CD_OPEN_IF },
|
|
|
505 |
{ "SMB_CD_OVERWRITE", SMB_CD_OVERWRITE },
|
|
|
506 |
{ "SMB_CD_OVERWRITE_IF", SMB_CD_OVERWRITE_IF },
|
|
|
507 |
{ 0 }
|
|
|
508 |
};
|
|
|
509 |
|
|
|
510 |
static void
|
|
|
511 |
smbsblutlogprint(uchar cmd, SmbSblut *sblut, ulong mask)
|
|
|
512 |
{
|
|
|
513 |
while (sblut->s) {
|
|
|
514 |
if (mask && (sblut->mask & mask) || (mask == 0 && sblut->mask == 0))
|
|
|
515 |
smblogprint(cmd, " %s", sblut->s);
|
|
|
516 |
sblut++;
|
|
|
517 |
}
|
|
|
518 |
}
|
|
|
519 |
|
|
|
520 |
SmbProcessResult
|
|
|
521 |
smbcomntcreateandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
|
|
|
522 |
{
|
|
|
523 |
uchar andxcommand;
|
|
|
524 |
ushort andxoffset;
|
|
|
525 |
char *path = nil;
|
|
|
526 |
SmbProcessResult pr;
|
|
|
527 |
ulong namelength;
|
|
|
528 |
ulong flags;
|
|
|
529 |
ulong rootdirectoryfid, desiredaccess;
|
|
|
530 |
uvlong allocationsize;
|
|
|
531 |
ulong extfileattributes, shareaccess, createdisposition, createoptions, impersonationlevel;
|
|
|
532 |
uchar securityflags;
|
|
|
533 |
int p9mode;
|
|
|
534 |
int sharemode;
|
|
|
535 |
ushort mode;
|
|
|
536 |
SmbTree *t;
|
|
|
537 |
ushort ofun;
|
|
|
538 |
SmbFile *f;
|
|
|
539 |
ushort fid;
|
|
|
540 |
Dir *d = nil;
|
|
|
541 |
ushort action;
|
|
|
542 |
uvlong mtime;
|
|
|
543 |
ulong andxoffsetfixup;
|
|
|
544 |
|
|
|
545 |
if (!smbcheckwordcount("comntcreateandx", h, 24))
|
|
|
546 |
return SmbProcessResultFormat;
|
|
|
547 |
|
|
|
548 |
andxcommand = *pdata++;
|
|
|
549 |
pdata++;
|
|
|
550 |
andxoffset = smbnhgets(pdata); pdata += 2;
|
|
|
551 |
pdata++;
|
|
|
552 |
namelength = smbnhgets(pdata); pdata += 2;
|
|
|
553 |
flags = smbnhgetl(pdata); pdata += 4;
|
|
|
554 |
rootdirectoryfid = smbnhgetl(pdata); pdata += 4;
|
|
|
555 |
desiredaccess = smbnhgetl(pdata); pdata += 4;
|
|
|
556 |
allocationsize = smbnhgetv(pdata); pdata += 8;
|
|
|
557 |
extfileattributes = smbnhgetl(pdata); pdata += 4;
|
|
|
558 |
shareaccess = smbnhgetl(pdata); pdata += 4;
|
|
|
559 |
createdisposition = smbnhgetl(pdata); pdata += 4;
|
|
|
560 |
createoptions = smbnhgetl(pdata); pdata += 4;
|
|
|
561 |
impersonationlevel = smbnhgetl(pdata); pdata += 4;
|
|
|
562 |
securityflags = *pdata++;
|
|
|
563 |
USED(pdata);
|
|
|
564 |
|
|
|
565 |
if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
|
|
|
566 |
pr = SmbProcessResultFormat;
|
|
|
567 |
goto done;
|
|
|
568 |
}
|
|
|
569 |
|
|
|
570 |
smblogprint(h->command, "namelength %d\n", namelength);
|
|
|
571 |
smblogprint(h->command, "flags 0x%.8lux\n", flags);
|
|
|
572 |
smblogprint(h->command, "rootdirectoryfid %lud\n", rootdirectoryfid);
|
|
|
573 |
smblogprint(h->command, "desiredaccess 0x%.8lux", desiredaccess);
|
|
|
574 |
smbsblutlogprint(h->command, dasblut, desiredaccess);
|
|
|
575 |
smblogprint(h->command, "\n");
|
|
|
576 |
smblogprint(h->command, "allocationsize %llud\n", allocationsize);
|
|
|
577 |
smblogprint(h->command, "extfileattributes 0x%.8lux", extfileattributes);
|
|
|
578 |
smbsblutlogprint(h->command, efasblut, extfileattributes);
|
|
|
579 |
smblogprint(h->command, "\n");
|
|
|
580 |
smblogprint(h->command, "shareaccess 0x%.8lux", shareaccess);
|
|
|
581 |
smbsblutlogprint(h->command, sasblut, shareaccess);
|
|
|
582 |
smblogprint(h->command, "\n");
|
|
|
583 |
smblogprint(h->command, "createdisposition 0x%.8lux %s\n",
|
|
|
584 |
createdisposition, smbrevslut(cdslut, createdisposition));
|
|
|
585 |
smblogprint(h->command, "createoptions 0x%.8lux", createoptions);
|
|
|
586 |
smbsblutlogprint(h->command, cosblut, createoptions);
|
|
|
587 |
smblogprint(h->command, "\n");
|
|
|
588 |
smblogprint(h->command, "impersonationlevel 0x%.8lux\n", impersonationlevel);
|
|
|
589 |
smblogprint(h->command, "securityflags 0x%.2ux\n", securityflags);
|
|
|
590 |
smblogprint(h->command, "path %s\n", path);
|
|
|
591 |
|
|
|
592 |
if (rootdirectoryfid != 0) {
|
|
|
593 |
smblogprint(-1, "smbcomntcreateandx: fid relative not implemented\n");
|
|
|
594 |
goto unimp;
|
|
|
595 |
}
|
|
|
596 |
|
|
|
597 |
if (desiredaccess & SMB_DA_GENERIC_MASK)
|
|
|
598 |
switch (desiredaccess & SMB_DA_GENERIC_MASK){
|
|
|
599 |
case SMB_DA_GENERIC_READ_ACCESS:
|
|
|
600 |
p9mode = OREAD;
|
|
|
601 |
break;
|
|
|
602 |
case SMB_DA_GENERIC_WRITE_ACCESS:
|
|
|
603 |
p9mode = OWRITE;
|
|
|
604 |
break;
|
|
|
605 |
case SMB_DA_GENERIC_ALL_ACCESS:
|
|
|
606 |
p9mode = ORDWR;
|
|
|
607 |
break;
|
|
|
608 |
case SMB_DA_GENERIC_EXECUTE_ACCESS:
|
|
|
609 |
p9mode = OEXEC;
|
|
|
610 |
break;
|
|
|
611 |
default:
|
|
|
612 |
p9mode = OREAD;
|
|
|
613 |
break;
|
|
|
614 |
}
|
|
|
615 |
else
|
|
|
616 |
if (desiredaccess & SMB_DA_SPECIFIC_READ_DATA)
|
|
|
617 |
if (desiredaccess & (SMB_DA_SPECIFIC_WRITE_DATA | SMB_DA_SPECIFIC_APPEND_DATA))
|
|
|
618 |
p9mode = ORDWR;
|
|
|
619 |
else
|
|
|
620 |
p9mode = OREAD;
|
|
|
621 |
else if (desiredaccess & (SMB_DA_SPECIFIC_WRITE_DATA | SMB_DA_SPECIFIC_APPEND_DATA))
|
|
|
622 |
p9mode = ORDWR;
|
|
|
623 |
else
|
|
|
624 |
p9mode = OREAD;
|
|
|
625 |
|
|
|
626 |
if (shareaccess == SMB_SA_NO_SHARE)
|
|
|
627 |
sharemode = SMB_OPEN_MODE_SHARE_EXCLUSIVE;
|
|
|
628 |
else if (shareaccess & (SMB_SA_SHARE_READ | SMB_SA_SHARE_WRITE) ==
|
|
|
629 |
(SMB_SA_SHARE_READ | SMB_SA_SHARE_WRITE))
|
|
|
630 |
sharemode = SMB_OPEN_MODE_SHARE_DENY_NONE;
|
|
|
631 |
else if (shareaccess & SMB_SA_SHARE_READ)
|
|
|
632 |
sharemode = SMB_OPEN_MODE_SHARE_DENY_WRITE;
|
|
|
633 |
else if (shareaccess & SMB_SA_SHARE_WRITE)
|
|
|
634 |
sharemode = SMB_OPEN_MODE_SHARE_DENY_READOREXEC;
|
|
|
635 |
else
|
|
|
636 |
sharemode = SMB_OPEN_MODE_SHARE_DENY_NONE;
|
|
|
637 |
|
|
|
638 |
mode = (sharemode << SMB_OPEN_MODE_SHARE_SHIFT) | (p9mode << SMB_OPEN_MODE_ACCESS_SHIFT);
|
|
|
639 |
|
|
|
640 |
switch (createdisposition) {
|
|
|
641 |
default:
|
|
|
642 |
smblogprint(-1, "smbcomntcreateandx: createdisposition 0x%.8lux not implemented\n", createdisposition);
|
|
|
643 |
goto unimp;
|
|
|
644 |
case SMB_CD_OPEN:
|
|
|
645 |
ofun = SMB_OFUN_EXIST_OPEN;
|
|
|
646 |
break;
|
|
|
647 |
case SMB_CD_CREATE:
|
|
|
648 |
ofun = SMB_OFUN_EXIST_FAIL | SMB_OFUN_NOEXIST_CREATE;
|
|
|
649 |
break;
|
|
|
650 |
case SMB_CD_OPEN_IF:
|
|
|
651 |
ofun = SMB_OFUN_EXIST_OPEN | SMB_OFUN_NOEXIST_CREATE;
|
|
|
652 |
break;
|
|
|
653 |
case SMB_CD_OVERWRITE:
|
|
|
654 |
ofun = SMB_OFUN_EXIST_TRUNCATE;
|
|
|
655 |
break;
|
|
|
656 |
case SMB_CD_OVERWRITE_IF:
|
|
|
657 |
ofun = SMB_OFUN_EXIST_TRUNCATE | SMB_OFUN_NOEXIST_CREATE;
|
|
|
658 |
break;
|
|
|
659 |
}
|
|
|
660 |
|
|
|
661 |
t = smbidmapfind(s->tidmap, h->tid);
|
|
|
662 |
if (t == nil) {
|
|
|
663 |
smbseterror(s, ERRSRV, ERRinvtid);
|
|
|
664 |
pr = SmbProcessResultError;
|
|
|
665 |
goto done;
|
|
|
666 |
}
|
|
|
667 |
|
|
|
668 |
f = openfile(s, t, path, mode, extfileattributes, ofun, createoptions, allocationsize, &fid, &d, &action);
|
|
|
669 |
|
|
|
670 |
if (f == nil) {
|
|
|
671 |
pr = SmbProcessResultError;
|
|
|
672 |
goto done;
|
|
|
673 |
}
|
|
|
674 |
|
|
|
675 |
h->wordcount = 42;
|
|
|
676 |
mtime = smbplan9time2time(d->mtime);
|
|
|
677 |
if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup)
|
|
|
678 |
|| !smbbufferputb(s->response, 0) // oplocks? pah
|
|
|
679 |
|| !smbbufferputs(s->response, fid)
|
|
|
680 |
|| !smbbufferputl(s->response, action)
|
|
|
681 |
|| !smbbufferputv(s->response, mtime)
|
|
|
682 |
|| !smbbufferputv(s->response, smbplan9time2time(d->atime))
|
|
|
683 |
|| !smbbufferputv(s->response, mtime)
|
|
|
684 |
|| !smbbufferputv(s->response, mtime)
|
|
|
685 |
|| !smbbufferputl(s->response, smbplan9mode2dosattr(d->mode))
|
|
|
686 |
|| !smbbufferputv(s->response, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))
|
|
|
687 |
|| !smbbufferputv(s->response, d->length)
|
|
|
688 |
|| !smbbufferputbytes(s->response, nil, 4)
|
|
|
689 |
|| !smbbufferputb(s->response, (d->qid.type & QTDIR) != 0)
|
|
|
690 |
|| !smbbufferputbytes(s->response, nil, 8)
|
|
|
691 |
|| !smbbufferputs(s->response, 0)) {
|
|
|
692 |
pr = SmbProcessResultMisc;
|
|
|
693 |
goto done;
|
|
|
694 |
}
|
|
|
695 |
|
|
|
696 |
if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
|
|
|
697 |
pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
|
|
|
698 |
else
|
|
|
699 |
pr = SmbProcessResultReply;
|
|
|
700 |
|
|
|
701 |
goto done;
|
|
|
702 |
|
|
|
703 |
unimp:
|
|
|
704 |
pr = SmbProcessResultUnimp;
|
|
|
705 |
|
|
|
706 |
done:
|
|
|
707 |
free(path);
|
|
|
708 |
free(d);
|
|
|
709 |
|
|
|
710 |
return pr;
|
|
|
711 |
}
|
|
|
712 |
|