smbtrans2query.c 8.1 KB

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