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 1566 : NTSTATUS push_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
26 : struct netlogon_samlogon_response *response)
27 : {
28 : enum ndr_err_code ndr_err;
29 1566 : if (response->ntver == NETLOGON_NT_VERSION_1) {
30 128 : ndr_err = ndr_push_struct_blob(data, mem_ctx,
31 128 : &response->data.nt4,
32 : (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_NT40);
33 1438 : } else if (response->ntver & NETLOGON_NT_VERSION_5EX) {
34 1365 : ndr_err = ndr_push_struct_blob(data, mem_ctx,
35 1365 : &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 1566 : 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 1566 : return NT_STATUS_OK;
51 : }
52 :
53 1389 : NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
54 : struct netlogon_samlogon_response *response)
55 : {
56 : uint32_t ntver;
57 : enum ndr_err_code ndr_err;
58 :
59 1389 : if (data->length < 8) {
60 0 : return NT_STATUS_BUFFER_TOO_SMALL;
61 : }
62 :
63 : /* lmnttoken */
64 1389 : if (SVAL(data->data, data->length - 4) != 0xffff) {
65 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
66 : }
67 : /* lm20token */
68 1389 : if (SVAL(data->data, data->length - 2) != 0xffff) {
69 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
70 : }
71 :
72 1389 : ntver = IVAL(data->data, data->length - 8);
73 :
74 1389 : if (ntver == NETLOGON_NT_VERSION_1) {
75 127 : ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
76 127 : &response->data.nt4,
77 : (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_NT40);
78 127 : response->ntver = NETLOGON_NT_VERSION_1;
79 127 : 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 1262 : } else if (ntver & NETLOGON_NT_VERSION_5EX) {
85 : struct ndr_pull *ndr;
86 1189 : ndr = ndr_pull_init_blob(data, mem_ctx);
87 1189 : if (!ndr) {
88 0 : return NT_STATUS_NO_MEMORY;
89 : }
90 1189 : ndr_err = ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(
91 : ndr, NDR_SCALARS|NDR_BUFFERS, &response->data.nt5_ex,
92 : ntver);
93 1189 : 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 1189 : response->ntver = NETLOGON_NT_VERSION_5EX;
108 1189 : 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 1389 : 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 1389 : return NT_STATUS_OK;
137 : }
138 :
139 1129 : void map_netlogon_samlogon_response(struct netlogon_samlogon_response *response)
140 : {
141 : struct NETLOGON_SAM_LOGON_RESPONSE_EX response_5_ex;
142 1129 : switch (response->ntver) {
143 927 : case NETLOGON_NT_VERSION_5EX:
144 927 : 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 130 : case NETLOGON_NT_VERSION_1:
165 130 : ZERO_STRUCT(response_5_ex);
166 130 : response_5_ex.command = response->data.nt4.command;
167 130 : response_5_ex.pdc_name = response->data.nt4.pdc_name;
168 130 : response_5_ex.user_name = response->data.nt4.user_name;
169 130 : response_5_ex.domain_name = response->data.nt4.domain_name;
170 130 : response_5_ex.nt_version = response->data.nt4.nt_version;
171 130 : response_5_ex.lmnt_token = response->data.nt4.lmnt_token;
172 130 : response_5_ex.lm20_token = response->data.nt4.lm20_token;
173 130 : response->ntver = NETLOGON_NT_VERSION_5EX;
174 130 : response->data.nt5_ex = response_5_ex;
175 130 : break;
176 : }
177 1129 : return;
178 : }
179 :
180 12 : NTSTATUS push_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
181 : struct nbt_netlogon_response *response)
182 : {
183 : NTSTATUS status;
184 : enum ndr_err_code ndr_err;
185 12 : switch (response->response_type) {
186 3 : case NETLOGON_GET_PDC:
187 3 : ndr_err = ndr_push_struct_blob(data, mem_ctx,
188 3 : &response->data.get_pdc,
189 : (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response_from_pdc);
190 3 : 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 3 : status = NT_STATUS_OK;
200 3 : break;
201 9 : case NETLOGON_SAMLOGON:
202 9 : status = push_netlogon_samlogon_response(
203 : data, mem_ctx,
204 : &response->data.samlogon);
205 9 : 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 12 : return status;
221 : }
222 :
223 :
224 10 : NTSTATUS pull_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
225 : struct nbt_netlogon_response *response)
226 : {
227 : NTSTATUS status;
228 : enum netlogon_command command;
229 : enum ndr_err_code ndr_err;
230 10 : if (data->length < 4) {
231 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
232 : }
233 :
234 10 : command = SVAL(data->data, 0);
235 :
236 10 : switch (command) {
237 3 : case NETLOGON_RESPONSE_FROM_PDC:
238 3 : ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
239 3 : &response->data.get_pdc,
240 : (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response_from_pdc);
241 3 : 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 3 : status = NT_STATUS_OK;
251 3 : response->response_type = NETLOGON_GET_PDC;
252 3 : 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 7 : 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 7 : status = pull_netlogon_samlogon_response(
269 : data, mem_ctx,
270 : &response->data.samlogon);
271 7 : response->response_type = NETLOGON_SAMLOGON;
272 7 : 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 10 : return status;
284 :
285 : }
|