smbcomopen.c 20 KB

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