2 Unix SMB/CIFS implementation.
4 CLDAP server structures
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
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.
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.
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/>.
23 #include "../libcli/netlogon/netlogon.h"
25 NTSTATUS
push_netlogon_samlogon_response(DATA_BLOB
*data
, TALLOC_CTX
*mem_ctx
,
26 struct netlogon_samlogon_response
*response
)
28 enum ndr_err_code ndr_err
;
29 if (response
->ntver
== NETLOGON_NT_VERSION_1
) {
30 ndr_err
= ndr_push_struct_blob(data
, mem_ctx
,
32 (ndr_push_flags_fn_t
)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_NT40
);
33 } else if (response
->ntver
& NETLOGON_NT_VERSION_5EX
) {
34 ndr_err
= ndr_push_struct_blob(data
, mem_ctx
,
35 &response
->data
.nt5_ex
,
36 (ndr_push_flags_fn_t
)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags
);
37 } else if (response
->ntver
& NETLOGON_NT_VERSION_5
) {
38 ndr_err
= ndr_push_struct_blob(data
, mem_ctx
,
40 (ndr_push_flags_fn_t
)ndr_push_NETLOGON_SAM_LOGON_RESPONSE
);
42 DEBUG(0, ("Asked to push unknown netlogon response type 0x%02x\n", response
->ntver
));
43 return NT_STATUS_INVALID_PARAMETER
;
45 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
46 DEBUG(2,("failed to push netlogon response of type 0x%02x\n",
48 return ndr_map_error2ntstatus(ndr_err
);
53 NTSTATUS
pull_netlogon_samlogon_response(DATA_BLOB
*data
, TALLOC_CTX
*mem_ctx
,
54 struct netlogon_samlogon_response
*response
)
57 enum ndr_err_code ndr_err
;
59 if (data
->length
< 8) {
60 return NT_STATUS_BUFFER_TOO_SMALL
;
64 if (SVAL(data
->data
, data
->length
- 4) != 0xffff) {
65 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
68 if (SVAL(data
->data
, data
->length
- 2) != 0xffff) {
69 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
72 ntver
= IVAL(data
->data
, data
->length
- 8);
74 if (ntver
== NETLOGON_NT_VERSION_1
) {
75 ndr_err
= ndr_pull_struct_blob_all(data
, mem_ctx
,
77 (ndr_pull_flags_fn_t
)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_NT40
);
78 response
->ntver
= NETLOGON_NT_VERSION_1
;
79 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && DEBUGLEVEL
>= 10) {
80 NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_NT40
,
84 } else if (ntver
& NETLOGON_NT_VERSION_5EX
) {
86 ndr
= ndr_pull_init_blob(data
, mem_ctx
);
88 return NT_STATUS_NO_MEMORY
;
90 ndr_err
= ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(
91 ndr
, NDR_SCALARS
|NDR_BUFFERS
, &response
->data
.nt5_ex
,
93 if (ndr
->offset
< ndr
->data_size
) {
96 * We need to handle a bug in FreeIPA (at least <= 4.1.2).
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.
103 ndr_err
= ndr_pull_struct_blob_all(data
, mem_ctx
,
105 (ndr_pull_flags_fn_t
)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX
);
107 response
->ntver
= NETLOGON_NT_VERSION_5EX
;
108 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && DEBUGLEVEL
>= 10) {
109 NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_EX
,
110 &response
->data
.nt5_ex
);
113 } else if (ntver
& NETLOGON_NT_VERSION_5
) {
114 ndr_err
= ndr_pull_struct_blob_all(data
, mem_ctx
,
116 (ndr_pull_flags_fn_t
)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE
);
117 response
->ntver
= NETLOGON_NT_VERSION_5
;
118 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && DEBUGLEVEL
>= 10) {
119 NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE
,
120 &response
->data
.nt5
);
123 DEBUG(2,("failed to parse netlogon response of type 0x%02x - unknown response type\n",
125 dump_data(10, data
->data
, data
->length
);
126 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
129 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
130 DEBUG(2,("failed to parse netlogon response of type 0x%02x\n",
132 dump_data(10, data
->data
, data
->length
);
133 return ndr_map_error2ntstatus(ndr_err
);
139 void map_netlogon_samlogon_response(struct netlogon_samlogon_response
*response
)
141 struct NETLOGON_SAM_LOGON_RESPONSE_EX response_5_ex
;
142 switch (response
->ntver
) {
143 case NETLOGON_NT_VERSION_5EX
:
145 case NETLOGON_NT_VERSION_5
:
146 ZERO_STRUCT(response_5_ex
);
147 response_5_ex
.command
= response
->data
.nt5
.command
;
148 response_5_ex
.pdc_name
= response
->data
.nt5
.pdc_name
;
149 response_5_ex
.user_name
= response
->data
.nt5
.user_name
;
150 response_5_ex
.domain_name
= response
->data
.nt5
.domain_name
;
151 response_5_ex
.domain_uuid
= response
->data
.nt5
.domain_uuid
;
152 response_5_ex
.forest
= response
->data
.nt5
.forest
;
153 response_5_ex
.dns_domain
= response
->data
.nt5
.dns_domain
;
154 response_5_ex
.pdc_dns_name
= response
->data
.nt5
.pdc_dns_name
;
155 response_5_ex
.sockaddr
.pdc_ip
= response
->data
.nt5
.pdc_ip
;
156 response_5_ex
.server_type
= response
->data
.nt5
.server_type
;
157 response_5_ex
.nt_version
= response
->data
.nt5
.nt_version
;
158 response_5_ex
.lmnt_token
= response
->data
.nt5
.lmnt_token
;
159 response_5_ex
.lm20_token
= response
->data
.nt5
.lm20_token
;
160 response
->ntver
= NETLOGON_NT_VERSION_5EX
;
161 response
->data
.nt5_ex
= response_5_ex
;
164 case NETLOGON_NT_VERSION_1
:
165 ZERO_STRUCT(response_5_ex
);
166 response_5_ex
.command
= response
->data
.nt4
.command
;
167 response_5_ex
.pdc_name
= response
->data
.nt4
.pdc_name
;
168 response_5_ex
.user_name
= response
->data
.nt4
.user_name
;
169 response_5_ex
.domain_name
= response
->data
.nt4
.domain_name
;
170 response_5_ex
.nt_version
= response
->data
.nt4
.nt_version
;
171 response_5_ex
.lmnt_token
= response
->data
.nt4
.lmnt_token
;
172 response_5_ex
.lm20_token
= response
->data
.nt4
.lm20_token
;
173 response
->ntver
= NETLOGON_NT_VERSION_5EX
;
174 response
->data
.nt5_ex
= response_5_ex
;
180 NTSTATUS
push_nbt_netlogon_response(DATA_BLOB
*data
, TALLOC_CTX
*mem_ctx
,
181 struct nbt_netlogon_response
*response
)
183 NTSTATUS status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
184 enum ndr_err_code ndr_err
;
185 switch (response
->response_type
) {
186 case NETLOGON_GET_PDC
:
187 ndr_err
= ndr_push_struct_blob(data
, mem_ctx
,
188 &response
->data
.get_pdc
,
189 (ndr_push_flags_fn_t
)ndr_push_nbt_netlogon_response_from_pdc
);
190 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
191 status
= ndr_map_error2ntstatus(ndr_err
);
192 DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
193 (int)data
->length
, nt_errstr(status
)));
195 file_save("netlogon.dat", data
->data
, data
->length
);
199 status
= NT_STATUS_OK
;
201 case NETLOGON_SAMLOGON
:
202 status
= push_netlogon_samlogon_response(
204 &response
->data
.samlogon
);
206 case NETLOGON_RESPONSE2
:
207 ndr_err
= ndr_push_struct_blob(data
, mem_ctx
,
208 &response
->data
.response2
,
209 (ndr_push_flags_fn_t
)ndr_push_nbt_netlogon_response2
);
210 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
211 return ndr_map_error2ntstatus(ndr_err
);
213 status
= NT_STATUS_OK
;
221 NTSTATUS
pull_nbt_netlogon_response(DATA_BLOB
*data
, TALLOC_CTX
*mem_ctx
,
222 struct nbt_netlogon_response
*response
)
224 NTSTATUS status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
225 enum netlogon_command command
;
226 enum ndr_err_code ndr_err
;
227 if (data
->length
< 4) {
228 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
231 command
= SVAL(data
->data
, 0);
234 case NETLOGON_RESPONSE_FROM_PDC
:
235 ndr_err
= ndr_pull_struct_blob_all(data
, mem_ctx
,
236 &response
->data
.get_pdc
,
237 (ndr_pull_flags_fn_t
)ndr_pull_nbt_netlogon_response_from_pdc
);
238 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
239 status
= ndr_map_error2ntstatus(ndr_err
);
240 DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
241 (int)data
->length
, nt_errstr(status
)));
243 file_save("netlogon.dat", data
->data
, data
->length
);
247 status
= NT_STATUS_OK
;
248 response
->response_type
= NETLOGON_GET_PDC
;
250 case LOGON_RESPONSE2
:
251 ndr_err
= ndr_pull_struct_blob(data
, mem_ctx
, &response
->data
.response2
,
252 (ndr_pull_flags_fn_t
)ndr_pull_nbt_netlogon_response2
);
253 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
254 return ndr_map_error2ntstatus(ndr_err
);
256 status
= NT_STATUS_OK
;
257 response
->response_type
= NETLOGON_RESPONSE2
;
259 case LOGON_SAM_LOGON_RESPONSE
:
260 case LOGON_SAM_LOGON_PAUSE_RESPONSE
:
261 case LOGON_SAM_LOGON_USER_UNKNOWN
:
262 case LOGON_SAM_LOGON_RESPONSE_EX
:
263 case LOGON_SAM_LOGON_PAUSE_RESPONSE_EX
:
264 case LOGON_SAM_LOGON_USER_UNKNOWN_EX
:
265 status
= pull_netlogon_samlogon_response(
267 &response
->data
.samlogon
);
268 response
->response_type
= NETLOGON_SAMLOGON
;
271 /* These levels are queries, not responses */
272 case LOGON_PRIMARY_QUERY
:
274 case NETLOGON_ANNOUNCE_UAS
:
275 case LOGON_SAM_LOGON_REQUEST
:
276 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;