~ubuntu-branches/ubuntu/trusty/libesmtp/trusty-proposed

« back to all changes in this revision

Viewing changes to ntlm/ntlmstruct.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy T. Bouse
  • Date: 2002-03-06 08:37:48 UTC
  • Revision ID: james.westby@ubuntu.com-20020306083748-ihmt32mddsslvg5i
Tags: upstream-0.8.11
ImportĀ upstreamĀ versionĀ 0.8.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Authentication module for the Micr$oft NTLM mechanism.
 
3
 *
 
4
 *  This file is part of libESMTP, a library for submission of RFC 2822
 
5
 *  formatted electronic mail messages using the SMTP protocol described
 
6
 *  in RFC 2821.
 
7
 *
 
8
 *  Copyright (C) 2002  Brian Stafford  <brian@stafford.uklinux.net>
 
9
 *
 
10
 *  This library is free software; you can redistribute it and/or
 
11
 *  modify it under the terms of the GNU Lesser General Public
 
12
 *  License as published by the Free Software Foundation; either
 
13
 *  version 2.1 of the License, or (at your option) any later version.
 
14
 *
 
15
 *  This library is distributed in the hope that it will be useful,
 
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
 *  Lesser General Public License for more details.
 
19
 *
 
20
 *  You should have received a copy of the GNU Lesser General Public
 
21
 *  License along with this library; if not, write to the Free Software
 
22
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
23
 */
 
24
#if HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include <stdlib.h>
 
29
#include <string.h>
 
30
#include <assert.h>
 
31
#ifdef WORDS_BIGENDIAN
 
32
#include <byteswap.h>
 
33
#endif
 
34
 
 
35
/* Must have at least 32 bits in an int (at least pending a more thorough
 
36
   code review - this module is still experimental) */
 
37
#if SIZEOF_UNSIGNED_INT < 32 / 8
 
38
# error "unsigned int is less than 32 bits wide"
 
39
#endif
 
40
 
 
41
#if SIZEOF_UNSIGNED_SHORT == 16 / 8
 
42
typedef unsigned short unsigned16_t;
 
43
#else
 
44
#include <sys/types.h>
 
45
typedef uint16 unsigned16_t;
 
46
#endif
 
47
 
 
48
#if SIZEOF_UNSIGNED_INT == 32 / 8
 
49
typedef unsigned int unsigned32_t;
 
50
#elif SIZEOF_UNSIGNED_LONG == 32 / 8
 
51
typedef unsigned long unsigned32_t;
 
52
#else
 
53
#include <sys/types.h>
 
54
typedef uint32 unsigned32_t;
 
55
#endif
 
56
 
 
57
#include "ntlm.h"
 
58
 
 
59
static void
 
60
write_uint16 (char *buf, size_t offset, unsigned int value)
 
61
{
 
62
  unsigned16_t i16 = value;
 
63
 
 
64
  assert (sizeof i16 == 2);
 
65
#ifdef WORDS_BIGENDIAN
 
66
  i16 = bswap_16 (i16);
 
67
#endif
 
68
  memcpy (buf + offset, &i16, sizeof i16);
 
69
}
 
70
 
 
71
static inline void
 
72
write_uint32 (char *buf, size_t offset, unsigned int value)
 
73
{
 
74
  unsigned32_t i32 = value;
 
75
 
 
76
  assert (sizeof i32 == 4);
 
77
#ifdef WORDS_BIGENDIAN
 
78
  i32 = bswap_32 (i32);
 
79
#endif
 
80
  memcpy (buf + offset, &i32, sizeof i32);
 
81
}
 
82
 
 
83
static inline unsigned int
 
84
read_uint16 (const char *buf, size_t offset)
 
85
{
 
86
  unsigned16_t i16;
 
87
 
 
88
  assert (sizeof i16 == 2);
 
89
  memcpy (&i16, buf + offset, sizeof i16);
 
90
#ifdef WORDS_BIGENDIAN
 
91
  i16 = bswap_16 (i16);
 
92
#endif
 
93
  return i16;
 
94
}
 
95
 
 
96
static inline unsigned int
 
97
read_uint32 (const char *buf, size_t offset)
 
