]>
Commit | Line | Data |
---|---|---|
04e4e140 | 1 | /* |
5b74111a | 2 | * Copyright (C) 1996-2018 The Squid Software Foundation and contributors |
04e4e140 AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
7c16470c AJ |
9 | /* UNIX SMBlib NetBIOS implementation |
10 | ||
11 | Version 1.0 | |
12 | SMBlib Routines. Experimental Section ... | |
13 | ||
14 | Copyright (C) Richard Sharpe 1996 | |
7c16470c AJ |
15 | */ |
16 | ||
17 | /* | |
18 | This program is free software; you can redistribute it and/or modify | |
19 | it under the terms of the GNU General Public License as published by | |
20 | the Free Software Foundation; either version 2 of the License, or | |
21 | (at your option) any later version. | |
22 | ||
23 | This program is distributed in the hope that it will be useful, | |
24 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
26 | GNU General Public License for more details. | |
27 | ||
28 | You should have received a copy of the GNU General Public License | |
29 | along with this program; if not, write to the Free Software | |
30 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
31 | */ | |
32 | ||
04e4e140 | 33 | #include "squid.h" |
0ab648c9 | 34 | #include "rfcnb/rfcnb.h" |
602d9612 | 35 | #include "smblib/smblib-priv.h" |
7c16470c AJ |
36 | |
37 | #include <signal.h> | |
0ab648c9 AJ |
38 | #if HAVE_STRING_H |
39 | #include <string.h> | |
40 | #endif | |
7c16470c AJ |
41 | |
42 | /* Logon and tree connect to the server */ | |
43 | ||
44 | int SMB_Logon_And_TCon(SMB_Handle_Type Con_Handle, char *UserName, | |
45 | char *PassWord, | |
46 | char *service, | |
47 | char *service_type) | |
48 | ||
49 | { | |
50 | struct RFCNB_Pkt *pkt; | |
51 | int param_len, i, pkt_len, andx_len, andx_param_len; | |
52 | char *p, *AndXCom; | |
53 | ||
54 | /* First we need a packet etc ... but we need to know what protocol has */ | |
55 | /* been negotiated to figure out if we can do it and what SMB format to */ | |
56 | /* use ... */ | |
57 | ||
58 | /* Since we are going to do a LogonAndX with a TCon as the second command*/ | |
59 | /* We need the packet size correct. So TCon starts at wct field */ | |
60 | ||
61 | if (SMB_Types[Con_Handle -> protocol] < SMB_P_LanMan1) { | |
62 | ||
63 | SMBlib_errno = SMBlibE_ProtLow; | |
64 | return(SMBlibE_BAD); | |
65 | ||
66 | } | |
67 | ||
68 | /* Now build the correct structure */ | |
69 | ||
70 | if (SMB_Types[Con_Handle -> protocol] < SMB_P_NT1) { | |
71 | ||
72 | param_len = strlen(UserName) + 1 + strlen(PassWord) + | |
73 | strlen(Con_Handle -> PDomain) + 1 + | |
74 | strlen(Con_Handle -> OSName) + 1; | |
75 | ||
76 | pkt_len = SMB_ssetpLM_len + param_len; | |
77 | ||
78 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
79 | ||
80 | if (pkt == NULL) { | |
81 | ||
82 | SMBlib_errno = SMBlibE_NoSpace; | |
83 | return(SMBlibE_BAD); /* Should handle the error */ | |
84 | ||
85 | } | |
86 | ||
0ab648c9 | 87 | memset(SMB_Hdr(pkt), 0, SMB_ssetpLM_len); |
7c16470c AJ |
88 | SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ |
89 | *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; | |
90 | SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); | |
91 | SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); | |
92 | SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); | |
93 | SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid); | |
94 | *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10; | |
95 | *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra command */ | |
96 | SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0); | |
97 | ||
98 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT); | |
99 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2); | |
100 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle -> pid); | |
101 | SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0); | |
102 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, strlen(PassWord)); | |
103 | SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0); | |
104 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len); | |
105 | ||
106 | /* Now copy the param strings in with the right stuff */ | |
107 | ||
108 | p = (char *)(SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset); | |
109 | ||
110 | /* Copy in password, then the rest. Password has no null at end */ | |
111 | ||
112 | strcpy(p, PassWord); | |
113 | ||
114 | p = p + strlen(PassWord); | |
115 | ||
116 | strcpy(p, UserName); | |
117 | p = p + strlen(UserName); | |
118 | *p = 0; | |
119 | ||
120 | p = p + 1; | |
121 | ||
122 | strcpy(p, Con_Handle -> PDomain); | |
123 | p = p + strlen(Con_Handle -> PDomain); | |
124 | *p = 0; | |
125 | p = p + 1; | |
126 | ||
127 | strcpy(p, Con_Handle -> OSName); | |
128 | p = p + strlen(Con_Handle -> OSName); | |
129 | *p = 0; | |
130 | ||
131 | } else { | |
132 | ||
133 | /* We don't admit to UNICODE support ... */ | |
134 | ||
135 | param_len = strlen(UserName) + 1 + strlen(PassWord) + | |
136 | strlen(Con_Handle -> PDomain) + 1 + | |
137 | strlen(Con_Handle -> OSName) + 1; | |
138 | ||
139 | andx_len = SMB_tcon_len - SMB_hdr_wct_offset; | |
140 | ||
141 | /* We send a null password as we sent one in the setup and X */ | |
142 | ||
143 | andx_param_len = strlen(service) + 2 + 2 + strlen(service_type) + 2; | |
144 | ||
145 | pkt_len = SMB_ssetpNTLM_len + param_len + andx_len + andx_param_len; | |
146 | ||
147 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
148 | ||
149 | if (pkt == NULL) { | |
150 | ||
151 | SMBlib_errno = SMBlibE_NoSpace; | |
152 | return(-1); /* Should handle the error */ | |
153 | ||
154 | } | |
155 | ||
0ab648c9 | 156 | memset(SMB_Hdr(pkt), 0, SMB_ssetpNTLM_len); |
7c16470c AJ |
157 | SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ |
158 | *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; | |
159 | SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); | |
160 | SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); | |
161 | SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); | |
162 | SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid); | |
163 | *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13; | |
164 | *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = SMBtcon; | |
165 | SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, SMB_ssetpNTLM_len + param_len); | |
166 | ||
167 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT); | |
168 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 2); | |
169 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 0); | |
170 | SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0); | |
171 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, strlen(PassWord)); | |
172 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0); | |
173 | SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0); | |
174 | SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0); | |
175 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len); | |
176 | ||
177 | /* Now copy the param strings in with the right stuff */ | |
178 | ||
179 | p = (char *)(SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset); | |
180 | ||
181 | /* Copy in password, then the rest. Password has no null at end */ | |
182 | ||
183 | strcpy(p, PassWord); | |
184 | ||
185 | p = p + strlen(PassWord); | |
186 | ||
187 | strcpy(p, UserName); | |
188 | p = p + strlen(UserName); | |
189 | *p = 0; | |
190 | ||
191 | p = p + 1; | |
192 | ||
193 | strcpy(p, Con_Handle -> PDomain); | |
194 | p = p + strlen(Con_Handle -> PDomain); | |
195 | *p = 0; | |
196 | p = p + 1; | |
197 | ||
198 | strcpy(p, Con_Handle -> OSName); | |
199 | p = p + strlen(Con_Handle -> OSName); | |
200 | *p = 0; | |
201 | ||
202 | /* Now set up the TCON Part ... from WCT, make up a pointer that will | |
203 | help us ... */ | |
204 | ||
205 | AndXCom = SMB_Hdr(pkt) + SMB_ssetpNTLM_len + param_len - SMB_hdr_wct_offset; | |
206 | ||
207 | *(AndXCom + SMB_hdr_wct_offset) = 0; /* No Words */ | |
208 | ||
209 | SSVAL(AndXCom, SMB_tcon_bcc_offset, andx_param_len); | |
210 | ||
211 | p = (char *)(AndXCom + SMB_tcon_buf_offset); | |
212 | ||
213 | *p = SMBasciiID; | |
214 | strcpy(p + 1, service); | |
215 | p = p + strlen(service) + 2; | |
216 | *p = SMBasciiID; /* No password ... */ | |
217 | *(p + 1) = 0; | |
218 | p = p + 2; | |
219 | *p = SMBasciiID; | |
220 | strcpy(p + 1, service_type); | |
221 | ||
222 | } | |
223 | ||
224 | /* Now send it and get a response */ | |
225 | ||
226 | if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) { | |
227 | ||
228 | #ifdef DEBUG | |
229 | fprintf(stderr, "Error sending SessSetupAndTCon request\n"); | |
230 | #endif | |
231 | ||
232 | RFCNB_Free_Pkt(pkt); | |
233 | SMBlib_errno = SMBlibE_SendFailed; | |
234 | return(SMBlibE_BAD); | |
235 | ||
236 | } | |
237 | ||
238 | /* Now get the response ... */ | |
239 | ||
240 | if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) { | |
241 | ||
242 | #ifdef DEBUG | |
243 | fprintf(stderr, "Error receiving response to SessSetupAndTCon\n"); | |
244 | #endif | |
245 | ||
246 | RFCNB_Free_Pkt(pkt); | |
247 | SMBlib_errno = SMBlibE_RecvFailed; | |
248 | return(SMBlibE_BAD); | |
249 | ||
250 | } | |
251 | ||
252 | /* Check out the response type ... */ | |
253 | ||
254 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
255 | ||
256 | #ifdef DEBUG | |
257 | fprintf(stderr, "SMB_SessSetupAndTCon failed with errorclass = %i, Error Code = %i\n", | |
258 | CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset), | |
259 | SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset)); | |
260 | #endif | |
261 | ||
262 | /* Note, here, that we have not properly handled the error processing */ | |
263 | /* and so we cannot tell how much of our request crapped out */ | |
264 | ||
265 | SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); | |
266 | RFCNB_Free_Pkt(pkt); | |
267 | SMBlib_errno = SMBlibE_Remote; | |
268 | return(SMBlibE_BAD); | |
269 | ||
270 | } | |
271 | ||
272 | #ifdef DEBUG | |
273 | fprintf(stderr, "SessSetupAndX response. Action = %i\n", | |
274 | SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset)); | |
275 | #endif | |
276 | ||
277 | /* Now pick up the UID for future reference ... */ | |
278 | ||
279 | Con_Handle -> uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset); | |
280 | ||
281 | /* And pick up the TID as well, which will be at offset 4? from wct */ | |
282 | ||
283 | AndXCom = (char *)SMB_Hdr(pkt) + SVAL(SMB_Hdr(pkt), SMB_ssetpr_axo_offset); | |
284 | ||
285 | Con_Handle -> tid = SVAL(AndXCom, 3); /* Naughty */ | |
286 | Con_Handle -> max_xmit = SVAL(AndXCom, 1); /* And Again */ | |
287 | ||
288 | RFCNB_Free_Pkt(pkt); | |
289 | ||
290 | return(0); | |
291 | ||
292 | } | |
293 |