1 #include "headers.h"
2
3 static char *s9p2000 = "9p2000";
4
5 SmbProcessResult
smbcomtreeconnectandx(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)6 smbcomtreeconnectandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
7 {
8 uchar andxcommand;
9 ushort andxoffset;
10 char *path = nil;
11 char *service = nil;
12 ushort flags;
13 ushort passwordlength;
14 // ushort bytecount;
15 uchar errclass;
16 ushort error;
17 SmbService *serv;
18 SmbTree *tree;
19 ulong andxfixupoffset, bytecountfixup;
20 SmbProcessResult pr;
21
22 if (!smbcheckwordcount("comtreeconnectandx", h, 4)) {
23 fmtfail:
24 pr = SmbProcessResultFormat;
25 goto done;
26 }
27
28 switch (s->state) {
29 case SmbSessionNeedNegotiate:
30 smblogprint(-1, "smbcomtreeconnectandx: called when negotiate expected\n");
31 return SmbProcessResultUnimp;
32 case SmbSessionNeedSetup:
33 smbseterror(s, ERRDOS, ERRbadpw);
34 return SmbProcessResultError;
35 }
36
37 andxcommand = *pdata++;
38 switch (andxcommand) {
39 case SMB_COM_OPEN:
40 case SMB_COM_CREATE_NEW:
41 case SMB_COM_DELETE_DIRECTORY:
42 case SMB_COM_FIND_UNIQUE:
43 case SMB_COM_CHECK_DIRECTORY:
44 case SMB_COM_GET_PRINT_QUEUE:
45 case SMB_COM_TRANSACTION:
46 case SMB_COM_SET_INFORMATION:
47 case SMB_COM_OPEN_ANDX:
48 case SMB_COM_CREATE_DIRECTORY:
49 case SMB_COM_FIND:
50 case SMB_COM_RENAME:
51 case SMB_COM_QUERY_INFORMATION:
52 case SMB_COM_OPEN_PRINT_FILE:
53 case SMB_COM_NO_ANDX_COMMAND:
54 case SMB_COM_NT_RENAME:
55 case SMB_COM_CREATE:
56 case SMB_COM_DELETE:
57 case SMB_COM_COPY:
58 break;
59 default:
60 smblogprint(h->command, "smbcomtreeconnectandx: invalid andxcommand %s (0x%.2ux)\n",
61 smboptable[andxcommand].name, andxcommand);
62 goto fmtfail;
63 }
64 pdata++;
65 andxoffset = smbnhgets(pdata); pdata += 2;
66 flags = smbnhgets(pdata); pdata += 2;
67 passwordlength = smbnhgets(pdata); //pdata += 2;
68 // bytecount = smbnhgets(pdata); pdata += 2;
69 smblogprint(h->command, "passwordlength: %ud\n", passwordlength);
70 smblogprint(h->command, "flags: 0x%.4ux\n", flags);
71 if (!smbbuffergetbytes(b, nil, passwordlength)) {
72 smblogprint(h->command, "smbcomtreeconnectandx: not enough bytes for password\n");
73 goto fmtfail;
74 }
75 smblogprint(h->command, "offset %lud limit %lud\n", smbbufferreadoffset(b), smbbufferwriteoffset(b));
76 if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)
77 || !smbbuffergetstr(b, 0, &service)) {
78 smblogprint(h->command, "smbcomtreeconnectandx: not enough bytes for strings\n");
79 goto fmtfail;
80 }
81 smblogprint(h->command, "path: %s\n", path);
82 smblogprint(h->command, "service: %s\n", service);
83 if (flags & 1)
84 smbtreedisconnectbyid(s, h->tid);
85 serv = smbservicefind(s, path, service, &errclass, &error);
86 if (serv == nil) {
87 pr = SmbProcessResultError;
88 smbseterror(s, errclass, error);
89 goto done;
90 }
91 tree = smbtreeconnect(s, serv);
92 h->tid = tree->id;
93 h->wordcount = 3;
94 if (!smbresponseputandxheader(s, h, andxcommand, &andxfixupoffset)
95 || !smbresponseputs(s, 1)) {
96 misc:
97 pr = SmbProcessResultMisc;
98 goto done;
99 }
100 bytecountfixup = smbresponseoffset(s);
101 if (!smbresponseputs(s, 0)
102 || !smbresponseputstr(s, serv->type)
103 || !smbresponseputstring(s, 1, s9p2000))
104 goto misc;
105 if (!smbbufferfixuprelatives(s->response, bytecountfixup))
106 goto misc;
107 if (andxcommand != SMB_COM_NO_ANDX_COMMAND) {
108 pr = smbchaincommand(s, h, andxfixupoffset, andxcommand, andxoffset, b);
109 }
110 else
111 pr = SmbProcessResultReply;
112 done:
113 free(path);
114 free(service);
115 return pr;
116 }
117