98
{
 
99
  unsigned32_t i32;
 
100
 
 
101
  assert (sizeof i32 == 4);
 
102
  memcpy (&i32, buf + offset, sizeof i32);
 
103
#ifdef WORDS_BIGENDIAN
 
104
  i32 = bswap_32 (i32);
 
105
#endif
 
106
  return i32;
 
107
}
 
108
 
 
109
static inline void
 
110
write_string (char *buf, size_t offset, size_t *str_offset,
 
111
              const void *data, size_t len)
 
112
{
 
113
  if (data == NULL)
 
114
    len = 0;
 
115
  write_uint16 (buf, offset, len);
 
116
  write_uint16 (buf, offset + 2, len);
 
117
  write_uint32 (buf, offset + 4, *str_offset);
 
118
  if (len > 0)
 
119
    memcpy (buf + *str_offset, data, len);
 
120
  *str_offset += len;
 
121
}
 
122
 
 
123
/* Offsets into on-the-wire NTLM structures */
 
124
#define PROTOCOL                        0       /* "NTLMSSP" */
 
125
#define MSGTYPE                         8       /* 1..3 */
 
126
/* Type 1 fields */
 
127
#define T1FLAGS                         12      /* 0xb203 */
 
128
#define T1DOMAIN                        16      /* domain to authenticate in */
 
129
#define T1WKSTN                         24      /* client workstation name */
 
130
#define T1SIZE                          32
 
131
/* Type 2 fields */
 
132
#define T2AUTHTARGET                    12      /* domain/server */
 
133
#define T2FLAGS                         20      /* 0x8201 */
 
134
#define T2NONCE                         24      /* server challenge */
 
135
#define T2RESERVED                      32
 
136
#define T2SIZE                          40
 
137
/* Type 3 fields */
 
138
#define T3LMRESPONSE                    12      /* lanmanager hash */
 
139
#define T3NTRESPONSE                    20      /* nt hash */
 
140
#define T3DOMAIN                        28      /* domain to authenticate against */
 
141
#define T3USER                          36      /* user name */
 
142
#define T3WKSTN                         44      /* client workstation name */
 
143
#define T3SESSIONKEY                    52      /* client workstation name */
 
144
#define T3FLAGS                         60      /* 0xb203 */
 
145
#define T3SIZE                          64
 
146
 
 
147
static const char NTLMSSP[] = "NTLMSSP";
 
148
 
 
149
/* Build a NTLM type 1 structure in the buffer.
 
150
        domain - the NT domain the workstation belongs to
 
151
   workstation - the NT (netbios) name of the workstation */
 
152
size_t
 
153
ntlm_build_type_1 (char *buf, size_t buflen,
 
154
                   const char *domain, const char *workstation)
 
155
{
 
156
  size_t offset = T1SIZE;
 
157
  size_t len;
 
158
  unsigned char *up;
 
159
  char string[256];
 
160
 
 
161
  if (buflen < offset)
 
162
    return 0;
 
163
  memcpy (buf, NTLMSSP, 8);
 
164
  write_uint32 (buf, MSGTYPE, 1);
 
165
  write_uint32 (buf, T1FLAGS, 0xB203);
 
166
  up = NULL;
 
167
  len = 0;
 
168
  if (domain != NULL)
 
169
    {
 
170
      len = strlen (domain);
 
171
      if (offset + len > buflen)
 
172
        return 0;
 
173
      lm_uccpy (string, len, domain);
 
174
    }
 
175
  write_string (buf, T1DOMAIN, &offset, string, len);
 
176
  up = NULL;
 
177
  len = 0;
 
178
  if (workstation != NULL)
 
179
    {
 
180
      len = strlen (workstation);
 
181
      if (offset + len > buflen)
 
182
        return 0;
 
183
      lm_uccpy (string, len, workstation);
 
184
    }
 
185
  write_string (buf, T1WKSTN, &offset, string, len);
 
186
  return offset;
 
187
}
 
188
 
 
189
/* Build a NTLM type 2 structure in the buffer */
 
190
size_t
 
191
ntlm_build_type_2 (char *buf, size_t buflen,
 
192
                   const unsigned char *nonce, const char *domain)
 
