]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/smblib/smblib.c
Portability fix: removed unused code from smblib
[thirdparty/squid.git] / lib / smblib / smblib.c
1 #include "config.h"
2
3 /* UNIX SMBlib NetBIOS implementation
4
5 Version 1.0
6 SMBlib Routines
7
8 Copyright (C) Richard Sharpe 1996
9
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 int SMBlib_errno;
29 int SMBlib_SMB_Error;
30 #define SMBLIB_ERRNO
31
32 #include "smblib/smblib.h"
33 #include "smblib/smblib-priv.h"
34 #include "rfcnb/rfcnb.h"
35
36 #include <signal.h>
37 #if HAVE_STRING_H
38 #include <string.h>
39 #endif
40
41 SMB_State_Types SMBlib_State;
42
43 const char *SMB_Prots[] = {"PC NETWORK PROGRAM 1.0",
44 "MICROSOFT NETWORKS 1.03",
45 "MICROSOFT NETWORKS 3.0",
46 "DOS LANMAN1.0",
47 "LANMAN1.0",
48 "DOS LM1.2X002",
49 "LM1.2X002",
50 "DOS LANMAN2.1",
51 "LANMAN2.1",
52 "Samba",
53 "NT LM 0.12",
54 "NT LANMAN 1.0",
55 NULL
56 };
57
58
59 /* Initialize the SMBlib package */
60
61 int SMB_Init()
62
63 {
64
65 SMBlib_State = SMB_State_Started;
66
67 signal(SIGPIPE, SIG_IGN); /* Ignore these ... */
68
69 /* If SMBLIB_Instrument is defines, turn on the instrumentation stuff */
70 #ifdef SMBLIB_INSTRUMENT
71
72 SMBlib_Instrument_Init();
73
74 #endif
75
76 return 0;
77
78 }
79
80 /* SMB_Create: Create a connection structure and return for later use */
81 /* We have other helper routines to set variables */
82
83 SMB_Handle_Type SMB_Create_Con_Handle()
84
85 {
86
87 SMBlib_errno = SMBlibE_NotImpl;
88 return(NULL);
89
90 }
91
92 /* SMB_Connect_Server: Connect to a server, but don't negotiate protocol */
93 /* or anything else ... */
94
95 SMB_Handle_Type SMB_Connect_Server(SMB_Handle_Type Con_Handle,
96 char *server, const char *NTdomain)
97
98 {
99 SMB_Handle_Type con;
100 char called[80], calling[80], *address;
101 int i;
102
103 /* Get a connection structure if one does not exist */
104
105 con = Con_Handle;
106
107 if (Con_Handle == NULL) {
108
109 if ((con = (struct SMB_Connect_Def *)malloc(sizeof(struct SMB_Connect_Def))) == NULL) {
110
111
112 SMBlib_errno = SMBlibE_NoSpace;
113 return NULL;
114 }
115
116 }
117
118 /* Init some things ... */
119
120 strcpy(con -> service, "");
121 strcpy(con -> username, "");
122 strcpy(con -> password, "");
123 strcpy(con -> sock_options, "");
124 strcpy(con -> address, "");
125 strcpy(con -> desthost, server);
126 strcpy(con -> PDomain, NTdomain);
127 strcpy(con -> OSName, SMBLIB_DEFAULT_OSNAME);
128 strcpy(con -> LMType, SMBLIB_DEFAULT_LMTYPE);
129 con -> first_tree = con -> last_tree = NULL;
130
131 SMB_Get_My_Name(con -> myname, sizeof(con -> myname));
132
133 con -> port = 0; /* No port selected */
134
135 /* Get some things we need for the SMB Header */
136
137 con -> pid = getpid();
138 con -> mid = con -> pid; /* This will do for now ... */
139 con -> uid = 0; /* Until we have done a logon, no uid ... */
140 con -> gid = getgid();
141
142 /* Now connect to the remote end, but first upper case the name of the
143 service we are going to call, sine some servers want it in uppercase */
144
145 for (i=0; i < strlen(server); i++)
146 called[i] = toupper(server[i]);
147
148 called[strlen(server)] = 0; /* Make it a string */
149
150 for (i=0; i < strlen(con -> myname); i++)
151 calling[i] = toupper(con -> myname[i]);
152
153 calling[strlen(con -> myname)] = 0; /* Make it a string */
154
155 if (strcmp(con -> address, "") == 0)
156 address = con -> desthost;
157 else
158 address = con -> address;
159
160 con -> Trans_Connect = RFCNB_Call(called,
161 calling,
162 address, /* Protocol specific */
163 con -> port);
164
165 /* Did we get one? */
166
167 if (con -> Trans_Connect == NULL) {
168
169 if (Con_Handle == NULL) {
170 Con_Handle = NULL;
171 free(con);
172 }
173 SMBlib_errno = -SMBlibE_CallFailed;
174 return NULL;
175
176 }
177
178 return(con);
179
180 }
181
182 /* SMB_Connect: Connect to the indicated server */
183 /* If Con_Handle == NULL then create a handle and connect, otherwise */
184 /* use the handle passed */
185
186 const char *SMB_Prots_Restrict[] = {"PC NETWORK PROGRAM 1.0",
187 NULL
188 };
189
190
191 SMB_Handle_Type SMB_Connect(SMB_Handle_Type Con_Handle,
192 SMB_Tree_Handle *tree,
193 char *service,
194 char *username,
195 char *password)
196
197 {
198 SMB_Handle_Type con;
199 char *host, *address;
200 char temp[80], called[80], calling[80];
201 int i;
202
203 /* Get a connection structure if one does not exist */
204
205 con = Con_Handle;
206
207 if (Con_Handle == NULL) {
208
209 if ((con = (struct SMB_Connect_Def *)malloc(sizeof(struct SMB_Connect_Def))) == NULL) {
210
211 SMBlib_errno = SMBlibE_NoSpace;
212 return NULL;
213 }
214
215 }
216
217 /* Init some things ... */
218
219 strcpy(con -> service, service);
220 strcpy(con -> username, username);
221 strcpy(con -> password, password);
222 strcpy(con -> sock_options, "");
223 strcpy(con -> address, "");
224 strcpy(con -> PDomain, SMBLIB_DEFAULT_DOMAIN);
225 strcpy(con -> OSName, SMBLIB_DEFAULT_OSNAME);
226 strcpy(con -> LMType, SMBLIB_DEFAULT_LMTYPE);
227 con -> first_tree = con -> last_tree = NULL;
228
229 SMB_Get_My_Name(con -> myname, sizeof(con -> myname));
230
231 con -> port = 0; /* No port selected */
232
233 /* Get some things we need for the SMB Header */
234
235 con -> pid = getpid();
236 con -> mid = con -> pid; /* This will do for now ... */
237 con -> uid = 0; /* Until we have done a logon, no uid */
238 con -> gid = getgid();
239
240 /* Now figure out the host portion of the service */
241
242 strcpy(temp, service);
243 host = strtok(temp, "/\\"); /* Separate host name portion */
244 strcpy(con -> desthost, host);
245
246 /* Now connect to the remote end, but first upper case the name of the
247 service we are going to call, sine some servers want it in uppercase */
248
249 for (i=0; i < strlen(host); i++)
250 called[i] = toupper(host[i]);
251
252 called[strlen(host)] = 0; /* Make it a string */
253
254 for (i=0; i < strlen(con -> myname); i++)
255 calling[i] = toupper(con -> myname[i]);
256
257 calling[strlen(con -> myname)] = 0; /* Make it a string */
258
259 if (strcmp(con -> address, "") == 0)
260 address = con -> desthost;
261 else
262 address = con -> address;
263
264 con -> Trans_Connect = RFCNB_Call(called,
265 calling,
266 address, /* Protocol specific */
267 con -> port);
268
269 /* Did we get one? */
270
271 if (con -> Trans_Connect == NULL) {
272
273 if (Con_Handle == NULL) {
274 free(con);
275 Con_Handle = NULL;
276 }
277 SMBlib_errno = -SMBlibE_CallFailed;
278 return NULL;
279
280 }
281
282 /* Now, negotiate the protocol */
283
284 if (SMB_Negotiate(con, SMB_Prots_Restrict) < 0) {
285
286 /* Hmmm what should we do here ... We have a connection, but could not
287 negotiate ... */
288
289 return NULL;
290
291 }
292
293 /* Now connect to the service ... */
294
295 if ((*tree = SMB_TreeConnect(con, NULL, service, password, "A:")) == NULL) {
296
297 return NULL;
298
299 }
300
301 return(con);
302
303 }
304
305 /* Logon to the server. That is, do a session setup if we can. We do not do */
306 /* Unicode yet! */
307
308 int SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName,
309 char *PassWord, const char *NtDomain, int PreCrypted)
310
311 {
312 struct RFCNB_Pkt *pkt;
313 int param_len, pkt_len, pass_len;
314 char *p, pword[128];
315
316 /* First we need a packet etc ... but we need to know what protocol has */
317 /* been negotiated to figure out if we can do it and what SMB format to */
318 /* use ... */
319
320 if (Con_Handle -> protocol < SMB_P_LanMan1) {
321
322 SMBlib_errno = SMBlibE_ProtLow;
323 return(SMBlibE_BAD);
324
325 }
326
327 if (PreCrypted) {
328 pass_len = 24;
329 memcpy(pword, PassWord, 24);
330 } else {
331 strcpy(pword, PassWord);
332 #ifdef PAM_SMB_ENC_PASS
333 if (Con_Handle->encrypt_passwords) {
334 pass_len = 24;
335 SMBencrypt((uchar *) PassWord, (uchar *) Con_Handle->Encrypt_Key, (uchar *) pword);
336 } else
337 #endif
338 pass_len = strlen(pword);
339 }
340
341 /* Now build the correct structure */
342
343 if (Con_Handle -> protocol < SMB_P_NT1) {
344
345 /* We don't handle encrypted passwords ... */
346
347 param_len = strlen(UserName) + 1 + pass_len + 1 +
348 (NtDomain!=NULL ? strlen(NtDomain) : strlen(Con_Handle->PDomain)) + 1 +
349 strlen(Con_Handle -> OSName) + 1;
350
351 pkt_len = SMB_ssetpLM_len + param_len;
352
353 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
354
355 if (pkt == NULL) {
356
357 SMBlib_errno = SMBlibE_NoSpace;
358 return(SMBlibE_BAD); /* Should handle the error */
359
360 }
361
362 memset(SMB_Hdr(pkt), 0, SMB_ssetpLM_len);
363 SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */
364 *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
365 SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
366 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
367 SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
368 SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
369 *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10;
370 *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra command */
371 SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
372
373 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT);
374 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2);
375 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle -> pid);
376 SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0);
377 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, pass_len + 1);
378 SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0);
379 SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len);
380
381 /* Now copy the param strings in with the right stuff */
382
383 p = (char *)(SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset);
384
385 /* Copy in password, then the rest. Password has a null at end */
386
387 memcpy(p, pword, pass_len);
388
389 p = p + pass_len + 1;
390
391 strcpy(p, UserName);
392 p = p + strlen(UserName);
393 *p = 0;
394
395 p = p + 1;
396
397 if (NtDomain != NULL) {
398 strcpy(p, Con_Handle -> PDomain);
399 p = p + strlen(Con_Handle -> PDomain);
400 } else {
401 strcpy(p, NtDomain);
402 p = p + strlen(NtDomain);
403 }
404 *p = 0;
405 p = p + 1;
406
407 strcpy(p, Con_Handle -> OSName);
408 p = p + strlen(Con_Handle -> OSName);
409 *p = 0;
410
411 } else {
412
413 /* We don't admit to UNICODE support ... */
414
415 param_len = strlen(UserName) + 1 + pass_len +
416 strlen(Con_Handle -> PDomain) + 1 +
417 strlen(Con_Handle -> OSName) + 1 +
418 strlen(Con_Handle -> LMType) + 1;
419
420 pkt_len = SMB_ssetpNTLM_len + param_len;
421
422 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
423
424 if (pkt == NULL) {
425
426 SMBlib_errno = SMBlibE_NoSpace;
427 return(-1); /* Should handle the error */
428
429 }
430
431 memset(SMB_Hdr(pkt), 0, SMB_ssetpNTLM_len);
432 SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */
433 *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
434 SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid);
435 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
436 SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid);
437 SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid);
438 *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13;
439 *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra command */
440 SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
441
442 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT);
443 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 0);
444 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 1); /* Thanks Tridge! */
445 SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0);
446 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, pass_len);
447 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0);
448 SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0);
449 SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0);
450 SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len);
451
452 /* Now copy the param strings in with the right stuff */
453
454 p = (char *)(SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset);
455
456 /* Copy in password, then the rest. Password has no null at end */
457
458 memcpy(p, pword, pass_len);
459
460 p = p + pass_len;
461
462 strcpy(p, UserName);
463 p = p + strlen(UserName);
464 *p = 0;
465
466 p = p + 1;
467
468 strcpy(p, Con_Handle -> PDomain);
469 p = p + strlen(Con_Handle -> PDomain);
470 *p = 0;
471 p = p + 1;
472
473 strcpy(p, Con_Handle -> OSName);
474 p = p + strlen(Con_Handle -> OSName);
475 *p = 0;
476 p = p + 1;
477
478 strcpy(p, Con_Handle -> LMType);
479 p = p + strlen(Con_Handle -> LMType);
480 *p = 0;
481
482 }
483
484 /* Now send it and get a response */
485
486 if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
487
488 #ifdef DEBUG
489 fprintf(stderr, "Error sending SessSetupX request\n");
490 #endif
491
492 RFCNB_Free_Pkt(pkt);
493 SMBlib_errno = SMBlibE_SendFailed;
494 return(SMBlibE_BAD);
495
496 }
497
498 /* Now get the response ... */
499
500 if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
501
502 #ifdef DEBUG
503 fprintf(stderr, "Error receiving response to SessSetupAndX\n");
504 #endif
505
506 RFCNB_Free_Pkt(pkt);
507 SMBlib_errno = SMBlibE_RecvFailed;
508 return(SMBlibE_BAD);
509
510 }
511
512 /* Check out the response type ... */
513
514 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
515
516 #ifdef DEBUG
517 fprintf(stderr, "SMB_SessSetupAndX failed with errorclass = %i, Error Code = %i\n",
518 CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
519 SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
520 #endif
521
522 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
523 RFCNB_Free_Pkt(pkt);
524 SMBlib_errno = SMBlibE_Remote;
525 return(SMBlibE_BAD);
526
527 }
528
529 /** @@@ mdz: check for guest login { **/
530 if (SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset) & 0x1) {
531 /* do we allow guest login? NO! */
532 return (SMBlibE_BAD);
533 }
534 /** @@@ mdz: } **/
535
536 #ifdef DEBUG
537 fprintf(stderr, "SessSetupAndX response. Action = %i\n",
538 SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset));
539 #endif
540
541 /* Now pick up the UID for future reference ... */
542
543 Con_Handle -> uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset);
544 RFCNB_Free_Pkt(pkt);
545
546 return(0);
547
548 }
549
550
551 /* Disconnect from the server, and disconnect all tree connects */
552
553 int SMB_Discon(SMB_Handle_Type Con_Handle, BOOL KeepHandle)
554
555 {
556
557 /* We just disconnect the connection for now ... */
558
559 RFCNB_Hangup(Con_Handle -> Trans_Connect);
560
561 if (!KeepHandle)
562 free(Con_Handle);
563
564 return(0);
565
566 }