~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to helpers/ntlm_auth/SMB/libntlmssp.c

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2010-05-04 11:15:49 UTC
  • mfrom: (1.3.1 upstream)
  • mto: (20.3.1 squeeze) (21.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20100504111549-1apjh2g5sndki4te
Tags: upstream-3.1.3
ImportĀ upstreamĀ versionĀ 3.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * (C) 2000 Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it>
3
 
 * Distributed freely under the terms of the GNU General Public License,
4
 
 * version 2. See the file COPYING for licensing details
5
 
 *
6
 
 * This program is distributed in the hope that it will be useful,
7
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9
 
 * GNU General Public License for more details.
10
 
 
11
 
 * You should have received a copy of the GNU General Public License
12
 
 * along with this program; if not, write to the Free Software
13
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
14
 
 */
15
 
 
16
 
typedef unsigned char uchar;
17
 
 
18
 
#include "ntlm.h"
19
 
#include "util.h"               /* from Squid */
20
 
#include "valid.h"
21
 
#include "smbencrypt.h"
22
 
 
23
 
#if HAVE_STRING_H
24
 
#include <string.h>
25
 
#endif /* HAVE_STRING_H */
26
 
#if HAVE_STDLIB_H
27
 
#include <stdlib.h>
28
 
#endif /* HAVE_STDLIB_H */
29
 
#ifdef HAVE_UNISTD_H
30
 
#include <unistd.h>
31
 
#endif
32
 
 
33
 
/* these are part of rfcnb-priv.h and smblib-priv.h */
34
 
extern int SMB_Get_Error_Msg(int msg, char *msgbuf, int len);
35
 
extern int SMB_Get_Last_Error();
36
 
extern int RFCNB_Get_Last_Errno();
37
 
 
38
 
#include "smblib-priv.h"        /* for SMB_Handle_Type */
39
 
 
40
 
/* a few forward-declarations. Hackish, but I don't care right now */
41
 
SMB_Handle_Type SMB_Connect_Server(SMB_Handle_Type Con_Handle, char *server, char *NTdomain);
42
 
 
43
 
/* this one is reallllly haackiish. We really should be using anything from smblib-priv.h
44
 
 */
45
 
static char *SMB_Prots[] =
46
 
{"PC NETWORK PROGRAM 1.0",
47
 
    "MICROSOFT NETWORKS 1.03",
48
 
    "MICROSOFT NETWORKS 3.0",
49
 
    "DOS LANMAN1.0",
50
 
    "LANMAN1.0",
51
 
    "DOS LM1.2X002",
52
 
    "LM1.2X002",
53
 
    "DOS LANMAN2.1",
54
 
    "LANMAN2.1",
55
 
    "Samba",
56
 
    "NT LM 0.12",
57
 
    "NT LANMAN 1.0",
58
 
    NULL
59
 
};
60
 
 
61
 
#if 0
62
 
int SMB_Discon(SMB_Handle_Type Con_Handle, BOOL KeepHandle);
63
 
int SMB_Negotiate(void *Con_Handle, char *Prots[]);
64
 
int SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName, char *PassWord, char *Domain, int precrypted);
65
 
#endif
66
 
 
67
 
#ifdef DEBUG
68
 
#define debug_dump_ntlmssp_flags dump_ntlmssp_flags
69
 
#else /* DEBUG */
70
 
#define debug_dump_ntlmssp_flags(X)     /* empty */
71
 
#endif /* DEBUG */
72
 
 
73
 
 
74
 
#define ENCODED_PASS_LEN 24
75
 
static unsigned char challenge[NONCE_LEN];
76
 
static unsigned char lmencoded_empty_pass[ENCODED_PASS_LEN],
77
 
        ntencoded_empty_pass[ENCODED_PASS_LEN];
78
 
SMB_Handle_Type handle = NULL;
79
 
 
80
 
/* Disconnects from the DC. A reconnection will be done upon the next request
81
 
 */
82
 
void
83
 
dc_disconnect()
84
 
{
85
 
    if (handle != NULL)
86
 
        SMB_Discon(handle, 0);
87
 
    handle = NULL;
88
 
}
89
 
 
90
 
int
91
 
connectedp()
92
 
{
93
 
    return (handle != NULL);
94
 
}
95
 
 
96
 
 
97
 
/* Tries to connect to a DC. Returns 0 on failure, 1 on OK */
98
 
int
99
 
is_dc_ok(char *domain, char *domain_controller)
100
 
{
101
 
    SMB_Handle_Type h = SMB_Connect_Server(NULL, domain_controller, domain);
102
 
    if (h == NULL)
103
 
        return 0;
104
 
    SMB_Discon(h, 0);
105
 
    return 1;
106
 
}
107
 
 
108
 
 
109
 
