~ubuntu-branches/ubuntu/saucy/openvpn/saucy-proposed

« back to all changes in this revision

Viewing changes to ntlm.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2013-05-24 17:42:45 UTC
  • mfrom: (1.1.19) (10.2.22 sid)
  • Revision ID: package-import@ubuntu.com-20130524174245-g9y6wlforycufqy5
Tags: 2.3.1-2ubuntu1
* Merge from Debian unstable. Remaining changes:
  - debian/openvpn.init.d:
    + Do not use start-stop-daemon and </dev/null to avoid blocking boot.
    + Show per-VPN result messages.
    + Add "--script-security 2" by default for backwards compatabliity.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  ntlm proxy support for OpenVPN
3
 
 *
4
 
 *  Copyright (C) 2004 William Preston
5
 
 *
6
 
 *  *NTLMv2 support and domain name parsing by Miroslav Zajic, Nextsoft s.r.o.*
7
 
 *
8
 
 *  This program is free software; you can redistribute it and/or modify
9
 
 *  it under the terms of the GNU General Public License as published by
10
 
 *  the Free Software Foundation; either version 2 of the License, or
11
 
 *  (at your option) any later version.
12
 
 *
13
 
 *  This program is distributed in the hope that it will be useful,
14
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 *  GNU General Public License for more details.
17
 
 *
18
 
 *  You should have received a copy of the GNU General Public License
19
 
 *  along with this program (see the file COPYING included with this
20
 
 *  distribution); if not, write to the Free Software Foundation, Inc.,
21
 
 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 
 */
23
 
 
24
 
#include "syshead.h"
25
 
 
26
 
#if NTLM
27
 
 
28
 
#include "common.h"
29
 
#include "buffer.h"
30
 
#include "misc.h"
31
 
#include "socket.h"
32
 
#include "fdmisc.h"
33
 
#include "proxy.h"
34
 
#include "ntlm.h"
35
 
#include "base64.h"
36
 
#include "crypto.h"
37
 
 
38
 
#include "memdbg.h"
39
 
 
40
 
 
41
 
/* 64bit datatype macros */
42
 
#ifdef _MSC_VER 
43
 
        /* MS compilers */
44
 
#       define UINTEGER64 __int64
45
 
#       define UINT64(c) c ## Ui64
46
 
#else 
47
 
        /* Non MS compilers */
48
 
#       define UINTEGER64 unsigned long long
49
 
#       define UINT64(c) c ## LL
50
 
#endif
51
 
 
52
 
 
53
 
 
54
 
 
55
 
static void
56
 
create_des_keys(const unsigned char *hash, unsigned char *key)
57
 
{
58
 
  key[0] = hash[0];
59
 
  key[1] = ((hash[0]&1)<<7)|(hash[1]>>1);
60
 
  key[2] = ((hash[1]&3)<<6)|(hash[2]>>2);
61
 
  key[3] = ((hash[2]&7)<<5)|(hash[3]>>3);
62
 
  key[4] = ((hash[3]&15)<<4)|(hash[4]>>4);
63
 
  key[5] = ((hash[4]&31)<<3)|(hash[5]>>5);
64
 
  key[6] = ((hash[5]&63)<<2)|(hash[6]>>6);
65
 
  key[7] = ((hash[6]&127)<<1);
66
 
  des_set_odd_parity((des_cblock *)key);
67
 
}
68
 
 
69
 
static void
70
 
gen_md4_hash (const char* data, int data_len, char *result)
71
 
{
72
 
  /* result is 16 byte md4 hash */
73
 
 
74
 
  MD4_CTX c;
75
 
  char md[16];
76
 
 
77
 
  MD4_Init (&c);
78
 
  MD4_Update (&c, data, data_len);
79
 
  MD4_Final ((unsigned char *)md, &c);
80
 
 
81
 
  memcpy (result, md, 16);
82
 
}
83
 
 
84
 
static void
85
 
gen_hmac_md5 (const char* data, int data_len, const char* key, int key_len,char *result)
86
 
{
87
 
        unsigned int len;
88
 
 
89
 
        HMAC_CTX c;
90
 
        HMAC_Init (&c, key, key_len, EVP_md5());
91
 
        HMAC_Update (&c, (const unsigned char *)data, data_len);
92
 
        HMAC_Final (&c, (unsigned char *)result, &len);
93
 
        HMAC_CTX_cleanup(&c);
94
 
}
95
 
 
96
 
