s3-libnetapi: pass down ndr_interface_table to libnetapi_get_binding_handle().
[metze/samba/wip.git] / source3 / lib / netapi / netlogon.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  NetApi LogonControl Support
4  *  Copyright (C) Guenther Deschner 2009
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21
22 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
23 #include "librpc/gen_ndr/libnetapi.h"
24 #include "lib/netapi/netapi.h"
25 #include "lib/netapi/netapi_private.h"
26 #include "lib/netapi/libnetapi.h"
27
28 static WERROR construct_data(enum netr_LogonControlCode function_code,
29                              const uint8_t *data_in,
30                              union netr_CONTROL_DATA_INFORMATION *data_out)
31 {
32         switch (function_code) {
33         case NETLOGON_CONTROL_QUERY:
34         case NETLOGON_CONTROL_REDISCOVER:
35         case NETLOGON_CONTROL_TC_QUERY:
36         case NETLOGON_CONTROL_CHANGE_PASSWORD:
37         case NETLOGON_CONTROL_TC_VERIFY:
38                 data_out->domain = (const char *)data_in;
39                 break;
40         case NETLOGON_CONTROL_FIND_USER:
41                 data_out->user = (const char *)data_in;
42                 break;
43         case NETLOGON_CONTROL_SET_DBFLAG:
44                 data_out->debug_level = atoi((const char *)data_in);
45                 break;
46         case NETLOGON_CONTROL_FORCE_DNS_REG:
47                 ZERO_STRUCTP(data_out);
48                 break;
49         default:
50                 return WERR_INVALID_PARAM;
51         }
52
53         return WERR_OK;
54 }
55
56 static WERROR construct_buffer(TALLOC_CTX *mem_ctx,
57                                uint32_t level,
58                                union netr_CONTROL_QUERY_INFORMATION *q,
59                                uint8_t **buffer)
60 {
61         struct NETLOGON_INFO_1 *i1;
62         struct NETLOGON_INFO_2 *i2;
63         struct NETLOGON_INFO_3 *i3;
64         struct NETLOGON_INFO_4 *i4;
65
66         if (!q) {
67                 return WERR_INVALID_PARAM;
68         }
69
70         switch (level) {
71         case 1:
72                 i1 = talloc(mem_ctx, struct NETLOGON_INFO_1);
73                 W_ERROR_HAVE_NO_MEMORY(i1);
74
75                 i1->netlog1_flags                       = q->info1->flags;
76                 i1->netlog1_pdc_connection_status       = W_ERROR_V(q->info1->pdc_connection_status);
77
78                 *buffer = (uint8_t *)i1;
79
80                 break;
81         case 2:
82                 i2 = talloc(mem_ctx, struct NETLOGON_INFO_2);
83                 W_ERROR_HAVE_NO_MEMORY(i2);
84
85                 i2->netlog2_flags                       = q->info2->flags;
86                 i2->netlog2_pdc_connection_status       = W_ERROR_V(q->info2->pdc_connection_status);
87                 i2->netlog2_trusted_dc_name             = talloc_strdup(mem_ctx, q->info2->trusted_dc_name);
88                 i2->netlog2_tc_connection_status        = W_ERROR_V(q->info2->tc_connection_status);
89
90                 *buffer = (uint8_t *)i2;
91
92                 break;
93         case 3:
94                 i3 = talloc(mem_ctx, struct NETLOGON_INFO_3);
95                 W_ERROR_HAVE_NO_MEMORY(i3);
96
97                 i3->netlog1_flags                       = q->info3->flags;
98                 i3->netlog3_logon_attempts              = q->info3->logon_attempts;
99                 i3->netlog3_reserved1                   = q->info3->unknown1;
100                 i3->netlog3_reserved2                   = q->info3->unknown2;
101                 i3->netlog3_reserved3                   = q->info3->unknown3;
102                 i3->netlog3_reserved4                   = q->info3->unknown4;
103                 i3->netlog3_reserved5                   = q->info3->unknown5;
104
105                 *buffer = (uint8_t *)i3;
106
107                 break;
108         case 4:
109                 i4 = talloc(mem_ctx, struct NETLOGON_INFO_4);
110                 W_ERROR_HAVE_NO_MEMORY(i4);
111
112                 i4->netlog4_trusted_dc_name             = talloc_strdup(mem_ctx, q->info4->trusted_dc_name);
113                 i4->netlog4_trusted_domain_name         = talloc_strdup(mem_ctx, q->info4->trusted_domain_name);
114
115                 *buffer = (uint8_t *)i4;
116
117                 break;
118         default:
119                 return WERR_UNKNOWN_LEVEL;
120         }
121         return WERR_OK;
122 }
123
124 /****************************************************************
125 ****************************************************************/
126
127 WERROR I_NetLogonControl_r(struct libnetapi_ctx *ctx,
128                            struct I_NetLogonControl *r)
129 {
130         WERROR werr;
131         NTSTATUS status;
132         union netr_CONTROL_QUERY_INFORMATION query;
133         struct dcerpc_binding_handle *b;
134
135         werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
136                                             &ndr_table_netlogon,
137                                             &b);
138         if (!W_ERROR_IS_OK(werr)) {
139                 goto done;
140         }
141
142         status = dcerpc_netr_LogonControl(b, talloc_tos(),
143                                           r->in.server_name,
144                                           r->in.function_code,
145                                           r->in.query_level,
146                                           &query,
147                                           &werr);
148         if (!NT_STATUS_IS_OK(status)) {
149                 werr = ntstatus_to_werror(status);
150                 goto done;
151         }
152         if (!W_ERROR_IS_OK(werr)) {
153                 goto done;
154         }
155
156         werr = construct_buffer(ctx, r->in.query_level, &query,
157                                 r->out.buffer);
158         if (!W_ERROR_IS_OK(werr)) {
159                 goto done;
160         }
161
162  done:
163         return werr;
164 }
165
166 /****************************************************************
167 ****************************************************************/
168
169 WERROR I_NetLogonControl_l(struct libnetapi_ctx *ctx,
170                            struct I_NetLogonControl *r)
171 {
172         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, I_NetLogonControl);
173 }
174
175 /****************************************************************
176 ****************************************************************/
177
178 WERROR I_NetLogonControl2_r(struct libnetapi_ctx *ctx,
179                             struct I_NetLogonControl2 *r)
180 {
181         WERROR werr;
182         NTSTATUS status;
183         union netr_CONTROL_DATA_INFORMATION data;
184         union netr_CONTROL_QUERY_INFORMATION query;
185         struct dcerpc_binding_handle *b;
186
187         werr = construct_data(r->in.function_code, r->in.data, &data);
188         if (!W_ERROR_IS_OK(werr)) {
189                 goto done;
190         }
191
192         werr = libnetapi_get_binding_handle(ctx, r->in.server_name,
193                                             &ndr_table_netlogon,
194                                             &b);
195         if (!W_ERROR_IS_OK(werr)) {
196                 goto done;
197         }
198
199         switch (r->in.function_code) {
200         case NETLOGON_CONTROL_TC_VERIFY:
201         case NETLOGON_CONTROL_SET_DBFLAG:
202         case NETLOGON_CONTROL_FORCE_DNS_REG:
203                 status = dcerpc_netr_LogonControl2Ex(b, talloc_tos(),
204                                                      r->in.server_name,
205                                                      r->in.function_code,
206                                                      r->in.query_level,
207                                                      &data,
208                                                      &query,
209                                                      &werr);
210                 break;
211         default:
212                 status = dcerpc_netr_LogonControl2(b, talloc_tos(),
213                                                    r->in.server_name,
214                                                    r->in.function_code,
215                                                    r->in.query_level,
216                                                    &data,
217                                                    &query,
218                                                    &werr);
219                 break;
220         }
221
222         if (!NT_STATUS_IS_OK(status)) {
223                 werr = ntstatus_to_werror(status);
224                 goto done;
225         }
226
227         if (!W_ERROR_IS_OK(werr)) {
228                 goto done;
229         }
230
231         werr = construct_buffer(ctx, r->in.query_level, &query,
232                                 r->out.buffer);
233         if (!W_ERROR_IS_OK(werr)) {
234                 goto done;
235         }
236
237  done:
238         return werr;
239 }
240
241 /****************************************************************
242 ****************************************************************/
243
244 WERROR I_NetLogonControl2_l(struct libnetapi_ctx *ctx,
245                             struct I_NetLogonControl2 *r)
246 {
247         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, I_NetLogonControl2);
248 }