static char errstr[1001];
110
 
/* returns 0 on success, > 0 on failure */
111
 
static int
112
 
init_challenge(char *domain, char *domain_controller)
113
 
{
114
 
    int smberr;
115
 
 
116
 
    if (handle != NULL) {
117
 
        return 0;
118
 
    }
119
 
    debug("Connecting to server %s domain %s\n", domain_controller, domain);
120
 
    handle = SMB_Connect_Server(NULL, domain_controller, domain);
121
 
    smberr = SMB_Get_Last_Error();
122
 
    SMB_Get_Error_Msg(smberr, errstr, 1000);
123
 
 
124
 
 
125
 
    if (handle == NULL) {       /* couldn't connect */
126
 
        debug("Couldn't connect to SMB Server. Error:%s\n", errstr);
127
 
        return 1;
128
 
    }
129
 
    if (SMB_Negotiate(handle, SMB_Prots) < 0) {         /* An error */
130
 
        debug("Error negotiating protocol with SMB Server\n");
131
 
        SMB_Discon(handle, 0);
132
 
        handle = NULL;
133
 
        return 2;
134
 
    }
135
 
    if (handle->Security == 0) {        /* share-level security, unuseable */
136
 
        debug("SMB Server uses share-level security .. we need user security.\n");
137
 
        SMB_Discon(handle, 0);
138
 
        handle = NULL;
139
 
        return 3;
140
 
    }
141
 
    memcpy(challenge, handle->Encrypt_Key, NONCE_LEN);
142
 
                SMBencrypt((unsigned char *)"",challenge,lmencoded_empty_pass);
143
 
                SMBNTencrypt((unsigned char *)"",challenge,ntencoded_empty_pass);
144
 
    return 0;
145
 
}
146
 
 
147
 
static char my_domain[100], my_domain_controller[100];
148
 
const char *
149
 
make_challenge(char *domain, char *domain_controller)
150
 
{
151
 
        /* trying to circumvent some strange problem wih pointers in SMBLib */
152
 
        /* Ugly as hell, but the lib is going to be dropped... */
153
 
        strcpy(my_domain,domain);
154
 
        strcpy(my_domain_controller,domain_controller);
155
 
    if (init_challenge(my_domain, my_domain_controller) > 0) {
156
 
        return NULL;
157
 
    }
158
 
    return ntlm_make_challenge(my_domain, my_domain_controller, (char *)challenge, NONCE_LEN);
159
 
}
160
 
 
161
 
#define min(A,B) (A<B?A:B)
162
 
 
163
 
int ntlm_errno;
164
 
#define MAX_USERNAME_LEN 255
165
 
#define MAX_DOMAIN_LEN 255
166
 
#define MAX_PASSWD_LEN 31
167
 
static char credentials[MAX_USERNAME_LEN+MAX_DOMAIN_LEN+2];     /* we can afford to waste */
168
 
 
169
 
 
170
 
/* Fetches the user's credentials from the challenge.
171
 
 * Returns NULL if domain or user is not defined
172
 
 * No identity control is performed.
173
 
 * WARNING! The result is static storage, shared with ntlm_check_auth
174
 
 */
175
 
char *
176
 
fetch_credentials(ntlm_authenticate * auth, int auth_length)
177
 
{
178
 
    char *p = credentials;
179
 
    lstring tmp;
180
 
    tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain);
181
 
    *p = '\0';
182
 
    if (tmp.str == NULL)
183
 
        return NULL;
184
 
    memcpy(p, tmp.str, tmp.l);
185
 
    p += tmp.l;
186
 
    *p++ = '\\';
187
 
    *p = '\0';
188
 
    tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->user);
189
 
    if (tmp.str == NULL)
190
 
        return NULL;
191
 
    memcpy(p, tmp.str, tmp.l);
192
 
    *(p + tmp.l) = '\0';
193
 
    return credentials;
194
 
}
195
 
 
196
 
/* returns NULL on failure, or a pointer to
197
 
 * the user's credentials (domain\\username)
198
 
 * upon success. WARNING. It's pointing to static storage.
199
 
 * In case of problem sets as side-effect ntlm_errno to one of the
200
 
 * codes defined in ntlm.h
201
 
 */
202
 
char *
203
 
ntlm_check_auth(ntlm_authenticate * auth, int auth_length)
204
 
{
205
 
    int rv;
206
 
    char pass[MAX_PASSWD_LEN+1];
207
 
    char *domain = credentials;
208
 
    char *user;
209
 
    lstring tmp;
210
 
 
211
 
    if (handle == NULL) {       /*if null we aren't connected, but it shouldn't happen */
212
 
        debug("Weird, we've been disconnected\n");
213
 
        ntlm_errno = NTLM_NOT_CONNECTED;
214
 
        return NULL;
215
 
    }
216
 
 
217
 
/*      debug("fetching domain\n"); */
218
 
    tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain);
