xref: /plan9-contrib/sys/src/cmd/aquarela/smbcomsessionsetupandx.c (revision 08d9be5d6ac53f09e0668042eb5820fbcaf7c8a2)
1 #include "headers.h"
2 #include <mp.h>
3 #include <libsec.h>
4 
5 SmbProcessResult
smbcomsessionsetupandx(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)6 smbcomsessionsetupandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
7 {
8 	uchar andxcommand;
9 	ushort andxoffset;
10 	ulong andxfixupoffset;
11 	ushort vcnumber;
12 	ulong sessionkey;
13 	ushort caseinsensitivepasswordlength;
14 	ushort casesensitivepasswordlength;
15 	ushort bytecountfixup, offset;
16 	uchar *mschapreply;
17 	AuthInfo *ai;
18 	char *sp;
19 	SmbProcessResult pr;
20 	char *accountname = nil;
21 	char *primarydomain = nil;
22 	char *nativeos = nil;
23 	char *nativelanman = nil;
24 
25 	if (!smbcheckwordcount("comsessionsetupandx", h, 13)) {
26 	fmtfail:
27 		pr = SmbProcessResultFormat;
28 		goto done;
29 	}
30 
31 	andxcommand = *pdata++;
32 	switch (andxcommand) {
33 	case SMB_COM_TREE_CONNECT_ANDX:
34 	case SMB_COM_OPEN_ANDX:
35 	case SMB_COM_CREATE_NEW:
36 	case SMB_COM_DELETE:
37 	case SMB_COM_FIND:
38 	case SMB_COM_COPY:
39 	case SMB_COM_NT_RENAME:
40 	case SMB_COM_QUERY_INFORMATION:
41 	case SMB_COM_NO_ANDX_COMMAND:
42 	case SMB_COM_OPEN:
43 	case SMB_COM_CREATE:
44 	case SMB_COM_CREATE_DIRECTORY:
45 	case SMB_COM_DELETE_DIRECTORY:
46 	case SMB_COM_FIND_UNIQUE:
47 	case SMB_COM_RENAME:
48 	case SMB_COM_CHECK_DIRECTORY:
49 	case SMB_COM_SET_INFORMATION:
50 	case SMB_COM_OPEN_PRINT_FILE:
51 		break;
52 	default:
53 		smblogprint(h->command, "smbcomsessionsetupandx: invalid andxcommand %s (0x%.2ux)\n",
54 			smboptable[andxcommand].name, andxcommand);
55 		goto fmtfail;
56 	}
57 	pdata++;
58 	andxoffset = smbnhgets(pdata); pdata += 2;
59 	s->peerinfo.maxlen = smbnhgets(pdata); pdata += 2;
60 	smbresponseinit(s, s->peerinfo.maxlen);
61 	s->client.maxmpxcount = smbnhgets(pdata); pdata += 2;
62 	vcnumber = smbnhgets(pdata); pdata += 2;
63 	sessionkey = smbnhgetl(pdata); pdata += 4;
64 	caseinsensitivepasswordlength = smbnhgets(pdata); pdata += 2;
65 	casesensitivepasswordlength = smbnhgets(pdata); pdata += 2;
66 	pdata += 4;
67 	s->peerinfo.capabilities = smbnhgetl(pdata); /*pdata += 4;*/
68 smbloglock();
69 smblogprint(h->command, "andxcommand: %s offset %ud\n", smboptable[andxcommand].name, andxoffset);
70 smblogprint(h->command, "client.maxbuffersize: %ud\n", s->peerinfo.maxlen);
71 smblogprint(h->command, "client.maxmpxcount: %ud\n", s->client.maxmpxcount);
72 smblogprint(h->command, "vcnumber: %ud\n", vcnumber);
73 smblogprint(h->command, "sessionkey: 0x%.8lux\n", sessionkey);
74 smblogprint(h->command, "caseinsensitivepasswordlength: %ud\n", caseinsensitivepasswordlength);
75 smblogprint(h->command, "casesensitivepasswordlength: %ud\n", casesensitivepasswordlength);
76 smblogprint(h->command, "clientcapabilities: 0x%.8lux\n", s->peerinfo.capabilities);
77 smblogunlock();
78 
79 	mschapreply = smbbufferreadpointer(b);
80 
81 	if (!smbbuffergetbytes(b, nil, caseinsensitivepasswordlength + casesensitivepasswordlength)) {
82 		smblogprint(h->command, "smbcomsessionsetupandx: not enough bdata for passwords\n");
83 		goto fmtfail;
84 	}
85 	if (!smbbuffergetstring(b, h, 0, &accountname)
86 		|| !smbbuffergetstring(b, h, 0, &primarydomain)
87 		|| !smbbuffergetstring(b, h, 0, &nativeos)
88 		|| !smbbuffergetstring(b, h, 0, &nativelanman)) {
89 		smblogprint(h->command, "smbcomsessionsetupandx: not enough bytes for strings\n");
90 		goto fmtfail;
91 	}
92 
93 	for (sp = accountname; *sp; sp++)
94 		*sp = tolower(*sp);
95 
96 smblogprint(h->command, "account: %s\n", accountname);
97 smblogprint(h->command, "primarydomain: %s\n", primarydomain);
98 smblogprint(h->command, "nativeos: %s\n", nativeos);
99 smblogprint(h->command, "nativelanman: %s\n", nativelanman);
100 
101 	if (s->client.accountname && accountname[0] && strcmp(s->client.accountname, accountname) != 0) {
102 		smblogprint(h->command, "smbcomsessionsetupandx: more than one user on VC (before %s, now %s)\n",
103 			s->client.accountname, accountname);
104 		smbseterror(s, ERRSRV, ERRtoomanyuids);
105 	errordone:
106 		pr = SmbProcessResultError;
107 		goto done;
108 	}
109 
110 	if (s->client.accountname == nil) {
111 		/* first time */
112 		if (accountname[0] == 0) {
113 			smbseterror(s, ERRSRV, ERRbaduid);
114 			goto errordone;
115 		}
116 		if ((casesensitivepasswordlength != 24 || caseinsensitivepasswordlength != 24)) {
117 			smblogprint(h->command,
118 				"smbcomsessionsetupandx: case sensitive/insensitive password length not 24\n");
119 			smbseterror(s, ERRSRV, ERRbadpw);
120 			goto errordone;
121 		}
122 		memcpy(&s->client.mschapreply, mschapreply, sizeof(s->client.mschapreply));
123 		if(s->cs == nil){
124 			smbseterror(s, ERRSRV, ERRerror);
125 			goto errordone;
126 		}
127 		s->cs->user = accountname;
128 		s->cs->resp = &s->client.mschapreply;
129 		s->cs->nresp = sizeof(MSchapreply);
130 		ai = auth_response(s->cs);
131 		if (ai == nil) {
132 			smblogprint(h->command, "authentication failed\n");
133 			smbseterror(s, ERRSRV, ERRbadpw);
134 			goto errordone;
135 		}
136 		smblogprint(h->command, "authentication succeeded\n");
137 		if (auth_chuid(ai, nil) < 0) {
138 			smblogprint(h->command, "smbcomsessionsetupandx: chuid failed: %r\n");
139 			auth_freeAI(ai);
140 		miscerror:
141 			pr = SmbProcessResultMisc;
142 			goto done;
143 		}
144 		auth_freeAI(ai);
145 		h->uid = 1;
146 		s->client.accountname = accountname;
147 		s->client.primarydomain = primarydomain;
148 		s->client.nativeos = nativeos;
149 		s->client.nativelanman = nativelanman;
150 		accountname = nil;
151 		primarydomain = nil;
152 		nativeos = nil;
153 		nativelanman = nil;
154 	}
155 	else {
156 		if (caseinsensitivepasswordlength == 24 && casesensitivepasswordlength == 24
157 			&& memcmp(&s->client.mschapreply, mschapreply, sizeof(MSchapreply)) != 0) {
158 			smblogprint(h->command, "second time authentication failed\n");
159 			smbseterror(s, ERRSRV, ERRbadpw);
160 			goto errordone;
161 		}
162 	}
163 
164 	/* CIFS says 4 with or without extended security, samba/ms says 3 without */
165 	h->wordcount = 3;
166 	if (!smbresponseputandxheader(s, h, andxcommand, &andxfixupoffset))
167 		goto miscerror;
168 	if (!smbresponseputs(s, 0))
169 		goto miscerror;
170 	bytecountfixup = smbresponseoffset(s);
171 	if (!smbresponseputs(s, 0))
172 		goto miscerror;
173 	if (!smbresponseputstring(s, 1, smbglobals.nativeos)
174 		|| !smbresponseputstring(s, 1, smbglobals.serverinfo.nativelanman)
175 		|| !smbresponseputstring(s, 1, smbglobals.primarydomain))
176 		goto miscerror;
177 	offset = smbresponseoffset(s);
178 	smbresponseoffsetputs(s, bytecountfixup, offset - bytecountfixup - 2);
179 	s->state = SmbSessionEstablished;
180 	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
181 		pr = smbchaincommand(s, h, andxfixupoffset, andxcommand, andxoffset, b);
182 	else
183 		pr = SmbProcessResultReply;
184 done:
185 	free(accountname);
186 	free(primarydomain);
187 	free(nativeos);
188 	free(nativelanman);
189 	return pr;
190 }
191