static void
97
 
gen_timestamp (unsigned char *timestamp)
98
 
99
 
        /* Copies 8 bytes long timestamp into "timestamp" buffer. 
100
 
         * Timestamp is Little-endian, 64-bit signed value representing the number of tenths of a microsecond since January 1, 1601.
101
 
         */
102
 
 
103
 
        UINTEGER64 timestamp_ull;
104
 
 
105
 
        timestamp_ull = openvpn_time(NULL);
106
 
        timestamp_ull = (timestamp_ull + UINT64(11644473600)) * UINT64(10000000);
107
 
 
108
 
        /* store little endian value */
109
 
        timestamp[0]= timestamp_ull & UINT64(0xFF);
110
 
        timestamp[1]= (timestamp_ull  >> 8)  & UINT64(0xFF);
111
 
        timestamp[2]= (timestamp_ull  >> 16) & UINT64(0xFF);
112
 
        timestamp[3]= (timestamp_ull  >> 24) & UINT64(0xFF);
113
 
        timestamp[4]= (timestamp_ull  >> 32) & UINT64(0xFF);
114
 
        timestamp[5]= (timestamp_ull  >> 40) & UINT64(0xFF);
115
 
        timestamp[6]= (timestamp_ull  >> 48) & UINT64(0xFF);
116
 
        timestamp[7]= (timestamp_ull  >> 56) & UINT64(0xFF);
117
 
}
118
 
 
119
 
static void
120
 
gen_nonce (unsigned char *nonce)
121
 
122
 
        /* Generates 8 random bytes to be used as client nonce */
123
 
        int i;
124
 
 
125
 
        for(i=0;i<8;i++){
126
 
                nonce[i] = (unsigned char)get_random();
127
 
        }
128
 
}
129
 
 
130
 
unsigned char *my_strupr(unsigned char *str)
131
 
132
 
        /* converts string to uppercase in place */
133
 
        unsigned char *tmp = str;;
134
 
 
135
 
        do *str = toupper(*str); while (*(++str));
136
 
        return tmp;
137
 
}
138
 
 
139
 
static int
140
 
unicodize (char *dst, const char *src)
141
 
{
142
 
  /* not really unicode... */
143
 
  int i = 0;
144
 
  do
145
 
    {
146
 
      dst[i++] = *src;
147
 
      dst[i++] = 0;
148
 
    }
149
 
  while (*src++);
150
 
 
151
 
  return i;
152
 
}
153
 
 
154
 
static void
155
 
add_security_buffer(int sb_offset, void *data, int length, unsigned char *msg_buf, int *msg_bufpos)
156
 
{
157
 
        /* Adds security buffer data to a message and sets security buffer's offset and length */
158
 
        msg_buf[sb_offset] = (unsigned char)length;
159
 
        msg_buf[sb_offset + 2] = msg_buf[sb_offset];
160
 
        msg_buf[sb_offset + 4] = (unsigned char)(*msg_bufpos & 0xff);
161
 
        msg_buf[sb_offset + 5] = (unsigned char)((*msg_bufpos >> 8) & 0xff);
162
 
        memcpy(&msg_buf[*msg_bufpos], data, msg_buf[sb_offset]);
163
 
        *msg_bufpos += length;
164
 
}
165
 
 
166
 
const char *
167
 
ntlm_phase_1 (const struct http_proxy_info *p, struct gc_arena *gc)
168
 
{
169
 
  struct buffer out = alloc_buf_gc (96, gc);
170
 
  /* try a minimal NTLM handshake
171
 
   *
172
 
   * http://davenport.sourceforge.net/ntlm.html
173
 
   *
174
 
   * This message contains only the NTLMSSP signature,
175
 
   * the NTLM message type,
176
 
   * and the minimal set of flags (Negotiate NTLM and Negotiate OEM).
177
 
   *
178
 
   */
179
 
  buf_printf (&out, "%s", "TlRMTVNTUAABAAAAAgIAAA==");
180
 
  return (BSTR (&out));
181
 
}
182
 
 
183
 
const char *
184
 
ntlm_phase_3 (const struct http_proxy_info *p, const char *phase_2, struct gc_arena *gc)
185
 
