"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* mod_ntlm file: $Id: smblib.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
2
3 /* UNIX SMBlib NetBIOS implementation
4 *
5 * Version 1.0 SMBlib Routines
6 *
7 * Copyright (C) Richard Sharpe 1996
8 *
9 */
10
11 /*
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. This program is distributed in the hope
16 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
17 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
18 * PURPOSE. See the GNU General Public License for more details. You
19 * should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #include <stdio.h>
23 #include <malloc.h>
24
25 static int SMBlib_errno;
26 static int SMBlib_SMB_Error;
27 #define SMBLIB_ERRNO
28 #define uchar unsigned char
29 #include "smblib-priv.h"
30
31 #include "rfcnb.h"
32
33 #include <signal.h>
34
35 static SMB_State_Types SMBlib_State;
36
37 /* Initialize the SMBlib package */
38 static int
39 SMB_Init()
40 {
41 SMBlib_State = SMB_State_Started;
42 signal(SIGPIPE, SIG_IGN); /* Ignore these ... */
43
44 /* If SMBLIB_Instrument is defines, turn on the instrumentation stuff */
45 #ifdef SMBLIB_INSTRUMENT
46 SMBlib_Instrument_Init();
47 #endif
48
49 return 0;
50 }
51
52 /* SMB_Connect_Server: Connect to a server, but don't negotiate protocol */
53 /* or anything else ... */
54 static SMB_Handle_Type
55 SMB_Connect_Server(SMB_Handle_Type Con_Handle,
56 char *server, char *NTdomain)
57 {
58 SMB_Handle_Type con;
59 char called[80], calling[80], *address;
60 int i;
61
62 /* Get a connection structure if one does not exist */
63 con = Con_Handle;
64 if (Con_Handle == NULL) {
65 if ((con = (struct SMB_Connect_Def *) malloc(
66 sizeof(struct SMB_Connect_Def))) == NULL) {
67 SMBlib_errno = SMBlibE_NoSpace;
68 return NULL;
69 }
70 }
71 /* Init some things ... */
72
73 strcpy(con->service, "");
74 strcpy(con->username, "");
75 strcpy(con->password, "");
76 strcpy(con->sock_options, "");
77 strcpy(con->address, "");
78 strcpy(con->desthost, server);
79 strcpy(con->PDomain, NTdomain);
80 strcpy(con->OSName, SMBLIB_DEFAULT_OSNAME);
81 strcpy(con->LMType, SMBLIB_DEFAULT_LMTYPE);
82 con->first_tree = con->last_tree = NULL;
83
84 SMB_Get_My_Name(con->myname, sizeof(con->myname));
85
86 con->port = 0; /* No port selected */
87
88 /* Get some things we need for the SMB Header */
89 con->pid = getpid();
90 con->mid = con->pid; /* This will do for now ... */
91 con->uid = 0; /* Until we have done a logon, no uid ... */
92 con->gid = getgid();
93
94 /* Now connect to the remote end, but first upper case the name of
95 * the service we are going to call, sine some servers want it in
96 * uppercase */
97 for (i = 0; i < strlen(server); i++)
98 called[i] = toupper(server[i]);
99
100 called[strlen(server)] = 0; /* Make it a string */
101
102 for (i = 0; i < strlen(con->myname); i++)
103 calling[i] = toupper(con->myname[i]);
104
105 calling[strlen(con->myname)] = 0; /* Make it a string */
106
107 if (strcmp(con->address, "") == 0)
108 address = con->desthost;
109 else
110 address = con->address;
111
112 con->Trans_Connect = RFCNB_Call(called,
113 calling,
114 address, /* Protocol specific */
115 con->port);
116
117 /* Did we get one? */
118 if (con->Trans_Connect == NULL) {
119 if (Con_Handle == NULL) {
120 Con_Handle = NULL;
121 free(con);
122 }
123 SMBlib_errno = -SMBlibE_CallFailed;
124 return NULL;
125 }
126 return (con);
127 }
128
129 /* Logon to the server. That is, do a session setup if we can. We do
130 * not do Unicode yet! */
131 static int
132 SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName,
133 char *PassWord, int precrypted)
134 {
135 struct RFCNB_Pkt *pkt;
136 int param_len, pkt_len, pass_len;
137 char *p, pword[128];
138
139 /* First we need a packet etc ... but we need to know what
140 * protocol has been negotiated to figure out if we can do it and
141 * what SMB format to use ... */
142 if (Con_Handle->protocol < SMB_P_LanMan1) {
143 #ifdef LOG
144 flog("SMB_Logon_Server: bad protocol");
145 #endif
146 SMBlib_errno = SMBlibE_ProtLow;
147 return (SMBlibE_BAD);
148 }
149 if (precrypted) {
150 pass_len = 24;
151 memcpy(pword, PassWord, 24);
152 } else {
153 strcpy(pword, PassWord);
154 if (Con_Handle->encrypt_passwords) {
155 pass_len = 24;
156 SMBencrypt((uchar *) PassWord,
157 (uchar *) Con_Handle->Encrypt_Key, (uchar *) pword);
158 } else
159 pass_len = strlen(pword);
160 }
161
162 /* Now build the correct structure */
163 if (Con_Handle->protocol < SMB_P_NT1) {
164 #ifdef LOG
165 flog("SMB_Logon_Server: type is LM (%d)", Con_Handle->protocol);
166 #endif
167 param_len = strlen(UserName) + 1 + pass_len + 1 +
168 strlen(Con_Handle->PDomain) + 1 +
169 strlen(Con_Handle->OSName) + 1;
170
171 pkt_len = SMB_ssetpLM_len + param_len;
172
173 pkt = (struct RFCNB_Pkt *) RFCNB_Alloc_Pkt(pkt_len);
174
175 if (pkt == NULL) {
176 #ifdef LOG
177 flog("SMB_Logon_Server: pkt == NULL");
178 #endif
179 SMBlib_errno = SMBlibE_NoSpace;
180 return (SMBlibE_BAD); /* Should handle the error */
181 }
182 bzero(SMB_Hdr(pkt), SMB_ssetpLM_len);
183 SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk
184 * in IDF */
185 *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
186 SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle->pid);
187 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
188 SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle->mid);
189 SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle->uid);
190 *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10;
191 *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra
192 * command */
193 SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
194
195 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT);
196 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2);
197 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle->pid);
198 SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0);
199 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, pass_len + 1);
200 SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0);
201 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len);
202
203 /* Now copy the param strings in with the right stuff */
204 p = (char *) (SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset);
205
206 /* Copy in password, then the rest. Password has a null at end */
207 memcpy(p, pword, pass_len);
208
209 p = p + pass_len + 1;
210
211 strcpy(p, UserName);
212 p = p + strlen(UserName);
213 *p = 0;
214
215 p = p + 1;
216
217 strcpy(p, Con_Handle->PDomain);
218 p = p + strlen(Con_Handle->PDomain);
219 *p = 0;
220 p = p + 1;
221
222 strcpy(p, Con_Handle->OSName);
223 p = p + strlen(Con_Handle->OSName);
224 *p = 0;
225 } else {
226 #ifdef LOG
227 flog("SMB_Logon_Server: type is NTLM (%d)", Con_Handle->protocol);
228 #endif
229 /* We don't admit to UNICODE support ... */
230 param_len = strlen(UserName) + 1 + pass_len +
231 strlen(Con_Handle->PDomain) + 1 +
232 strlen(Con_Handle->OSName) + 1 +
233 strlen(Con_Handle->LMType) + 1;
234
235 pkt_len = SMB_ssetpNTLM_len + param_len;
236
237 pkt = (struct RFCNB_Pkt *) RFCNB_Alloc_Pkt(pkt_len);
238
239 if (pkt == NULL) {
240 #ifdef LOG
241 flog("SMB_Logon_Server: pkt == NULL, second check");
242 #endif
243 SMBlib_errno = SMBlibE_NoSpace;
244 return (-1); /* Should handle the error */
245 }
246 bzero(SMB_Hdr(pkt), SMB_ssetpNTLM_len);
247 SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk
248 * in IDF */
249 *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
250 SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle->pid);
251 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
252 SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle->mid);
253 SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle->uid);
254 *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13;
255 *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra
256 * command */
257 SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
258
259 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT);
260 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 0);
261 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 0);
262 SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0);
263 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, pass_len);
264 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0);
265 SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0);
266 SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0);
267 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len);
268
269 /* Now copy the param strings in with the right stuff */
270 p = (char *) (SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset);
271
272 /* Copy in password, then the rest. Password has no null at end */
273 memcpy(p, pword, pass_len);
274
275 p = p + pass_len;
276
277 strcpy(p, UserName);
278 p = p + strlen(UserName);
279 *p = 0;
280
281 p = p + 1;
282
283 strcpy(p, Con_Handle->PDomain);
284 p = p + strlen(Con_Handle->PDomain);
285 *p = 0;
286 p = p + 1;
287
288 strcpy(p, Con_Handle->OSName);
289 p = p + strlen(Con_Handle->OSName);
290 *p = 0;
291 p = p + 1;
292
293 strcpy(p, Con_Handle->LMType);
294 p = p + strlen(Con_Handle->LMType);
295 *p = 0;
296 }
297
298 /* Now send it and get a response */
299 if (RFCNB_Send(Con_Handle->Trans_Connect, pkt, pkt_len) < 0) {
300 #ifdef LOG
301 flog("SMB_Logon_Server: Error sending SessSetupX request");
302 #endif
303 #ifdef SMB_DEBUG
304 fprintf(stderr, "Error sending SessSetupX request\n");
305 #endif
306 RFCNB_Free_Pkt(pkt);
307 SMBlib_errno = SMBlibE_SendFailed;
308 return (SMBlibE_BAD);
309 }
310
311 /* Now get the response ... */
312 if (RFCNB_Recv(Con_Handle->Trans_Connect, pkt, pkt_len) < 0) {
313 #ifdef LOG
314 flog("SMB_Logon_Server: Error receiving response to SessSetupAndX");
315 #endif
316 #ifdef SMB_DEBUG
317 fprintf(stderr, "Error receiving response to SessSetupAndX\n");
318 #endif
319 RFCNB_Free_Pkt(pkt);
320 SMBlib_errno = SMBlibE_RecvFailed;
321 return (SMBlibE_BAD);
322 }
323 /* Check out the response type ... */
324
325 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) {
326 /* Process error */
327 #ifdef LOG
328 flog("SMB_Logon_Server: SMB_SessSetupAndX failed; errorclass = %i, Error Code = %i\n",
329 CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
330 SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
331 #endif
332 #ifdef SMB_DEBUG
333 fprintf(stderr,
334 "SMB_SessSetupAndX failed; errorclass = %i, Error Code = %i\n",
335 CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
336 SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
337 #endif
338 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
339 RFCNB_Free_Pkt(pkt);
340 SMBlib_errno = SMBlibE_Remote;
341 return (SMBlibE_BAD);
342 }
343 /** @@@ mdz: check for guest login { **/
344 if (SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset) & 0x1) {
345 /* do we allow guest login? NO! */
346 #ifdef LOG
347 flog("SMB_Logon_Server: no guest login");
348 #endif
349 return (SMBlibE_BAD);
350 }
351 /** @@@ mdz: } **/
352
353 #ifdef SMB_DEBUG
354 fprintf(stderr, "SessSetupAndX response. Action = %i\n",
355 SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset));
356 #endif
357
358 /* Now pick up the UID for future reference ... */
359 Con_Handle->uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset);
360 RFCNB_Free_Pkt(pkt);
361
362 #ifdef LOG
363 flog("SMB_Logon_Server: login OK");
364 #endif
365 return 0;
366 }
367
368 /* Disconnect from the server, and disconnect all tree connects */
369 static int
370 SMB_Discon(SMB_Handle_Type Con_Handle, BOOL KeepHandle)
371 {
372 /* We just disconnect the connection for now ... */
373 RFCNB_Hangup(Con_Handle->Trans_Connect);
374
375 if (!KeepHandle)
376 free(Con_Handle);
377
378 return 0;
379 }