~squid/squid/sbuf-use

« back to all changes in this revision

Viewing changes to helpers/basic_auth/MSNT/rfcnb-util.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 RFCNB (RFC1001/RFC1002) NetBIOS implementation
 
2
 * 
 
3
 * Version 1.0
 
4
 * RFCNB Utility 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
#include "std-includes.h"
 
27
#include "rfcnb-priv.h"
 
28
#include "rfcnb-util.h"
 
29
#include "rfcnb-io.h"
 
30
 
 
31
#include <stdlib.h>
 
32
#include <unistd.h>
 
33
#include <sys/types.h>
 
34
#include <sys/socket.h>
 
35
#include <netinet/in.h>
 
36
#include <arpa/inet.h>
 
37
#include <string.h>
 
38
 
 
39
char *RFCNB_Error_Strings[] =
 
40
{
 
41
 
 
42
    "RFCNBE_OK: Routine completed successfully.",
 
43
    "RFCNBE_NoSpace: No space available for a malloc call.",
 
44
    "RFCNBE_BadName: NetBIOS name could not be translated to IP address.",
 
45
    "RFCNBE_BadRead: Read system call returned an error. Check errno.",
 
46
    "RFCNBE_BadWrite: Write system call returned an error. Check errno.",
 
47
    "RFCNBE_ProtErr: A protocol error has occurred.",
 
48
    "RFCNBE_ConGone: Connection dropped during a read or write system call.",
 
49
    "RFCNBE_BadHandle: Bad connection handle passed.",
 
50
    "RFCNBE_BadSocket: Problems creating socket.",
 
51
    "RFCNBE_ConnectFailed: Connection failed. See errno.",
 
52
    "RFCNBE_CallRejNLOCN: Call rejected. Not listening on called name.",
 
53
    "RFCNBE_CallRejNLFCN: Call rejected. Not listening for called name.",
 
54
    "RFCNBE_CallRejCNNP: Call rejected. Called name not present.",
 
55
    "RFCNBE_CallRejInfRes: Call rejected. Name present, but insufficient resources.",
 
56
    "RFCNBE_CallRejUnSpec: Call rejected. Unspecified error.",
 
57
    "RFCNBE_BadParam: Bad parameters passed to a routine.",
 
58
    "RFCNBE_Timeout: IO Operation timed out ..."
 
59
 
 
60
};
 
61
 
 
62
extern void (*Prot_Print_Routine) ();   /* Pointer to protocol print routine */
 
63
 
 
64
/* Convert name and pad to 16 chars as needed */
 
65
/* Name 1 is a C string with null termination, name 2 may not be */
 
66
/* If SysName is true, then put a <00> on end, else space>       */
 
67
 
 
68
void
 
69
RFCNB_CvtPad_Name(char *name1, char *name2)
 
70
{
 
71
    char c, c1, c2;
 
72
    int i, len;
 
73
 
 
74
    len = strlen(name1);
 
75
 
 
76
    for (i = 0; i < 16; i++) {
 
77
 
 
78
        if (i >= len) {
 
79
 
 
80
            c1 = 'C';
 
81
            c2 = 'A';           /* CA is a space */
 
82
 
 
83
        } else {
 
84
 
 
85
            c = name1[i];
 
86
            c1 = (char) ((int) c / 16 + (int) 'A');
 
87
            c2 = (char) ((int) c % 16 + (int) 'A');
 
88
        }
 
89
 
 
90
        name2[i * 2] = c1;
 
91
        name2[i * 2 + 1] = c2;
 
92
 
 
93
    }
 
94
 
 
95
    name2[32] = 0;              /* Put in the nll ... */
 
96
 
 
97
}
 
98
 
 
99
/* Converts an Ascii NB Name (16 chars) to an RFCNB Name (32 chars)
 
100
 * Uses the encoding in RFC1001. Each nibble of byte is added to 'A'
 
101
 * to produce the next byte in the name.
 
102
 * 
 
103
 * This routine assumes that AName is 16 bytes long and that NBName has 
 
104
 * space for 32 chars, so be careful ... 
 
105
 * 
 
106
 */
 
107
 
 
108
void
 
109
RFCNB_AName_To_NBName(char *AName, char *NBName)
 
