]>
Commit | Line | Data |
---|---|---|
04e4e140 | 1 | /* |
bde978a6 | 2 | * Copyright (C) 1996-2015 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. If a tree handle was given to us, */ | |
43 | /* we use it and return it, otherwise we create one ... */ | |
44 | ||
45 | SMB_Tree_Handle SMB_Logon_And_TCon(SMB_Handle_Type Con_Handle, | |
46 | SMB_Tree_Handle Tree_Handle, | |
47 | char *UserName, | |
48 | char *PassWord, | |
49 | char *service, | |
50 | char *service_type) | |
51 | ||
52 | { | |
53 | struct RFCNB_Pkt *pkt; | |
54 | int param_len, i, pkt_len, andx_len, andx_param_len; | |
55 | char *p, *AndXCom; | |
56 | SMB_Tree_Handle tree; | |
57 | ||
58 | /* Lets create a tree if we need one ... */ | |
59 | ||
60 | if (Tree_Handle == NULL) { | |
61 | ||
62 | tree = (SMB_Tree_Handle)malloc(sizeof(struct SMB_Tree_Structure)); | |
63 | ||
64 | if (tree == NULL) { | |
65 | ||
66 | SMBlib_errno = SMBlibE_NoSpace; | |
67 | return(tree); | |
68 | ||
69 | } else { /* Initialize the tree */ | |
70 | ||
71 | tree -> con = Con_Handle; | |
72 | tree -> prev = tree -> next = NULL; | |
73 | ||
74 | } | |
75 | } else | |
76 | tree = Tree_Handle; | |
77 | ||
78 | /* First we need a packet etc ... but we need to know what protocol has */ | |
79 | /* been negotiated to figure out if we can do it and what SMB format to */ | |
80 | /* use ... */ | |
81 | ||
82 | /* Since we are going to do a LogonAndX with a TCon as the second command*/ | |
83 | /* We need the packet size correct. So TCon starts at wct field */ | |
84 | ||
85 | if (Con_Handle -> protocol < SMB_P_LanMan1) { | |
86 | ||
87 | SMBlib_errno = SMBlibE_ProtLow; | |
88 | if (Tree_Handle == NULL) | |
89 | free(tree); | |
90 | return(NULL); | |
91 | ||
92 | } | |
93 | ||
94 | /* Now build the correct structure */ | |
95 | ||
96 | andx_len = SMB_tconx_len - SMB_hdr_wct_offset; | |
97 | ||
98 | /* We send a null password as we sent one in the setup and X */ | |
99 | ||
100 | andx_param_len = strlen(service) + 1 + strlen(service_type) + 1; | |
101 | ||
102 | if (Con_Handle -> protocol < SMB_P_NT1) { | |
103 | ||
104 | #ifdef SMBLIB_DEBUG | |
105 | fprintf(stderr, "Doing an LM session setup etc ...\n"); | |
106 | #endif | |
107 | ||
108 | /* We don't do encrypted passwords ... */ | |
109 | ||
110 | param_len = strlen(UserName) + 1 + strlen(PassWord) + 1 + | |
111 | strlen(Con_Handle -> PDomain) + 1 + | |
112 | strlen(Con_Handle -> OSName) + 1; | |
113 | ||
114 | pkt_len = SMB_ssetpLM_len + param_len + andx_len + andx_param_len; | |
115 | ||
116 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
117 | ||
118 | if (pkt == NULL) { | |
119 | ||
120 | SMBlib_errno = SMBlibE_NoSpace; | |
121 | if (Tree_Handle == NULL) | |
122 | free(tree); | |
123 | return(NULL); /* Should handle the error */ | |
124 | ||
125 | } | |
126 | ||
0ab648c9 | 127 | memset(SMB_Hdr(pkt), 0, SMB_ssetpLM_len); |
7c16470c AJ |
128 | SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ |
129 | *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; | |
130 | SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); | |
131 | SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); | |
132 | SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); | |
133 | SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, 0); | |
134 | *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10; | |
135 | *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = SMBtconX; | |
136 | SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, SMB_ssetpLM_len + param_len); | |
137 | ||
138 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT); | |
139 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2); | |
140 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle -> pid); | |
141 | SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0); | |
142 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, strlen(PassWord) + 1); | |
143 | SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0); | |
144 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len); | |
145 | ||
146 | /* Now copy the param strings in with the right stuff */ | |
147 | ||
148 | p = (char *)(SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset); | |
149 | ||
150 | /* Copy in password, then the rest. Password has no null at end */ | |
151 | ||
152 | strcpy(p, PassWord); | |
153 | ||
154 | p = p + strlen(PassWord) + 1; | |
155 | ||
156 | strcpy(p, UserName); | |
157 | p = p + strlen(UserName); | |
158 | *p = 0; | |
159 | ||
160 | p = p + 1; | |
161 | ||
162 | strcpy(p, Con_Handle -> PDomain); | |
163 | p = p + strlen(Con_Handle -> PDomain); | |
164 | *p = 0; | |
165 | p = p + 1; | |
166 | ||
167 | strcpy(p, Con_Handle -> OSName); | |
168 | p = p + strlen(Con_Handle -> OSName); | |
169 | *p = 0; | |
170 | ||
171 | AndXCom = SMB_Hdr(pkt) + SMB_ssetpLM_len + param_len - SMB_hdr_wct_offset; | |
172 | ||
173 | } else { | |
174 | ||
175 | /* We don't admit to UNICODE support ... */ | |
176 | ||
177 | #ifdef SMBLIB_DEBUG | |
178 | fprintf(stderr, "Doing NT LM Sess Setup etc ... \n"); | |
179 | #endif | |
180 | ||
181 | param_len = strlen(UserName) + 1 + strlen(PassWord) + | |
182 | strlen(Con_Handle -> PDomain) + 1 + | |
183 | strlen(Con_Handle -> OSName) + 1 + | |
184 | strlen(Con_Handle -> LMType) + 1; | |
185 | ||
186 | pkt_len = SMB_ssetpNTLM_len + param_len + andx_len + andx_param_len; | |
187 | ||
188 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
189 | ||
190 | if (pkt == NULL) { | |
191 | ||
192 | SMBlib_errno = SMBlibE_NoSpace; | |
193 | if (Tree_Handle == NULL) | |
194 | free(tree); | |
195 | return(NULL); /* Should handle the error */ | |
196 | ||
197 | } | |
198 | ||
0ab648c9 | 199 | memset(SMB_Hdr(pkt), 0, SMB_ssetpNTLM_len); |
7c16470c AJ |
200 | SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ |
201 | *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; | |
202 | SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); | |
203 | SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); | |
204 | SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); | |
205 | SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, 0); | |
206 | *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13; | |
207 | *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = SMBtconX; | |
208 | SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, SMB_ssetpNTLM_len + param_len); | |
209 | ||
210 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT); | |
211 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 2); | |
212 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 0); | |
213 | SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0); | |
214 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, strlen(PassWord)); | |
215 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0); | |
216 | SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0); | |
217 | SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0); | |
218 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len); | |
219 | ||
220 | /* Now copy the param strings in with the right stuff */ | |
221 | ||
222 | p = (char *)(SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset); | |
223 | ||
224 | /* Copy in password, then the rest. Password has no null at end */ | |
225 | ||
226 | strcpy(p, PassWord); | |
227 | ||
228 | p = p + strlen(PassWord); | |
229 | ||
230 | strcpy(p, UserName); | |
231 | p = p + strlen(UserName); | |
232 | *p = 0; | |
233 | ||
234 | p = p + 1; | |
235 | ||
236 | strcpy(p, Con_Handle -> PDomain); | |
237 | p = p + strlen(Con_Handle -> PDomain); | |
238 | *p = 0; | |
239 | p = p + 1; | |
240 | ||
241 | strcpy(p, Con_Handle -> OSName); | |
242 | p = p + strlen(Con_Handle -> OSName); | |
243 | *p = 0; | |
244 | p = p + 1; | |
245 | ||
246 | strcpy(p, Con_Handle -> LMType); | |
247 | p = p + strlen(Con_Handle -> LMType); | |
248 | *p = 0; | |
249 | ||
250 | /* Now set up the TCON Part ... from WCT, make up a pointer that will | |
251 | help us ... */ | |
252 | ||
253 | AndXCom = SMB_Hdr(pkt) + SMB_ssetpNTLM_len + param_len - SMB_hdr_wct_offset; | |
254 | ||
255 | } | |
256 | *(AndXCom + SMB_hdr_wct_offset) = 4; | |
257 | *(AndXCom + SMB_tconx_axc_offset) = 0xFF; /* No command */ | |
258 | SSVAL(AndXCom, SMB_tconx_axo_offset, 0); | |
259 | SSVAL(AndXCom, SMB_tconx_flg_offset, 0); /* Don't disconnect TID */ | |
260 | SSVAL(AndXCom, SMB_tconx_pwl_offset, 0); /* No password, */ | |
261 | SSVAL(AndXCom, SMB_tconx_bcc_offset, andx_param_len); | |
262 | ||
263 | p = (char *)(AndXCom + SMB_tconx_buf_offset); | |
264 | ||
265 | /**p = 0; | |
266 | p = p + 1; */ | |
267 | strcpy(p, service); | |
268 | p = p + strlen(service) + 1; | |
269 | strcpy(p, service_type); | |
270 | ||
271 | /* Now send it and get a response */ | |
272 | ||
273 | if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) { | |
274 | ||
275 | #ifdef DEBUG | |
276 | fprintf(stderr, "Error sending SessSetupAndTCon request\n"); | |
277 | #endif | |
278 | ||
279 | RFCNB_Free_Pkt(pkt); | |
280 | free(tree); | |
281 | SMBlib_errno = SMBlibE_SendFailed; | |
282 | return(NULL); | |
283 | ||
284 | } | |
285 | ||
286 | /* Now get the response ... */ | |
287 | ||
288 | if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) { | |
289 | ||
290 | #ifdef DEBUG | |
291 | fprintf(stderr, "Error receiving response to SessSetupAndTCon\n"); | |
292 | #endif | |
293 | ||
294 | RFCNB_Free_Pkt(pkt); | |
295 | free(tree); | |
296 | SMBlib_errno = SMBlibE_RecvFailed; | |
297 | return(NULL); | |
298 | ||
299 | } | |
300 | ||
301 | /* Check out the response type ... */ | |
302 | ||
303 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
304 | ||
305 | #ifdef DEBUG | |
306 | fprintf(stderr, "SMB_SessSetupAndTCon failed with errorclass = %i, Error Code = %i\n", | |
307 | CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset), | |
308 | SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset)); | |
309 | #endif | |
310 | ||
311 | /* Note, here, that we have not properly handled the error processing */ | |
312 | /* and so we cannot tell how much of our request crapped out */ | |
313 | ||
314 | SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); | |
315 | free(tree); | |
316 | RFCNB_Free_Pkt(pkt); | |
317 | SMBlib_errno = SMBlibE_Remote; | |
318 | return(NULL); | |
319 | ||
320 | } | |
321 | ||
322 | #ifdef DEBUG | |
323 | fprintf(stderr, "SessSetupAndX response. Action = %i\n", | |
324 | SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset)); | |
325 | #endif | |
326 | ||
327 | /* Now pick up the UID for future reference ... */ | |
328 | ||
329 | Con_Handle -> uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset); | |
330 | ||
331 | /* And pick up the TID as well */ | |
332 | ||
333 | tree -> tid = SVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset); | |
334 | ||
335 | tree -> mbs = Con_Handle -> max_xmit; | |
336 | ||
337 | /* Link the tree into the list in con */ | |
338 | ||
339 | if (Con_Handle -> first_tree == NULL) { | |
340 | ||
341 | Con_Handle -> first_tree == tree; | |
342 | Con_Handle -> last_tree == tree; | |
343 | ||
344 | } else { | |
345 | ||
346 | Con_Handle -> last_tree -> next = tree; | |
347 | tree -> prev = Con_Handle -> last_tree; | |
348 | Con_Handle -> last_tree = tree; | |
349 | ||
350 | } | |
351 | ||
352 | RFCNB_Free_Pkt(pkt); | |
353 | ||
354 | return(tree); | |
355 | ||
356 | } | |
357 | ||
358 | /* Logon and TCon and Open to a file on the server, but we need to pass */ | |
359 | /* back a file pointer, so we better have one in the parameter list */ | |
360 | ||
361 | int SMB_Logon_TCon_Open(SMB_Handle_Type Con_Handle, char *UserName, | |
362 | char *PassWord, | |
363 | char *service, | |
364 | char *service_type, | |
365 | SMB_Tree_Handle *Tree_Handle, | |
366 | char *filename, | |
367 | WORD mode, | |
368 | WORD search, | |
369 | SMB_File **File_Handle) | |
370 | ||
371 | { | |
372 | struct RFCNB_Pkt *pkt; | |
373 | int param_len, i, pkt_len, tcon_len, tcon_param_len, open_len, | |
f53969cc | 374 | open_param_len, header_len; |
7c16470c AJ |
375 | struct SMB_File_Def *file_tmp; |
376 | SMB_Tree_Handle tree; | |
377 | char *p, *AndXCom; | |
378 | ||
379 | /* First, we need a tree STRUCTURE as we are going to tree connect */ | |
380 | ||
381 | tree = (SMB_Tree_Handle)malloc(sizeof(struct SMB_Tree_Structure)); | |
382 | ||
383 | if (tree == NULL) { | |
384 | ||
385 | SMBlib_errno = SMBlibE_NoSpace; | |
386 | return(SMBlibE_BAD); | |
387 | ||
388 | } else { | |
389 | ||
390 | tree -> con = Con_Handle; | |
391 | tree -> next = tree -> prev = NULL; | |
392 | ||
393 | } | |
394 | ||
395 | /* Next, we need a file handle as we are going to pass one back ... */ | |
396 | /* Hmm, there is a bug here ... We should check on File_Handle ... */ | |
397 | ||
398 | if ((file_tmp = (SMB_File *)malloc(sizeof(SMB_File))) == NULL) { | |
399 | ||
400 | #ifdef DEBUG | |
401 | fprintf(stderr, "Could not allocate file handle space ..."); | |
402 | #endif | |
403 | ||
404 | SMBlib_errno = SMBlibE_NoSpace; | |
405 | free(tree); | |
406 | return(SMBlibE_BAD); | |
407 | ||
408 | } | |
409 | ||
410 | /* Next we need a packet etc ... but we need to know what protocol has */ | |
411 | /* been negotiated to figure out if we can do it and what SMB format to */ | |
412 | /* use ... */ | |
413 | ||
414 | /* Since we are going to do a LogonAndX with a TCon as the second command*/ | |
415 | /* We need the packet size correct. So TCon starts at wct field */ | |
416 | ||
417 | if (Con_Handle -> protocol < SMB_P_LanMan1) { | |
418 | ||
419 | free(tree); | |
420 | free(file_tmp); | |
421 | SMBlib_errno = SMBlibE_ProtLow; | |
422 | return(SMBlibE_BAD); | |
423 | ||
424 | } | |
425 | ||
426 | /* Now build the correct structure */ | |
427 | ||
428 | /* We send a null password in the TconAndX ... */ | |
429 | ||
430 | tcon_len = SMB_tconx_len - SMB_hdr_wct_offset; | |
431 | tcon_param_len = strlen(service) + 1 + strlen(service_type) + 1; | |
432 | ||
433 | open_len = SMB_openx_len - SMB_hdr_wct_offset; | |
434 | open_param_len = 1 + strlen(filename) + 1; /* AsciiID + null */ | |
435 | ||
436 | if (Con_Handle -> protocol < SMB_P_NT1) { | |
437 | ||
438 | /* We don't do encrypted passwords yet */ | |
439 | ||
440 | param_len = strlen(UserName) + 1 + strlen(PassWord) + 1 + | |
441 | strlen(Con_Handle -> PDomain) + 1 + | |
442 | strlen(Con_Handle -> OSName) + 1; | |
443 | ||
444 | header_len = SMB_ssetpLM_len + param_len; | |
445 | ||
446 | pkt_len = header_len + tcon_len + tcon_param_len + | |
447 | open_len + open_param_len; | |
448 | ||
449 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
450 | ||
451 | if (pkt == NULL) { | |
452 | ||
453 | SMBlib_errno = SMBlibE_NoSpace; | |
454 | free(tree); | |
455 | free(file_tmp); | |
456 | return(SMBlibE_BAD); /* Should handle the error */ | |
457 | ||
458 | } | |
459 | ||
0ab648c9 | 460 | memset(SMB_Hdr(pkt), 0, SMB_ssetpLM_len); |
7c16470c AJ |
461 | SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ |
462 | *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; | |
463 | SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); | |
464 | SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); | |
465 | SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); | |
466 | SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, 0); | |
467 | *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10; | |
468 | *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = SMBtconX; | |
469 | SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, SMB_ssetpLM_len + param_len); | |
470 | ||
471 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT); | |
472 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2); | |
473 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle -> pid); | |
474 | SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0); | |
475 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, strlen(PassWord) + 1); | |
476 | SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0); | |
477 | SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len); | |
478 | ||
479 | /* Now copy the param strings in with the right stuff */ | |
480 | ||
481 | p = (char *)(SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset); | |
482 | ||
483 | /* Copy in password, then the rest. Password has no null at end */ | |
484 | ||
485 | strcpy(p, PassWord); | |
486 | ||
487 | p = p + strlen(PassWord) + 1; | |
488 | ||
489 | strcpy(p, UserName); | |
490 | p = p + strlen(UserName); | |
491 | *p = 0; | |
492 | ||
493 | p = p + 1; | |
494 | ||
495 | strcpy(p, Con_Handle -> PDomain); | |
496 | p = p + strlen(Con_Handle -> PDomain); | |
497 | *p = 0; | |
498 | p = p + 1; | |
499 | ||
500 | strcpy(p, Con_Handle -> OSName); | |
501 | p = p + strlen(Con_Handle -> OSName); | |
502 | *p = 0; | |
503 | ||
504 | AndXCom = SMB_Hdr(pkt) + SMB_ssetpLM_len + param_len - SMB_hdr_wct_offset; | |
505 | ||
506 | } else { | |
507 | ||
508 | /* We don't admit to UNICODE support ... */ | |
509 | ||
510 | param_len = strlen(UserName) + 1 + strlen(PassWord) + | |
511 | strlen(Con_Handle -> PDomain) + 1 + | |
512 | strlen(Con_Handle -> OSName) + 1 + | |
513 | strlen(Con_Handle -> LMType) + 1; | |
514 | ||
515 | header_len = SMB_ssetpNTLM_len + param_len; | |
516 | ||
517 | pkt_len = header_len + tcon_len + tcon_param_len + | |
518 | open_len + open_param_len; | |
519 | ||
520 | pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); | |
521 | ||
522 | if (pkt == NULL) { | |
523 | ||
524 | SMBlib_errno = SMBlibE_NoSpace; | |
525 | free(tree); | |
526 | free(file_tmp); /* Should only do if we created one ... */ | |
527 | return(-1); /* Should handle the error */ | |
528 | ||
529 | } | |
530 | ||
0ab648c9 | 531 | memset(SMB_Hdr(pkt), 0, SMB_ssetpNTLM_len); |
7c16470c AJ |
532 | SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ |
533 | *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; | |
534 | SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); | |
535 | SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); | |
536 | SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); | |
537 | SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, 0); | |
538 | *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13; | |
539 | *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = SMBtconX; | |
540 | SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, SMB_ssetpNTLM_len + param_len); | |
541 | ||
542 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT); | |
543 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 2); | |
544 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 0); | |
545 | SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0); | |
546 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, strlen(PassWord)); | |
547 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0); | |
548 | SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0); | |
549 | SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0); | |
550 | SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len); | |
551 | ||
552 | /* Now copy the param strings in with the right stuff */ | |
553 | ||
554 | p = (char *)(SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset); | |
555 | ||
556 | /* Copy in password, then the rest. Password has no null at end */ | |
557 | ||
558 | strcpy(p, PassWord); | |
559 | ||
560 | p = p + strlen(PassWord); | |
561 | ||
562 | strcpy(p, UserName); | |
563 | p = p + strlen(UserName); | |
564 | *p = 0; | |
565 | ||
566 | p = p + 1; | |
567 | ||
568 | strcpy(p, Con_Handle -> PDomain); | |
569 | p = p + strlen(Con_Handle -> PDomain); | |
570 | *p = 0; | |
571 | p = p + 1; | |
572 | ||
573 | strcpy(p, Con_Handle -> OSName); | |
574 | p = p + strlen(Con_Handle -> OSName); | |
575 | *p = 0; | |
576 | p = p + 1; | |
577 | ||
578 | strcpy(p, Con_Handle -> LMType); | |
579 | p = p + strlen(Con_Handle -> LMType); | |
580 | *p = 0; | |
581 | ||
582 | /* Now set up the TCON Part ... from WCT, make up a pointer that will | |
583 | help us ... */ | |
584 | ||
585 | AndXCom = SMB_Hdr(pkt) + SMB_ssetpNTLM_len + param_len - SMB_hdr_wct_offset; | |
586 | ||
587 | } | |
588 | ||
589 | *(AndXCom + SMB_hdr_wct_offset) = 4; | |
590 | *(AndXCom + SMB_tconx_axc_offset) = SMBopenX; | |
591 | SSVAL(AndXCom, SMB_tconx_axo_offset, (header_len + | |
592 | tcon_len + tcon_param_len)); | |
593 | SSVAL(AndXCom, SMB_tconx_flg_offset, 0); /* Don't disconnect TID */ | |
594 | SSVAL(AndXCom, SMB_tconx_pwl_offset, 0); /* No password */ | |
595 | SSVAL(AndXCom, SMB_tconx_bcc_offset, tcon_param_len); | |
596 | ||
597 | p = (char *)(AndXCom + SMB_tconx_buf_offset); | |
598 | ||
599 | /* *p = 0; | |
600 | p = p + 1; */ | |
601 | strcpy(p, service); | |
602 | p = p + strlen(service) + 1; | |
603 | strcpy(p, service_type); | |
604 | ||
605 | /* Now the open bit ... */ | |
606 | ||
607 | AndXCom = AndXCom + tcon_len + tcon_param_len; /* Should get us there */ | |
608 | ||
609 | *(AndXCom + SMB_hdr_wct_offset) = 15; | |
610 | *(AndXCom + SMB_openx_axc_offset) = 0xFF; | |
611 | *(AndXCom + SMB_openx_axr_offset) = 0; | |
612 | SSVAL(AndXCom, SMB_openx_axo_offset, 0); | |
613 | SSVAL(AndXCom, SMB_openx_flg_offset, 0); | |
614 | SSVAL(AndXCom, SMB_openx_mod_offset, mode); | |
615 | SSVAL(AndXCom, SMB_openx_atr_offset, search); | |
616 | SSVAL(AndXCom, SMB_openx_fat_offset, 0); | |
617 | SIVAL(AndXCom, SMB_openx_tim_offset, 0); | |
618 | SSVAL(AndXCom, SMB_openx_ofn_offset, 0x0011); /* Create or open */ | |
619 | SIVAL(AndXCom, SMB_openx_als_offset, 0); | |
620 | SSVAL(AndXCom, SMB_openx_bcc_offset, open_param_len); | |
621 | ||
622 | p = (char *)(AndXCom + SMB_openx_buf_offset); | |
623 | ||
624 | /* *p = SMBasciiID; */ | |
625 | strcpy(p, filename); | |
626 | ||
627 | /* Now send it and get a response */ | |
628 | ||
629 | if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) { | |
630 | ||
631 | #ifdef DEBUG | |
632 | fprintf(stderr, "Error sending SessSetupAndTCon request\n"); | |
633 | #endif | |
634 | ||
635 | RFCNB_Free_Pkt(pkt); | |
636 | free(tree); | |
637 | free(file_tmp); | |
638 | SMBlib_errno = SMBlibE_SendFailed; | |
639 | return(SMBlibE_BAD); | |
640 | ||
641 | } | |
642 | ||
643 | /* Now get the response ... */ | |
644 | ||
645 | if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) { | |
646 | ||
647 | #ifdef DEBUG | |
648 | fprintf(stderr, "Error receiving response to SessSetupAndTCon\n"); | |
649 | #endif | |
650 | ||
651 | RFCNB_Free_Pkt(pkt); | |
652 | free(tree); | |
653 | free(file_tmp); | |
654 | SMBlib_errno = SMBlibE_RecvFailed; | |
655 | return(SMBlibE_BAD); | |
656 | ||
657 | } | |
658 | ||
659 | /* Check out the response type ... */ | |
660 | ||
661 | if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ | |
662 | ||
663 | #ifdef DEBUG | |
664 | fprintf(stderr, "SMB_SessSetupAndTCon failed with errorclass = %i, Error Code = %i\n", | |
665 | CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset), | |
666 | SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset)); | |
667 | #endif | |
668 | ||
669 | /* Note, here, that we have not properly handled the error processing */ | |
670 | /* and so we cannot tell how much of our request crapped out */ | |
671 | ||
672 | SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); | |
673 | RFCNB_Free_Pkt(pkt); | |
674 | free(tree); | |
675 | free(file_tmp); | |
676 | SMBlib_errno = SMBlibE_Remote; | |
677 | return(SMBlibE_BAD); | |
678 | ||
679 | } | |
680 | ||
681 | #ifdef DEBUG | |
682 | fprintf(stderr, "SessSetupAndX response. Action = %i\n", | |
683 | SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset)); | |
684 | #endif | |
685 | ||
686 | /* Now pick up the UID for future reference ... */ | |
687 | ||
688 | Con_Handle -> uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset); | |
689 | ||
690 | /* And pick up the TID as well */ | |
691 | ||
692 | tree -> tid = SVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset); | |
693 | tree -> mbs = Con_Handle -> max_xmit; /* We need this */ | |
694 | ||
695 | #ifdef DEBUG | |
696 | fprintf(stderr, "mbs=%i\n", tree -> mbs); | |
697 | #endif | |
698 | ||
699 | /* Now we populate the file hanble and pass it back ... */ | |
700 | ||
701 | strncpy(file_tmp -> filename, filename, sizeof(file_tmp -> filename) - 1); | |
702 | file_tmp -> tree = tree; | |
703 | ||
704 | /* Pick up a pointer to the right part ... */ | |
705 | ||
706 | AndXCom = SMB_Hdr(pkt) + SVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset) - | |
707 | SMB_hdr_wct_offset; | |
708 | ||
709 | /* Now skip the response to the TConX */ | |
710 | ||
711 | AndXCom = SMB_Hdr(pkt) + SVAL(AndXCom, SMB_tconxr_axo_offset) - | |
712 | SMB_hdr_wct_offset; | |
713 | ||
714 | #ifdef DEBUG | |
715 | fprintf(stderr, "Word Params = %x, AXO = %x\n", | |
716 | CVAL(AndXCom, SMB_hdr_wct_offset), | |
717 | SVAL(AndXCom, SMB_openxr_axo_offset)); | |
718 | #endif | |
719 | ||
720 | /* Now pick up the things from the openX response that we need */ | |
721 | ||
722 | file_tmp -> fid = SVAL(AndXCom, SMB_openxr_fid_offset); | |
723 | file_tmp -> lastmod = IVAL(AndXCom, SMB_openxr_tim_offset); | |
724 | file_tmp -> size = IVAL(AndXCom, SMB_openxr_fsz_offset); | |
725 | file_tmp -> access = SVAL(AndXCom, SMB_openxr_acc_offset); | |
726 | file_tmp -> fileloc = 0; | |
727 | ||
728 | *File_Handle = file_tmp; | |
729 | ||
730 | /* Now link the tree into the right place ... */ | |
731 | ||
732 | if (Con_Handle -> first_tree == NULL) { | |
733 | ||
734 | Con_Handle -> first_tree == tree; | |
735 | Con_Handle -> last_tree == tree; | |
736 | ||
737 | } else { | |
738 | ||
739 | Con_Handle -> last_tree -> next = tree; | |
740 | tree -> prev = Con_Handle -> last_tree; | |
741 | Con_Handle -> last_tree = tree; | |
742 | ||
743 | } | |
744 | ||
745 | RFCNB_Free_Pkt(pkt); | |
746 | ||
747 | *Tree_Handle = tree; | |
748 | ||
749 | return(0); | |
750 | ||
751 | } | |
752 |