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.h"
25 NTSTATUS
push_netlogon_samlogon_response(DATA_BLOB
*data
, TALLOC_CTX
*mem_ctx
,
26 struct smb_iconv_convenience
*iconv_convenience
,
27 struct netlogon_samlogon_response
*response
)
29 enum ndr_err_code ndr_err
;
30 if (response
->ntver
== NETLOGON_NT_VERSION_1
) {
31 ndr_err
= ndr_push_struct_blob(data
, mem_ctx
,
34 (ndr_push_flags_fn_t
)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_NT40
);
35 } else if (response
->ntver
& NETLOGON_NT_VERSION_5EX
) {
36 ndr_err
= ndr_push_struct_blob(data
, mem_ctx
,
39 (ndr_push_flags_fn_t
)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags
);
40 } else if (response
->ntver
& NETLOGON_NT_VERSION_5
) {
41 ndr_err
= ndr_push_struct_blob(data
, mem_ctx
,
44 (ndr_push_flags_fn_t
)ndr_push_NETLOGON_SAM_LOGON_RESPONSE
);
46 DEBUG(0, ("Asked to push unknown netlogon response type 0x%02x\n", response
->ntver
));
47 return NT_STATUS_INVALID_PARAMETER
;
49 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
50 DEBUG(2,("failed to push netlogon response of type 0x%02x\n",
52 return ndr_map_error2ntstatus(ndr_err
);
57 NTSTATUS
pull_netlogon_samlogon_response(DATA_BLOB
*data
, TALLOC_CTX
*mem_ctx
,
58 struct smb_iconv_convenience
*iconv_convenience
,
59 struct netlogon_samlogon_response
*response
)
62 enum ndr_err_code ndr_err
;
64 if (data
->length
< 8) {
65 return NT_STATUS_BUFFER_TOO_SMALL
;
69 if (SVAL(data
->data
, data
->length
- 4) != 0xffff) {
70 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
73 if (SVAL(data
->data
, data
->length
- 2) != 0xffff) {
74 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
77 ntver
= IVAL(data
->data
, data
->length
- 8);
79 if (ntver
== NETLOGON_NT_VERSION_1
) {
80 ndr_err
= ndr_pull_struct_blob_all(data
, mem_ctx
,
83 (ndr_pull_flags_fn_t
)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_NT40
);
84 response
->ntver
= NETLOGON_NT_VERSION_1
;
85 } else if (ntver
& NETLOGON_NT_VERSION_5EX
) {
87 ndr
= ndr_pull_init_blob(data
, mem_ctx
, iconv_convenience
);
89 return NT_STATUS_NO_MEMORY
;
91 ndr_err
= ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(ndr
, NDR_SCALARS
|NDR_BUFFERS
, &response
->nt5_ex
, ntver
);
92 if (ndr
->offset
< ndr
->data_size
) {
93 ndr_err
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
94 "not all bytes consumed ofs[%u] size[%u]",
95 ndr
->offset
, ndr
->data_size
);
97 response
->ntver
= NETLOGON_NT_VERSION_5EX
;
99 } else if (ntver
& NETLOGON_NT_VERSION_5
) {
100 ndr_err
= ndr_pull_struct_blob_all(data
, mem_ctx
,
103 (ndr_pull_flags_fn_t
)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE
);
104 response
->ntver
= NETLOGON_NT_VERSION_5
;
106 DEBUG(2,("failed to parse netlogon response of type 0x%02x - unknown response type\n",
108 dump_data(10, data
->data
, data
->length
);
109 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
112 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
113 DEBUG(2,("failed to parse netlogon response of type 0x%02x\n",
115 dump_data(10, data
->data
, data
->length
);
116 return ndr_map_error2ntstatus(ndr_err
);
121 void map_netlogon_samlogon_response(struct netlogon_samlogon_response
*response
)
123 struct NETLOGON_SAM_LOGON_RESPONSE_EX response_5_ex
;
124 switch (response
->ntver
) {
125 case NETLOGON_NT_VERSION_5EX
:
127 case NETLOGON_NT_VERSION_5
:
128 ZERO_STRUCT(response_5_ex
);
129 response_5_ex
.command
= response
->nt5
.command
;
130 response_5_ex
.pdc_name
= response
->nt5
.pdc_name
;
131 response_5_ex
.user_name
= response
->nt5
.user_name
;
132 response_5_ex
.domain
= response
->nt5
.domain_name
;
133 response_5_ex
.domain_uuid
= response
->nt5
.domain_uuid
;
134 response_5_ex
.forest
= response
->nt5
.forest
;
135 response_5_ex
.dns_domain
= response
->nt5
.dns_domain
;
136 response_5_ex
.pdc_dns_name
= response
->nt5
.pdc_dns_name
;
137 response_5_ex
.sockaddr
.pdc_ip
= response
->nt5
.pdc_ip
;
138 response_5_ex
.server_type
= response
->nt5
.server_type
;
139 response_5_ex
.nt_version
= response
->nt5
.nt_version
;
140 response_5_ex
.lmnt_token
= response
->nt5
.lmnt_token
;
141 response_5_ex
.lm20_token
= response
->nt5
.lm20_token
;
142 response
->ntver
= NETLOGON_NT_VERSION_5EX
;
143 response
->nt5_ex
= response_5_ex
;
146 case NETLOGON_NT_VERSION_1
:
147 ZERO_STRUCT(response_5_ex
);
148 response_5_ex
.command
= response
->nt4
.command
;
149 response_5_ex
.pdc_name
= response
->nt4
.server
;
150 response_5_ex
.user_name
= response
->nt4
.user_name
;
151 response_5_ex
.domain
= response
->nt4
.domain
;
152 response_5_ex
.nt_version
= response
->nt4
.nt_version
;
153 response_5_ex
.lmnt_token
= response
->nt4
.lmnt_token
;
154 response_5_ex
.lm20_token
= response
->nt4
.lm20_token
;
155 response
->ntver
= NETLOGON_NT_VERSION_5EX
;
156 response
->nt5_ex
= response_5_ex
;
162 NTSTATUS
push_nbt_netlogon_response(DATA_BLOB
*data
, TALLOC_CTX
*mem_ctx
,
163 struct smb_iconv_convenience
*iconv_convenience
,
164 struct nbt_netlogon_response
*response
)
166 NTSTATUS status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
167 enum ndr_err_code ndr_err
;
168 switch (response
->response_type
) {
169 case NETLOGON_GET_PDC
:
170 ndr_err
= ndr_push_struct_blob(data
, mem_ctx
, iconv_convenience
, &response
->get_pdc
,
171 (ndr_push_flags_fn_t
)ndr_push_nbt_netlogon_response_from_pdc
);
172 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
173 status
= ndr_map_error2ntstatus(ndr_err
);
174 DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
175 (int)data
->length
, nt_errstr(status
)));
177 file_save("netlogon.dat", data
->data
, data
->length
);
181 status
= NT_STATUS_OK
;
183 case NETLOGON_SAMLOGON
:
184 status
= push_netlogon_samlogon_response(data
, mem_ctx
, iconv_convenience
, &response
->samlogon
);
191 NTSTATUS
pull_nbt_netlogon_response(DATA_BLOB
*data
, TALLOC_CTX
*mem_ctx
,
192 struct smb_iconv_convenience
*iconv_convenience
,
193 struct nbt_netlogon_response
*response
)
195 NTSTATUS status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
196 enum netlogon_command command
;
197 enum ndr_err_code ndr_err
;
198 if (data
->length
< 4) {
199 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
202 command
= SVAL(data
->data
, 0);
205 case NETLOGON_RESPONSE_FROM_PDC
:
206 ndr_err
= ndr_pull_struct_blob_all(data
, mem_ctx
, iconv_convenience
, &response
->get_pdc
,
207 (ndr_pull_flags_fn_t
)ndr_pull_nbt_netlogon_response_from_pdc
);
208 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
209 status
= ndr_map_error2ntstatus(ndr_err
);
210 DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
211 (int)data
->length
, nt_errstr(status
)));
213 file_save("netlogon.dat", data
->data
, data
->length
);
217 status
= NT_STATUS_OK
;
218 response
->response_type
= NETLOGON_GET_PDC
;
220 case LOGON_SAM_LOGON_RESPONSE
:
221 case LOGON_SAM_LOGON_PAUSE_RESPONSE
:
222 case LOGON_SAM_LOGON_USER_UNKNOWN
:
223 case LOGON_SAM_LOGON_RESPONSE_EX
:
224 case LOGON_SAM_LOGON_PAUSE_RESPONSE_EX
:
225 case LOGON_SAM_LOGON_USER_UNKNOWN_EX
:
226 status
= pull_netlogon_samlogon_response(data
, mem_ctx
, iconv_convenience
, &response
->samlogon
);
227 response
->response_type
= NETLOGON_SAMLOGON
;
230 /* These levels are queries, not responses */
231 case LOGON_PRIMARY_QUERY
:
232 case NETLOGON_ANNOUNCE_UAS
:
233 case LOGON_SAM_LOGON_REQUEST
:
234 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;