110
{
 
111
    char c, c1, c2;
 
112
    int i;
 
113
 
 
114
    for (i = 0; i < 16; i++) {
 
115
 
 
116
        c = AName[i];
 
117
 
 
118
        c1 = (char) ((c >> 4) + 'A');
 
119
        c2 = (char) ((c & 0xF) + 'A');
 
120
 
 
121
        NBName[i * 2] = c1;
 
122
        NBName[i * 2 + 1] = c2;
 
123
    }
 
124
 
 
125
    NBName[32] = 0;             /* Put in a null */
 
126
 
 
127
}
 
128
 
 
129
/* Do the reverse of the above ... */
 
130
 
 
131
void
 
132
RFCNB_NBName_To_AName(char *NBName, char *AName)
 
133
{
 
134
    char c, c1, c2;
 
135
    int i;
 
136
 
 
137
    for (i = 0; i < 16; i++) {
 
138
 
 
139
        c1 = NBName[i * 2];
 
140
        c2 = NBName[i * 2 + 1];
 
141
 
 
142
        c = (char) (((int) c1 - (int) 'A') * 16 + ((int) c2 - (int) 'A'));
 
143
 
 
144
        AName[i] = c;
 
145
 
 
146
    }
 
147
 
 
148
    AName[i] = 0;               /* Put a null on the end ... */
 
149
 
 
150
}
 
151
 
 
152
/* Print a string of bytes in HEX etc */
 
153
 
 
154
void
 
155
RFCNB_Print_Hex(FILE * fd, struct RFCNB_Pkt *pkt, int Offset, int Len)
 
156
{
 
157
    char c1, c2, outbuf1[33];
 
158
    unsigned char c;
 
159
    int i, j;
 
160
    struct RFCNB_Pkt *pkt_ptr = pkt;
 
161
    static char Hex_List[17] = "0123456789ABCDEF";
 
162
 
 
163
    j = 0;
 
164
 
 
165
    /* We only want to print as much as sepcified in Len */
 
166
 
 
167
    while (pkt_ptr != NULL) {
 
168
 
 
169
        for (i = 0;
 
170
            i < ((Len > (pkt_ptr->len) ? pkt_ptr->len : Len) - Offset);
 
171
            i++) {
 
172
 
 
173
            c = pkt_ptr->data[i + Offset];
 
174
            c1 = Hex_List[c >> 4];
 
175
            c2 = Hex_List[c & 0xF];
 
176
 
 
177
            outbuf1[j++] = c1;
 
178
            outbuf1[j++] = c2;
 
179
 
 
180
            if (j == 32) {      /* Print and reset */
 
181
                outbuf1[j] = 0;
 
182
                fprintf(fd, "    %s\n", outbuf1);
 
183
                j = 0;
 
184
            }
 
185
        }
 
186
 
 
187
        Offset = 0;
 
188
        Len = Len - pkt_ptr->len;       /* Reduce amount by this much */
 
189
        pkt_ptr = pkt_ptr->next;
 
190
 
 
191
    }
 
192
 
 
193
    /* Print last lot in the buffer ... */
 
194
 
 
195
    if (j > 0) {
 
196
 
 
197
        outbuf1[j] = 0;
 
198
        fprintf(fd, "    %s\n", outbuf1);
 
199
 
 
200
    }
 
201
    fprintf(fd, "\n");
 
202
 
 
203
}
 
204
 
 
205
/* Get a packet of size n */
 
206
 
 
207
struct RFCNB_Pkt *
 
208
RFCNB_Alloc_Pkt(int n)
 
209
{
 
210
    RFCNB_Pkt *pkt;
 
211
 
 
212
    if ((pkt = (struct RFCNB_Pkt *) malloc(sizeof(struct RFCNB_Pkt))) == NULL) {
 
213
 
 
214
        RFCNB_errno = RFCNBE_NoSpace;
 
215
        RFCNB_saved_errno = errno;
 
216
        return (NULL);
 
217
 
 
218
    }
 
219
    pkt->next = NULL;
 
220
    pkt->len = n;
 
221
 
 
222
    if (n == 0)
 
223
        return (pkt);
 
224
 
 
225
    if ((pkt->data = (char *) malloc(n)) == NULL) {
 
226
 
 
227
        RFCNB_errno = RFCNBE_NoSpace;
 
228
        RFCNB_saved_errno = errno;
 
229
        free(pkt);
 
230
        return (NULL);
 
231
 
 
232
    }
 
233
    return (pkt);
 
234
 
 
235
}
 
