2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 /* UNIX SMBlib NetBIOS implementation
12 SMBlib Routines. Experimental Section ...
14 Copyright (C) Richard Sharpe 1996
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.
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.
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.
34 #include "rfcnb/rfcnb.h"
35 #include "smblib/smblib-priv.h"
42 /* Logon and tree connect to the server */
44 int SMB_Logon_And_TCon(SMB_Handle_Type Con_Handle
, char *UserName
,
50 struct RFCNB_Pkt
*pkt
;
51 int param_len
, i
, pkt_len
, andx_len
, andx_param_len
;
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 */
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 */
61 if (SMB_Types
[Con_Handle
-> protocol
] < SMB_P_LanMan1
) {
63 SMBlib_errno
= SMBlibE_ProtLow
;
68 /* Now build the correct structure */
70 if (SMB_Types
[Con_Handle
-> protocol
] < SMB_P_NT1
) {
72 param_len
= strlen(UserName
) + 1 + strlen(PassWord
) +
73 strlen(Con_Handle
-> PDomain
) + 1 +
74 strlen(Con_Handle
-> OSName
) + 1;
76 pkt_len
= SMB_ssetpLM_len
+ param_len
;
78 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
82 SMBlib_errno
= SMBlibE_NoSpace
;
83 return(SMBlibE_BAD
); /* Should handle the error */
87 memset(SMB_Hdr(pkt
), 0, SMB_ssetpLM_len
);
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);
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
);
106 /* Now copy the param strings in with the right stuff */
108 p
= (char *)(SMB_Hdr(pkt
) + SMB_ssetpLM_buf_offset
);
110 /* Copy in password, then the rest. Password has no null at end */
114 p
= p
+ strlen(PassWord
);
117 p
= p
+ strlen(UserName
);
122 strcpy(p
, Con_Handle
-> PDomain
);
123 p
= p
+ strlen(Con_Handle
-> PDomain
);
127 strcpy(p
, Con_Handle
-> OSName
);
128 p
= p
+ strlen(Con_Handle
-> OSName
);
133 /* We don't admit to UNICODE support ... */
135 param_len
= strlen(UserName
) + 1 + strlen(PassWord
) +
136 strlen(Con_Handle
-> PDomain
) + 1 +
137 strlen(Con_Handle
-> OSName
) + 1;
139 andx_len
= SMB_tcon_len
- SMB_hdr_wct_offset
;
141 /* We send a null password as we sent one in the setup and X */
143 andx_param_len
= strlen(service
) + 2 + 2 + strlen(service_type
) + 2;
145 pkt_len
= SMB_ssetpNTLM_len
+ param_len
+ andx_len
+ andx_param_len
;
147 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
151 SMBlib_errno
= SMBlibE_NoSpace
;
152 return(-1); /* Should handle the error */
156 memset(SMB_Hdr(pkt
), 0, SMB_ssetpNTLM_len
);
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
);
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
);
177 /* Now copy the param strings in with the right stuff */
179 p
= (char *)(SMB_Hdr(pkt
) + SMB_ssetpNTLM_buf_offset
);
181 /* Copy in password, then the rest. Password has no null at end */
185 p
= p
+ strlen(PassWord
);
188 p
= p
+ strlen(UserName
);
193 strcpy(p
, Con_Handle
-> PDomain
);
194 p
= p
+ strlen(Con_Handle
-> PDomain
);
198 strcpy(p
, Con_Handle
-> OSName
);
199 p
= p
+ strlen(Con_Handle
-> OSName
);
202 /* Now set up the TCON Part ... from WCT, make up a pointer that will
205 AndXCom
= SMB_Hdr(pkt
) + SMB_ssetpNTLM_len
+ param_len
- SMB_hdr_wct_offset
;
207 *(AndXCom
+ SMB_hdr_wct_offset
) = 0; /* No Words */
209 SSVAL(AndXCom
, SMB_tcon_bcc_offset
, andx_param_len
);
211 p
= (char *)(AndXCom
+ SMB_tcon_buf_offset
);
214 strcpy(p
+ 1, service
);
215 p
= p
+ strlen(service
) + 2;
216 *p
= SMBasciiID
; /* No password ... */
220 strcpy(p
+ 1, service_type
);
224 /* Now send it and get a response */
226 if (RFCNB_Send(Con_Handle
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
229 fprintf(stderr
, "Error sending SessSetupAndTCon request\n");
233 SMBlib_errno
= SMBlibE_SendFailed
;
238 /* Now get the response ... */
240 if (RFCNB_Recv(Con_Handle
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
243 fprintf(stderr
, "Error receiving response to SessSetupAndTCon\n");
247 SMBlib_errno
= SMBlibE_RecvFailed
;
252 /* Check out the response type ... */
254 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
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
));
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 */
265 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
267 SMBlib_errno
= SMBlibE_Remote
;
273 fprintf(stderr
, "SessSetupAndX response. Action = %i\n",
274 SVAL(SMB_Hdr(pkt
), SMB_ssetpr_act_offset
));
277 /* Now pick up the UID for future reference ... */
279 Con_Handle
-> uid
= SVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
);
281 /* And pick up the TID as well, which will be at offset 4? from wct */
283 AndXCom
= (char *)SMB_Hdr(pkt
) + SVAL(SMB_Hdr(pkt
), SMB_ssetpr_axo_offset
);
285 Con_Handle
-> tid
= SVAL(AndXCom
, 3); /* Naughty */
286 Con_Handle
-> max_xmit
= SVAL(AndXCom
, 1); /* And Again */