r889: convert samba4 to use [u]int16_t instead of [u]int16
[bbaumbach/samba-autobuild/.git] / source4 / rpc_server / remote / dcesrv_remote.c
1 /* 
2    Unix SMB/CIFS implementation.
3    remote dcerpc operations
4
5    Copyright (C) Stefan (metze) Metzmacher 2004
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 struct dcesrv_remote_private {
25         struct dcerpc_pipe *c_pipe;
26         void *private;  
27 };
28
29 static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
30 {
31         NTSTATUS status;
32         struct dcesrv_remote_private *private;
33         const char *binding = lp_parm_string(-1, "dcerpc_remote", "binding");
34
35         if (!binding) {
36                 printf("You must specify a ncacn binding string\n");
37                 return NT_STATUS_INVALID_PARAMETER;
38         }
39
40         private = talloc_p(dce_call->conn->mem_ctx, struct dcesrv_remote_private);
41         if (!private) {
42                 return NT_STATUS_NO_MEMORY;     
43         }
44
45         status = dcerpc_pipe_connect(&(private->c_pipe), binding, iface->ndr->uuid, iface->ndr->if_version,
46                                      lp_workgroup(), 
47                                      lp_parm_string(-1, "dcerpc_remote", "username"),
48                                      lp_parm_string(-1, "dcerpc_remote", "password"));
49
50         dce_call->conn->private = private;
51
52         return NT_STATUS_OK;    
53 }
54
55 static void remote_op_unbind(struct dcesrv_connection *dce_conn, const struct dcesrv_interface *iface)
56 {
57         struct dcesrv_remote_private *private = dce_conn->private;
58
59         dcerpc_pipe_close(private->c_pipe);
60
61         return; 
62 }
63
64 static NTSTATUS remote_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
65 {
66         struct dcesrv_remote_private *private = dce_call->conn->private;
67         NTSTATUS status;
68         uint16_t opnum = dce_call->pkt.u.request.opnum;
69         const char *name = dce_call->conn->iface->ndr->calls[opnum].name;
70         ndr_push_flags_fn_t ndr_push_fn = dce_call->conn->iface->ndr->calls[opnum].ndr_push;
71         ndr_pull_flags_fn_t ndr_pull_fn = dce_call->conn->iface->ndr->calls[opnum].ndr_pull;
72         ndr_print_function_t ndr_print_fn = dce_call->conn->iface->ndr->calls[opnum].ndr_print;
73         size_t struct_size = dce_call->conn->iface->ndr->calls[opnum].struct_size;
74
75         if (private->c_pipe->flags & DCERPC_DEBUG_PRINT_IN) {
76                 ndr_print_function_debug(ndr_print_fn, name, NDR_IN | NDR_SET_VALUES, r);               
77         }
78
79         status = dcerpc_ndr_request(private->c_pipe, opnum, mem_ctx,
80                                     (ndr_push_flags_fn_t) ndr_push_fn,
81                                     (ndr_pull_flags_fn_t) ndr_pull_fn,
82                                     r, struct_size);
83
84         if (!NT_STATUS_IS_OK(status)) {
85                 DEBUG(0,("dcesrv_remote: call[%s] failed with: %s!\n",name, nt_errstr(status)));
86                 return status;
87         }
88
89         if (NT_STATUS_IS_OK(status) && (private->c_pipe->flags & DCERPC_DEBUG_PRINT_OUT)) {
90                 ndr_print_function_debug(ndr_print_fn, name, NDR_OUT, r);               
91         }
92
93         return status;
94 }
95
96 static NTSTATUS remote_register_one_iface(struct dcesrv_context *dce_ctx, const struct dcesrv_interface *iface)
97 {
98         int i;
99
100         for (i=0;i<iface->ndr->endpoints->count;i++) {
101                 NTSTATUS ret;
102                 const char *name = iface->ndr->endpoints->names[i];
103
104                 ret = dcesrv_interface_register(dce_ctx, name, iface, NULL);
105                 if (!NT_STATUS_IS_OK(ret)) {
106                         DEBUG(1,("remote_op_init_server: failed to register endpoint '%s'\n",name));
107                         return ret;
108                 }
109         }
110
111         return NT_STATUS_OK;
112 }
113
114 static NTSTATUS remote_op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
115 {
116         int i;
117         char **ifaces = str_list_make(lp_parm_string(-1,"dcerpc_remote","interfaces"),NULL);
118
119         if (!ifaces) {
120                 DEBUG(3,("remote_op_init_server: no interfaces configured\n"));
121                 return NT_STATUS_OK;
122         }
123
124         for (i=0;ifaces[i];i++) {
125                 NTSTATUS ret;
126                 struct dcesrv_interface iface;
127                 
128                 if (!ep_server->interface_by_name(&iface, ifaces[i])) {
129                         DEBUG(0,("remote_op_init_server: failed to find interface = '%s'\n", ifaces[i]));
130                         str_list_free(&ifaces);
131                         return NT_STATUS_UNSUCCESSFUL;
132                 }
133
134                 ret = remote_register_one_iface(dce_ctx, &iface);
135                 if (!NT_STATUS_IS_OK(ret)) {
136                         DEBUG(0,("remote_op_init_server: failed to register interface = '%s'\n", ifaces[i]));
137                         str_list_free(&ifaces);
138                         return ret;
139                 }
140         }
141
142         str_list_free(&ifaces);
143         return NT_STATUS_OK;
144 }
145
146 static BOOL remote_fill_interface(struct dcesrv_interface *iface, const struct dcerpc_interface_table *if_tabl)
147 {
148         iface->ndr = if_tabl;
149
150         iface->bind = remote_op_bind;
151         iface->unbind = remote_op_unbind;
152         iface->dispatch = remote_op_dispatch;
153
154         return True;
155 }
156
157 static BOOL remote_op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32_t if_version)
158 {
159         int i;
160
161         for (i=0;dcerpc_pipes[i];i++) {
162                 if (dcerpc_pipes[i]->if_version == if_version &&
163                         strcmp(dcerpc_pipes[i]->uuid, uuid)==0) {
164                         return remote_fill_interface(iface, dcerpc_pipes[i]);
165                 }
166         }
167
168         return False;   
169 }
170
171 static BOOL remote_op_interface_by_name(struct dcesrv_interface *iface, const char *name)
172 {
173         int i;
174
175         for (i=0;dcerpc_pipes[i];i++) {
176                 if (strcmp(dcerpc_pipes[i]->name, name)==0) {
177                         return remote_fill_interface(iface, dcerpc_pipes[i]);
178                 }
179         }
180
181         return False;   
182 }
183
184 NTSTATUS dcerpc_remote_init(void)
185 {
186         NTSTATUS ret;
187         struct dcesrv_endpoint_server ep_server;
188
189         ZERO_STRUCT(ep_server);
190
191         /* fill in our name */
192         ep_server.name = "remote";
193
194         /* fill in all the operations */
195         ep_server.init_server = remote_op_init_server;
196
197         ep_server.interface_by_uuid = remote_op_interface_by_uuid;
198         ep_server.interface_by_name = remote_op_interface_by_name;
199
200         /* register ourselves with the DCERPC subsystem. */
201         ret = register_backend("dcerpc", &ep_server);
202         if (!NT_STATUS_IS_OK(ret)) {
203                 DEBUG(0,("Failed to register 'remote' endpoint server!\n"));
204                 return ret;
205         }
206
207         return ret;
208 }