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