219
 
    if (tmp.str == NULL || tmp.l == 0) {
220
 
        debug("No domain supplied. Returning no-auth\n");
221
 
        ntlm_errno = NTLM_LOGON_ERROR;
222
 
        return NULL;
223
 
    }
224
 
    if (tmp.l > MAX_DOMAIN_LEN) {
225
 
        debug("Domain string exceeds %d bytes, rejecting\n", MAX_DOMAIN_LEN);
226
 
        ntlm_errno = NTLM_LOGON_ERROR;
227
 
        return NULL;
228
 
    }
229
 
    memcpy(domain, tmp.str, tmp.l);
230
 
    user = domain + tmp.l;
231
 
    *user++ = '\0';
232
 
 
233
 
/*      debug("fetching user name\n"); */
234
 
    tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->user);
235
 
    if (tmp.str == NULL || tmp.l == 0) {
236
 
        debug("No username supplied. Returning no-auth\n");
237
 
        ntlm_errno = NTLM_LOGON_ERROR;
238
 
        return NULL;
239
 
    }
240
 
    if (tmp.l > MAX_USERNAME_LEN) {
241
 
        debug("Username string exceeds %d bytes, rejecting\n", MAX_USERNAME_LEN);
242
 
        ntlm_errno = NTLM_LOGON_ERROR;
243
 
        return NULL;
244
 
    }
245
 
    memcpy(user, tmp.str, tmp.l);
246
 
    *(user + tmp.l) = '\0';
247
 
 
248
 
                
249
 
    /* Authenticating against the NT response doesn't seem to work... */
250
 
    tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->lmresponse);
251
 
    if (tmp.str == NULL || tmp.l == 0) {
252
 
        fprintf(stderr, "No auth at all. Returning no-auth\n");
253
 
        ntlm_errno = NTLM_LOGON_ERROR;
254
 
        return NULL;
255
 
    }
256
 
    if (tmp.l > MAX_PASSWD_LEN) {
257
 
        debug("Password string exceeds %d bytes, rejecting\n", MAX_PASSWD_LEN);
258
 
        ntlm_errno = NTLM_LOGON_ERROR;
259
 
        return NULL;
260
 
    }
261
 
 
262
 
    memcpy(pass, tmp.str, tmp.l);
263
 
    pass[min(MAX_PASSWD_LEN,tmp.l)] = '\0';
264
 
 
265
 
#if 1
266
 
                debug ("Empty LM pass detection: user: '%s', ours:'%s', his: '%s'"
267
 
                                         "(length: %d)\n",
268
 
                                         user,lmencoded_empty_pass,tmp.str,tmp.l);
269
 
                if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) {
270
 
                        fprintf(stderr,"Empty LM password supplied for user %s\\%s. "
271
 
                                                        "No-auth\n",domain,user);
272
 
                        ntlm_errno=NTLM_LOGON_ERROR;
273
 
                        return NULL;
274
 
                }
275
 
                
276
 
                tmp = ntlm_fetch_string ((char *) auth, auth_length, &auth->ntresponse);
277
 
                if (tmp.str != NULL && tmp.l != 0) {
278
 
                        debug ("Empty NT pass detection: user: '%s', ours:'%s', his: '%s'"
279
 
                                                 "(length: %d)\n",
280
 
                                                 user,ntencoded_empty_pass,tmp.str,tmp.l);
281
 
                        if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) {
282
 
                                fprintf(stderr,"Empty NT password supplied for user %s\\%s. "
283
 
                                                                "No-auth\n",domain,user);
284
 
                                ntlm_errno=NTLM_LOGON_ERROR;
285
 
                                return NULL;
286
 
                        }
287
 
                }
288
 
#endif
289
 
 
290
 
                /* TODO: check against empty password!!!!! */
291
 
                
292
 
 
293
 
 
294
 
    debug("checking domain: '%s', user: '%s', pass='%s'\n", domain, user, pass);
295
 
 
296
 
    rv = SMB_Logon_Server(handle, user, pass, domain, 1);
297
 
    debug("Login attempt had result %d\n", rv);
298
 
 
299
 
    if (rv != NTV_NO_ERROR) {   /* failed */
300
 
        ntlm_errno = rv;
301
 
        return NULL;
302
 
    }
303
 
    *(user - 1) = '\\';         /* hack. Performing, but ugly. */
304
 
 
305
 
    debug("credentials: %s\n", credentials);
306
 
    return credentials;
307
 
}