aquarela.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #include "headers.h"
  2. #include <pool.h>
  3. static void
  4. disconnecttree(void *magic, void *arg)
  5. {
  6. smbtreedisconnect((SmbSession *)magic, (SmbTree *)arg);
  7. }
  8. static void
  9. closesearch(void *magic, void *arg)
  10. {
  11. smbsearchclose((SmbSession *)magic, (SmbSearch *)arg);
  12. }
  13. static void
  14. smbsessionfree(SmbSession *s)
  15. {
  16. if (s) {
  17. smbidmapfree(&s->tidmap, disconnecttree, s);
  18. smbidmapfree(&s->sidmap, closesearch, s);
  19. smbbufferfree(&s->response);
  20. free(s->client.accountname);
  21. free(s->client.primarydomain);
  22. free(s->client.nativeos);
  23. free(s->client.nativelanman);
  24. free(s->transaction.in.parameters);
  25. free(s->transaction.in.data);
  26. free(s->transaction.in.setup);
  27. free(s->transaction.in.name);
  28. smbbufferfree(&s->transaction.out.parameters);
  29. smbbufferfree(&s->transaction.out.data);
  30. auth_freechal(s->cs);
  31. free(s);
  32. }
  33. }
  34. int
  35. smbsessionwrite(SmbSession *smbs, void *p, long n)
  36. {
  37. SmbHeader h;
  38. SmbOpTableEntry *ote;
  39. uchar *pdata;
  40. int rv;
  41. SmbBuffer *b = nil;
  42. ushort bytecount;
  43. SmbProcessResult pr;
  44. if (smbs->response == nil)
  45. smbs->response = smbbuffernew(576);
  46. else
  47. smbresponsereset(smbs);
  48. smbs->errclass = SUCCESS;
  49. smbs->error = SUCCESS;
  50. // print("received %ld bytes\n", n);
  51. if (n <= 0)
  52. goto closedown;
  53. b = smbbufferinit(p, p, n);
  54. if (!smbbuffergetheader(b, &h, &pdata, &bytecount)) {
  55. smblogprint(-1, "smb: invalid header\n");
  56. goto closedown;
  57. }
  58. smbloglock();
  59. smblogprint(h.command, "received:\n");
  60. smblogdata(h.command, smblogprint, p, n, 0x1000);
  61. smblogunlock();
  62. ote = smboptable + h.command;
  63. if (ote->name == nil) {
  64. smblogprint(-1, "smb: illegal opcode 0x%.2ux\n", h.command);
  65. goto unimp;
  66. }
  67. if (ote->process == nil) {
  68. smblogprint(-1, "smb: opcode %s unimplemented\n", ote->name);
  69. goto unimp;
  70. }
  71. if (smbs->nextcommand != SMB_COM_NO_ANDX_COMMAND
  72. && smbs->nextcommand != h.command) {
  73. smblogprint(-1, "smb: wrong command - expected %.2ux\n", smbs->nextcommand);
  74. goto misc;
  75. }
  76. smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
  77. switch (h.command) {
  78. case SMB_COM_NEGOTIATE:
  79. case SMB_COM_SESSION_SETUP_ANDX:
  80. case SMB_COM_TREE_CONNECT_ANDX:
  81. case SMB_COM_ECHO:
  82. break;
  83. default:
  84. if (smbs->state != SmbSessionEstablished) {
  85. smblogprint(-1, "aquarela: command %.2ux unexpected\n", h.command);
  86. goto unimp;
  87. }
  88. }
  89. pr = (*ote->process)(smbs, &h, pdata, b);
  90. switch (pr) {
  91. case SmbProcessResultUnimp:
  92. unimp:
  93. smbseterror(smbs, ERRDOS, ERRunsup);
  94. pr = SmbProcessResultError;
  95. break;
  96. case SmbProcessResultFormat:
  97. smbseterror(smbs, ERRSRV, ERRsmbcmd);
  98. pr = SmbProcessResultError;
  99. break;
  100. case SmbProcessResultMisc:
  101. misc:
  102. smbseterror(smbs, ERRSRV, ERRerror);
  103. pr = SmbProcessResultError;
  104. break;
  105. }
  106. if (pr == SmbProcessResultError) {
  107. smblogprint(h.command, "reply: error %d/%d\n", smbs->errclass, smbs->error);
  108. if (!smbresponseputerror(smbs, &h, smbs->errclass, smbs->error))
  109. pr = SmbProcessResultDie;
  110. else
  111. pr = SmbProcessResultReply;
  112. }
  113. else
  114. smblogprint(h.command, "reply: ok\n");
  115. if (pr == SmbProcessResultReply)
  116. rv = smbresponsesend(smbs) == SmbProcessResultOk ? 0 : -1;
  117. else if (pr == SmbProcessResultDie)
  118. rv = -1;
  119. else
  120. rv = 0;
  121. goto done;
  122. closedown:
  123. rv = -1;
  124. done:
  125. if (rv < 0) {
  126. smblogprintif(smbglobals.log.sessions, "shutting down\n");
  127. smbsessionfree(smbs);
  128. }
  129. smbbufferfree(&b);
  130. if (smbglobals.log.poolparanoia)
  131. poolcheck(mainmem);
  132. return rv;
  133. }
  134. static int
  135. nbwrite(NbSession *nbss, void *p, long n)
  136. {
  137. return smbsessionwrite((SmbSession *)nbss->magic, p, n);
  138. }
  139. static int
  140. cifswrite(SmbCifsSession *cifs, void *p, long n)
  141. {
  142. return smbsessionwrite((SmbSession *)cifs->magic, p, n);
  143. }
  144. int
  145. nbssaccept(void *, NbSession *s, NBSSWRITEFN **writep)
  146. {
  147. SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1);
  148. smbs->nbss = s;
  149. s->magic = smbs;
  150. smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
  151. *writep = nbwrite;
  152. smblogprintif(smbglobals.log.sessions, "netbios session started\n");
  153. return 1;
  154. }
  155. int
  156. cifsaccept(SmbCifsSession *s, SMBCIFSWRITEFN **writep)
  157. {
  158. SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1);
  159. smbs->cifss = s;
  160. s->magic = smbs;
  161. smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
  162. *writep = cifswrite;
  163. smblogprintif(smbglobals.log.sessions, "cifs session started\n");
  164. return 1;
  165. }
  166. void
  167. usage(void)
  168. {
  169. fprint(2, "usage: %s [-np] [-d debug] [-u N] [-w workgroup]\n", argv0);
  170. threadexitsall("usage");
  171. }
  172. static void
  173. logset(char *cmd)
  174. {
  175. int x;
  176. if (strcmp(cmd, "allcmds") == 0) {
  177. for (x = 0; x < 256; x++)
  178. smboptable[x].debug = 1;
  179. for (x = 0; x < smbtrans2optablesize; x++)
  180. smbtrans2optable[x].debug = 1;
  181. return;
  182. }
  183. if (strcmp(cmd, "tids") == 0) {
  184. smbglobals.log.tids = 1;
  185. return;
  186. }
  187. if (strcmp(cmd, "sids") == 0) {
  188. smbglobals.log.sids = 1;
  189. return;
  190. }
  191. if (strcmp(cmd, "fids") == 0) {
  192. smbglobals.log.fids = 1;
  193. return;
  194. }
  195. if (strcmp(cmd, "rap2") == 0) {
  196. smbglobals.log.rap2 = 1;
  197. return;
  198. }
  199. else if (strcmp(cmd, "find") == 0) {
  200. smbglobals.log.find = 1;
  201. return;
  202. }
  203. if (strcmp(cmd, "query") == 0) {
  204. smbglobals.log.query = 1;
  205. return;
  206. }
  207. if (strcmp(cmd, "sharedfiles") == 0) {
  208. smbglobals.log.sharedfiles = 1;
  209. return;
  210. }
  211. if (strcmp(cmd, "poolparanoia") == 0) {
  212. mainmem->flags |= POOL_PARANOIA;
  213. smbglobals.log.poolparanoia = 1;
  214. return;
  215. }
  216. if (strcmp(cmd, "sessions") == 0) {
  217. smbglobals.log.sessions = 1;
  218. return;
  219. }
  220. if (strcmp(cmd, "rep") == 0) {
  221. smbglobals.log.rep = 1;
  222. return;
  223. }
  224. if (strcmp(cmd, "locks") == 0) {
  225. smbglobals.log.locks = 1;
  226. return;
  227. }
  228. for (x = 0; x < 256; x++)
  229. if (smboptable[x].name && strcmp(smboptable[x].name, cmd) == 0) {
  230. smboptable[x].debug = 1;
  231. return;
  232. }
  233. for (x = 0; x < smbtrans2optablesize; x++)
  234. if (smbtrans2optable[x].name && strcmp(smbtrans2optable[x].name, cmd) == 0) {
  235. smbtrans2optable[x].debug = 1;
  236. return;
  237. }
  238. if (strlen(cmd) == 4 && cmd[0] == '0' && cmd[1] == 'x') {
  239. int c;
  240. c = strtoul(cmd + 2, 0, 16);
  241. if (c >= 0 && c <= 255) {
  242. smboptable[c].debug = 1;
  243. return;
  244. }
  245. }
  246. print("debugging command %s not recognised\n", cmd);
  247. }
  248. void
  249. threadmain(int argc, char **argv)
  250. {
  251. NbName from, to;
  252. char *e = nil;
  253. int netbios = 0;
  254. ARGBEGIN {
  255. case 'u':
  256. smbglobals.unicode = strtol(ARGF(), 0, 0) != 0;
  257. break;
  258. case 'p':
  259. smbglobals.log.print = 1;
  260. break;
  261. case 'd':
  262. logset(ARGF());
  263. break;
  264. case 'w':
  265. smbglobals.primarydomain = ARGF();
  266. break;
  267. case 'n':
  268. netbios = 1;
  269. break;
  270. default:
  271. usage();
  272. } ARGEND;
  273. smbglobalsguess(0);
  274. smblistencifs(cifsaccept);
  275. if (netbios) {
  276. nbinit();
  277. nbmknamefromstring(from, "*");
  278. nbmknamefromstring(to, "*smbserver\\x20");
  279. nbsslisten(to, from, nbssaccept, nil);
  280. nbmknamefromstringandtype(to, smbglobals.serverinfo.name, 0x20);
  281. nbsslisten(to, from, nbssaccept, nil);
  282. }
  283. smblogprint(-1, "Aquarela %d.%d running\n", smbglobals.serverinfo.vmaj, smbglobals.serverinfo.vmin);
  284. for (;;) {
  285. if (netbios&& !smbbrowsesendhostannouncement(smbglobals.serverinfo.name, 60 * 1000,
  286. SV_TYPE_SERVER,
  287. smbglobals.serverinfo.remark, &e)) {
  288. smblogprint(-1, "hostannounce failed: %s\n", e);
  289. }
  290. if (sleep(60 * 1000) < 0)
  291. break;
  292. }
  293. }