236
 
 
237
/* Free up a packet */
 
238
 
 
239
void
 
240
RFCNB_Free_Pkt(struct RFCNB_Pkt *pkt)
 
241
{
 
242
    struct RFCNB_Pkt *pkt_next;
 
243
    char *data_ptr;
 
244
 
 
245
    while (pkt != NULL) {
 
246
 
 
247
        pkt_next = pkt->next;
 
248
 
 
249
        data_ptr = pkt->data;
 
250
 
 
251
        if (data_ptr != NULL)
 
252
            free(data_ptr);
 
253
 
 
254
        free(pkt);
 
255
 
 
256
        pkt = pkt_next;
 
257
 
 
258
    }
 
259
 
 
260
}
 
261
 
 
262
/* Print an RFCNB packet */
 
263
 
 
264
void
 
265
RFCNB_Print_Pkt(FILE * fd, char *dirn, struct RFCNB_Pkt *pkt, int len)
 
266
{
 
267
    char lname[17];
 
268
 
 
269
    /* We assume that the first fragment is the RFCNB Header  */
 
270
    /* We should loop through the fragments printing them out */
 
271
 
 
272
    fprintf(fd, "RFCNB Pkt %s:", dirn);
 
273
 
 
274
    switch (RFCNB_Pkt_Type(pkt->data)) {
 
275
 
 
276
    case RFCNB_SESSION_MESSAGE:
 
277
 
 
278
        fprintf(fd, "SESSION MESSAGE: Length = %i\n", RFCNB_Pkt_Len(pkt->data));
 
279
        RFCNB_Print_Hex(fd, pkt, RFCNB_Pkt_Hdr_Len,
 
280
#ifdef RFCNB_PRINT_DATA
 
281
            RFCNB_Pkt_Len(pkt->data) - RFCNB_Pkt_Hdr_Len);
 
282
#else
 
283
            40);
 
284
#endif
 
285
 
 
286
        if (Prot_Print_Routine != 0) {  /* Print the rest of the packet */
 
287
 
 
288
            Prot_Print_Routine(fd, strcmp(dirn, "sent"), pkt, RFCNB_Pkt_Hdr_Len,
 
289
                RFCNB_Pkt_Len(pkt->data) - RFCNB_Pkt_Hdr_Len);
 
290
 
 
291
        }
 
292
        break;
 
293
 
 
294
    case RFCNB_SESSION_REQUEST:
 
295
 
 
296
        fprintf(fd, "SESSION REQUEST: Length = %i\n",
 
297
            RFCNB_Pkt_Len(pkt->data));
 
298
        RFCNB_NBName_To_AName((char *) (pkt->data + RFCNB_Pkt_Called_Offset), lname);
 
299
        fprintf(fd, "  Called Name: %s\n", lname);
 
300
        RFCNB_NBName_To_AName((char *) (pkt->data + RFCNB_Pkt_Calling_Offset), lname);
 
301
        fprintf(fd, "  Calling Name: %s\n", lname);
 
302
 
 
303
        break;
 
304
 
 
305
    case RFCNB_SESSION_ACK:
 
306
 
 
307
        fprintf(fd, "RFCNB SESSION ACK: Length = %i\n",
 
308
            RFCNB_Pkt_Len(pkt->data));
 
309
 
 
310
        break;
 
311
 
 
312
    case RFCNB_SESSION_REJ:
 
313
        fprintf(fd, "RFCNB SESSION REJECT: Length = %i\n",
 
314
            RFCNB_Pkt_Len(pkt->data));
 
315
 
 
316
        if (RFCNB_Pkt_Len(pkt->data) < 1) {
 
317
            fprintf(fd, "   Protocol Error, short Reject packet!\n");
 
318
        } else {
 
319
            fprintf(fd, "   Error = %x\n", CVAL(pkt->data, RFCNB_Pkt_Error_Offset));
 
320
        }
 
321
 
 
322
        break;
 
323
 
 
324
    case RFCNB_SESSION_RETARGET:
 
325
 
 
326
        fprintf(fd, "RFCNB SESSION RETARGET: Length = %i\n",
 
327
            RFCNB_Pkt_Len(pkt->data));
 
328
 
 
329
        /* Print out the IP address etc and the port? */
 
330
 
 
331
        break;
 
332
 
 
333
    case RFCNB_SESSION_KEEP_ALIVE:
 
334
 
 
335
        fprintf(fd, "RFCNB SESSION KEEP ALIVE: Length = %i\n",
 
336
            RFCNB_Pkt_Len(pkt->data));
 
337
        break;
 
338
 
 
339
    default:
 
340
 
 
341
        break;
 
342
    }
 
