This commit was manufactured by cvs2svn to create branch 'SAMBA_TNG'.
[Samba.git] / source / rpc_parse / parse_netsec.c
blob43ad697afa53aa9ef0ba43b9a6c80449efba1b6b
2 /*
3 * Unix SMB/Netbios implementation.
4 * Version 1.9.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
26 #include "rpc_parse.h"
28 extern int DEBUGLEVEL;
31 /*******************************************************************
32 checks an RPC_HDR_AUTH structure.
33 ********************************************************************/
34 BOOL rpc_hdr_netsec_auth_chk(RPC_HDR_AUTH *rai)
36 return (rai->auth_type == 0x44 && rai->auth_level == 0x06);
39 /*******************************************************************
40 creates an RPC_AUTH_NETSEC_NEG structure.
41 ********************************************************************/
42 BOOL make_rpc_auth_netsec_neg(RPC_AUTH_NETSEC_NEG *neg,
43 fstring domain,
44 fstring myname)
46 if (neg == NULL) return False;
48 fstrcpy(neg->domain, domain);
49 fstrcpy(neg->myname, myname);
51 return True;
54 /*******************************************************************
55 reads or writes an RPC_AUTH_NETSEC_NEG structure.
57 *** lkclXXXX HACK ALERT! ***
59 ********************************************************************/
60 BOOL smb_io_rpc_auth_netsec_neg(char *desc, RPC_AUTH_NETSEC_NEG *neg, prs_struct *ps, int depth)
62 if (neg == NULL) return False;
64 prs_debug(ps, depth, desc, "smb_io_rpc_auth_netsec_neg");
65 depth++;
67 prs_string("domain", ps, depth, neg->domain, 0, sizeof(neg->domain));
68 prs_string("myname", ps, depth, neg->myname, 0, sizeof(neg->myname));
70 return True;
73 /*******************************************************************
74 creates an RPC_AUTH_NETSEC_RESP structure.
76 *** lkclXXXX FUDGE! HAVE TO MANUALLY SPECIFY OFFSET HERE (0x1c bytes) ***
77 *** lkclXXXX the actual offset is at the start of the auth verifier ***
79 ********************************************************************/
80 BOOL make_rpc_auth_netsec_resp(RPC_AUTH_NETSEC_RESP *rsp, uint32 flags)
82 DEBUG(5,("make_rpc_auth_netsec_resp\n"));
84 if (rsp == NULL) return False;
86 rsp->flags = flags;
88 return True;
91 /*******************************************************************
92 reads or writes an RPC_AUTH_NETSEC_RESP structure.
94 *** lkclXXXX FUDGE! HAVE TO MANUALLY SPECIFY OFFSET HERE (0x1c bytes) ***
95 *** lkclXXXX the actual offset is at the start of the auth verifier ***
97 ********************************************************************/
98 BOOL smb_io_rpc_auth_netsec_resp(char *desc, RPC_AUTH_NETSEC_RESP *rsp, prs_struct *ps, int depth)
100 if (rsp == NULL) return False;
102 prs_debug(ps, depth, desc, "smb_io_rpc_auth_netsec_resp");
103 depth++;
105 prs_uint32("flags", ps, depth, &rsp->flags);
107 return True;
110 /*******************************************************************
111 checks an RPC_AUTH_NETSEC_CHK structure.
112 ********************************************************************/
113 BOOL rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK *chk)
115 static const uchar netsec_sig[8] = NETSEC_SIGNATURE;
117 if (chk == NULL)
119 return False;
122 if (memcmp(chk, netsec_sig, 8) != 0)
124 return False;
126 return True;
129 /*******************************************************************
130 creates an RPC_AUTH_NETSEC_CHK structure.
131 ********************************************************************/
132 BOOL make_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK *chk,
133 const uchar sig[8],
134 const uchar data1[8],
135 const uchar data3[8],
136 const uchar data8[8])
138 if (chk == NULL) return False;
140 if (sig != NULL)
142 memcpy(chk->sig , sig , sizeof(chk->sig ));
144 if (data1 != NULL)
146 memcpy(chk->data1, data1, sizeof(chk->data1));
148 if (data3 != NULL)
150 memcpy(chk->data3, data3, sizeof(chk->data3));
152 if (data8 != NULL)
154 memcpy(chk->data8, data8, sizeof(chk->data8));
157 return True;
160 /*******************************************************************
161 reads or writes an RPC_AUTH_NETSEC_CHK structure.
162 ********************************************************************/
163 BOOL smb_io_rpc_auth_netsec_chk(char *desc, RPC_AUTH_NETSEC_CHK *chk, prs_struct *ps, int depth)
165 if (chk == NULL) return False;
167 prs_debug(ps, depth, desc, "smb_io_rpc_auth_netsec_chk");
168 depth++;
170 prs_uint8s(False, "sig ", ps, depth, chk->sig , sizeof(chk->sig ));
171 prs_uint8s(False, "data3", ps, depth, chk->data3, sizeof(chk->data3));
172 prs_uint8s(False, "data1", ps, depth, chk->data1, sizeof(chk->data1));
173 prs_uint8s(False, "data8", ps, depth, chk->data8, sizeof(chk->data8));
175 return True;
178 static void netsechash(uchar *key, uchar *data, int data_len)
180 uchar hash[256];
181 uchar index_i = 0;
182 uchar index_j = 0;
183 uchar j = 0;
184 int ind;
186 for (ind = 0; ind < 256; ind++)
188 hash[ind] = (uchar)ind;
191 for( ind = 0; ind < 256; ind++)
193 uchar tc;
195 j += (hash[ind] + key[ind%16]);
197 tc = hash[ind];
198 hash[ind] = hash[j];
199 hash[j] = tc;
202 for( ind = 0; ind < data_len; ind++)
204 uchar tc;
205 uchar t;
207 index_i++;
208 index_j += hash[index_i];
210 tc = hash[index_i];
211 hash[index_i] = hash[index_j];
212 hash[index_j] = tc;
214 t = hash[index_i] + hash[index_j];
215 data[ind] ^= hash[t];
220 BOOL netsec_encode(struct netsec_auth_struct *a,
221 RPC_AUTH_NETSEC_CHK *verf,
222 char *data, size_t data_len)
224 char dataN[4];
225 char digest1[16];
226 struct MD5Context ctx3;
227 uchar sess_kf0[16];
228 int i;
230 /* store the sequence number */
231 SIVAL(dataN, 0, a->seq_num);
233 for (i = 0; i < sizeof(sess_kf0); i++)
235 sess_kf0[i] = a->sess_key[i] ^ 0xf0;
238 dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key));
239 dump_data_pw("a->seq_num :\n", dataN, sizeof(dataN));
241 MD5Init(&ctx3);
242 MD5Update(&ctx3, dataN, 0x4);
243 MD5Update(&ctx3, verf->sig, 8);
245 MD5Update(&ctx3, verf->data8, 8);
247 dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8));
248 dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0));
250 hmac_md5(sess_kf0, dataN, 0x4, digest1 );
251 dump_data_pw("digest1 (ebp-8):\n", digest1, sizeof(digest1));
252 hmac_md5(digest1, verf->data3, 8, digest1);
253 dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1));
254 netsechash(digest1, verf->data8, 8);
256 dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8));
258 dump_data_pw("data :\n", data, data_len);
259 MD5Update(&ctx3, data, data_len);
262 char digest_tmp[16];
263 char digest2[16];
264 MD5Final(digest_tmp, &ctx3);
265 hmac_md5(a->sess_key, digest_tmp, 16, digest2);
266 dump_data_pw("digest_tmp:\n", digest_tmp, sizeof(digest_tmp));
267 dump_data_pw("digest:\n", digest2, sizeof(digest2));
268 memcpy(verf->data1, digest2, sizeof(verf->data1));
271 netsechash(digest1, data , data_len);
272 dump_data_pw("data:\n", data, data_len);
274 hmac_md5(a->sess_key, dataN , 0x4, digest1 );
275 dump_data_pw("ctx:\n", digest1, sizeof(digest1));
277 hmac_md5(digest1, verf->data1, 8, digest1);
279 dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1));
281 dump_data_pw("verf->data3:\n", verf->data3, sizeof(verf->data3));
282 netsechash(digest1, verf->data3, 8);
283 dump_data_pw("verf->data3:\n", verf->data3, sizeof(verf->data3));
286 return True;
289 BOOL netsec_decode(struct netsec_auth_struct *a,
290 RPC_AUTH_NETSEC_CHK *verf,
291 char *data, size_t data_len)
293 char dataN[4];
294 char digest1[16];
295 struct MD5Context ctx3;
296 uchar sess_kf0[16];
297 int i;
299 /* store the sequence number */
300 SIVAL(dataN, 0, a->seq_num);
302 for (i = 0; i < sizeof(sess_kf0); i++)
304 sess_kf0[i] = a->sess_key[i] ^ 0xf0;
307 dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key));
308 dump_data_pw("a->seq_num :\n", dataN, sizeof(dataN));
309 hmac_md5(a->sess_key, dataN , 0x4, digest1 );
310 dump_data_pw("ctx:\n", digest1, sizeof(digest1));
312 hmac_md5(digest1, verf->data1, 8, digest1);
314 dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1));
315 dump_data_pw("verf->data3:\n", verf->data3, sizeof(verf->data3));
316 netsechash(digest1, verf->data3, 8);
317 dump_data_pw("verf->data3_dec:\n", verf->data3, sizeof(verf->data3));
319 MD5Init(&ctx3);
320 MD5Update(&ctx3, dataN, 0x4);
321 MD5Update(&ctx3, verf->sig, 8);
323 dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0));
325 hmac_md5(sess_kf0, dataN, 0x4, digest1 );
326 dump_data_pw("digest1 (ebp-8):\n", digest1, sizeof(digest1));
327 hmac_md5(digest1, verf->data3, 8, digest1);
328 dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1));
330 dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8));
331 netsechash(digest1, verf->data8, 8);
332 dump_data_pw("verf->data8_dec:\n", verf->data8, sizeof(verf->data8));
333 MD5Update(&ctx3, verf->data8, 8);
335 dump_data_pw("data :\n", data, data_len);
336 netsechash(digest1, data , data_len);
337 dump_data_pw("datadec:\n", data, data_len);
339 MD5Update(&ctx3, data, data_len);
341 char digest_tmp[16];
342 MD5Final(digest_tmp, &ctx3);
343 hmac_md5(a->sess_key, digest_tmp, 16, digest1);
344 dump_data_pw("digest_tmp:\n", digest_tmp, sizeof(digest_tmp));
347 dump_data_pw("digest:\n", digest1, sizeof(digest1));
348 dump_data_pw("verf->data1:\n", verf->data1, sizeof(verf->data1));
350 return memcmp(digest1, verf->data1, sizeof(verf->data1)) == 0;