xref: /plan9/sys/src/cmd/aquarela/smbcomtreeconnectandx.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
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