preparing for release of alpha-2.6
[Samba/gbeck.git] / source / rpc_client / cli_pipe_netsec.c
blob8b796e48ba88e15440ba32739ecc1528fdb93852
1 /*
2 * Unix SMB/Netbios implementation.
3 * Version 1.9.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
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.
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.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "rpc_parse.h"
25 #include "rpc_client.h"
27 extern int DEBUGLEVEL;
29 /****************************************************************************
30 decrypt data on an rpc pipe
31 ****************************************************************************/
32 static BOOL decode_netsec_pdu(struct cli_connection *con,
33 prs_struct *rdata, int len, int auth_len)
35 RPC_AUTH_NETSEC_CHK chk;
36 RPC_HDR_AUTH auth_info;
37 int data_len = len - 0x18 - auth_len - 8;
38 char *reply_data = prs_data(rdata, 0x18);
39 uint32 old_offset;
41 netsec_auth_struct *a;
42 a = (netsec_auth_struct *)cli_conn_get_auth_info(con);
44 if (a == NULL)
46 return False;
49 DEBUG(5,("decode_netsec_pdu: len: %d auth_len: %d\n",
50 len, auth_len));
52 if (reply_data == NULL) return False;
54 if (auth_len != 0x20 )
56 return False;
59 /*** skip the data, record the offset so we can restore it again */
60 old_offset = rdata->offset;
62 rdata->offset = data_len + 0x18;
63 smb_io_rpc_hdr_auth("hdr_auth", &auth_info, rdata, 0);
64 if (!rpc_hdr_netsec_auth_chk(&(auth_info)))
66 return False;
69 smb_io_rpc_auth_netsec_chk("auth_sign", &chk, rdata, 0);
71 if (!netsec_decode(a, &chk, reply_data, data_len))
73 return False;
76 a->seq_num++;
78 /* restore the [data, now decoded] offset */
79 rdata->offset = old_offset;
81 return True;
84 /****************************************************************************
85 send a request on an rpc pipe.
86 ****************************************************************************/
87 static BOOL create_netsec_pdu(struct cli_connection *con,
88 uint8 op_num,
89 prs_struct *data, int data_start, int *data_end,
90 prs_struct *dataa,
91 uint8 *flags)
93 prs_struct data_t;
94 prs_struct hdr;
95 prs_struct hdr_auth;
96 prs_struct auth_verf;
97 int data_len;
98 int frag_len;
99 int auth_len;
100 char *d = prs_data(data, data_start);
101 struct ntdom_info *nt = cli_conn_get_ntinfo(con);
102 netsec_auth_struct *a = NULL;
103 BOOL ret;
104 RPC_HDR_AUTH auth_info;
105 RPC_AUTH_NETSEC_CHK verf;
106 uchar sign[8];
107 static const uchar netsec_sig[8] = NETSEC_SIGNATURE;
109 a = (netsec_auth_struct *)cli_conn_get_auth_info(con);
110 if (a == NULL)
112 return False;
115 *flags = 0;
117 auth_len = 0x20;
118 data_len = data->offset - data_start;
120 if (data_start == 0)
122 (*flags) |= RPC_FLG_FIRST;
125 if (data_len > nt->max_recv_frag)
127 data_len = nt->max_recv_frag - auth_len - 8 - 0x18;
129 else
131 (*flags) |= RPC_FLG_LAST;
134 (*data_end) += data_len;
136 /* happen to know that NETSEC authentication verifier is 16 bytes */
137 frag_len = data_len + auth_len + 8 + 0x18;
139 prs_init(&data_t , 0 , 4, False);
140 prs_init(&hdr , frag_len, 4, False);
141 prs_init(&hdr_auth , 0 , 4, False);
142 prs_init(&auth_verf, auth_len, 4, False);
144 prs_append_data(&data_t, d, data_len);
145 data_t.end = data_t.data_size;
146 data_t.offset = data_t.data_size;
148 create_rpc_request(&hdr, nt->key.vuid, op_num, (*flags),
149 frag_len, auth_len);
151 DEBUG(5,("create_netsec_reply: data %d auth %d\n",
152 data_len, auth_len));
154 make_rpc_hdr_auth(&auth_info, 0x44, 0x06, 0x0, 1);
155 smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &hdr_auth, 0);
157 memset(sign, 0, sizeof(sign));
158 sign[4] = 0x80;
160 make_rpc_auth_netsec_chk(&verf, netsec_sig, NULL, sign, NULL);
162 ret = netsec_encode(a, &verf, prs_data(&data_t, 0),
163 prs_buf_len(&data_t));
165 if (ret)
167 smb_io_rpc_auth_netsec_chk("auth_sign", &verf, &auth_verf, 0);
170 if (ret)
172 prs_link(NULL , &hdr , &data_t );
173 prs_link(&hdr , &data_t , &hdr_auth );
174 prs_link(&data_t , &hdr_auth , &auth_verf);
175 prs_link(&hdr_auth, &auth_verf, NULL );
177 prs_init(dataa, 0, 4, False);
178 ret = prs_copy(dataa, &hdr);
181 prs_free_data(&hdr_auth );
182 prs_free_data(&data_t );
183 prs_free_data(&auth_verf);
184 prs_free_data(&hdr );
186 return True;
189 /*******************************************************************
190 creates a DCE/RPC bind request
192 - initialises the parse structure.
193 - dynamically allocates the header data structure
194 - caller is expected to free the header data structure once used.
196 ********************************************************************/
197 static BOOL create_netsec_bind_req(struct cli_connection *con,
198 prs_struct *data,
199 uint32 rpc_call_id,
200 RPC_IFACE *abstract, RPC_IFACE *transfer)
202 prs_struct rhdr;
203 prs_struct rhdr_rb;
204 prs_struct rhdr_auth;
205 prs_struct auth_req;
207 RPC_HDR_RB hdr_rb;
208 RPC_HDR hdr;
209 RPC_HDR_AUTH hdr_auth;
210 RPC_AUTH_VERIFIER auth_verifier;
211 RPC_AUTH_NETSEC_NEG netsec_neg;
213 struct ntdom_info *nt = cli_conn_get_ntinfo(con);
214 netsec_auth_struct *a;
215 struct netsec_creds *usr;
216 usr = (struct netsec_creds*)cli_conn_get_auth_creds(con);
218 prs_init(&rhdr , 0x0, 4, False);
219 prs_init(&rhdr_rb , 0x0, 4, False);
220 prs_init(&rhdr_auth, 0x0, 4, False);
221 prs_init(&auth_req , 0x0, 4, False);
223 /* create the bind request RPC_HDR_RB */
224 make_rpc_hdr_rb(&hdr_rb, 0x1630, 0x1630, nt->key.pid,
225 0x1, nt->key.vuid, 0x1, abstract, transfer);
227 /* stream the bind request data */
228 smb_io_rpc_hdr_rb("", &hdr_rb, &rhdr_rb, 0);
230 make_rpc_hdr_auth(&hdr_auth, 0x44, 0x06, 0x00, 1);
231 smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &rhdr_auth, 0);
233 make_rpc_auth_verifier(&auth_verifier, "", 0x3);
235 smb_io_rpc_auth_verifier("auth_verifier", &auth_verifier, &auth_req, 0);
237 make_rpc_auth_netsec_neg(&netsec_neg, usr->domain, usr->myname);
239 smb_io_rpc_auth_netsec_neg("netsec_neg", &netsec_neg, &auth_req, 0);
241 /* create the request RPC_HDR */
242 make_rpc_hdr(&hdr, RPC_BIND, 0x0, rpc_call_id,
243 auth_req .offset + rhdr_auth.offset +
244 rhdr_rb.offset + 0x10,
245 auth_req .offset);
247 smb_io_rpc_hdr("hdr" , &hdr , &rhdr, 0);
249 if (rhdr.data == NULL || rhdr_rb.data == NULL) return False;
251 /***/
252 /*** link rpc header, bind ack and auth responses ***/
253 /***/
255 prs_link(NULL , &rhdr , &rhdr_rb );
256 prs_link(&rhdr , &rhdr_rb , &rhdr_auth);
257 prs_link(&rhdr_rb , &rhdr_auth , &auth_req );
258 prs_link(&rhdr_auth, &auth_req , NULL );
260 prs_init(data, prs_buf_len(&rhdr), 4, False);
261 prs_buf_copy(data->data, &rhdr, 0, prs_buf_len(&rhdr));
263 prs_free_data(&rhdr );
264 prs_free_data(&rhdr_rb );
265 prs_free_data(&rhdr_auth);
266 prs_free_data(&auth_req );
268 a = malloc(sizeof(struct netsec_auth_struct));
269 if (a == NULL)
271 return False;
274 memcpy(a->sess_key, usr->sess_key, sizeof(a->sess_key));
276 if (!cli_conn_set_auth_info(con, (void*)a))
278 free(a);
279 return False;
281 return True;
284 static BOOL decode_netsec_bind_resp(struct cli_connection *con,
285 prs_struct *rdata)
287 BOOL valid_ack = True;
288 netsec_auth_struct *a;
289 a = (netsec_auth_struct *)cli_conn_get_auth_info(con);
291 if (a == NULL)
293 return False;
296 if (valid_ack)
298 RPC_HDR_AUTH rhdr_auth;
299 smb_io_rpc_hdr_auth("", &rhdr_auth, rdata, 0);
300 if (rdata->offset == 0 ||
301 !rpc_hdr_netsec_auth_chk(&rhdr_auth))
303 valid_ack = False;
306 if (valid_ack)
308 RPC_AUTH_VERIFIER rhdr_verf;
309 smb_io_rpc_auth_verifier("", &rhdr_verf, rdata, 0);
310 if (rdata->offset == 0 ||
311 !rpc_auth_verifier_chk(&rhdr_verf, "\001", 0))
313 valid_ack = False;
316 if (valid_ack)
318 RPC_AUTH_NETSEC_RESP rresp;
319 smb_io_rpc_auth_netsec_resp("", &rresp, rdata, 0);
320 if (rdata->offset == 0) valid_ack = False;
322 return valid_ack;
325 cli_auth_fns cli_netsec_fns =
327 create_netsec_bind_req,
328 decode_netsec_bind_resp,
329 NULL,
330 create_netsec_pdu,
331 decode_netsec_pdu