~squid/squid/sbuf-use

« back to all changes in this revision

Viewing changes to helpers/ntlm_auth/fakeauth/fakeauth_auth.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
/*
 
2
 *
 
3
 * AUTHOR: Robert Collins <rbtcollins@hotmail.com>
 
4
 *
 
5
 * Example ntlm authentication program for Squid, based on the
 
6
 * original proxy_auth code from client_side.c, written by
 
7
 * Jon Thackray <jrmt@uk.gdscorp.com>. and the inital ntlm code
 
8
 * Andy Doran.
 
9
 *
 
10
 * This code gets the username and returns it. No validation is done.
 
11
 * and by the way: it is a complete patch-up. Use the "real thing" NTLMSSP
 
12
 * if you can.
 
13
 */
 
14
 
 
15
#include "config.h"
 
16
 
 
17
#include "ntlm.h"
 
18
#include "util.h"
 
19
#include <ctype.h>
 
20
 
 
21
#if HAVE_STDIO_H
 
22
#include <stdio.h>
 
23
#endif
 
24
#if HAVE_STDLIB_H
 
25
#include <stdlib.h>
 
26
#endif
 
27
#if HAVE_UNISTD_H
 
28
#include <unistd.h>
 
29
#endif
 
30
#if HAVE_STRING_H
 
31
#include <string.h>
 
32
#endif
 
33
#if HAVE_CRYPT_H
 
34
#include <crypt.h>
 
35
#endif
 
36
#if HAVE_PWD_H
 
37
#include <pwd.h>
 
38
#endif
 
39
 
 
40
 
 
41
#define ERR    "ERR\n"
 
42
#define OK     "OK\n"
 
43
 
 
44
#if 0
 
45
#define NTLM_STATIC_CHALLENGE "deadbeef"
 
46
#endif
 
47
static char *authenticate_ntlm_domain = "LIFELESSWKS";
 
48
 
 
49
/* NTLM authentication by ad@netbsd.org - 07/1999 */
 
50
/* XXX this is not done cleanly... */
 
51
 
 
52
/* makes a null-terminated string lower-case. Changes CONTENTS! */
 
53
static void
 
54
lc(char *string)
 
55
{
 
56
    char *p = string, c;
 
57
    while ((c = *p)) {
 
58
        *p = tolower(c);
 
59
        p++;
 
60
    }
 
61
}
 
62
 
 
63
 
 
64
/*
 
65
 * Generates a challenge request. The randomness of the 8 byte 
 
66
 * challenge strings can be guarenteed to be poor at best.
 
67
 */
 
68
void
 
69
ntlmMakeChallenge(struct ntlm_challenge *chal)
 
70
{
 
71
#ifndef NTLM_STATIC_CHALLENGE
 
72
    static unsigned hash;
 
73
    int r;
 
74
#endif
 
75
    char *d;
 
76
    int i;
 
77
 
 
78
    memset(chal, 0, sizeof(*chal));
 
79
    memcpy(chal->hdr.signature, "NTLMSSP", 8);
 
80
    chal->flags = WSWAP(0x00018206);
 
81
    chal->hdr.type = WSWAP(NTLM_CHALLENGE);
 
82
    chal->unknown[6] = SSWAP(0x003a);
 
83
 
 
84
    d = (char *) chal + 48;
 
85
    i = 0;
 
86
 
 
87
    if (authenticate_ntlm_domain != NULL)
 
88
        while (authenticate_ntlm_domain[i++]);
 
89
 
 
90
 
 
91
    chal->target.offset = WSWAP(48);
 
92
    chal->target.maxlen = SSWAP(i);
 
93
    chal->target.len = chal->target.maxlen;
 
94
 
 
95
#ifdef NTLM_STATIC_CHALLENGE
 
96
    memcpy(chal->challenge, NTLM_STATIC_CHALLENGE, 8);
 
97
#else
 
98
    r = (int) rand();
 
99
    r = (hash ^ r) + r;
 
100
 
 
101
    for (i = 0; i < 8; i++) {
 
102
        chal->challenge[i] = r;
 
103
        r = (r >> 2) ^ r;
 
104
    }
 
105
 
 
106
    hash = r;
 
107
#endif
 
108
}
 
109
 
 
110
/*
 
111
 * Check the vailidity of a request header. Return -1 on error.
 
112
 */
 
113
int
 
