3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
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.
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
,
46 if (neg
== NULL
) return False
;
48 fstrcpy(neg
->domain
, domain
);
49 fstrcpy(neg
->myname
, myname
);
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");
67 prs_string("domain", ps
, depth
, neg
->domain
, 0, sizeof(neg
->domain
));
68 prs_string("myname", ps
, depth
, neg
->myname
, 0, sizeof(neg
->myname
));
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
;
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");
105 prs_uint32("flags", ps
, depth
, &rsp
->flags
);
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
;
122 if (memcmp(chk
, netsec_sig
, 8) != 0)
129 /*******************************************************************
130 creates an RPC_AUTH_NETSEC_CHK structure.
131 ********************************************************************/
132 BOOL
make_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK
*chk
,
134 const uchar data1
[8],
135 const uchar data3
[8],
136 const uchar data8
[8])
138 if (chk
== NULL
) return False
;
142 memcpy(chk
->sig
, sig
, sizeof(chk
->sig
));
146 memcpy(chk
->data1
, data1
, sizeof(chk
->data1
));
150 memcpy(chk
->data3
, data3
, sizeof(chk
->data3
));
154 memcpy(chk
->data8
, data8
, sizeof(chk
->data8
));
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");
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
));
178 static void netsechash(uchar
*key
, uchar
*data
, int data_len
)
186 for (ind
= 0; ind
< 256; ind
++)
188 hash
[ind
] = (uchar
)ind
;
191 for( ind
= 0; ind
< 256; ind
++)
195 j
+= (hash
[ind
] + key
[ind
%16]);
202 for( ind
= 0; ind
< data_len
; ind
++)
208 index_j
+= hash
[index_i
];
211 hash
[index_i
] = hash
[index_j
];
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
)
226 struct MD5Context ctx3
;
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
));
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
);
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
));
289 BOOL
netsec_decode(struct netsec_auth_struct
*a
,
290 RPC_AUTH_NETSEC_CHK
*verf
,
291 char *data
, size_t data_len
)
295 struct MD5Context ctx3
;
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
));
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
);
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;