Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : CLDAP server structures
5 :
6 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
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 3 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, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "../libcli/netlogon/netlogon.h"
24 :
25 2763 : NTSTATUS push_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
26 : struct netlogon_samlogon_response *response)
27 : {
28 36 : enum ndr_err_code ndr_err;
29 2763 : if (response->ntver == NETLOGON_NT_VERSION_1) {
30 155 : ndr_err = ndr_push_struct_blob(data, mem_ctx,
31 155 : &response->data.nt4,
32 : (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_NT40);
33 2608 : } else if (response->ntver & NETLOGON_NT_VERSION_5EX) {
34 2535 : ndr_err = ndr_push_struct_blob(data, mem_ctx,
35 2535 : &response->data.nt5_ex,
36 : (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags);
37 73 : } else if (response->ntver & NETLOGON_NT_VERSION_5) {
38 73 : ndr_err = ndr_push_struct_blob(data, mem_ctx,
39 73 : &response->data.nt5,
40 : (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE);
41 : } else {
42 0 : DEBUG(0, ("Asked to push unknown netlogon response type 0x%02x\n", response->ntver));
43 0 : return NT_STATUS_INVALID_PARAMETER;
44 : }
45 2763 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
46 0 : DEBUG(2,("failed to push netlogon response of type 0x%02x\n",
47 : response->ntver));
48 0 : return ndr_map_error2ntstatus(ndr_err);
49 : }
50 2763 : return NT_STATUS_OK;
51 : }
52 :
53 2506 : NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
54 : struct netlogon_samlogon_response *response)
55 : {
56 36 : uint32_t ntver;
57 36 : enum ndr_err_code ndr_err;
58 :
59 2506 : if (data->length < 8) {
60 0 : return NT_STATUS_BUFFER_TOO_SMALL;
61 : }
62 :
63 : /* lmnttoken */
64 2506 : if (SVAL(data->data, data->length - 4) != 0xffff) {
65 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
66 : }
67 : /* lm20token */
68 2506 : if (SVAL(data->data, data->length - 2) != 0xffff) {
69 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
70 : }
71 :
72 2506 : ntver = IVAL(data->data, data->length - 8);
73 :
74 2506 : if (ntver == NETLOGON_NT_VERSION_1) {
75 146 : ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
76 146 : &response->data.nt4,
77 : (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_NT40);
78 146 : response->ntver = NETLOGON_NT_VERSION_1;
79 146 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
80 0 : NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_NT40,
81 : &response->data.nt4);
82 : }
83 :
84 2360 : } else if (ntver & NETLOGON_NT_VERSION_5EX) {
85 36 : struct ndr_pull *ndr;
86 2287 : ndr = ndr_pull_init_blob(data, mem_ctx);
87 2287 : if (!ndr) {
88 0 : return NT_STATUS_NO_MEMORY;
89 : }
90 2287 : ndr_err = ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(
91 : ndr, NDR_SCALARS|NDR_BUFFERS, &response->data.nt5_ex,
92 : ntver);
93 2287 : if (ndr->offset < ndr->data_size) {
94 0 : TALLOC_FREE(ndr);
95 : /*
96 : * We need to handle a bug in IPA (at least <= 4.1.2).
97 : *
98 : * They include the ip address information without setting
99 : * NETLOGON_NT_VERSION_5EX_WITH_IP, while using
100 : * ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX instead of
101 : * ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags.
102 : */
103 0 : ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
104 0 : &response->data.nt5,
105 : (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX);
106 : }
107 2287 : response->ntver = NETLOGON_NT_VERSION_5EX;
108 2287 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
109 2 : NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_EX,
110 : &response->data.nt5_ex);
111 : }
112 :
113 73 : } else if (ntver & NETLOGON_NT_VERSION_5) {
114 73 : ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
115 73 : &response->data.nt5,
116 : (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE);
117 73 : response->ntver = NETLOGON_NT_VERSION_5;
118 73 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
119 0 : NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE,
120 : &response->data.nt5);
121 : }
122 : } else {
123 0 : DEBUG(2,("failed to parse netlogon response of type 0x%02x - unknown response type\n",
124 : ntver));
125 0 : dump_data(10, data->data, data->length);
126 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
127 : }
128 :
129 2506 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
130 0 : DEBUG(2,("failed to parse netlogon response of type 0x%02x\n",
131 : ntver));
132 0 : dump_data(10, data->data, data->length);
133 0 : return ndr_map_error2ntstatus(ndr_err);
134 : }
135 :
136 2506 : return NT_STATUS_OK;
137 : }
138 :
139 1595 : void map_netlogon_samlogon_response(struct netlogon_samlogon_response *response)
140 : {
141 36 : struct NETLOGON_SAM_LOGON_RESPONSE_EX response_5_ex;
142 1595 : switch (response->ntver) {
143 1323 : case NETLOGON_NT_VERSION_5EX:
144 1323 : break;
145 72 : case NETLOGON_NT_VERSION_5:
146 72 : ZERO_STRUCT(response_5_ex);
147 72 : response_5_ex.command = response->data.nt5.command;
148 72 : response_5_ex.pdc_name = response->data.nt5.pdc_name;
149 72 : response_5_ex.user_name = response->data.nt5.user_name;
150 72 : response_5_ex.domain_name = response->data.nt5.domain_name;
151 72 : response_5_ex.domain_uuid = response->data.nt5.domain_uuid;
152 72 : response_5_ex.forest = response->data.nt5.forest;
153 72 : response_5_ex.dns_domain = response->data.nt5.dns_domain;
154 72 : response_5_ex.pdc_dns_name = response->data.nt5.pdc_dns_name;
155 72 : response_5_ex.sockaddr.pdc_ip = response->data.nt5.pdc_ip;
156 72 : response_5_ex.server_type = response->data.nt5.server_type;
157 72 : response_5_ex.nt_version = response->data.nt5.nt_version;
158 72 : response_5_ex.lmnt_token = response->data.nt5.lmnt_token;
159 72 : response_5_ex.lm20_token = response->data.nt5.lm20_token;
160 72 : response->ntver = NETLOGON_NT_VERSION_5EX;
161 72 : response->data.nt5_ex = response_5_ex;
162 72 : break;
163 :
164 164 : case NETLOGON_NT_VERSION_1:
165 164 : ZERO_STRUCT(response_5_ex);
166 164 : response_5_ex.command = response->data.nt4.command;
167 164 : response_5_ex.pdc_name = response->data.nt4.pdc_name;
168 164 : response_5_ex.user_name = response->data.nt4.user_name;
169 164 : response_5_ex.domain_name = response->data.nt4.domain_name;
170 164 : response_5_ex.nt_version = response->data.nt4.nt_version;
171 164 : response_5_ex.lmnt_token = response->data.nt4.lmnt_token;
172 164 : response_5_ex.lm20_token = response->data.nt4.lm20_token;
173 164 : response->ntver = NETLOGON_NT_VERSION_5EX;
174 164 : response->data.nt5_ex = response_5_ex;
175 164 : break;
176 : }
177 1595 : return;
178 : }
179 :
180 51 : NTSTATUS push_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
181 : struct nbt_netlogon_response *response)
182 : {
183 0 : NTSTATUS status;
184 0 : enum ndr_err_code ndr_err;
185 51 : switch (response->response_type) {
186 13 : case NETLOGON_GET_PDC:
187 13 : ndr_err = ndr_push_struct_blob(data, mem_ctx,
188 13 : &response->data.get_pdc,
189 : (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response_from_pdc);
190 13 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
191 0 : status = ndr_map_error2ntstatus(ndr_err);
192 0 : DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
193 : (int)data->length, nt_errstr(status)));
194 0 : if (DEBUGLVL(10)) {
195 0 : (void)file_save("netlogon.dat", data->data, data->length);
196 : }
197 0 : return status;
198 : }
199 13 : status = NT_STATUS_OK;
200 13 : break;
201 38 : case NETLOGON_SAMLOGON:
202 38 : status = push_netlogon_samlogon_response(
203 : data, mem_ctx,
204 : &response->data.samlogon);
205 38 : break;
206 0 : case NETLOGON_RESPONSE2:
207 0 : ndr_err = ndr_push_struct_blob(data, mem_ctx,
208 0 : &response->data.response2,
209 : (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response2);
210 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
211 0 : return ndr_map_error2ntstatus(ndr_err);
212 : }
213 0 : status = NT_STATUS_OK;
214 0 : break;
215 0 : default:
216 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
217 0 : break;
218 : }
219 :
220 51 : return status;
221 : }
222 :
223 :
224 39 : NTSTATUS pull_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
225 : struct nbt_netlogon_response *response)
226 : {
227 0 : NTSTATUS status;
228 0 : enum netlogon_command command;
229 0 : enum ndr_err_code ndr_err;
230 39 : if (data->length < 4) {
231 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
232 : }
233 :
234 39 : command = SVAL(data->data, 0);
235 :
236 39 : switch (command) {
237 13 : case NETLOGON_RESPONSE_FROM_PDC:
238 13 : ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
239 13 : &response->data.get_pdc,
240 : (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response_from_pdc);
241 13 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
242 0 : status = ndr_map_error2ntstatus(ndr_err);
243 0 : DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
244 : (int)data->length, nt_errstr(status)));
245 0 : if (DEBUGLVL(10)) {
246 0 : (void)file_save("netlogon.dat", data->data, data->length);
247 : }
248 0 : return status;
249 : }
250 13 : status = NT_STATUS_OK;
251 13 : response->response_type = NETLOGON_GET_PDC;
252 39 : break;
253 0 : case LOGON_RESPONSE2:
254 0 : ndr_err = ndr_pull_struct_blob(data, mem_ctx, &response->data.response2,
255 : (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response2);
256 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
257 0 : return ndr_map_error2ntstatus(ndr_err);
258 : }
259 0 : status = NT_STATUS_OK;
260 0 : response->response_type = NETLOGON_RESPONSE2;
261 0 : break;
262 26 : case LOGON_SAM_LOGON_RESPONSE:
263 : case LOGON_SAM_LOGON_PAUSE_RESPONSE:
264 : case LOGON_SAM_LOGON_USER_UNKNOWN:
265 : case LOGON_SAM_LOGON_RESPONSE_EX:
266 : case LOGON_SAM_LOGON_PAUSE_RESPONSE_EX:
267 : case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
268 26 : status = pull_netlogon_samlogon_response(
269 : data, mem_ctx,
270 : &response->data.samlogon);
271 26 : response->response_type = NETLOGON_SAMLOGON;
272 26 : break;
273 :
274 : /* These levels are queries, not responses */
275 0 : case LOGON_PRIMARY_QUERY:
276 : case LOGON_REQUEST:
277 : case NETLOGON_ANNOUNCE_UAS:
278 : case LOGON_SAM_LOGON_REQUEST:
279 : default:
280 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
281 : }
282 :
283 39 : return status;
284 :
285 : }
|