343
 
 
344
}
 
345
 
 
346
/* Resolve a name into an address */
 
347
 
 
348
int
 
349
RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP)
 
350
{
 
351
    int addr;                   /* Assumes IP4, 32 bit network addresses */
 
352
    struct hostent *hp;
 
353
 
 
354
    /* Use inet_addr to try to convert the address */
 
355
 
 
356
    if ((addr = inet_addr(host)) == INADDR_NONE) {      /* Oh well, a good try :-) */
 
357
 
 
358
        /* Now try a name look up with gethostbyname */
 
359
 
 
360
        if ((hp = gethostbyname(host)) == NULL) {       /* Not in DNS */
 
361
 
 
362
            /* Try NetBIOS name lookup, how the hell do we do that? */
 
363
 
 
364
            RFCNB_errno = RFCNBE_BadName;       /* Is this right? */
 
365
            RFCNB_saved_errno = errno;
 
366
            return (RFCNBE_Bad);
 
367
 
 
368
        } else {                /* We got a name */
 
369
 
 
370
            memcpy((void *) Dest_IP, (void *) hp->h_addr_list[0], sizeof(struct in_addr));
 
371
 
 
372
        }
 
373
    } else {                    /* It was an IP address */
 
374
 
 
375
        memcpy((void *) Dest_IP, (void *) &addr, sizeof(struct in_addr));
 
376
 
 
377
    }
 
378
 
 
379
    return 0;
 
380
 
 
381
}
 
382
 
 
383
/* Disconnect the TCP connection to the server */
 
384
 
 
385
int
 
386
RFCNB_Close(int socket)
 
387
{
 
388
 
 
389
    close(socket);
 
390
 
 
391
    /* If we want to do error recovery, here is where we put it */
 
392
 
 
393
    return 0;
 
394
 
 
395
}
 
396
 
 
397
/* Connect to the server specified in the IP address.
 
398
 * Not sure how to handle socket options etc.         */
 
399
 
 
400
int
 
401
RFCNB_IP_Connect(struct in_addr Dest_IP, int port)
 
402
{
 
403
    struct sockaddr_in Socket;
 
404
    int fd;
 
405
 
 
406
    /* Create a socket */
 
407
 
 
408
    if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {   /* Handle the error */
 
409
 
 
410
        RFCNB_errno = RFCNBE_BadSocket;
 
411
        RFCNB_saved_errno = errno;
 
412
        return (RFCNBE_Bad);
 
413
    }
 
414
    bzero((char *) &Socket, sizeof(Socket));
 
415
    memcpy((char *) &Socket.sin_addr, (char *) &Dest_IP, sizeof(Dest_IP));
 
416
 
 
417
    Socket.sin_port = htons(port);
 
418
    Socket.sin_family = PF_INET;
 
419
 
 
420
    /* Now connect to the destination */
 
421
 
 
422
    if (connect(fd, (struct sockaddr *) &Socket, sizeof(Socket)) < 0) {         /* Error */
 
423
 
 
424
        close(fd);
 
425
        RFCNB_errno = RFCNBE_ConnectFailed;
 
426
        RFCNB_saved_errno = errno;
 
427
        return (RFCNBE_Bad);
 
428
    }
 
429
    return (fd);
 
430
 
 
431
}
 
432
 
 
433
/* handle the details of establishing the RFCNB session with remote 
 
434
 * end 
 
435
 * 
 
436
 */
 
437
 
 
438
int
 
439
RFCNB_Session_Req(struct RFCNB_Con *con,
 
440
    char *Called_Name,
 
441
    char *Calling_Name,
 
442
    BOOL * redirect,
 
443
    struct in_addr *Dest_IP,
 
444
    int *port)
 
445
{
 
446
    char *sess_pkt;
 
447
 
 
448
    /* Response packet should be no more than 9 bytes, make 16 jic */
 
449
 
 
450
    char resp[16];
 
451
    int len;
 
452
    struct RFCNB_Pkt *pkt, res_pkt;
 
453
 
 
454
    /* We build and send the session request, then read the response */
 
455
 
 
456
    pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Sess_Len);
 
