smbtrans2query.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #include "headers.h"
  2. static SmbProcessResult
  3. query(SmbSession *s, char *cmdname, char *filename, ushort infolevel, vlong cbo, Dir *d)
  4. {
  5. vlong ntatime, ntmtime;
  6. ushort dosmode;
  7. ulong fnlfixupoffset;
  8. vlong allocsize;
  9. if (d == nil) {
  10. smbseterror(s, ERRDOS, ERRbadfile);
  11. return SmbProcessResultError;
  12. }
  13. switch (infolevel) {
  14. case SMB_QUERY_FILE_BASIC_INFO:
  15. ntatime = smbplan9time2time(d->atime);
  16. ntmtime = smbplan9time2time(d->mtime);
  17. dosmode = smbplan9mode2dosattr(d->mode);
  18. translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_BASIC_INFO\n");
  19. translogprint(s->transaction.in.setup[0], "REPLY:\n");
  20. translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
  21. translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
  22. translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
  23. if (!smbbufferputv(s->transaction.out.data, ntmtime)
  24. || !smbbufferputv(s->transaction.out.data, ntatime)
  25. || !smbbufferputv(s->transaction.out.data, ntmtime)
  26. || !smbbufferputv(s->transaction.out.data, ntmtime)
  27. || !smbbufferputl(s->transaction.out.data, dosmode))
  28. // || !smbbufferputl(s->transaction.out.data, 0))
  29. return SmbProcessResultMisc;
  30. break;
  31. case SMB_QUERY_FILE_ALL_INFO:
  32. ntatime = smbplan9time2time(d->atime);
  33. ntmtime = smbplan9time2time(d->mtime);
  34. dosmode = smbplan9mode2dosattr(d->mode);
  35. allocsize = (d->length + (1 << smbglobals.l2allocationsize) - 1) & ~((1 << smbglobals.l2allocationsize) - 1);
  36. translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_ALL_INFO\n");
  37. translogprint(s->transaction.in.setup[0], "REPLY:\n");
  38. translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
  39. translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
  40. translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
  41. translogprint(s->transaction.in.setup[0], "allocsize=%d\n", allocsize);
  42. translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->mode & DMDIR) != 0);
  43. if (!smbbufferputv(s->transaction.out.data, ntmtime)
  44. || !smbbufferputv(s->transaction.out.data, ntatime)
  45. || !smbbufferputv(s->transaction.out.data, ntmtime)
  46. || !smbbufferputv(s->transaction.out.data, ntmtime)
  47. || !smbbufferputs(s->transaction.out.data, dosmode)
  48. || !smbbufferputbytes(s->transaction.out.data, nil, 6)
  49. || !smbbufferputv(s->transaction.out.data, allocsize)
  50. || !smbbufferputv(s->transaction.out.data, d->length)
  51. || !smbbufferputl(s->transaction.out.data, 0) // hard links - ha
  52. || !smbbufferputb(s->transaction.out.data, 0) // TODO delete pending
  53. || !smbbufferputb(s->transaction.out.data, (d->mode & DMDIR) != 0)
  54. || !smbbufferputv(s->transaction.out.data, d->qid.path)
  55. || !smbbufferputl(s->transaction.out.data, 0) // EA size
  56. || !smbbufferputl(s->transaction.out.data, (dosmode & SMB_ATTR_READ_ONLY) ? 0xa1 : 0x1a7)
  57. || !smbbufferputv(s->transaction.out.data, cbo)
  58. || !smbbufferputs(s->transaction.out.data, dosmode)
  59. || !smbbufferputl(s->transaction.out.data, 0)) // alignment
  60. return SmbProcessResultMisc;
  61. fnlfixupoffset = smbbufferwriteoffset(s->transaction.out.data);
  62. if (!smbbufferputl(s->transaction.out.data, 0)
  63. || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_REVPATH, filename)
  64. || !smbbufferfixuprelativel(s->transaction.out.data, fnlfixupoffset))
  65. return SmbProcessResultMisc;
  66. break;
  67. case SMB_QUERY_FILE_STANDARD_INFO:
  68. translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STANDARD_INFO\n");
  69. translogprint(s->transaction.in.setup[0], "REPLY:\n");
  70. translogprint(s->transaction.in.setup[0], "length=%lld", d->length);
  71. translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->qid.type & QTDIR) != 0);
  72. if (!smbbufferputv(s->transaction.out.data, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))
  73. || !smbbufferputv(s->transaction.out.data, d->length)
  74. || !smbbufferputl(s->transaction.out.data, 1)
  75. || !smbbufferputb(s->transaction.out.data, 0)
  76. || !smbbufferputb(s->transaction.out.data, (d->qid.type & QTDIR) != 0))
  77. return SmbProcessResultMisc;
  78. break;
  79. case SMB_QUERY_FILE_EA_INFO:
  80. translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_EA_INFO\n");
  81. translogprint(s->transaction.in.setup[0], "REPLY:\n");
  82. translogprint(s->transaction.in.setup[0], "ea_len=0\n");
  83. if (!smbbufferputl(s->transaction.out.data, 0))
  84. return SmbProcessResultMisc;
  85. break;
  86. case SMB_QUERY_FILE_STREAM_INFO:
  87. translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STREAM_INFO\n");
  88. translogprint(s->transaction.in.setup[0], "REPLY: failed\n");
  89. /* don't do it, never will */
  90. goto unknownlevel;
  91. default:
  92. smblogprint(-1, "smbtrans2query%sinformation: infolevel 0x%.4ux not implemented\n", cmdname, infolevel);
  93. unknownlevel:
  94. translogprint(s->transaction.in.setup[0], "[not supported]\n");
  95. smbseterror(s, ERRDOS, ERRunknownlevel);
  96. return SmbProcessResultError;
  97. }
  98. return SmbProcessResultReply;
  99. }
  100. SmbProcessResult
  101. smbtrans2querypathinformation(SmbSession *s, SmbHeader *h)
  102. {
  103. SmbTree *t;
  104. SmbBuffer *b = nil;
  105. SmbProcessResult pr;
  106. ushort infolevel;
  107. Dir *d;
  108. char *path = nil;
  109. char *fullpath;
  110. t = smbidmapfind(s->tidmap, h->tid);
  111. if (t == nil) {
  112. smbseterror(s, ERRSRV, ERRinvtid);
  113. pr = SmbProcessResultError;
  114. goto done;
  115. }
  116. b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
  117. if (!smbbuffergets(b, &infolevel) || !smbbuffergetbytes(b, nil, 4)
  118. || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
  119. pr = SmbProcessResultMisc;
  120. goto done;
  121. }
  122. translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
  123. translogprint(s->transaction.in.setup[0], "path %s\n", path);
  124. fullpath = nil;
  125. smbstringprint(&fullpath, "%s%s", t->serv->path, path);
  126. translogprint(s->transaction.in.setup[0], "fullpath %s\n", fullpath);
  127. d = dirstat(fullpath);
  128. pr = query(s, "path", path, infolevel, 0, d);
  129. free(d);
  130. free(fullpath);
  131. done:
  132. free(path);
  133. smbbufferfree(&b);
  134. return pr;
  135. }
  136. SmbProcessResult
  137. smbtrans2queryfileinformation(SmbSession *s, SmbHeader *h)
  138. {
  139. SmbTree *t;
  140. SmbFile *f;
  141. SmbBuffer *b = nil;
  142. SmbProcessResult pr;
  143. ushort fid;
  144. ushort infolevel;
  145. Dir *d;
  146. t = smbidmapfind(s->tidmap, h->tid);
  147. if (t == nil) {
  148. smbseterror(s, ERRSRV, ERRinvtid);
  149. pr = SmbProcessResultError;
  150. goto done;
  151. }
  152. b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
  153. if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) {
  154. pr = SmbProcessResultMisc;
  155. goto done;
  156. }
  157. translogprint(s->transaction.in.setup[0], "fid 0x%.4ux\n", fid);
  158. translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
  159. f = smbidmapfind(s->fidmap, fid);
  160. if (f == nil) {
  161. smbseterror(s, ERRDOS, ERRbadfid);
  162. pr = SmbProcessResultError;
  163. goto done;
  164. }
  165. d = dirfstat(f->fd);
  166. pr = query(s, "file", f->name, infolevel, seek(f->fd, 0, 1), d);
  167. free(d);
  168. done:
  169. smbbufferfree(&b);
  170. return pr;
  171. }
  172. SmbProcessResult
  173. smbtrans2queryfsinformation(SmbSession *s, SmbHeader *h)
  174. {
  175. SmbTree *t;
  176. ushort infolevel;
  177. SmbBuffer *b;
  178. SmbProcessResult pr;
  179. ulong fixup;
  180. ulong vnbase;
  181. t = smbidmapfind(s->tidmap, h->tid);
  182. if (t == nil) {
  183. smbseterror(s, ERRSRV, ERRinvtid);
  184. pr = SmbProcessResultError;
  185. goto done;
  186. }
  187. b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
  188. if (!smbbuffergets(b, &infolevel)) {
  189. misc:
  190. pr = SmbProcessResultMisc;
  191. goto done;
  192. }
  193. pr = SmbProcessResultReply;
  194. switch (infolevel) {
  195. case SMB_INFO_ALLOCATION:
  196. translogprint(s->transaction.in.setup[0], "SMB_INFO_ALLOCATION\n");
  197. if (!smbbufferputl(s->transaction.out.data, 0)
  198. || !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
  199. || !smbbufferputl(s->transaction.out.data, 0xffffffff)
  200. || !smbbufferputl(s->transaction.out.data, 0xffffffff)
  201. || !smbbufferputs(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
  202. goto misc;
  203. break;
  204. case SMB_INFO_VOLUME:
  205. translogprint(s->transaction.in.setup[0], "SMB_INFO_VOLUME\n");
  206. if (!smbbufferputl(s->transaction.out.data, 0xdeadbeef)
  207. || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name))
  208. goto misc;
  209. break;
  210. case SMB_QUERY_FS_VOLUME_INFO:
  211. translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_VOLUME_INFO\n");
  212. if (!smbbufferputv(s->transaction.out.data, 0)
  213. || !smbbufferputl(s->transaction.out.data, 0xdeadbeef))
  214. goto misc;
  215. fixup = smbbufferwriteoffset(s->transaction.out.data);
  216. if (!smbbufferputl(s->transaction.out.data, 0)
  217. || !smbbufferputs(s->transaction.out.data, 0))
  218. goto misc;
  219. vnbase = smbbufferwriteoffset(s->transaction.out.data);
  220. if (!smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name)
  221. || !smbbufferfixupl(s->transaction.out.data, fixup,
  222. smbbufferwriteoffset(s->transaction.out.data) - vnbase))
  223. goto misc;
  224. break;
  225. case SMB_QUERY_FS_SIZE_INFO:
  226. translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_SIZE_INFO\n");
  227. if (!smbbufferputv(s->transaction.out.data, 0xffffffffffffffffLL)
  228. || !smbbufferputv(s->transaction.out.data, 0xffffffffffffffffLL)
  229. || !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
  230. || !smbbufferputl(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
  231. goto misc;
  232. break;
  233. case SMB_QUERY_FS_ATTRIBUTE_INFO:
  234. translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_ATTRIBUTE_INFO\n");
  235. if (!smbbufferputl(s->transaction.out.data, 3)
  236. || !smbbufferputl(s->transaction.out.data, 255))
  237. goto misc;
  238. fixup = smbbufferwriteoffset(s->transaction.out.data);
  239. if (!smbbufferputl(s->transaction.out.data, 0)
  240. || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_UNTERMINATED, smbglobals.serverinfo.nativelanman)
  241. || !smbbufferfixuprelativel(s->transaction.out.data, fixup))
  242. goto misc;
  243. break;
  244. default:
  245. smblogprint(-1, "smbtrans2queryfsinformation: infolevel 0x%.4ux not implemented\n", infolevel);
  246. smbseterror(s, ERRDOS, ERRunknownlevel);
  247. pr = SmbProcessResultError;
  248. }
  249. done:
  250. smbbufferfree(&b);
  251. return pr;
  252. }