114
ntlmCheckHeader(struct ntlmhdr *hdr, int type)
 
115
{
 
116
    /* 
 
117
     * Must be the correct security package and request type. The
 
118
     * 8 bytes compared includes the ASCII 'NUL'. 
 
119
     */
 
120
    if (memcmp(hdr->signature, "NTLMSSP", 8) != 0) {
 
121
        fprintf(stderr, "ntlmCheckHeader: bad header signature\n");
 
122
        return (-1);
 
123
    }
 
124
    if (type == NTLM_ANY)
 
125
        return 0;
 
126
 
 
127
    if (WSWAP(hdr->type) != type) {
 
128
/* don't report this error - it's ok as we do a if() around this function */
 
129
//      fprintf(stderr, "ntlmCheckHeader: type is %d, wanted %d\n",
 
130
        //          WSWAP(hdr->type), type);
 
131
        return (-1);
 
132
    }
 
133
    return (0);
 
134
}
 
135
 
 
136
/*
 
137
 * Extract a string from an NTLM request and return as ASCII.
 
138
 */
 
139
char *
 
140
ntlmGetString(ntlmhdr * hdr, strhdr * str, int flags)
 
141
{
 
142
    static char buf[512];
 
143
    u_short *s, c;
 
144
    char *d, *sc;
 
145
    int l, o;
 
146
 
 
147
    l = SSWAP(str->len);
 
148
    o = WSWAP(str->offset);
 
149
 
 
150
    /* Sanity checks. XXX values arbitrarialy chosen */
 
151
    if (l <= 0 || l >= 32 || o >= 256) {
 
152
        fprintf(stderr, "ntlmGetString: insane: l:%d o:%d\n", l, o);
 
153
        return (NULL);
 
154
    }
 
155
    if ((flags & 2) == 0) {
 
156
        /* UNICODE string */
 
157
        s = (u_short *) ((char *) hdr + o);
 
158
        d = buf;
 
159
 
 
160
        for (l >>= 1; l; s++, l--) {
 
161
            c = SSWAP(*s);
 
162
            if (c > 254 || c == '\0' || !isprint(c)) {
 
163
                fprintf(stderr, "ntlmGetString: bad uni: %04x\n", c);
 
164
                return (NULL);
 
165
            }
 
166
            *d++ = c;
 
167
            fprintf(stderr, "ntlmGetString: conv: '%c'\n", c);
 
168
        }
 
169
 
 
170
        *d = 0;
 
171
    } else {
 
172
        /* ASCII string */
 
173
        sc = (char *) hdr + o;
 
174
        d = buf;
 
175
 
 
176
        for (; l; l--) {
 
177
            if (*sc == '\0' || !isprint(*sc)) {
 
178
                fprintf(stderr, "ntlmGetString: bad ascii: %04x\n", *sc);
 
179
                return (NULL);
 
180
            }
 
181
            *d++ = *sc++;
 
182
        }
 
183
 
 
184
        *d = 0;
 
185
    }
 
186
 
 
187
    return (buf);
 
188
}
 
189
 
 
190
/*
 
191
 * Decode the strings in an NTLM authentication request
 
192
 */
 
193
int
 
194
ntlmDecodeAuth(struct ntlm_authenticate *auth, char *buf, size_t size)
 
195
{
 
196
    char *p, *origbuf;
 
197
    int s;
 
198
 
 
199
    if (!buf) {
 
200
        return 1;
 
201
    }
 
202
    origbuf = buf;
 
203
    if (ntlmCheckHeader(&auth->hdr, NTLM_AUTHENTICATE)) {
 
204
 
 
205
        fprintf(stderr, "ntlmDecodeAuth: header check fails\n");
 
206
        return -1;
 
207
    }
 
208
/* only on when you need to debug
 
209
 * fprintf(stderr,"ntlmDecodeAuth: size of %d\n", size);
 
210
 * fprintf(stderr,"ntlmDecodeAuth: flg %08x\n", auth->flags);
 
211
 * fprintf(stderr,"ntlmDecodeAuth: usr o(%d) l(%d)\n", auth->user.offset, auth->user.len);
 
212
 */
 
213
    if ((p = ntlmGetString(&auth->hdr, &auth->domain, 2)) == NULL)
 
214
        p = authenticate_ntlm_domain;
 
215
//      fprintf(stderr,"ntlmDecodeAuth: Domain '%s'.\n",p);
 
216
    if ((s = strlen(p) + 1) >= size)
 
217
        return 1;
 
218
    strcpy(buf, p);
 
219
//      fprintf(stdout,"ntlmDecodeAuth: Domain '%s'.\n",buf);
 
220
 
 
221
    size -= s;
 
222
    buf += (s - 1);
 
223
    *buf++ = '\\';              /* Using \ is more consistent with MS-proxy */
 
224
 
 
225
    p = ntlmGetString(&auth->hdr, &auth->user, 2);
 
226
    if ((s = strlen(p) + 1) >= size)
 
227
        return 1;
 
228
    while (*p)
 
229
        *buf++ = (*p++);        //tolower
 
230
 
 
231
    *buf++ = '\0';
 
232
    size -= s;
 
233
//      fprintf(stderr, "ntlmDecodeAuth: user: %s%s\n",origbuf, p);
 
234
 
 
235
 
 
236
    return 0;
 
237
}
 
