aquarela.c 7.3 KB

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