Serious (and I *mean* serious) attempt to fix little/bigendian RPC issues.
[tprouty/samba.git] / source / lib / msrpc-client.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB msrpcent generic functions
5    Copyright (C) Andrew Tridgell 1994-1999
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
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; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #define NO_SYSLOG
24
25 #include "includes.h"
26
27 extern int DEBUGLEVEL;
28
29 /****************************************************************************
30   read an msrpc pdu from a fd. 
31   The timeout is in milliseconds. 
32 ****************************************************************************/
33 BOOL receive_msrpc(int fd, prs_struct *data, unsigned int timeout)
34 {
35         BOOL ok;
36         size_t len;
37         RPC_HDR hdr;
38
39         prs_init(data, 0, NULL, True);
40
41         ok = prs_read(data, fd, 16, timeout);
42
43         if (!ok)
44         {
45                 prs_mem_free(data);
46                 return False;
47         }
48
49         if (!smb_io_rpc_hdr("hdr", &hdr, data, 0))
50         {
51                 prs_mem_free(data);
52                 return False;
53         }
54
55         len = hdr.frag_len - 16;
56         if (len > 0)
57         {
58                 ok = prs_read(data, fd, hdr.frag_len, 0);
59                 if (!ok)
60                 {
61                         prs_mem_free(data);
62                         return False;
63                 }
64                 data->data_offset = hdr.frag_len;
65                 return True;
66         }
67
68         prs_mem_free(data);
69         return False;
70 }
71
72 /****************************************************************************
73   send an smb to a fd and re-establish if necessary
74 ****************************************************************************/
75 BOOL msrpc_send(int fd, prs_struct *ps)
76 {
77         size_t len = ps != NULL ? ps->buffer_size : 0;
78         size_t nwritten=0;
79         ssize_t ret;
80         char *outbuf = ps->data_p;
81
82         DEBUG(10,("msrpc_send_prs: data: %p len %d\n", outbuf, len));
83         dbgflush();
84
85         dump_data(10, outbuf, len);
86
87         while (nwritten < len)
88         {
89                 ret = write_socket(fd,outbuf+nwritten,len - nwritten);
90                 if (ret <= 0)
91                 {
92                         DEBUG(0,("Error writing %d msrpc bytes. %d.\n",
93                                  len,ret));
94                         prs_mem_free(ps);
95                         return False;
96                 }
97                 nwritten += ret;
98         }
99         
100         prs_mem_free(ps);
101         return True;
102 }
103
104 /****************************************************************************
105   receive msrpc packet
106 ****************************************************************************/
107 BOOL msrpc_receive(int fd, prs_struct *ps)
108 {
109         int len;
110
111         DEBUG(10,("msrpc_receive: %d\n", __LINE__));
112
113         if (!receive_msrpc(fd, ps, 0))
114         {
115                 return False;
116         }
117
118         len = ps->buffer_size;
119
120         if (ps->data_p == NULL || len <= 0)
121         {
122                 return False;
123         }
124
125         dump_data(10, ps->data_p, len);
126
127         DEBUG(10,("msrpc_receive: len %d\n", len));
128
129         return True;
130 }
131
132 /****************************************************************************
133 open the msrpcent sockets
134 ****************************************************************************/
135 BOOL msrpc_connect(struct msrpc_state *msrpc, const char *pipe_name)
136 {
137         fstring path;
138         slprintf(path, sizeof(path)-1, "%s/.msrpc/%s", LOCKDIR, pipe_name);
139
140         fstrcpy(msrpc->pipe_name, pipe_name);
141         
142         msrpc->fd = open_pipe_sock(path);
143
144         if (msrpc->fd == -1)
145         {
146                 return False;
147         }
148
149         return True;
150 }
151
152
153 /****************************************************************************
154 initialise a msrpcent structure
155 ****************************************************************************/
156 void msrpc_init_creds(struct msrpc_state *msrpc, const struct user_creds *usr)
157 {
158         copy_user_creds(&msrpc->usr, usr);
159 }
160
161 /****************************************************************************
162 close the socket descriptor
163 ****************************************************************************/
164 void msrpc_close_socket(struct msrpc_state *msrpc)
165 {
166         if (msrpc->fd != -1) 
167         {
168                 close(msrpc->fd);
169         }
170         msrpc->fd = -1;
171 }
172
173
174 /****************************************************************************
175 set socket options on a open connection
176 ****************************************************************************/
177 void msrpc_sockopt(struct msrpc_state *msrpc, char *options)
178 {
179         set_socket_options(msrpc->fd, options);
180 }
181
182
183 static BOOL msrpc_authenticate(struct msrpc_state *msrpc,
184                                struct user_creds *usr)
185 {
186         struct msrpc_state msrpc_redir;
187
188         int sock = msrpc->fd;
189         char *data;
190         prs_struct ps;
191         uint32 len;
192         char *in = msrpc->inbuf;
193         char *out = msrpc->outbuf;
194         uint16 command;
195
196         command = usr != NULL ? AGENT_CMD_CON : AGENT_CMD_CON_ANON;
197
198         if (!create_user_creds(&ps, msrpc->pipe_name, 0x0, command,
199                                 msrpc->pid, usr))
200         {
201                 DEBUG(0,("could not parse credentials\n"));
202                 close(sock);
203                 return False;
204         }
205
206         len = ps.data_offset;
207         data = ps.data_p;
208
209         SIVAL(data, 0, len);
210
211 #ifdef DEBUG_PASSWORD
212         DEBUG(100,("data len: %d\n", len));
213         dump_data(100, data, len);
214 #endif
215
216         if (write(sock, data, len) <= 0)
217         {
218                 DEBUG(0,("write failed\n"));
219                 return False;
220         }
221
222         if (msrpc->redirect)
223         {
224                 len = read(sock, &msrpc_redir, sizeof(msrpc_redir));
225
226                 if (len != sizeof(msrpc_redir))
227                 {
228                         DEBUG(0,("read failed\n"));
229                         return False;
230                 }
231                 
232                 memcpy(msrpc, &msrpc_redir, sizeof(msrpc_redir));
233                 msrpc->inbuf = in;
234                 msrpc->outbuf = out;
235                 msrpc->fd = sock;
236                 msrpc->usr.reuse = False;
237         }
238         else
239         {
240                 uint32 status;
241                 len = read(sock, &status, sizeof(status));
242
243                 return len == sizeof(status) && status == 0x0;
244         }
245         return True;
246 }
247
248 static BOOL msrpc_init_redirect(struct msrpc_state *msrpc,
249                                 const char* pipe_name,
250                                 struct user_creds *usr)
251 {
252         int sock;
253         fstring path;
254
255         slprintf(path, sizeof(path)-1, "/tmp/.msrpc/.%s/agent", pipe_name);
256
257         sock = open_pipe_sock(path);
258
259         if (sock < 0)
260         {
261                 return False;
262         }
263
264         msrpc->fd = sock;
265
266         if (!msrpc_authenticate(msrpc, usr))
267         {
268                 DEBUG(0,("authenticate failed\n"));
269                 close(msrpc->fd);
270                 msrpc->fd = -1;
271                 return False;
272         }
273
274         return True;
275 }
276
277 BOOL msrpc_connect_auth(struct msrpc_state *msrpc,
278                                 uint32 pid,
279                                 const char* pipename,
280                                 const struct user_creds *usr)
281 {
282         ZERO_STRUCTP(msrpc);
283         if (!msrpc_initialise(msrpc, pid))
284         {
285                 DEBUG(0,("unable to initialise msrpcent connection.\n"));
286                 return False;
287         }
288
289         msrpc_init_creds(msrpc, usr);
290
291         if (!msrpc_establish_connection(msrpc, pipename))
292         {
293                 msrpc_shutdown(msrpc);
294                 return False;
295         }
296
297         return True;
298 }
299
300 /****************************************************************************
301 initialise a msrpcent structure
302 ****************************************************************************/
303 struct msrpc_state *msrpc_initialise(struct msrpc_state *msrpc, uint32 pid)
304 {
305         if (!msrpc) {
306                 msrpc = (struct msrpc_state *)malloc(sizeof(*msrpc));
307                 if (!msrpc)
308                         return NULL;
309                 ZERO_STRUCTP(msrpc);
310         }
311
312         if (msrpc->initialised) {
313                 msrpc_shutdown(msrpc);
314         }
315
316         ZERO_STRUCTP(msrpc);
317
318         msrpc->fd = -1;
319         msrpc->outbuf = (char *)malloc(CLI_BUFFER_SIZE+4);
320         msrpc->inbuf = (char *)malloc(CLI_BUFFER_SIZE+4);
321         if (!msrpc->outbuf || !msrpc->inbuf)
322         {
323                 return False;
324         }
325
326         msrpc->initialised = 1;
327         msrpc_init_creds(msrpc, NULL);
328         msrpc->pid = pid;
329
330         return msrpc;
331 }
332
333
334 /****************************************************************************
335 shutdown a msrpcent structure
336 ****************************************************************************/
337 void msrpc_shutdown(struct msrpc_state *msrpc)
338 {
339         DEBUG(10,("msrpc_shutdown\n"));
340         if (msrpc->outbuf)
341         {
342                 free(msrpc->outbuf);
343         }
344         if (msrpc->inbuf)
345         {
346                 free(msrpc->inbuf);
347         }
348         msrpc_close_socket(msrpc);
349         memset(msrpc, 0, sizeof(*msrpc));
350 }
351
352 /****************************************************************************
353 establishes a connection right up to doing tconX, reading in a password.
354 ****************************************************************************/
355 BOOL msrpc_establish_connection(struct msrpc_state *msrpc,
356                 const char *pipe_name)
357 {
358         DEBUG(5,("msrpc_establish_connection: connecting to %s (%s) - %s\n",
359                           pipe_name,
360                       msrpc->usr.ntc.user_name, msrpc->usr.ntc.domain));
361
362         /* establish connection */
363
364         if ((!msrpc->initialised))
365         {
366                 return False;
367         }
368
369         if (msrpc->fd == -1 && msrpc->redirect)
370         {
371                 if (msrpc_init_redirect(msrpc, pipe_name, &msrpc->usr))
372                 {
373                         DEBUG(10,("msrpc_establish_connection: redirected OK\n"));
374                         return True;
375                 }
376                 else
377                 {
378                         DEBUG(10,("redirect FAILED\n"));
379                         return False;
380                 }
381         }
382         if (msrpc->fd == -1)
383         {
384                 if (!msrpc_connect(msrpc, pipe_name))
385                 {
386                         DEBUG(1,("msrpc_establish_connection: failed %s)\n",
387                                 pipe_name));
388                                           
389                         return False;
390                 }
391         }
392
393         if (!msrpc_authenticate(msrpc, &msrpc->usr))
394         {
395                 DEBUG(0,("authenticate failed\n"));
396                 close(msrpc->fd);
397                 msrpc->fd = -1;
398                 return False;
399         }
400
401         return True;
402 }
403