]> git.ipfire.org Git - thirdparty/squid.git/blame - lib/smblib/smblib-util.c
SourceFormat Enforcement
[thirdparty/squid.git] / lib / smblib / smblib-util.c
CommitLineData
f7f3304a 1#include "squid.h"
94439e4e 2
7c16470c 3/* UNIX SMBlib NetBIOS implementation
94439e4e 4
7c16470c
AJ
5 Version 1.0
6 SMBlib Utility Routines
a19a836d 7
7c16470c 8 Copyright (C) Richard Sharpe 1996
a19a836d 9
7c16470c
AJ
10*/
11
12/*
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26*/
27
7c16470c 28#include "rfcnb/rfcnb.h"
602d9612
A
29#include "smblib/smblib-priv.h"
30#include "smblib/smblib.h"
7c16470c
AJ
31
32#if HAVE_STRING_H
33#include <string.h>
34#endif
94439e4e 35
eb3ffa70
AJ
36int SMB_Types[] = {SMB_P_Core,
37 SMB_P_CorePlus,
38 SMB_P_DOSLanMan1,
39 SMB_P_DOSLanMan1,
40 SMB_P_LanMan1,
41 SMB_P_DOSLanMan2,
42 SMB_P_LanMan2,
43 SMB_P_LanMan2_1,
44 SMB_P_LanMan2_1,
45 SMB_P_NT1,
46 SMB_P_NT1,
47 SMB_P_NT1,
48 -1
49 };
26ac0430 50
20a423f3 51#if UNDEFINED
7c16470c
AJ
52char *SMB_DOSTimToStr(int DOS_time);
53char *SMB_AtrToStr(int attribs, BOOL verbose);
54int SMB_Get_Tree_MBS(SMB_Tree_Handle tree);
55int SMB_Get_Max_Buf_Siz(SMB_Handle_Type Con_Handle);
56int SMB_Get_Protocol_IDX(SMB_Handle_Type Con_Handle);
20a423f3 57#endif /* UNDEFINED */
7c16470c
AJ
58int SMB_Get_Protocol(SMB_Handle_Type Con_Handle);
59int SMB_Figure_Protocol(const char *dialects[], int prot_index);
60int SMB_TreeDisconnect(SMB_Tree_Handle Tree_Handle, BOOL discard);
94439e4e 61
7c16470c 62#if UNDEFINED
94439e4e 63/* Print out an SMB pkt in all its gory detail ... */
7c16470c
AJ
64
65void SMB_Print_Pkt(FILE fd, RFCNB_Pkt *pkt, BOOL command, int Offset, int Len)
66
94439e4e 67{
68
69 /* Well, just how do we do this ... print it I suppose */
70
71 /* Print out the SMB header ... */
72
73 /* Print the command */
74
75 /* Print the other bits in the header */
76
94439e4e 77 /* etc */
78
79}
7c16470c 80#endif
94439e4e 81
82/* Convert a DOS Date_Time to a local host type date time for printing */
83
20a423f3 84#if UNDEFINED
7c16470c
AJ
85char *SMB_DOSTimToStr(int DOS_time)
86
94439e4e 87{
88 static char SMB_Time_Temp[48];
89 int DOS_sec, DOS_min, DOS_hour, DOS_day, DOS_month, DOS_year;
90
91 SMB_Time_Temp[0] = 0;
92
7c16470c
AJ
93 DOS_sec = (DOS_time & 0x001F) * 2;
94 DOS_min = (DOS_time & 0x07E0) >> 5;
95 DOS_hour = ((DOS_time & 0xF800) >> 11);
94439e4e 96
7c16470c 97 DOS_day = (DOS_time & 0x001F0000) >> 16;
94439e4e 98 DOS_month = (DOS_time & 0x01E00000) >> 21;
7c16470c 99 DOS_year = ((DOS_time & 0xFE000000) >> 25) + 80;
94439e4e 100
dc47f531 101 snprintf(SMB_Time_Temp, 48, "%2d/%02d/%2d %2d:%02d:%02d", DOS_day, DOS_month,
3c96dd46 102 DOS_year, DOS_hour, DOS_min, DOS_sec);
94439e4e 103
7c16470c 104 return(SMB_Time_Temp);
94439e4e 105
106}
107
7c16470c
AJ
108/* Convert an attribute byte/word etc to a string ... We return a pointer
109 to a static string which we guarantee is long enough. If verbose is
110 true, we print out long form of strings ... */
111
112char *SMB_AtrToStr(int attribs, BOOL verbose)
113
94439e4e 114{
115 static char SMB_Attrib_Temp[128];
116
117 SMB_Attrib_Temp[0] = 0;
118
119 if (attribs & SMB_FA_ROF)
7c16470c 120 strcat(SMB_Attrib_Temp, (verbose?"Read Only ":"R"));
94439e4e 121
122 if (attribs & SMB_FA_HID)
7c16470c 123 strcat(SMB_Attrib_Temp, (verbose?"Hidden ":"H"));
94439e4e 124
125 if (attribs & SMB_FA_SYS)
7c16470c 126 strcat(SMB_Attrib_Temp, (verbose?"System ":"S"));
94439e4e 127
128 if (attribs & SMB_FA_VOL)
7c16470c 129 strcat(SMB_Attrib_Temp, (verbose?"Volume ":"V"));
94439e4e 130
131 if (attribs & SMB_FA_DIR)
7c16470c 132 strcat(SMB_Attrib_Temp, (verbose?"Directory ":"D"));
94439e4e 133
134 if (attribs & SMB_FA_ARC)
7c16470c 135 strcat(SMB_Attrib_Temp, (verbose?"Archive ":"A"));
94439e4e 136
7c16470c 137 return(SMB_Attrib_Temp);
94439e4e 138
139}
140
7c16470c
AJ
141/* Pick up the Max Buffer Size from the Tree Structure ... */
142
143int SMB_Get_Tree_MBS(SMB_Tree_Handle tree)
144
94439e4e 145{
146 if (tree != NULL) {
7c16470c 147 return(tree -> mbs);
94439e4e 148 } else {
7c16470c 149 return(SMBlibE_BAD);
94439e4e 150 }
151}
152
7c16470c
AJ
153/* Pick up the Max buffer size */
154
155int SMB_Get_Max_Buf_Siz(SMB_Handle_Type Con_Handle)
156
94439e4e 157{
158 if (Con_Handle != NULL) {
7c16470c 159 return(Con_Handle -> max_xmit);
94439e4e 160 } else {
7c16470c 161 return(SMBlibE_BAD);
94439e4e 162 }
163
164}
a19a836d 165/* Pickup the protocol index from the connection structure */
7c16470c
AJ
166
167int SMB_Get_Protocol_IDX(SMB_Handle_Type Con_Handle)
168
94439e4e 169{
170 if (Con_Handle != NULL) {
7c16470c 171 return(Con_Handle -> prot_IDX);
94439e4e 172 } else {
7c16470c 173 return(0xFFFF); /* Invalid protocol */
94439e4e 174 }
175
176}
20a423f3 177#endif /* UNDEFINED */
94439e4e 178
7c16470c
AJ
179/* Pick up the protocol from the connection structure */
180
181int SMB_Get_Protocol(SMB_Handle_Type Con_Handle)
182
94439e4e 183{
184 if (Con_Handle != NULL) {
7c16470c 185 return(Con_Handle -> protocol);
94439e4e 186 } else {
7c16470c 187 return(0xFFFF); /* Invalid protocol */
94439e4e 188 }
189
190}
191
7c16470c
AJ
192/* Figure out what protocol was accepted, given the list of dialect strings */
193/* We offered, and the index back from the server. We allow for a user */
194/* supplied list, and assume that it is a subset of our list */
195
196int SMB_Figure_Protocol(const char *dialects[], int prot_index)
197
94439e4e 198{
199 int i;
200
7c16470c 201 if (dialects == SMB_Prots) { /* The jobs is easy, just index into table */
94439e4e 202
7c16470c
AJ
203 return(SMB_Types[prot_index]);
204 } else { /* Search through SMB_Prots looking for a match */
94439e4e 205
26ac0430 206 for (i = 0; SMB_Prots[i] != NULL; i++) {
94439e4e 207
7c16470c 208 if (strcmp(dialects[prot_index], SMB_Prots[i]) == 0) { /* A match */
94439e4e 209
7c16470c 210 return(SMB_Types[i]);
94439e4e 211
26ac0430 212 }
7c16470c 213
26ac0430 214 }
94439e4e 215
26ac0430
AJ
216 /* If we got here, then we are in trouble, because the protocol was not */
217 /* One we understand ... */
94439e4e 218
7c16470c 219 return(SMB_P_Unknown);
94439e4e 220
221 }
222
223}
224
94439e4e 225/* Negotiate the protocol we will use from the list passed in Prots */
226/* we return the index of the accepted protocol in NegProt, -1 indicates */
227/* none acceptible, and our return value is 0 if ok, <0 if problems */
228
7c16470c
AJ
229int SMB_Negotiate(SMB_Handle_Type Con_Handle, const char *Prots[])
230
94439e4e 231{
7c16470c
AJ
232// struct SMB_Neg_Prot_Def *prot_pkt;
233// struct SMB_Neg_Prot_Resp_Def *resp_pkt;
94439e4e 234 struct RFCNB_Pkt *pkt;
235 int prots_len, i, pkt_len, prot, alloc_len;
236 char *p;
237
238 /* Figure out how long the prot list will be and allocate space for it */
239
240 prots_len = 0;
241
242 for (i = 0; Prots[i] != NULL; i++) {
7c16470c
AJ
243
244 prots_len = prots_len + strlen(Prots[i]) + 2; /* Account for null etc */
245
94439e4e 246 }
247
248 /* The -1 accounts for the one byte smb_buf we have because some systems */
249 /* don't like char msg_buf[] */
250
251 pkt_len = SMB_negp_len + prots_len;
252
253 /* Make sure that the pkt len is long enough for the max response ... */
254 /* Which is a problem, because the encryption key len eec may be long */
255
256 if (pkt_len < (SMB_hdr_wct_offset + (19 * 2) + 40)) {
7c16470c 257
26ac0430 258 alloc_len = SMB_hdr_wct_offset + (19 * 2) + 40;
7c16470c 259
94439e4e 260 } else {
7c16470c 261
26ac0430 262 alloc_len = pkt_len;
7c16470c 263
94439e4e 264 }
265
7c16470c 266 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(alloc_len);
94439e4e 267
268 if (pkt == NULL) {
7c16470c 269
26ac0430 270 SMBlib_errno = SMBlibE_NoSpace;
7c16470c
AJ
271 return(SMBlibE_BAD);
272
94439e4e 273 }
94439e4e 274
a19a836d 275 /* Now plug in the bits we need */
7c16470c 276
04830959 277 memset(SMB_Hdr(pkt), 0, SMB_negp_len);
7c16470c 278 SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */
94439e4e 279 *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBnegprot;
7c16470c 280 SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
94439e4e 281 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
7c16470c
AJ
282 SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
283 SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
94439e4e 284 *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 0;
7c16470c 285
94439e4e 286 SSVAL(SMB_Hdr(pkt), SMB_negp_bcc_offset, prots_len);
287
288 /* Now copy the prot strings in with the right stuff */
289
7c16470c 290 p = (char *)(SMB_Hdr(pkt) + SMB_negp_buf_offset);
94439e4e 291
292 for (i = 0; Prots[i] != NULL; i++) {
7c16470c 293
26ac0430
AJ
294 *p = SMBdialectID;
295 strcpy(p + 1, Prots[i]);
7c16470c
AJ
296 p = p + strlen(Prots[i]) + 2; /* Adjust len of p for null plus dialectID */
297
94439e4e 298 }
299
300 /* Now send the packet and sit back ... */
7c16470c
AJ
301
302 if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
303
94439e4e 304#ifdef DEBUG
26ac0430 305 fprintf(stderr, "Error sending negotiate protocol\n");
94439e4e 306#endif
7c16470c 307
26ac0430 308 RFCNB_Free_Pkt(pkt);
7c16470c
AJ
309 SMBlib_errno = -SMBlibE_SendFailed; /* Failed, check lower layer errno */
310 return(SMBlibE_BAD);
311
94439e4e 312 }
94439e4e 313
a19a836d 314 /* Now get the response ... */
7c16470c
AJ
315
316 if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, alloc_len) < 0) {
317
94439e4e 318#ifdef DEBUG
26ac0430 319 fprintf(stderr, "Error receiving response to negotiate\n");
94439e4e 320#endif
7c16470c 321
26ac0430 322 RFCNB_Free_Pkt(pkt);
7c16470c
AJ
323 SMBlib_errno = -SMBlibE_RecvFailed; /* Failed, check lower layer errno */
324 return(SMBlibE_BAD);
325
94439e4e 326 }
94439e4e 327
7c16470c
AJ
328 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
329
94439e4e 330#ifdef DEBUG
26ac0430
AJ
331 fprintf(stderr, "SMB_Negotiate failed with errorclass = %i, Error Code = %i\n",
332 CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
333 SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
94439e4e 334#endif
7c16470c 335
26ac0430
AJ
336 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
337 RFCNB_Free_Pkt(pkt);
338 SMBlib_errno = SMBlibE_Remote;
7c16470c
AJ
339 return(SMBlibE_BAD);
340
94439e4e 341 }
94439e4e 342
a19a836d 343 if (SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset) == 0xFFFF) {
7c16470c 344
94439e4e 345#ifdef DEBUG
26ac0430 346 fprintf(stderr, "None of our protocols was accepted ... ");
94439e4e 347#endif
7c16470c 348
26ac0430
AJ
349 RFCNB_Free_Pkt(pkt);
350 SMBlib_errno = SMBlibE_NegNoProt;
7c16470c
AJ
351 return(SMBlibE_BAD);
352
94439e4e 353 }
a19a836d 354
94439e4e 355 /* Now, unpack the info from the response, if any and evaluate the proto */
356 /* selected. We must make sure it is one we like ... */
94439e4e 357
7c16470c
AJ
358 Con_Handle -> prot_IDX = prot = SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset);
359 Con_Handle -> protocol = SMB_Figure_Protocol(Prots, prot);
360
361 if (Con_Handle -> protocol == SMB_P_Unknown) { /* No good ... */
362
26ac0430
AJ
363 RFCNB_Free_Pkt(pkt);
364 SMBlib_errno = SMBlibE_ProtUnknown;
7c16470c
AJ
365 return(SMBlibE_BAD);
366
94439e4e 367 }
7c16470c 368
94439e4e 369 switch (CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset)) {
370
7c16470c
AJ
371 case 0x01: /* No more info ... */
372
26ac0430 373 break;
94439e4e 374
7c16470c 375 case 13: /* Up to and including LanMan 2.1 */
94439e4e 376
7c16470c
AJ
377 Con_Handle -> Security = SVAL(SMB_Hdr(pkt), SMB_negrLM_sec_offset);
378 Con_Handle -> encrypt_passwords = ((Con_Handle -> Security & SMB_sec_encrypt_mask) != 0x00);
379 Con_Handle -> Security = Con_Handle -> Security & SMB_sec_user_mask;
94439e4e 380
7c16470c
AJ
381 Con_Handle -> max_xmit = SVAL(SMB_Hdr(pkt), SMB_negrLM_mbs_offset);
382 Con_Handle -> MaxMPX = SVAL(SMB_Hdr(pkt), SMB_negrLM_mmc_offset);
383 Con_Handle -> MaxVC = SVAL(SMB_Hdr(pkt), SMB_negrLM_mnv_offset);
384 Con_Handle -> Raw_Support = SVAL(SMB_Hdr(pkt), SMB_negrLM_rm_offset);
385 Con_Handle -> SessionKey = IVAL(SMB_Hdr(pkt), SMB_negrLM_sk_offset);
386 Con_Handle -> SvrTZ = SVAL(SMB_Hdr(pkt), SMB_negrLM_stz_offset);
387 Con_Handle -> Encrypt_Key_Len = SVAL(SMB_Hdr(pkt), SMB_negrLM_ekl_offset);
94439e4e 388
26ac0430 389 p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset);
26ac0430 390 memcpy(Con_Handle->Encrypt_Key, p, 8);
94439e4e 391
7c16470c
AJ
392 p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset + Con_Handle -> Encrypt_Key_Len);
393
394 strncpy(p, Con_Handle -> Svr_PDom, sizeof(Con_Handle -> Svr_PDom) - 1);
94439e4e 395
26ac0430 396 break;
94439e4e 397
7c16470c 398 case 17: /* NT LM 0.12 and LN LM 1.0 */
94439e4e 399
7c16470c
AJ
400 Con_Handle -> Security = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_sec_offset);
401 Con_Handle -> encrypt_passwords = ((Con_Handle -> Security & SMB_sec_encrypt_mask) != 0x00);
402 Con_Handle -> Security = Con_Handle -> Security & SMB_sec_user_mask;
94439e4e 403
7c16470c
AJ
404 Con_Handle -> max_xmit = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_mbs_offset);
405 Con_Handle -> MaxMPX = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_mmc_offset);
406 Con_Handle -> MaxVC = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_mnv_offset);
407 Con_Handle -> MaxRaw = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_mrs_offset);
408 Con_Handle -> SessionKey = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_sk_offset);
409 Con_Handle -> SvrTZ = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_stz_offset);
410 Con_Handle -> Encrypt_Key_Len = CVAL(SMB_Hdr(pkt), SMB_negrNTLM_ekl_offset);
94439e4e 411
26ac0430
AJ
412 p = (SMB_Hdr(pkt) + SMB_negrNTLM_buf_offset);
413 memcpy(Con_Handle->Encrypt_Key, p, 8);
94439e4e 414
7c16470c
AJ
415 p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset + Con_Handle -> Encrypt_Key_Len);
416
417 strncpy(p, Con_Handle -> Svr_PDom, sizeof(Con_Handle -> Svr_PDom) - 1);
94439e4e 418
26ac0430 419 break;
94439e4e 420
421 default:
422
423#ifdef DEBUG
26ac0430
AJ
424 fprintf(stderr, "Unknown NegProt response format ... Ignored\n");
425 fprintf(stderr, " wct = %i\n", CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset));
94439e4e 426#endif
427
26ac0430 428 break;
94439e4e 429 }
430
431#ifdef DEBUG
432 fprintf(stderr, "Protocol selected is: %i:%s\n", prot, Prots[prot]);
433#endif
434
435 RFCNB_Free_Pkt(pkt);
7c16470c 436 return(0);
94439e4e 437
438}
439
440/* Get our hostname */
441
7c16470c 442void SMB_Get_My_Name(char *name, int len)
94439e4e 443
7c16470c
AJ
444{
445 if (gethostname(name, len) < 0) { /* Error getting name */
94439e4e 446
26ac0430 447 strncpy(name, "unknown", len);
94439e4e 448
26ac0430 449 /* Should check the error */
94439e4e 450
451#ifdef DEBUG
26ac0430
AJ
452 fprintf(stderr, "gethostname in SMB_Get_My_Name returned error:");
453 perror("");
94439e4e 454#endif
455
7c16470c
AJ
456 } else {
457 char *address;
458 /* only keep the portion up to the first "." */
459 if (NULL != (address = strchr(name, '.'))) {
3c96dd46 460 *address = '\0'; /* truncate at first '.' */
7c16470c 461 }
94439e4e 462 }
94439e4e 463}
464
465/* Send a TCON to the remote server ... */
466
7c16470c
AJ
467SMB_Tree_Handle SMB_TreeConnect(SMB_Handle_Type Con_Handle,
468 SMB_Tree_Handle Tree_Handle,
469 const char *path,
470 const char *password,
471 const char *device)
472
94439e4e 473{
474 struct RFCNB_Pkt *pkt;
475 int param_len, pkt_len;
476 char *p;
477 SMB_Tree_Handle tree;
478
479 /* Figure out how much space is needed for path, password, dev ... */
480
7c16470c 481 if ((path == NULL) | (password == NULL) | (device == NULL)) {
94439e4e 482
483#ifdef DEBUG
26ac0430 484 fprintf(stderr, "Bad parameter passed to SMB_TreeConnect\n");
94439e4e 485#endif
486
26ac0430 487 SMBlib_errno = SMBlibE_BadParam;
7c16470c 488 return(NULL);
94439e4e 489
490 }
7c16470c 491
94439e4e 492 /* The + 2 is because of the \0 and the marker ... */
493
494 param_len = strlen(path) + 2 + strlen(password) + 2 + strlen(device) + 2;
495
496 /* The -1 accounts for the one byte smb_buf we have because some systems */
497 /* don't like char msg_buf[] */
498
499 pkt_len = SMB_tcon_len + param_len;
500
7c16470c 501 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
94439e4e 502
503 if (pkt == NULL) {
504
26ac0430 505 SMBlib_errno = SMBlibE_NoSpace;
7c16470c 506 return(NULL); /* Should handle the error */
94439e4e 507
508 }
7c16470c 509
94439e4e 510 /* Now allocate a tree for this to go into ... */
511
512 if (Tree_Handle == NULL) {
513
7c16470c 514 tree = (SMB_Tree_Handle)malloc(sizeof(struct SMB_Tree_Structure));
94439e4e 515
26ac0430 516 if (tree == NULL) {
94439e4e 517
26ac0430
AJ
518 RFCNB_Free_Pkt(pkt);
519 SMBlib_errno = SMBlibE_NoSpace;
7c16470c 520 return(NULL);
94439e4e 521
26ac0430 522 }
94439e4e 523 } else {
524
26ac0430 525 tree = Tree_Handle;
94439e4e 526
527 }
528
7c16470c
AJ
529 tree -> next = tree -> prev = NULL;
530 tree -> con = Con_Handle;
531 strncpy(tree -> path, path, sizeof(tree -> path));
532 strncpy(tree -> device_type, device, sizeof(tree -> device_type));
94439e4e 533
534 /* Now plug in the values ... */
535
04830959 536 memset(SMB_Hdr(pkt), 0, SMB_tcon_len);
7c16470c 537 SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */
94439e4e 538 *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBtcon;
7c16470c 539 SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
94439e4e 540 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
7c16470c
AJ
541 SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
542 SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
94439e4e 543 *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 0;
544
545 SSVAL(SMB_Hdr(pkt), SMB_tcon_bcc_offset, param_len);
546
547 /* Now copy the param strings in with the right stuff */
548
7c16470c 549 p = (char *)(SMB_Hdr(pkt) + SMB_tcon_buf_offset);
94439e4e 550 *p = SMBasciiID;
551 strcpy(p + 1, path);
552 p = p + strlen(path) + 2;
553 *p = SMBasciiID;
554 strcpy(p + 1, password);
555 p = p + strlen(password) + 2;
556 *p = SMBasciiID;
557 strcpy(p + 1, device);
558
559 /* Now send the packet and sit back ... */
560
7c16470c 561 if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
94439e4e 562
563#ifdef DEBUG
26ac0430 564 fprintf(stderr, "Error sending TCon request\n");
94439e4e 565#endif
566
26ac0430
AJ
567 if (Tree_Handle == NULL)
568 free(tree);
569 RFCNB_Free_Pkt(pkt);
570 SMBlib_errno = -SMBlibE_SendFailed;
7c16470c 571 return(NULL);
94439e4e 572
573 }
7c16470c 574
94439e4e 575 /* Now get the response ... */
576
7c16470c 577 if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
94439e4e 578
579#ifdef DEBUG
26ac0430 580 fprintf(stderr, "Error receiving response to TCon\n");
94439e4e 581#endif
582
26ac0430
AJ
583 if (Tree_Handle == NULL)
584 free(tree);
585 RFCNB_Free_Pkt(pkt);
586 SMBlib_errno = -SMBlibE_RecvFailed;
7c16470c 587 return(NULL);
94439e4e 588
589 }
7c16470c 590
94439e4e 591 /* Check out the response type ... */
592
7c16470c 593 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
94439e4e 594
595#ifdef DEBUG
26ac0430
AJ
596 fprintf(stderr, "SMB_TCon failed with errorclass = %i, Error Code = %i\n",
597 CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
598 SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
94439e4e 599#endif
600
26ac0430
AJ
601 if (Tree_Handle == NULL)
602 free(tree);
603 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
604 RFCNB_Free_Pkt(pkt);
605 SMBlib_errno = SMBlibE_Remote;
7c16470c 606 return(NULL);
94439e4e 607
608 }
7c16470c
AJ
609
610 tree -> tid = SVAL(SMB_Hdr(pkt), SMB_tconr_tid_offset);
611 tree -> mbs = SVAL(SMB_Hdr(pkt), SMB_tconr_mbs_offset);
94439e4e 612
613#ifdef DEBUG
614 fprintf(stderr, "TConn succeeded, with TID=%i, Max Xmit=%i\n",
7c16470c 615 tree -> tid, tree -> mbs);
94439e4e 616#endif
617
618 /* Now link the Tree to the Server Structure ... */
619
7c16470c 620 if (Con_Handle -> first_tree == NULL) {
94439e4e 621
7c16470c
AJ
622 Con_Handle -> first_tree = tree;
623 Con_Handle -> last_tree = tree;
94439e4e 624
625 } else {
626
7c16470c
AJ
627 Con_Handle -> last_tree -> next = tree;
628 tree -> prev = Con_Handle -> last_tree;
629 Con_Handle -> last_tree = tree;
94439e4e 630
631 }
632
633 RFCNB_Free_Pkt(pkt);
7c16470c 634 return(tree);
94439e4e 635
636}
637
7c16470c
AJ
638int SMB_TreeDisconnect(SMB_Tree_Handle Tree_Handle, BOOL discard)
639
94439e4e 640{
641 struct RFCNB_Pkt *pkt;
642 int pkt_len;
643
644 pkt_len = SMB_tdis_len;
645
7c16470c 646 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
94439e4e 647
648 if (pkt == NULL) {
649
26ac0430 650 SMBlib_errno = SMBlibE_NoSpace;
7c16470c 651 return(SMBlibE_BAD); /* Should handle the error */
94439e4e 652
653 }
7c16470c 654
94439e4e 655 /* Now plug in the values ... */
656
04830959 657 memset(SMB_Hdr(pkt), 0, SMB_tdis_len);
7c16470c 658 SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */
94439e4e 659 *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBtdis;
7c16470c
AJ
660 SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Tree_Handle -> con -> pid);
661 SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Tree_Handle -> con -> mid);
662 SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Tree_Handle -> con -> uid);
94439e4e 663 *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 0;
664
7c16470c 665 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, Tree_Handle -> tid);
94439e4e 666 SSVAL(SMB_Hdr(pkt), SMB_tcon_bcc_offset, 0);
667
668 /* Now send the packet and sit back ... */
669
7c16470c 670 if (RFCNB_Send(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0) {
94439e4e 671
672#ifdef DEBUG
26ac0430 673 fprintf(stderr, "Error sending TDis request\n");
94439e4e 674#endif
675
26ac0430
AJ
676 RFCNB_Free_Pkt(pkt);
677 SMBlib_errno = -SMBlibE_SendFailed;
7c16470c 678 return(SMBlibE_BAD);
94439e4e 679
680 }
7c16470c 681
94439e4e 682 /* Now get the response ... */
683
7c16470c 684 if (RFCNB_Recv(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0) {
94439e4e 685
686#ifdef DEBUG
26ac0430 687 fprintf(stderr, "Error receiving response to TCon\n");
94439e4e 688#endif
689
26ac0430
AJ
690 RFCNB_Free_Pkt(pkt);
691 SMBlib_errno = -SMBlibE_RecvFailed;
7c16470c 692 return(SMBlibE_BAD);
94439e4e 693
694 }
7c16470c 695
94439e4e 696 /* Check out the response type ... */
697
7c16470c 698 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
94439e4e 699
700#ifdef DEBUG
26ac0430
AJ
701 fprintf(stderr, "SMB_TDis failed with errorclass = %i, Error Code = %i\n",
702 CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
703 SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
94439e4e 704#endif
705
26ac0430
AJ
706 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
707 RFCNB_Free_Pkt(pkt);
708 SMBlib_errno = SMBlibE_Remote;
7c16470c 709 return(SMBlibE_BAD);
94439e4e 710
711 }
7c16470c
AJ
712
713 Tree_Handle -> tid = 0xFFFF; /* Invalid TID */
714 Tree_Handle -> mbs = 0; /* Invalid */
94439e4e 715
716#ifdef DEBUG
717
718 fprintf(stderr, "Tree disconnect successful ...\n");
719
720#endif
721
722 /* What about the tree handle ? */
723
7c16470c 724 if (discard == TRUE) { /* Unlink it and free it ... */
94439e4e 725
7c16470c
AJ
726 if (Tree_Handle -> next == NULL)
727 Tree_Handle -> con -> first_tree = Tree_Handle -> prev;
26ac0430 728 else
7c16470c 729 Tree_Handle -> next -> prev = Tree_Handle -> prev;
94439e4e 730
7c16470c
AJ
731 if (Tree_Handle -> prev == NULL)
732 Tree_Handle -> con -> last_tree = Tree_Handle -> next;
26ac0430 733 else
7c16470c 734 Tree_Handle -> prev -> next = Tree_Handle -> next;
94439e4e 735
736 }
7c16470c 737
94439e4e 738 RFCNB_Free_Pkt(pkt);
7c16470c 739 return(0);
94439e4e 740
741}
742
743/* Pick up the last LMBlib error ... */
744
7c16470c
AJ
745int SMB_Get_Last_Error()
746
94439e4e 747{
748
7c16470c 749 return(SMBlib_errno);
94439e4e 750
751}
752
7c16470c
AJ
753/* Pick up the last error returned in an SMB packet */
754/* We will need macros to extract error class and error code */
755
756int SMB_Get_Last_SMB_Err()
757
94439e4e 758{
759
7c16470c 760 return(SMBlib_SMB_Error);
94439e4e 761
762}
763
764/* Pick up the error message associated with an error from SMBlib */
765
766/* Keep this table in sync with the message codes in smblib-common.h */
767
7c16470c 768static const char *SMBlib_Error_Messages[] = {
94439e4e 769
14e9491b 770 "Request completed successfully.",
94439e4e 771 "Server returned a non-zero SMB Error Class and Code.",
772 "A lower layer protocol error occurred.",
773 "Function not yet implemented.",
774 "The protocol negotiated does not support the request.",
775 "No space available for operation.",
776 "One or more bad parameters passed.",
777 "None of the protocols we offered were accepted.",
778 "The attempt to send an SMB request failed. See protocol error info.",
779 "The attempt to get an SMB response failed. See protocol error info.",
780 "The logon request failed, but you were logged in as guest.",
781 "The attempt to call the remote server failed. See protocol error info.",
782 "The protocol dialect specified in a NegProt and accepted by the server is unknown.",
26ac0430 783 /* This next one simplifies error handling */
94439e4e 784 "No such error code.",
26ac0430
AJ
785 NULL
786};
94439e4e 787
7c16470c
AJ
788void SMB_Get_Error_Msg(int msg, char *msgbuf, int len)
789
94439e4e 790{
791
792 if (msg >= 0) {
793
26ac0430 794 strncpy(msgbuf,
7c16470c 795 SMBlib_Error_Messages[msg>SMBlibE_NoSuchMsg?SMBlibE_NoSuchMsg:msg],
26ac0430 796 len - 1);
7c16470c
AJ
797 msgbuf[len - 1] = 0; /* Make sure it is a string */
798 } else { /* Add the lower layer message ... */
94439e4e 799
26ac0430 800 char prot_msg[1024];
94439e4e 801
7c16470c 802 msg = -msg; /* Make it positive */
94439e4e 803
26ac0430 804 strncpy(msgbuf,
7c16470c 805 SMBlib_Error_Messages[msg>SMBlibE_NoSuchMsg?SMBlibE_NoSuchMsg:msg],
26ac0430 806 len - 1);
94439e4e 807
7c16470c 808 msgbuf[len - 1] = 0; /* make sure it is a string */
94439e4e 809
7c16470c 810 if (strlen(msgbuf) < len) { /* If there is space, put rest in */
94439e4e 811
26ac0430 812 strncat(msgbuf, "\n\t", len - strlen(msgbuf));
94439e4e 813
26ac0430 814 RFCNB_Get_Error(prot_msg, sizeof(prot_msg) - 1);
94439e4e 815
26ac0430 816 strncat(msgbuf, prot_msg, len - strlen(msgbuf));
94439e4e 817
26ac0430 818 }
94439e4e 819 }
7c16470c 820
94439e4e 821}