diff options
Diffstat (limited to 'source3/rpc_client/util_netlogon.c')
-rw-r--r-- | source3/rpc_client/util_netlogon.c | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/source3/rpc_client/util_netlogon.c b/source3/rpc_client/util_netlogon.c new file mode 100644 index 0000000..52bd40b --- /dev/null +++ b/source3/rpc_client/util_netlogon.c @@ -0,0 +1,449 @@ +/* + Unix SMB/CIFS implementation. + Authentication utility functions + Copyright (C) Volker Lendecke 2010 + + 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 "../librpc/gen_ndr/netlogon.h" +#include "../libcli/security/security.h" +#include "rpc_client/util_netlogon.h" + +#define COPY_LSA_STRING(mem_ctx, in, out, name) do { \ + if (in->name.string) { \ + out->name.string = talloc_strdup(mem_ctx, in->name.string); \ + NT_STATUS_HAVE_NO_MEMORY(out->name.string); \ + } \ +} while (0) + +NTSTATUS copy_netr_SamBaseInfo(TALLOC_CTX *mem_ctx, + const struct netr_SamBaseInfo *in, + struct netr_SamBaseInfo *out) +{ + /* first copy all, then realloc pointers */ + *out = *in; + + COPY_LSA_STRING(mem_ctx, in, out, account_name); + COPY_LSA_STRING(mem_ctx, in, out, full_name); + COPY_LSA_STRING(mem_ctx, in, out, logon_script); + COPY_LSA_STRING(mem_ctx, in, out, profile_path); + COPY_LSA_STRING(mem_ctx, in, out, home_directory); + COPY_LSA_STRING(mem_ctx, in, out, home_drive); + + if (in->groups.count) { + out->groups.rids = (struct samr_RidWithAttribute *) + talloc_memdup(mem_ctx, in->groups.rids, + (sizeof(struct samr_RidWithAttribute) * + in->groups.count)); + NT_STATUS_HAVE_NO_MEMORY(out->groups.rids); + } + + COPY_LSA_STRING(mem_ctx, in, out, logon_server); + COPY_LSA_STRING(mem_ctx, in, out, logon_domain); + + if (in->domain_sid) { + out->domain_sid = dom_sid_dup(mem_ctx, in->domain_sid); + NT_STATUS_HAVE_NO_MEMORY(out->domain_sid); + } + + return NT_STATUS_OK; +} + +NTSTATUS copy_netr_SamInfo3(TALLOC_CTX *mem_ctx, + const struct netr_SamInfo3 *in, + struct netr_SamInfo3 **pout) +{ + struct netr_SamInfo3 *info3 = NULL; + unsigned int i; + NTSTATUS status; + + info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); + if (info3 == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + + status = copy_netr_SamBaseInfo(info3, &in->base, &info3->base); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + if (in->sidcount) { + info3->sidcount = in->sidcount; + info3->sids = talloc_array(info3, struct netr_SidAttr, + in->sidcount); + if (info3->sids == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + + for (i = 0; i < in->sidcount; i++) { + info3->sids[i].sid = dom_sid_dup(info3->sids, + in->sids[i].sid); + if (info3->sids[i].sid == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + info3->sids[i].attributes = in->sids[i].attributes; + } + } + + *pout = info3; + info3 = NULL; + + status = NT_STATUS_OK; +out: + TALLOC_FREE(info3); + return status; +} + +NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, + uint16_t validation_level, + union netr_Validation *validation, + struct netr_SamInfo3 **info3_p) +{ + struct netr_SamInfo3 *info3 = NULL; + struct netr_SamInfo6 *info6 = NULL; + NTSTATUS status; + + if (validation == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + switch (validation_level) { + case 3: + if (validation->sam3 == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + status = copy_netr_SamInfo3(mem_ctx, + validation->sam3, + &info3); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + break; + case 6: + if (validation->sam6 == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + info6 = validation->sam6; + + info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); + if (info3 == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = copy_netr_SamBaseInfo(info3, + &info6->base, + &info3->base); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(info3); + return status; + } + + if (validation->sam6->sidcount > 0) { + int i; + + info3->sidcount = info6->sidcount; + + info3->sids = talloc_array(info3, + struct netr_SidAttr, + info3->sidcount); + if (info3->sids == NULL) { + TALLOC_FREE(info3); + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < info3->sidcount; i++) { + info3->sids[i].sid = dom_sid_dup( + info3->sids, info6->sids[i].sid); + if (info3->sids[i].sid == NULL) { + TALLOC_FREE(info3); + return NT_STATUS_NO_MEMORY; + } + info3->sids[i].attributes = + info6->sids[i].attributes; + } + } + break; + default: + return NT_STATUS_BAD_VALIDATION_CLASS; + } + + *info3_p = info3; + + return NT_STATUS_OK; +} + +NTSTATUS copy_netr_SamInfo6(TALLOC_CTX *mem_ctx, + const struct netr_SamInfo6 *in, + struct netr_SamInfo6 **pout) +{ + struct netr_SamInfo6 *info6 = NULL; + unsigned int i; + NTSTATUS status; + + info6 = talloc_zero(mem_ctx, struct netr_SamInfo6); + if (info6 == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + + status = copy_netr_SamBaseInfo(info6, &in->base, &info6->base); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + if (in->sidcount) { + info6->sidcount = in->sidcount; + info6->sids = talloc_array(info6, struct netr_SidAttr, + in->sidcount); + if (info6->sids == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + + for (i = 0; i < in->sidcount; i++) { + info6->sids[i].sid = dom_sid_dup(info6->sids, + in->sids[i].sid); + if (info6->sids[i].sid == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + info6->sids[i].attributes = in->sids[i].attributes; + } + } + + if (in->dns_domainname.string != NULL) { + info6->dns_domainname.string = talloc_strdup(info6, + in->dns_domainname.string); + if (info6->dns_domainname.string == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + } + + if (in->principal_name.string != NULL) { + info6->principal_name.string = talloc_strdup(info6, + in->principal_name.string); + if (info6->principal_name.string == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + } + + *pout = info6; + info6 = NULL; + + status = NT_STATUS_OK; +out: + TALLOC_FREE(info6); + return status; +} + +NTSTATUS map_validation_to_info6(TALLOC_CTX *mem_ctx, + uint16_t validation_level, + union netr_Validation *validation, + struct netr_SamInfo6 **info6_p) +{ + struct netr_SamInfo3 *info3 = NULL; + struct netr_SamInfo6 *info6 = NULL; + NTSTATUS status; + + if (validation == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + switch (validation_level) { + case 3: + if (validation->sam3 == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + info3 = validation->sam3; + + info6 = talloc_zero(mem_ctx, struct netr_SamInfo6); + if (info6 == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = copy_netr_SamBaseInfo(info6, + &info3->base, + &info6->base); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(info6); + return status; + } + + if (validation->sam3->sidcount > 0) { + int i; + + info6->sidcount = info3->sidcount; + + info6->sids = talloc_array(info6, + struct netr_SidAttr, + info6->sidcount); + if (info6->sids == NULL) { + TALLOC_FREE(info6); + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < info6->sidcount; i++) { + info6->sids[i].sid = dom_sid_dup( + info6->sids, info3->sids[i].sid); + if (info6->sids[i].sid == NULL) { + TALLOC_FREE(info6); + return NT_STATUS_NO_MEMORY; + } + info6->sids[i].attributes = + info3->sids[i].attributes; + } + } + break; + case 6: + if (validation->sam6 == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + status = copy_netr_SamInfo6(mem_ctx, + validation->sam6, + &info6); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + break; + default: + return NT_STATUS_BAD_VALIDATION_CLASS; + } + + *info6_p = info6; + + return NT_STATUS_OK; +} + +NTSTATUS map_info3_to_validation(TALLOC_CTX *mem_ctx, + struct netr_SamInfo3 *info3, + uint16_t *_validation_level, + union netr_Validation **_validation) +{ + union netr_Validation *validation = NULL; + NTSTATUS status; + + validation = talloc_zero(mem_ctx, union netr_Validation); + if (validation == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = copy_netr_SamInfo3(mem_ctx, + info3, + &validation->sam3); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(validation); + return status; + } + + * _validation_level = 3; + *_validation = validation; + return NT_STATUS_OK; +} + +NTSTATUS map_info6_to_validation(TALLOC_CTX *mem_ctx, + const struct netr_SamInfo6 *info6, + uint16_t *_validation_level, + union netr_Validation **_validation) +{ + union netr_Validation *validation = NULL; + NTSTATUS status; + + validation = talloc_zero(mem_ctx, union netr_Validation); + if (validation == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = copy_netr_SamInfo6(validation, + info6, + &validation->sam6); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(validation); + return status; + } + + * _validation_level = 6; + *_validation = validation; + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS copy_netr_DsRGetDCNameInfo(TALLOC_CTX *mem_ctx, + const struct netr_DsRGetDCNameInfo *in, + struct netr_DsRGetDCNameInfo **pout) +{ + struct netr_DsRGetDCNameInfo *r; + + r = talloc_zero(mem_ctx, struct netr_DsRGetDCNameInfo); + if (r == NULL) { + return NT_STATUS_NO_MEMORY; + } + + r->dc_unc = talloc_strdup(r, in->dc_unc); + if (r->dc_unc == NULL) { + talloc_free(r); + return NT_STATUS_NO_MEMORY; + } + r->dc_address = talloc_strdup(r, in->dc_address); + if (r->dc_address == NULL) { + talloc_free(r); + return NT_STATUS_NO_MEMORY; + } + r->dc_address_type = in->dc_address_type; + r->domain_guid = in->domain_guid; + r->domain_name = talloc_strdup(r, in->domain_name); + if (r->domain_name == NULL) { + talloc_free(r); + return NT_STATUS_NO_MEMORY; + } + /* forest could be empty */ + if (in->forest_name != NULL) { + r->forest_name = talloc_strdup(r, in->forest_name); + if (r->forest_name == NULL) { + talloc_free(r); + return NT_STATUS_NO_MEMORY; + } + } + r->dc_flags = in->dc_flags; + if (in->dc_site_name != NULL) { + r->dc_site_name = talloc_strdup(r, in->dc_site_name); + if (r->dc_site_name == NULL) { + talloc_free(r); + return NT_STATUS_NO_MEMORY; + } + } + if (in->client_site_name != NULL) { + r->client_site_name = talloc_strdup(r, in->client_site_name); + if (r->client_site_name == NULL) { + talloc_free(r); + return NT_STATUS_NO_MEMORY; + } + } + + *pout = r; + + return NT_STATUS_OK; +} |