r12892: Add a 'Migrate from Windows' page to our installation section in SWAT.
[bbaumbach/samba-autobuild/.git] / source4 / libnet / libnet_rpc.c
1 /* 
2    Unix SMB/CIFS implementation.
3    
4    Copyright (C) Stefan Metzmacher  2004
5    Copyright (C) Rafal Szczesniak   2005
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 "libnet/libnet.h"
24 #include "libcli/libcli.h"
25
26 /**
27  * Connects rpc pipe on remote server
28  * 
29  * @param ctx initialised libnet context
30  * @param mem_ctx memory context of this call
31  * @param r data structure containing necessary parameters and return values
32  * @return nt status of the call
33  **/
34
35 static NTSTATUS libnet_RpcConnectSrv(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
36 {
37         NTSTATUS status;
38         const char *binding = NULL;
39
40         /* prepare binding string */
41         switch (r->level) {
42         case LIBNET_RPC_CONNECT_DC:
43         case LIBNET_RPC_CONNECT_PDC:
44         case LIBNET_RPC_CONNECT_SERVER:
45                 binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", r->in.name);
46                 break;
47
48         case LIBNET_RPC_CONNECT_BINDING:
49                 binding = r->in.binding;
50                 break;
51         }
52
53         /* connect to remote dcerpc pipe */
54         status = dcerpc_pipe_connect(mem_ctx, &r->out.dcerpc_pipe,
55                                      binding, r->in.dcerpc_iface,
56                                      ctx->cred, ctx->event_ctx);
57
58         if (!NT_STATUS_IS_OK(status)) {
59                 r->out.error_string = talloc_asprintf(mem_ctx,
60                                                       "dcerpc_pipe_connect to pipe %s[%s] failed with %s\n",
61                                                       r->in.dcerpc_iface->name, binding, nt_errstr(status));
62                 return status;
63         }
64
65         r->out.error_string = NULL;
66         ctx->pipe = r->out.dcerpc_pipe;
67
68         return status;
69 }
70
71
72 /**
73  * Connects rpc pipe on domain pdc
74  * 
75  * @param ctx initialised libnet context
76  * @param mem_ctx memory context of this call
77  * @param r data structure containing necessary parameters and return values
78  * @return nt status of the call
79  **/
80
81 static NTSTATUS libnet_RpcConnectPdc(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
82 {
83         NTSTATUS status;
84         struct libnet_RpcConnect r2;
85         struct libnet_LookupDCs f;
86         const char *connect_name;
87
88         f.in.domain_name  = r->in.name;
89         switch (r->level) {
90         case LIBNET_RPC_CONNECT_PDC:
91                 f.in.name_type = NBT_NAME_PDC;
92                 break;
93         case LIBNET_RPC_CONNECT_DC:
94                 f.in.name_type = NBT_NAME_LOGON;
95                 break;
96         default:
97                 break;
98         }
99         f.out.num_dcs = 0;
100         f.out.dcs  = NULL;
101
102         /* find the domain pdc first */
103         status = libnet_LookupDCs(ctx, mem_ctx, &f);
104         if (!NT_STATUS_IS_OK(status)) {
105                 r->out.error_string = talloc_asprintf(mem_ctx, "libnet_LookupDCs failed: %s",
106                                                       nt_errstr(status));
107                 return status;
108         }
109
110         /* we might not have got back a name.  Fall back to the IP */
111         if (f.out.dcs[0].name) {
112                 connect_name = f.out.dcs[0].name;
113         } else {
114                 connect_name = f.out.dcs[0].address;
115         }
116
117         /* ok, pdc has been found so do attempt to rpc connect */
118         r2.level            = LIBNET_RPC_CONNECT_SERVER;
119
120         /* This will cause yet another name resolution, but at least
121          * we pass the right name down the stack now */
122         r2.in.name          = talloc_strdup(mem_ctx, connect_name);
123         r2.in.dcerpc_iface  = r->in.dcerpc_iface;
124         
125         status = libnet_RpcConnect(ctx, mem_ctx, &r2);
126
127         r->out.dcerpc_pipe          = r2.out.dcerpc_pipe;
128         r->out.error_string         = r2.out.error_string;
129
130         ctx->pipe = r->out.dcerpc_pipe;
131
132         return status;
133 }
134
135
136 /**
137  * Connects to rpc pipe on remote server or pdc
138  * 
139  * @param ctx initialised libnet context
140  * @param mem_ctx memory context of this call
141  * @param r data structure containing necessary parameters and return values
142  * @return nt status of the call
143  **/
144
145 NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_RpcConnect *r)
146 {
147         switch (r->level) {
148                 case LIBNET_RPC_CONNECT_SERVER:
149                         return libnet_RpcConnectSrv(ctx, mem_ctx, r);
150
151                 case LIBNET_RPC_CONNECT_BINDING:
152                         return libnet_RpcConnectSrv(ctx, mem_ctx, r);
153
154                 case LIBNET_RPC_CONNECT_PDC:
155                 case LIBNET_RPC_CONNECT_DC:
156                         return libnet_RpcConnectPdc(ctx, mem_ctx, r);
157         }
158
159         return NT_STATUS_INVALID_LEVEL;
160 }