~squid/squid/sbuf-use

« back to all changes in this revision

Viewing changes to helpers/basic_auth/MSNT/smblib.c

  • Committer: hno
  • Date: 2001-01-08 06:32:04 UTC
  • Revision ID: cvs-1:hno-20010108063204-w6a8e1zz6eprqnp8
Major rewrite of proxy authentication to support other schemes than
Basic (auth_rewrite branch on SourceForge).
Contributors:
   Andy Doran
   Robert Collins
   Chemolli Francesco
   Henrik Nordstrom

For details about the new API's, see Programmers Guide.

As part of this change everything from auth_modules has been moved to
src/auth/basic/helpers

Show diffs side-by-side

added added

removed removed

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