457
 
 
458
    if (pkt == NULL) {
 
459
 
 
460
        return (RFCNBE_Bad);    /* Leave the error that RFCNB_Alloc_Pkt gives) */
 
461
 
 
462
    }
 
463
    sess_pkt = pkt->data;       /* Get pointer to packet proper */
 
464
 
 
465
    sess_pkt[RFCNB_Pkt_Type_Offset] = RFCNB_SESSION_REQUEST;
 
466
    RFCNB_Put_Pkt_Len(sess_pkt, (RFCNB_Pkt_Sess_Len - RFCNB_Pkt_Hdr_Len));
 
467
    sess_pkt[RFCNB_Pkt_N1Len_Offset] = 32;
 
468
    sess_pkt[RFCNB_Pkt_N2Len_Offset] = 32;
 
469
 
 
470
    RFCNB_CvtPad_Name(Called_Name, (sess_pkt + RFCNB_Pkt_Called_Offset));
 
471
    RFCNB_CvtPad_Name(Calling_Name, (sess_pkt + RFCNB_Pkt_Calling_Offset));
 
472
 
 
473
    /* Now send the packet */
 
474
 
 
475
#ifdef RFCNB_DEBUG
 
476
 
 
477
    fprintf(stderr, "Sending packet: ");
 
478
 
 
479
#endif
 
480
 
 
481
    if ((len = RFCNB_Put_Pkt(con, pkt, RFCNB_Pkt_Sess_Len)) < 0) {
 
482
 
 
483
        return (RFCNBE_Bad);    /* Should be able to write that lot ... */
 
484
 
 
485
    }
 
486
#ifdef RFCNB_DEBUG
 
487
 
 
488
    fprintf(stderr, "Getting packet.\n");
 
489
 
 
490
#endif
 
491
 
 
492
    res_pkt.data = resp;
 
493
    res_pkt.len = sizeof(resp);
 
494
    res_pkt.next = NULL;
 
495
 
 
496
    if ((len = RFCNB_Get_Pkt(con, &res_pkt, sizeof(resp))) < 0) {
 
497
 
 
498
        return (RFCNBE_Bad);
 
499
 
 
500
    }
 
501
    /* Now analyze the packet ... */
 
502
 
 
503
    switch (RFCNB_Pkt_Type(resp)) {
 
504
 
 
505
    case RFCNB_SESSION_REJ:     /* Didnt like us ... too bad */
 
506
 
 
507
        /* Why did we get rejected ? */
 
508
 
 
509
        switch (CVAL(resp, RFCNB_Pkt_Error_Offset)) {
 
510
 
 
511
        case 0x80:
 
512
            RFCNB_errno = RFCNBE_CallRejNLOCN;
 
513
            break;
 
514
        case 0x81:
 
515
            RFCNB_errno = RFCNBE_CallRejNLFCN;
 
516
            break;
 
517
        case 0x82:
 
518
            RFCNB_errno = RFCNBE_CallRejCNNP;
 
519
            break;
 
520
        case 0x83:
 
521
            RFCNB_errno = RFCNBE_CallRejInfRes;
 
522
            break;
 
523
        case 0x8F:
 
524
            RFCNB_errno = RFCNBE_CallRejUnSpec;
 
525
            break;
 
526
        default:
 
527
            RFCNB_errno = RFCNBE_ProtErr;
 
528
            break;
 
529
        }
 
530
 
 
531
        return (RFCNBE_Bad);
 
532
        break;
 
533
 
 
534
    case RFCNB_SESSION_ACK:     /* Got what we wanted ...      */
 
535
 
 
536
        return (0);
 
537
        break;
 
538
 
 
539
    case RFCNB_SESSION_RETARGET:        /* Go elsewhere                */
 
540
 
 
541
        *redirect = TRUE;       /* Copy port and ip addr       */
 
542
 
 
543
        memcpy(Dest_IP, (resp + RFCNB_Pkt_IP_Offset), sizeof(struct in_addr));
 
544
        *port = SVAL(resp, RFCNB_Pkt_Port_Offset);
 
545
 
 
546
        return (0);
 
547
        break;
 
548
 
 
549
    default:                    /* A protocol error */
 
550
 
 
551
        RFCNB_errno = RFCNBE_ProtErr;
 
552
        return (RFCNBE_Bad);
 
553
        break;
 
554
    }
 
555
}