238
 
 
239
 
 
240
int
 
241
main()
 
242
{
 
243
    char buf[256];
 
244
    char user[256], *p, *cleartext;
 
245
    struct ntlm_challenge chal;
 
246
    int len;
 
247
    char *data = NULL;
 
248
 
 
249
    setbuf(stdout, NULL);
 
250
    while (fgets(buf, 256, stdin) != NULL) {
 
251
        user[0] = '\0';         /*no usercode */
 
252
 
 
253
        if ((p = strchr(buf, '\n')) != NULL)
 
254
            *p = '\0';          /* strip \n */
 
255
#if defined(NTLMHELPPROTOCOLV3) || !defined(NTLMHELPPROTOCOLV2)
 
256
        if (strncasecmp(buf, "YR", 2) == 0) {
 
257
            ntlmMakeChallenge(&chal);
 
258
            len =
 
259
                sizeof(chal) - sizeof(chal.pad) +
 
260
                SSWAP(chal.target.maxlen);
 
261
            data = (char *) base64_encode_bin((char *) &chal, len);
 
262
            printf("TT %s\n", data);
 
263
        } else if (strncasecmp(buf, "KK ", 3) == 0) {
 
264
            cleartext = (char *) uudecode(buf + 3);
 
265
            if (!ntlmCheckHeader((struct ntlmhdr *) cleartext, NTLM_AUTHENTICATE)) {
 
266
                if (!ntlmDecodeAuth((struct ntlm_authenticate *) cleartext, user, 256)) {
 
267
                    lc(user);
 
268
                    printf("AF %s\n", user);
 
269
                } else {
 
270
                    lc(user);
 
271
                    printf("NA invalid credentials%s\n", user);
 
272
                }
 
273
            } else {
 
274
                lc(user);
 
275
                printf("BH wrong packet type!%s\n", user);
 
276
            }
 
277
        }
 
278
#endif
 
279
#ifdef NTLMHELPPROTOCOLV2
 
280
/* V2 of the protocol */
 
281
        if (strncasecmp(buf, "RESET", 5) == 0) {
 
282
            printf("RESET OK\n");
 
283
        } else {
 
284
            cleartext = (char *) uudecode(buf);
 
285
            if (!ntlmCheckHeader((struct ntlmhdr *) cleartext, NTLM_NEGOTIATE)) {
 
286
                ntlmMakeChallenge(&chal);
 
287
                len =
 
288
                    sizeof(chal) - sizeof(chal.pad) +
 
289
                    SSWAP(chal.target.maxlen);
 
290
                data = (char *) base64_encode_bin((char *) &chal, len);
 
291
                printf("CH %s\n", data);
 
292
            } else if (!ntlmCheckHeader
 
293
                ((struct ntlmhdr *) cleartext, NTLM_AUTHENTICATE)) {
 
294
                if (!ntlmDecodeAuth
 
295
                    ((struct ntlm_authenticate *) cleartext, user, 256)) {
 
296
                    lc(user);
 
297
                    printf("OK %s\n", user);
 
298
                } else {
 
299
                    lc(user);
 
300
                    printf("ERR %s\n", user);
 
301
                }
 
302
            } else {
 
303
                lc(user);
 
304
                printf("ERR %s\n", user);
 
305
            }
 
306
        }
 
307
#endif /*v2 */
 
308
    }
 
309
    exit(0);
 
310
}