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