smbcomopen.c 20 KB

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