{
186
 
        /* NTLM handshake
187
 
         *
188
 
         * http://davenport.sourceforge.net/ntlm.html
189
 
         *
190
 
         */
191
 
        
192
 
  char pwbuf[sizeof (p->up.password) * 2]; /* for unicode password */
193
 
  char buf2[128]; /* decoded reply from proxy */
194
 
  unsigned char phase3[464];
195
 
 
196
 
  char md4_hash[21];
197
 
  char challenge[8], ntlm_response[24];
198
 
  int i, ret_val;
199
 
  des_cblock key1, key2, key3;
200
 
  des_key_schedule sched1, sched2, sched3;
201
 
 
202
 
        char ntlmv2_response[144];
203
 
        char userdomain_u[256]; /* for uppercase unicode username and domain */
204
 
        char userdomain[128];   /* the same as previous but ascii */
205
 
        char ntlmv2_hash[16];
206
 
        char ntlmv2_hmacmd5[16];
207
 
        char *ntlmv2_blob = ntlmv2_response + 16; /* inside ntlmv2_response, length: 128 */
208
 
        int ntlmv2_blob_size=0;
209
 
        int phase3_bufpos = 0x40; /* offset to next security buffer data to be added */
210
 
        size_t len;
211
 
 
212
 
        char domain[128];
213
 
        char username[128];
214
 
        char *separator;
215
 
 
216
 
        bool ntlmv2_enabled = (p->auth_method == HTTP_AUTH_NTLM2);
217
 
 
218
 
  CLEAR (buf2);
219
 
 
220
 
  ASSERT (strlen (p->up.username) > 0);
221
 
  ASSERT (strlen (p->up.password) > 0);
222
 
        
223
 
        /* username parsing */
224
 
        separator = strchr(p->up.username, '\\');
225
 
        if (separator == NULL) {
226
 
                strncpy(username, p->up.username, sizeof(username)-1);
227
 
                username[sizeof(username)-1]=0;
228
 
                domain[0]=0;
229
 
        } else {
230
 
                strncpy(username, separator+1, sizeof(username)-1);
231
 
                username[sizeof(username)-1]=0;
232
 
                len = separator - p->up.username;
233
 
                if (len > sizeof(domain) - 1) len = sizeof(domain) - 1;
234
 
                strncpy(domain, p->up.username,  len);
235
 
                domain[len]=0;
236
 
        }
237
 
 
238
 
 
239
 
  /* fill 1st 16 bytes with md4 hash, disregard terminating null */
240
 
  gen_md4_hash (pwbuf, unicodize (pwbuf, p->up.password) - 2, md4_hash);
241
 
 
242
 
  /* pad to 21 bytes */
243
 
  memset (md4_hash + 16, 0, 5);
244
 
 
245
 
  ret_val = base64_decode( phase_2, (void *)buf2);
246
 
  if (ret_val < 0)
247
 
    return NULL;
248
 
 
249
 
  /* we can be sure that phase_2 is less than 128
250
 
   * therefore buf2 needs to be (3/4 * 128) */
251
 
 
252
 
  /* extract the challenge from bytes 24-31 */
253
 
  for (i=0; i<8; i++)
254
 
  {
255
 
    challenge[i] = buf2[i+24];
256
 
  }
257
 
 
258
 
        if (ntlmv2_enabled){ /* Generate NTLMv2 response */
259
 
                int tib_len;
260
 
 
261
 
                /* NTLMv2 hash */
262
 
                my_strupr((unsigned char *)strcpy(userdomain, username));
263
 
                if (strlen(username) + strlen(domain) < sizeof(userdomain))
264
 
                        strcat(userdomain, domain);
265
 
                else
266
 
                        msg (M_INFO, "Warning: Username or domain too long");
267
 
                unicodize (userdomain_u, userdomain);
268
 
                gen_hmac_md5(userdomain_u, 2 * strlen(userdomain), md4_hash, 16, ntlmv2_hash);
269
 
 
270
 
                /* NTLMv2 Blob */
271
 
                memset(ntlmv2_blob, 0, 128);                /* Clear blob buffer */ 
272
 
                ntlmv2_blob[0x00]=1;                        /* Signature */
273
 
                ntlmv2_blob[0x01]=1;                        /* Signature */
274
 
                ntlmv2_blob[0x04]=0;                        /* Reserved */
275
 
                gen_timestamp((unsigned char *)&ntlmv2_blob[0x08]);          /* 64-bit Timestamp */
276
 
                gen_nonce((unsigned char *)&ntlmv2_blob[0x10]);              /* 64-bit Client Nonce */
277
 
                ntlmv2_blob[0x18]=0;                        /* Unknown, zero should work */
278
 
 
279
 
                /* Add target information block to the blob */
280
 
                if (( *((long *)&buf2[0x14]) & 0x00800000) == 0x00800000){ /* Check for Target Information block */
281
 
                        tib_len = buf2[0x28];/* Get Target Information block size */
282
 
                        if (tib_len > 96) tib_len = 96;
283
 
                        {
284
 
                          char *tib_ptr = buf2 + buf2[0x2c]; /* Get Target Information block pointer */
285
 
                          memcpy(&ntlmv2_blob[0x1c], tib_ptr, tib_len); /* Copy Target Information block into the blob */
286
 
                        }
287
 
                } else {
288
 
                        tib_len = 0;
289
 
                }
290
 
 
291
 
                ntlmv2_blob[0x1c + tib_len] = 0;            /* Unknown, zero works */ 
292
 
 
293
 
                /* Get blob length */
294
 
                ntlmv2_blob_size = 0x20 + tib_len; 
295
 
 
296
 
                /* Add challenge from message 2 */
297
 
                memcpy(&ntlmv2_response[8], challenge, 8);
298
 
 
299
 
                /* hmac-md5 */
300
 
                gen_hmac_md5(&ntlmv2_response[8], ntlmv2_blob_size + 8, ntlmv2_hash, 16, ntlmv2_hmacmd5);
301
 
                
302
 
                /* Add hmac-md5 result to the blob */
303
 
                memcpy(ntlmv2_response, ntlmv2_hmacmd5, 16); /* Note: This overwrites challenge previously written at ntlmv2_response[8..15] */
304
 
        
305
 
        } else { /* Generate NTLM response */
306
 
 
307
 
                create_des_keys ((unsigned char *)md4_hash, key1);
308
 
                des_set_key_unchecked ((des_cblock *)key1, sched1);
309
 
                des_ecb_encrypt ((des_cblock *)challenge, (des_cblock *)ntlm_response, sched1, DES_ENCRYPT);
310
 
 
311
 
                create_des_keys ((unsigned char *)&(md4_hash[7]), key2);
312
 
                des_set_key_unchecked ((des_cblock *)key2, sched2);
313
 
                des_ecb_encrypt ((des_cblock *)challenge, (des_cblock *)&(ntlm_response[8]), sched2, DES_ENCRYPT);
314
 
 
315
 
                create_des_keys ((unsigned char *)&(md4_hash[14]), key3);
316
 
                des_set_key_unchecked ((des_cblock *)key3, sched3);
317
 
                des_ecb_encrypt ((des_cblock *)challenge, (des_cblock *)&(ntlm_response[16]), sched3, DES_ENCRYPT);
318
 
        }
319
 
        
320
 
        
321
 
        memset (phase3, 0, sizeof (phase3)); /* clear reply */
322
 
 
323
 
        strcpy ((char *)phase3, "NTLMSSP\0"); /* signature */
324
 
        phase3[8] = 3; /* type 3 */
325
 
 
326
 
        if (ntlmv2_enabled){ /* NTLMv2 response */
327
 
                add_security_buffer(0x14, ntlmv2_response, ntlmv2_blob_size + 16, phase3, &phase3_bufpos);
328
 
        }else{ /* NTLM response */
329
 
                add_security_buffer(0x14, ntlm_response, 24, phase3, &phase3_bufpos);
330
 
        }
331
 
        
332
 
        /* username in ascii */
333
 
        add_security_buffer(0x24, username, strlen (username), phase3, &phase3_bufpos);
334
 
 
335
 
        /* Set domain. If <domain> is empty, default domain will be used (i.e. proxy's domain) */ 
336
 
        add_security_buffer(0x1c, domain, strlen (domain), phase3, &phase3_bufpos);
337
 
        
338
 
 
339
 
        /* other security buffers will be empty */
340
 
        phase3[0x10] = phase3_bufpos; /* lm not used */
341
 
        phase3[0x30] = phase3_bufpos; /* no workstation name supplied */
342
 
        phase3[0x38] = phase3_bufpos; /* no session key */
343
 
        
344
 
        /* flags */
345
 
  phase3[0x3c] = 0x02; /* negotiate oem */
346
 
  phase3[0x3d] = 0x02; /* negotiate ntlm */
347
 
 
348
 
  return ((const char *)make_base64_string2 ((unsigned char *)phase3, phase3_bufpos, gc));
349
 
}
350
 
 
351
 
#else
352
 
static void dummy(void) {}
353
 
#endif