193
{
 
194
  size_t offset = T2SIZE;
 
195
  size_t len;
 
196
  char string[256];
 
197
  unsigned char *up;
 
198
 
 
199
  if (buflen < offset)
 
200
    return 0;
 
201
  memcpy (buf, NTLMSSP, 8);
 
202
  write_uint32 (buf, MSGTYPE, 2);
 
203
  up = NULL;
 
204
  len = 0;
 
205
  if (domain != NULL)
 
206
    {
 
207
      len = strlen (domain);
 
208
      if (offset + 2 * len > buflen)
 
209
        return 0;
 
210
      up = nt_unicode (lm_uccpy (string, len, domain), 2 * len);
 
211
    }
 
212
  write_string (buf, T2AUTHTARGET, &offset, up, len);
 
213
  if (up != NULL)
 
214
    free (up);
 
215
  write_uint32 (buf, T2FLAGS, 0x8201);
 
216
  memcpy (buf + T2NONCE, nonce, 8);
 
217
  memset (buf + T2RESERVED, 0, 8);
 
218
  return offset;
 
219
}
 
220
 
 
221
/* Build a NTLM type 3 structure in the buffer */
 
222
size_t
 
223
ntlm_build_type_3 (char *buf, size_t buflen,
 
224
                   const unsigned char *lm_resp, const unsigned char *nt_resp,
 
225
                   const char *domain, const char *user, const char *workstation)
 
226
{
 
227
  size_t offset = T3SIZE;
 
228
  size_t len;
 
229
  char string[256];
 
230
  unsigned char *up;
 
231
 
 
232
  if (buflen + 24 + 24 < offset)
 
233
    return 0;
 
234
  memcpy (buf, NTLMSSP, 8);
 
235
  write_uint32 (buf, MSGTYPE, 3);
 
236
  write_string (buf, T3LMRESPONSE, &offset, lm_resp, 24);
 
237
  write_string (buf, T3NTRESPONSE, &offset, nt_resp, 24);
 
238
  up = NULL;
 
239
  len = 0;
 
240
  if (domain != NULL)
 
241
    {
 
242
      len = strlen (domain);
 
243
      if (offset + 2 * len > buflen)
 
244
        return 0;
 
245
      up = nt_unicode (lm_uccpy (string, len, domain), 2 * len);
 
246
    }
 
247
  write_string (buf, T3DOMAIN, &offset, up, 2 * len);
 
248
  if (up != NULL)
 
249
    free (up);
 
250
  up = NULL;
 
251
  len = 0;
 
252
  if (user != NULL)
 
253
    {
 
254
      len = strlen (user);
 
255
      if (offset + 2 * len > buflen)
 
256
        return 0;
 
257
      up = nt_unicode (lm_uccpy (string, len, user), 2 * len);
 
258
    }
 
259
  write_string (buf, T3USER, &offset, up, 2 * len);
 
260
  if (up != NULL)
 
261
    free (up);
 
262
  up = NULL;
 
263
  len = 0;
 
264
  if (workstation != NULL)
 
265
    {
 
266
      len = strlen (workstation);
 
267
      if (offset + 2 * len > buflen)
 
268
        return 0;
 
269
      up = nt_unicode (lm_uccpy (string, len, workstation), 2 * len);
 
270
    }
 
271
  write_string (buf, T3WKSTN, &offset, up, 2 * len);
 
272
  if (up != NULL)
 
273
    free (up);
 
274
  write_string (buf, T3SESSIONKEY, &offset, NULL, 0);
 
275
  write_uint32 (buf, T3FLAGS, 0x8201);
 
276
  return offset;
 
277
}
 
278
 
 
279
/****/
 
280
 
 
281
/* Parse a NTLM type 2 structure in the buffer (partial implementation).
 
282
   Verify that the packet is a type 2 structure and copy the nonce to the
 
283
   supplied buffer (which must be eight bytes long) */
 
284
size_t
 
285
ntlm_parse_type_2 (const char *buf, size_t buflen,
 
286
                   unsigned char *nonce, char **domain)
 
287
{
 
288
  if (buflen < T2SIZE)
 
289
    return 0;
 
290
  if (memcmp (buf, NTLMSSP, 8) != 0)
 
291
    return 0;
 
292
  if (read_uint32 (buf, MSGTYPE) != 2)
 
293
    return 0;
 
294
  *domain = NULL;
 
295
  memcpy (nonce, buf + T2NONCE, 8);
 
296
  return 1;
 
297
}
 
298