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