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