diff options
Diffstat (limited to 'libcli/netlogon')
-rw-r--r-- | libcli/netlogon/ndr_netlogon.c | 210 | ||||
-rw-r--r-- | libcli/netlogon/ndr_netlogon_proto.h | 24 | ||||
-rw-r--r-- | libcli/netlogon/netlogon.c | 272 | ||||
-rw-r--r-- | libcli/netlogon/netlogon.h | 55 | ||||
-rw-r--r-- | libcli/netlogon/netlogon_proto.h | 28 | ||||
-rw-r--r-- | libcli/netlogon/wscript_build | 11 |
6 files changed, 600 insertions, 0 deletions
diff --git a/libcli/netlogon/ndr_netlogon.c b/libcli/netlogon/ndr_netlogon.c new file mode 100644 index 0000000000..7d6aa974b0 --- /dev/null +++ b/libcli/netlogon/ndr_netlogon.c @@ -0,0 +1,210 @@ +/* + Unix SMB/CIFS implementation. + + CLDAP server structures + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* parser auto-generated by pidl, then hand-modified by abartlet */ + +#include "includes.h" +#include "../libcli/netlogon/netlogon.h" + +/* Manually modified to handle the dom_sid being optional based on if it is present or all zero */ +enum ndr_err_code ndr_push_NETLOGON_SAM_LOGON_REQUEST(struct ndr_push *ndr, int ndr_flags, const struct NETLOGON_SAM_LOGON_REQUEST *r) +{ + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->request_count)); + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM); + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->computer_name)); + ndr->flags = _flags_save_string; + } + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM); + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->user_name)); + ndr->flags = _flags_save_string; + } + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM); + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->mailslot_name)); + ndr->flags = _flags_save_string; + } + NDR_CHECK(ndr_push_samr_AcctFlags(ndr, NDR_SCALARS, r->acct_control)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_size_dom_sid0(&r->sid, ndr->flags))); + if (ndr_size_dom_sid0(&r->sid, ndr->flags)) { + struct ndr_push *_ndr_sid; + uint32_t _flags_save_DATA_BLOB = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4); + NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->_pad)); + ndr->flags = _flags_save_DATA_BLOB; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_sid, 0, ndr_size_dom_sid0(&r->sid, ndr->flags))); + NDR_CHECK(ndr_push_dom_sid0(_ndr_sid, NDR_SCALARS|NDR_BUFFERS, &r->sid)); + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_sid, 0, ndr_size_dom_sid0(&r->sid, ndr->flags))); + } + NDR_CHECK(ndr_push_netlogon_nt_version_flags(ndr, NDR_SCALARS, r->nt_version)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->lmnt_token)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->lm20_token)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +/* Manually modified to handle the dom_sid being optional based on if it is present (size is non-zero) or not */ +enum ndr_err_code ndr_pull_NETLOGON_SAM_LOGON_REQUEST(struct ndr_pull *ndr, int ndr_flags, struct NETLOGON_SAM_LOGON_REQUEST *r) +{ + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->request_count)); + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM); + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->computer_name)); + ndr->flags = _flags_save_string; + } + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM); + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->user_name)); + ndr->flags = _flags_save_string; + } + { + uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM); + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->mailslot_name)); + ndr->flags = _flags_save_string; + } + NDR_CHECK(ndr_pull_samr_AcctFlags(ndr, NDR_SCALARS, &r->acct_control)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sid_size)); + if (r->sid_size) { + uint32_t _flags_save_DATA_BLOB = ndr->flags; + struct ndr_pull *_ndr_sid; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4); + NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->_pad)); + ndr->flags = _flags_save_DATA_BLOB; + NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_sid, 0, r->sid_size)); + NDR_CHECK(ndr_pull_dom_sid0(_ndr_sid, NDR_SCALARS|NDR_BUFFERS, &r->sid)); + NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_sid, 0, r->sid_size)); + } else { + ZERO_STRUCT(r->sid); + } + NDR_CHECK(ndr_pull_netlogon_nt_version_flags(ndr, NDR_SCALARS, &r->nt_version)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->lmnt_token)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->lm20_token)); + } + if (ndr_flags & NDR_BUFFERS) { + } + return NDR_ERR_SUCCESS; +} + +/* Manually modified to only push some parts of the structure if certain flags are set */ +enum ndr_err_code ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(struct ndr_push *ndr, int ndr_flags, const struct NETLOGON_SAM_LOGON_RESPONSE_EX *r) +{ + { + uint32_t _flags_save_STRUCT = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_netlogon_command(ndr, NDR_SCALARS, r->command)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->sbz)); + NDR_CHECK(ndr_push_nbt_server_type(ndr, NDR_SCALARS, r->server_type)); + NDR_CHECK(ndr_push_GUID(ndr, NDR_SCALARS, &r->domain_uuid)); + NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->forest)); + NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->dns_domain)); + NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->pdc_dns_name)); + NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->domain_name)); + NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->pdc_name)); + NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->user_name)); + NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->server_site)); + NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->client_site)); + if (r->nt_version & NETLOGON_NT_VERSION_5EX_WITH_IP) { + NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, ndr_size_nbt_sockaddr(&r->sockaddr, ndr->flags))); + { + struct ndr_push *_ndr_sockaddr; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_sockaddr, 0, ndr_size_nbt_sockaddr(&r->sockaddr, ndr->flags))); + NDR_CHECK(ndr_push_nbt_sockaddr(_ndr_sockaddr, NDR_SCALARS|NDR_BUFFERS, &r->sockaddr)); + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_sockaddr, 0, ndr_size_nbt_sockaddr(&r->sockaddr, ndr->flags))); + } + } + if (r->nt_version & NETLOGON_NT_VERSION_WITH_CLOSEST_SITE) { + NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->next_closest_site)); + } + NDR_CHECK(ndr_push_netlogon_nt_version_flags(ndr, NDR_SCALARS, r->nt_version)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->lmnt_token)); + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->lm20_token)); + } + if (ndr_flags & NDR_BUFFERS) { + NDR_CHECK(ndr_push_GUID(ndr, NDR_BUFFERS, &r->domain_uuid)); + } + ndr->flags = _flags_save_STRUCT; + } + return NDR_ERR_SUCCESS; +} + +/* Manually modified to only pull some parts of the structure if certain flags provided */ +enum ndr_err_code ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(struct ndr_pull *ndr, int ndr_flags, struct NETLOGON_SAM_LOGON_RESPONSE_EX *r, + uint32_t nt_version_flags) +{ + { + uint32_t _flags_save_STRUCT = ndr->flags; + ZERO_STRUCTP(r); + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN); + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_netlogon_command(ndr, NDR_SCALARS, &r->command)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->sbz)); + NDR_CHECK(ndr_pull_nbt_server_type(ndr, NDR_SCALARS, &r->server_type)); + NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->domain_uuid)); + NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->forest)); + NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->dns_domain)); + NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->pdc_dns_name)); + NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->domain_name)); + NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->pdc_name)); + NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->user_name)); + NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->server_site)); + NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->client_site)); + if (nt_version_flags & NETLOGON_NT_VERSION_5EX_WITH_IP) { + NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sockaddr_size)); + { + struct ndr_pull *_ndr_sockaddr; + NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_sockaddr, 0, r->sockaddr_size)); + NDR_CHECK(ndr_pull_nbt_sockaddr(_ndr_sockaddr, NDR_SCALARS|NDR_BUFFERS, &r->sockaddr)); + NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_sockaddr, 0, r->sockaddr_size)); + } + } + if (nt_version_flags & NETLOGON_NT_VERSION_WITH_CLOSEST_SITE) { + NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->next_closest_site)); + } + NDR_CHECK(ndr_pull_netlogon_nt_version_flags(ndr, NDR_SCALARS, &r->nt_version)); + if (r->nt_version != nt_version_flags) { + return NDR_ERR_VALIDATE; + } + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->lmnt_token)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->lm20_token)); + } + if (ndr_flags & NDR_BUFFERS) { + NDR_CHECK(ndr_pull_GUID(ndr, NDR_BUFFERS, &r->domain_uuid)); + } + ndr->flags = _flags_save_STRUCT; + } + return NDR_ERR_SUCCESS; +} diff --git a/libcli/netlogon/ndr_netlogon_proto.h b/libcli/netlogon/ndr_netlogon_proto.h new file mode 100644 index 0000000000..ca61c16138 --- /dev/null +++ b/libcli/netlogon/ndr_netlogon_proto.h @@ -0,0 +1,24 @@ +#ifndef _____LIBCLI_NDR_NETLOGON_PROTO_H__ +#define _____LIBCLI_NDR_NETLOGON_PROTO_H__ + +#undef _PRINTF_ATTRIBUTE +#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2) +/* This file was automatically generated by mkproto.pl. DO NOT EDIT */ + +/* this file contains prototypes for functions that are private + * to this subsystem or library. These functions should not be + * used outside this particular subsystem! */ + + +/* The following definitions come from ../libcli/ndr_netlogon.c */ + +enum ndr_err_code ndr_push_NETLOGON_SAM_LOGON_REQUEST(struct ndr_push *ndr, int ndr_flags, const struct NETLOGON_SAM_LOGON_REQUEST *r); +enum ndr_err_code ndr_pull_NETLOGON_SAM_LOGON_REQUEST(struct ndr_pull *ndr, int ndr_flags, struct NETLOGON_SAM_LOGON_REQUEST *r); +enum ndr_err_code ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(struct ndr_push *ndr, int ndr_flags, const struct NETLOGON_SAM_LOGON_RESPONSE_EX *r); +enum ndr_err_code ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(struct ndr_pull *ndr, int ndr_flags, struct NETLOGON_SAM_LOGON_RESPONSE_EX *r, + uint32_t nt_version_flags); +#undef _PRINTF_ATTRIBUTE +#define _PRINTF_ATTRIBUTE(a1, a2) + +#endif /* _____LIBCLI_NDR_NETLOGON_PROTO_H__ */ + diff --git a/libcli/netlogon/netlogon.c b/libcli/netlogon/netlogon.c new file mode 100644 index 0000000000..d82a2013b8 --- /dev/null +++ b/libcli/netlogon/netlogon.c @@ -0,0 +1,272 @@ +/* + Unix SMB/CIFS implementation. + + CLDAP server structures + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "../libcli/netlogon/netlogon.h" + +NTSTATUS push_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx, + struct netlogon_samlogon_response *response) +{ + enum ndr_err_code ndr_err; + if (response->ntver == NETLOGON_NT_VERSION_1) { + ndr_err = ndr_push_struct_blob(data, mem_ctx, + &response->data.nt4, + (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_NT40); + } else if (response->ntver & NETLOGON_NT_VERSION_5EX) { + ndr_err = ndr_push_struct_blob(data, mem_ctx, + &response->data.nt5_ex, + (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags); + } else if (response->ntver & NETLOGON_NT_VERSION_5) { + ndr_err = ndr_push_struct_blob(data, mem_ctx, + &response->data.nt5, + (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE); + } else { + DEBUG(0, ("Asked to push unknown netlogon response type 0x%02x\n", response->ntver)); + return NT_STATUS_INVALID_PARAMETER; + } + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(2,("failed to push netlogon response of type 0x%02x\n", + response->ntver)); + return ndr_map_error2ntstatus(ndr_err); + } + return NT_STATUS_OK; +} + +NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx, + struct netlogon_samlogon_response *response) +{ + uint32_t ntver; + enum ndr_err_code ndr_err; + + if (data->length < 8) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + /* lmnttoken */ + if (SVAL(data->data, data->length - 4) != 0xffff) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + /* lm20token */ + if (SVAL(data->data, data->length - 2) != 0xffff) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + ntver = IVAL(data->data, data->length - 8); + + if (ntver == NETLOGON_NT_VERSION_1) { + ndr_err = ndr_pull_struct_blob_all(data, mem_ctx, + &response->data.nt4, + (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_NT40); + response->ntver = NETLOGON_NT_VERSION_1; + if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_NT40, + &response->data.nt4); + } + + } else if (ntver & NETLOGON_NT_VERSION_5EX) { + struct ndr_pull *ndr; + ndr = ndr_pull_init_blob(data, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + ndr_err = ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags( + ndr, NDR_SCALARS|NDR_BUFFERS, &response->data.nt5_ex, + ntver); + if (ndr->offset < ndr->data_size) { + ndr_err = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES, + "not all bytes consumed ofs[%u] size[%u]", + ndr->offset, ndr->data_size); + } + response->ntver = NETLOGON_NT_VERSION_5EX; + if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_EX, + &response->data.nt5_ex); + } + + } else if (ntver & NETLOGON_NT_VERSION_5) { + ndr_err = ndr_pull_struct_blob_all(data, mem_ctx, + &response->data.nt5, + (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE); + response->ntver = NETLOGON_NT_VERSION_5; + if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE, + &response->data.nt5); + } + } else { + DEBUG(2,("failed to parse netlogon response of type 0x%02x - unknown response type\n", + ntver)); + dump_data(10, data->data, data->length); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(2,("failed to parse netlogon response of type 0x%02x\n", + ntver)); + dump_data(10, data->data, data->length); + return ndr_map_error2ntstatus(ndr_err); + } + + return NT_STATUS_OK; +} + +void map_netlogon_samlogon_response(struct netlogon_samlogon_response *response) +{ + struct NETLOGON_SAM_LOGON_RESPONSE_EX response_5_ex; + switch (response->ntver) { + case NETLOGON_NT_VERSION_5EX: + break; + case NETLOGON_NT_VERSION_5: + ZERO_STRUCT(response_5_ex); + response_5_ex.command = response->data.nt5.command; + response_5_ex.pdc_name = response->data.nt5.pdc_name; + response_5_ex.user_name = response->data.nt5.user_name; + response_5_ex.domain_name = response->data.nt5.domain_name; + response_5_ex.domain_uuid = response->data.nt5.domain_uuid; + response_5_ex.forest = response->data.nt5.forest; + response_5_ex.dns_domain = response->data.nt5.dns_domain; + response_5_ex.pdc_dns_name = response->data.nt5.pdc_dns_name; + response_5_ex.sockaddr.pdc_ip = response->data.nt5.pdc_ip; + response_5_ex.server_type = response->data.nt5.server_type; + response_5_ex.nt_version = response->data.nt5.nt_version; + response_5_ex.lmnt_token = response->data.nt5.lmnt_token; + response_5_ex.lm20_token = response->data.nt5.lm20_token; + response->ntver = NETLOGON_NT_VERSION_5EX; + response->data.nt5_ex = response_5_ex; + break; + + case NETLOGON_NT_VERSION_1: + ZERO_STRUCT(response_5_ex); + response_5_ex.command = response->data.nt4.command; + response_5_ex.pdc_name = response->data.nt4.pdc_name; + response_5_ex.user_name = response->data.nt4.user_name; + response_5_ex.domain_name = response->data.nt4.domain_name; + response_5_ex.nt_version = response->data.nt4.nt_version; + response_5_ex.lmnt_token = response->data.nt4.lmnt_token; + response_5_ex.lm20_token = response->data.nt4.lm20_token; + response->ntver = NETLOGON_NT_VERSION_5EX; + response->data.nt5_ex = response_5_ex; + break; + } + return; +} + +NTSTATUS push_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx, + struct nbt_netlogon_response *response) +{ + NTSTATUS status = NT_STATUS_INVALID_NETWORK_RESPONSE; + enum ndr_err_code ndr_err; + switch (response->response_type) { + case NETLOGON_GET_PDC: + ndr_err = ndr_push_struct_blob(data, mem_ctx, + &response->data.get_pdc, + (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response_from_pdc); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n", + (int)data->length, nt_errstr(status))); + if (DEBUGLVL(10)) { + file_save("netlogon.dat", data->data, data->length); + } + return status; + } + status = NT_STATUS_OK; + break; + case NETLOGON_SAMLOGON: + status = push_netlogon_samlogon_response( + data, mem_ctx, + &response->data.samlogon); + break; + case NETLOGON_RESPONSE2: + ndr_err = ndr_push_struct_blob(data, mem_ctx, + &response->data.response2, + (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response2); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } + status = NT_STATUS_OK; + break; + } + + return status; +} + + +NTSTATUS pull_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx, + struct nbt_netlogon_response *response) +{ + NTSTATUS status = NT_STATUS_INVALID_NETWORK_RESPONSE; + enum netlogon_command command; + enum ndr_err_code ndr_err; + if (data->length < 4) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + command = SVAL(data->data, 0); + + switch (command) { + case NETLOGON_RESPONSE_FROM_PDC: + ndr_err = ndr_pull_struct_blob_all(data, mem_ctx, + &response->data.get_pdc, + (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response_from_pdc); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n", + (int)data->length, nt_errstr(status))); + if (DEBUGLVL(10)) { + file_save("netlogon.dat", data->data, data->length); + } + return status; + } + status = NT_STATUS_OK; + response->response_type = NETLOGON_GET_PDC; + break; + case LOGON_RESPONSE2: + ndr_err = ndr_pull_struct_blob(data, mem_ctx, &response->data.response2, + (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response2); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } + status = NT_STATUS_OK; + response->response_type = NETLOGON_RESPONSE2; + break; + case LOGON_SAM_LOGON_RESPONSE: + case LOGON_SAM_LOGON_PAUSE_RESPONSE: + case LOGON_SAM_LOGON_USER_UNKNOWN: + case LOGON_SAM_LOGON_RESPONSE_EX: + case LOGON_SAM_LOGON_PAUSE_RESPONSE_EX: + case LOGON_SAM_LOGON_USER_UNKNOWN_EX: + status = pull_netlogon_samlogon_response( + data, mem_ctx, + &response->data.samlogon); + response->response_type = NETLOGON_SAMLOGON; + break; + + /* These levels are queries, not responses */ + case LOGON_PRIMARY_QUERY: + case LOGON_REQUEST: + case NETLOGON_ANNOUNCE_UAS: + case LOGON_SAM_LOGON_REQUEST: + status = NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + return status; + +} diff --git a/libcli/netlogon/netlogon.h b/libcli/netlogon/netlogon.h new file mode 100644 index 0000000000..9bf346af26 --- /dev/null +++ b/libcli/netlogon/netlogon.h @@ -0,0 +1,55 @@ +/* + Unix SMB/CIFS implementation. + + CLDAP server structures + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __LIBCLI_NETLOGON_H__ +#define __LIBCLI_NETLOGON_H__ + +#include "librpc/gen_ndr/ndr_nbt.h" + +#include "librpc/gen_ndr/ndr_misc.h" +#include "librpc/gen_ndr/ndr_security.h" +#include "librpc/gen_ndr/ndr_svcctl.h" +#include "librpc/gen_ndr/ndr_samr.h" + +struct netlogon_samlogon_response +{ + uint32_t ntver; + union { + struct NETLOGON_SAM_LOGON_RESPONSE_NT40 nt4; + struct NETLOGON_SAM_LOGON_RESPONSE nt5; + struct NETLOGON_SAM_LOGON_RESPONSE_EX nt5_ex; + } data; + +}; + +struct nbt_netlogon_response +{ + enum {NETLOGON_GET_PDC, NETLOGON_SAMLOGON, NETLOGON_RESPONSE2} response_type; + union { + struct nbt_netlogon_response_from_pdc get_pdc; + struct netlogon_samlogon_response samlogon; + struct nbt_netlogon_response2 response2; + } data; +}; + +#include "../libcli/netlogon/netlogon_proto.h" +#include "../libcli/netlogon/ndr_netlogon_proto.h" +#endif /* __CLDAP_SERVER_PROTO_H__ */ diff --git a/libcli/netlogon/netlogon_proto.h b/libcli/netlogon/netlogon_proto.h new file mode 100644 index 0000000000..53c7d004ee --- /dev/null +++ b/libcli/netlogon/netlogon_proto.h @@ -0,0 +1,28 @@ +#ifndef _____LIBCLI_NETLOGON_PROTO_H__ +#define _____LIBCLI_NETLOGON_PROTO_H__ + +#undef _PRINTF_ATTRIBUTE +#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2) +/* This file was automatically generated by mkproto.pl. DO NOT EDIT */ + +/* this file contains prototypes for functions that are private + * to this subsystem or library. These functions should not be + * used outside this particular subsystem! */ + + +/* The following definitions come from ../libcli/netlogon.c */ + +NTSTATUS push_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx, + struct netlogon_samlogon_response *response); +NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx, + struct netlogon_samlogon_response *response); +void map_netlogon_samlogon_response(struct netlogon_samlogon_response *response); +NTSTATUS push_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx, + struct nbt_netlogon_response *response); +NTSTATUS pull_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx, + struct nbt_netlogon_response *response); +#undef _PRINTF_ATTRIBUTE +#define _PRINTF_ATTRIBUTE(a1, a2) + +#endif /* _____LIBCLI_NETLOGON_PROTO_H__ */ + diff --git a/libcli/netlogon/wscript_build b/libcli/netlogon/wscript_build new file mode 100644 index 0000000000..6c5e57ba67 --- /dev/null +++ b/libcli/netlogon/wscript_build @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +bld.SAMBA_SUBSYSTEM('LIBCLI_NDR_NETLOGON', + source='ndr_netlogon.c', + public_deps='ndr NDR_SECURITY' + ) + +bld.SAMBA_SUBSYSTEM('LIBCLI_NETLOGON', + source='netlogon.c', + public_deps='samba-util LIBCLI_NDR_NETLOGON' + ) |