1 /* UNIX SMBlib NetBIOS implementation
6 Copyright (C) Richard Sharpe 1996
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.
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.
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.
34 typedef unsigned char uchar;
35 #include "smblib-priv.h"
39 /* Initialize the SMBlib package */
44 signal(SIGPIPE, SIG_IGN); /* Ignore these ... */
58 /* SMB_Connect_Server: Connect to a server, but don't negotiate protocol */
59 /* or anything else ... */
61 SMB_Handle_Type SMB_Connect_Server(SMB_Handle_Type Con_Handle,
62 char *server, char *NTdomain)
64 { SMB_Handle_Type con;
65 char called[80], calling[80], *address;
68 /* Get a connection structure if one does not exist */
72 if (Con_Handle == NULL) {
74 if ((con = (struct SMB_Connect_Def *)malloc(sizeof(struct SMB_Connect_Def))) == NULL) {
77 SMBlib_errno = SMBlibE_NoSpace;
83 /* Init some things ... */
85 strlcpy(con->service, "", sizeof(con->service));
86 strlcpy(con->username, "", sizeof(con->username));
87 strlcpy(con->password, "", sizeof(con->password));
88 strlcpy(con->sock_options, "", sizeof(con->sock_options));
89 strlcpy(con->address, "", sizeof(con->address));
90 strlcpy(con->desthost, server, sizeof(con->desthost));
91 strlcpy(con->PDomain, NTdomain, sizeof(con->PDomain));
92 strlcpy(con->OSName, SMBLIB_DEFAULT_OSNAME, sizeof(con->OSName));
93 strlcpy(con->LMType, SMBLIB_DEFAULT_LMTYPE, sizeof(con->LMType));
95 SMB_Get_My_Name(con -> myname, sizeof(con -> myname));
97 con -> port = 0; /* No port selected */
99 /* Get some things we need for the SMB Header */
101 con -> pid = getpid();
102 con -> mid = con -> pid; /* This will do for now ... */
103 con -> uid = 0; /* Until we have done a logon, no uid ... */
104 con -> gid = getgid();
106 /* Now connect to the remote end, but first upper case the name of the
107 service we are going to call, sine some servers want it in uppercase */
109 for (i=0; i < strlen(server); i++)
110 called[i] = toupper(server[i]);
112 called[strlen(server)] = 0; /* Make it a string */
114 for (i=0; i < strlen(con -> myname); i++)
115 calling[i] = toupper(con -> myname[i]);
117 calling[strlen(con -> myname)] = 0; /* Make it a string */
119 if (strcmp(con -> address, "") == 0)
120 address = con -> desthost;
122 address = con -> address;
124 con -> Trans_Connect = RFCNB_Call(called,
126 address, /* Protocol specific */
129 /* Did we get one? */
131 if (con -> Trans_Connect == NULL) {
133 if (Con_Handle == NULL) {
137 SMBlib_errno = -SMBlibE_CallFailed;
146 /* Logon to the server. That is, do a session setup if we can. We do not do */
149 int SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName,
152 { struct RFCNB_Pkt *pkt;
153 int param_len, pkt_len, pass_len;
156 /* First we need a packet etc ... but we need to know what protocol has */
157 /* been negotiated to figure out if we can do it and what SMB format to */
160 if (Con_Handle -> protocol < SMB_P_LanMan1) {
162 SMBlib_errno = SMBlibE_ProtLow;
167 strlcpy(pword, PassWord, sizeof(pword));
168 if (Con_Handle -> encrypt_passwords)
171 SMBencrypt((uchar *) PassWord, (uchar *)Con_Handle -> Encrypt_Key,(uchar *)pword);
174 pass_len=strlen(pword);
177 /* Now build the correct structure */
179 if (Con_Handle -> protocol < SMB_P_NT1) {
181 param_len = strlen(UserName) + 1 + pass_len + 1 +
182 strlen(Con_Handle -> PDomain) + 1 +
183 strlen(Con_Handle -> OSName) + 1;
185 pkt_len = SMB_ssetpLM_len + param_len;
187 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
191 SMBlib_errno = SMBlibE_NoSpace;
192 return(SMBlibE_BAD); /* Should handle the error */
196 memset(SMB_Hdr(pkt), 0, SMB_ssetpLM_len);
197 SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */
198 *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
199 SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
200 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
201 SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
202 SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
203 *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10;
204 *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra command */
205 SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
207 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT);
208 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2);
209 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle -> pid);
210 SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0);
211 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, pass_len + 1);
212 SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0);
213 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len);
215 /* Now copy the param strings in with the right stuff */
217 p = (char *)(SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset);
219 /* Copy in password, then the rest. Password has a null at end */
221 memcpy(p, pword, pass_len);
223 p = p + pass_len + 1;
226 p = p + strlen(UserName);
231 strcpy(p, Con_Handle -> PDomain);
232 p = p + strlen(Con_Handle -> PDomain);
236 strcpy(p, Con_Handle -> OSName);
237 p = p + strlen(Con_Handle -> OSName);
243 /* We don't admit to UNICODE support ... */
245 param_len = strlen(UserName) + 1 + pass_len +
246 strlen(Con_Handle -> PDomain) + 1 +
247 strlen(Con_Handle -> OSName) + 1 +
248 strlen(Con_Handle -> LMType) + 1;
250 pkt_len = SMB_ssetpNTLM_len + param_len;
252 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
256 SMBlib_errno = SMBlibE_NoSpace;
257 return(-1); /* Should handle the error */
261 memset(SMB_Hdr(pkt), 0, SMB_ssetpNTLM_len);
262 SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */
263 *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
264 SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
265 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
266 SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
267 SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
268 *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13;
269 *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra command */
270 SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
272 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT);
273 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 0);
274 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 0);
275 SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0);
276 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, pass_len);
277 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0);
278 SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0);
279 SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0);
280 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len);
282 /* Now copy the param strings in with the right stuff */
284 p = (char *)(SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset);
286 /* Copy in password, then the rest. Password has no null at end */
288 memcpy(p, pword, pass_len);
293 p = p + strlen(UserName);
298 strcpy(p, Con_Handle -> PDomain);
299 p = p + strlen(Con_Handle -> PDomain);
303 strcpy(p, Con_Handle -> OSName);
304 p = p + strlen(Con_Handle -> OSName);
308 strcpy(p, Con_Handle -> LMType);
309 p = p + strlen(Con_Handle -> LMType);
314 /* Now send it and get a response */
316 if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0){
319 SMBlib_errno = SMBlibE_SendFailed;
324 /* Now get the response ... */
326 if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
329 SMBlib_errno = SMBlibE_RecvFailed;
334 /* Check out the response type ... */
336 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
338 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
340 SMBlib_errno = SMBlibE_Remote;
344 /** @@@ mdz: check for guest login { **/
345 if (SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset) & 0x1)
347 /* do we allow guest login? NO! */
354 /* Now pick up the UID for future reference ... */
356 Con_Handle -> uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset);
364 /* Disconnect from the server, and disconnect all tree connects */
366 int SMB_Discon(SMB_Handle_Type Con_Handle, bool KeepHandle)
370 /* We just disconnect the connection for now ... */
372 RFCNB_Hangup(Con_Handle -> Trans_Connect);