7bb461bd6f58f67567a67c18ab775a36f69a4fed
[gd/samba/.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 #include "rpc_server/dcerpc_server.h"
24 #include "librpc/gen_ndr/tables.h"
25
26 struct dcesrv_remote_private {
27         struct dcerpc_pipe *c_pipe;
28         void *private;  
29 };
30
31 static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
32 {
33         NTSTATUS status;
34         struct dcesrv_remote_private *private;
35         const char *binding = lp_parm_string(-1, "dcerpc_remote", "binding");
36
37         if (!binding) {
38                 printf("You must specify a ncacn binding string\n");
39                 return NT_STATUS_INVALID_PARAMETER;
40         }
41
42         private = talloc_p(dce_call->conn, struct dcesrv_remote_private);
43         if (!private) {
44                 return NT_STATUS_NO_MEMORY;     
45         }
46
47         status = dcerpc_pipe_connect(&(private->c_pipe), binding, iface->ndr->uuid, iface->ndr->if_version,
48                                      lp_workgroup(), 
49                                      lp_parm_string(-1, "dcerpc_remote", "username"),
50                                      lp_parm_string(-1, "dcerpc_remote", "password"));
51
52         dce_call->conn->private = private;
53
54         return NT_STATUS_OK;    
55 }
56
57 static void remote_op_unbind(struct dcesrv_connection *dce_conn, const struct dcesrv_interface *iface)
58 {
59         struct dcesrv_remote_private *private = dce_conn->private;
60
61         dcerpc_pipe_close(private->c_pipe);
62
63         return; 
64 }
65
66 static NTSTATUS remote_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
67 {
68         struct dcesrv_remote_private *private = dce_call->conn->private;
69         NTSTATUS status;
70         uint16_t opnum = dce_call->pkt.u.request.opnum;
71         const char *name = dce_call->conn->iface->ndr->calls[opnum].name;
72         ndr_push_flags_fn_t ndr_push_fn = dce_call->conn->iface->ndr->calls[opnum].ndr_push;
73         ndr_pull_flags_fn_t ndr_pull_fn = dce_call->conn->iface->ndr->calls[opnum].ndr_pull;
74         ndr_print_function_t ndr_print_fn = dce_call->conn->iface->ndr->calls[opnum].ndr_print;
75         size_t struct_size = dce_call->conn->iface->ndr->calls[opnum].struct_size;
76
77         if (private->c_pipe->flags & DCERPC_DEBUG_PRINT_IN) {
78                 ndr_print_function_debug(ndr_print_fn, name, NDR_IN | NDR_SET_VALUES, r);               
79         }
80
81         status = dcerpc_ndr_request(private->c_pipe, NULL, opnum, mem_ctx,
82                                     (ndr_push_flags_fn_t) ndr_push_fn,
83                                     (ndr_pull_flags_fn_t) ndr_pull_fn,
84                                     r, struct_size);
85
86         if (!NT_STATUS_IS_OK(status)) {
87                 DEBUG(0,("dcesrv_remote: call[%s] failed with: %s!\n",name, nt_errstr(status)));
88                 return status;
89         }
90
91         if (NT_STATUS_IS_OK(status) && (private->c_pipe->flags & DCERPC_DEBUG_PRINT_OUT)) {
92                 ndr_print_function_debug(ndr_print_fn, name, NDR_OUT, r);               
93         }
94
95         return status;
96 }
97
98 static NTSTATUS remote_register_one_iface(struct dcesrv_context *dce_ctx, const struct dcesrv_interface *iface)
99 {
100         int i;
101
102         for (i=0;i<iface->ndr->endpoints->count;i++) {
103                 NTSTATUS ret;
104                 const char *name = iface->ndr->endpoints->names[i];
105
106                 ret = dcesrv_interface_register(dce_ctx, name, iface, NULL);
107                 if (!NT_STATUS_IS_OK(ret)) {
108                         DEBUG(1,("remote_op_init_server: failed to register endpoint '%s'\n",name));
109                         return ret;
110                 }
111         }
112
113         return NT_STATUS_OK;
114 }
115
116 static NTSTATUS remote_op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
117 {
118         int i;
119         char **ifaces = str_list_make(lp_parm_string(-1,"dcerpc_remote","interfaces"),NULL);
120
121         if (!ifaces) {
122                 DEBUG(3,("remote_op_init_server: no interfaces configured\n"));
123                 return NT_STATUS_OK;
124         }
125
126         for (i=0;ifaces[i];i++) {
127                 NTSTATUS ret;
128                 struct dcesrv_interface iface;
129                 
130                 if (!ep_server->interface_by_name(&iface, ifaces[i])) {
131                         DEBUG(0,("remote_op_init_server: failed to find interface = '%s'\n", ifaces[i]));
132                         str_list_free(&ifaces);
133                         return NT_STATUS_UNSUCCESSFUL;
134                 }
135
136                 ret = remote_register_one_iface(dce_ctx, &iface);
137                 if (!NT_STATUS_IS_OK(ret)) {
138                         DEBUG(0,("remote_op_init_server: failed to register interface = '%s'\n", ifaces[i]));
139                         str_list_free(&ifaces);
140                         return ret;
141                 }
142         }
143
144         str_list_free(&ifaces);
145         return NT_STATUS_OK;
146 }
147
148 static BOOL remote_fill_interface(struct dcesrv_interface *iface, const struct dcerpc_interface_table *if_tabl)
149 {
150         iface->ndr = if_tabl;
151
152         iface->bind = remote_op_bind;
153         iface->unbind = remote_op_unbind;
154         iface->dispatch = remote_op_dispatch;
155
156         return True;
157 }
158
159 static BOOL remote_op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32_t if_version)
160 {
161         int i;
162
163         for (i=0;dcerpc_pipes[i];i++) {
164                 if (dcerpc_pipes[i]->if_version == if_version &&
165                         strcmp(dcerpc_pipes[i]->uuid, uuid)==0) {
166                         return remote_fill_interface(iface, dcerpc_pipes[i]);
167                 }
168         }
169
170         return False;   
171 }
172
173 static BOOL remote_op_interface_by_name(struct dcesrv_interface *iface, const char *name)
174 {
175         int i;
176
177         for (i=0;dcerpc_pipes[i];i++) {
178                 if (strcmp(dcerpc_pipes[i]->name, name)==0) {
179                         return remote_fill_interface(iface, dcerpc_pipes[i]);
180                 }
181         }
182
183         return False;   
184 }
185
186 NTSTATUS dcerpc_remote_init(void)
187 {
188         NTSTATUS ret;
189         struct dcesrv_endpoint_server ep_server;
190
191         ZERO_STRUCT(ep_server);
192
193         /* fill in our name */
194         ep_server.name = "remote";
195
196         /* fill in all the operations */
197         ep_server.init_server = remote_op_init_server;
198
199         ep_server.interface_by_uuid = remote_op_interface_by_uuid;
200         ep_server.interface_by_name = remote_op_interface_by_name;
201
202         /* register ourselves with the DCERPC subsystem. */
203         ret = register_backend("dcerpc", &ep_server);
204         if (!NT_STATUS_IS_OK(ret)) {
205                 DEBUG(0,("Failed to register 'remote' endpoint server!\n"));
206                 return ret;
207         }
208
209         return ret;
210 }