smbcomopen.c 21 KB

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