static NTSTATUS rpc_service_create_internal(struct net_context *c, const DOM_SID *domain_sid, const char *domain_name, struct cli_state *cli, struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, int argc, const char **argv) { struct policy_handle hSCM, hService; WERROR result = WERR_GENERAL_FAILURE; NTSTATUS status; const char *ServiceName; const char *DisplayName; const char *binary_path; if (argc != 3) { d_printf(_("Usage: net rpc service create <service> " "<displayname> <binarypath>\n")); return NT_STATUS_OK; } /* Open the Service Control Manager */ status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx, pipe_hnd->srv_name_slash, NULL, SC_RIGHT_MGR_CREATE_SERVICE, &hSCM, &result); if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) { d_fprintf(stderr, _("Failed to open Service Control Manager. [%s]\n"), win_errstr(result)); return werror_to_ntstatus(result); } /* Create the service */ ServiceName = argv[0]; DisplayName = argv[1]; binary_path = argv[2]; status = rpccli_svcctl_CreateServiceW(pipe_hnd, mem_ctx, &hSCM, ServiceName, DisplayName, SERVICE_ALL_ACCESS, SERVICE_TYPE_WIN32_OWN_PROCESS, SVCCTL_DEMAND_START, SVCCTL_SVC_ERROR_NORMAL, binary_path, NULL, /* LoadOrderGroupKey */ NULL, /* TagId */ NULL, /* dependencies */ 0, /* dependencies_size */ NULL, /* service_start_name */ NULL, /* password */ 0, /* password_size */ &hService, &result); if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) { d_fprintf(stderr, _("Create service request failed. [%s]\n"), win_errstr(result)); goto done; } d_printf(_("Successfully created Service: %s\n"), argv[0]); done: if (is_valid_policy_hnd(&hService)) { rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL); } if (is_valid_policy_hnd(&hSCM)) { rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL); } return werror_to_ntstatus(result); }
static WERROR cmd_drsuapi_getdcinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; WERROR werr; struct GUID bind_guid; struct policy_handle bind_handle; struct dcerpc_binding_handle *b = cli->binding_handle; const char *domain = NULL; int32_t level = 1; int32_t level_out; union drsuapi_DsGetDCInfoRequest req; union drsuapi_DsGetDCInfoCtr ctr; if (argc < 2) { printf("usage: %s domain [level]\n", argv[0]); return WERR_OK; } domain = argv[1]; if (argc >= 3) { level = atoi(argv[2]); } GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid); status = dcerpc_drsuapi_DsBind(b, mem_ctx, &bind_guid, NULL, &bind_handle, &werr); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (!W_ERROR_IS_OK(werr)) { return werr; } req.req1.domain_name = domain; req.req1.level = level; status = dcerpc_drsuapi_DsGetDomainControllerInfo(b, mem_ctx, &bind_handle, 1, &req, &level_out, &ctr, &werr); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto out; } if (!W_ERROR_IS_OK(werr)) { goto out; } display_domain_controller_info(level_out, &ctr); out: if (is_valid_policy_hnd(&bind_handle)) { WERROR _werr; dcerpc_drsuapi_DsUnbind(b, mem_ctx, &bind_handle, &_werr); } return werr; }
static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32_t num_sids, const struct dom_sid *sids, uint32_t *pnum_aliases, uint32_t **palias_rids) { struct rpc_pipe_client *samr_pipe; struct policy_handle dom_pol; uint32_t num_aliases = 0; uint32_t *alias_rids = NULL; TALLOC_CTX *tmp_ctx; NTSTATUS status, result; struct dcerpc_binding_handle *b = NULL; DEBUG(3,("sam_lookup_useraliases\n")); ZERO_STRUCT(dom_pol); if (pnum_aliases) { *pnum_aliases = 0; } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } b = samr_pipe->binding_handle; status = rpc_lookup_useraliases(tmp_ctx, samr_pipe, &dom_pol, num_sids, sids, &num_aliases, &alias_rids); if (!NT_STATUS_IS_OK(status)) { goto done; } if (pnum_aliases) { *pnum_aliases = num_aliases; } if (palias_rids) { *palias_rids = talloc_move(mem_ctx, &alias_rids); } done: if (b && is_valid_policy_hnd(&dom_pol)) { dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); } TALLOC_FREE(tmp_ctx); return status; }
static NTSTATUS rpc_service_delete_internal(struct net_context *c, const DOM_SID *domain_sid, const char *domain_name, struct cli_state *cli, struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, int argc, const char **argv) { struct policy_handle hSCM, hService; WERROR result = WERR_GENERAL_FAILURE; NTSTATUS status; if (argc != 1 ) { d_printf(_("Usage: net rpc service delete <service>\n")); return NT_STATUS_OK; } /* Open the Service Control Manager */ status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx, pipe_hnd->srv_name_slash, NULL, SC_RIGHT_MGR_ENUMERATE_SERVICE, &hSCM, &result); if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) { d_fprintf(stderr, _("Failed to open Service Control Manager. [%s]\n"), win_errstr(result)); return werror_to_ntstatus(result); } /* Open the Service */ status = rpccli_svcctl_OpenServiceW(pipe_hnd, mem_ctx, &hSCM, argv[0], SERVICE_ALL_ACCESS, &hService, &result); if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) { d_fprintf(stderr, _("Failed to open service. [%s]\n"), win_errstr(result)); goto done; } /* Delete the Service */ status = rpccli_svcctl_DeleteService(pipe_hnd, mem_ctx, &hService, &result); if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) { d_fprintf(stderr, _("Delete service request failed. [%s]\n"), win_errstr(result)); goto done; } d_printf(_("Successfully deleted Service: %s\n"), argv[0]); done: if (is_valid_policy_hnd(&hService)) { rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL); } if (is_valid_policy_hnd(&hSCM)) { rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL); } return werror_to_ntstatus(result); }
static bool sync_eventlog_params(TALLOC_CTX *mem_ctx, struct messaging_context *msg_ctx, EVENTLOG_INFO *info) { struct dcerpc_binding_handle *h = NULL; uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED; struct policy_handle hive_hnd, key_hnd; uint32_t uiMaxSize = 0; uint32_t uiRetention = 0; char *path = NULL; NTSTATUS status; WERROR wresult = WERR_OK; char *elogname = info->logname; TALLOC_CTX *ctx; bool ret = false; ctx = talloc_stackframe(); if (ctx == NULL) { return false; } DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) ); if ( !info->etdb ) { DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) ); goto done; } /* set resonable defaults. 512Kb on size and 1 week on time */ uiMaxSize = 0x80000; uiRetention = 604800; /* the general idea is to internally open the registry key and retrieve the values. That way we can continue to use the same fetch/store api that we use in srv_reg_nt.c */ path = talloc_asprintf(ctx, "%s\\%s", TOP_LEVEL_EVENTLOG_KEY, elogname); if (!path) { goto done; } status = dcerpc_winreg_int_hklm_openkey(ctx, get_session_info_system(), msg_ctx, &h, path, false, access_mask, &hive_hnd, &key_hnd, &wresult); if (!NT_STATUS_IS_OK(status)) { DEBUG(4,("sync_eventlog_params: Failed to open key [%s] (%s)\n", path, nt_errstr(status))); goto done; } if ( !W_ERROR_IS_OK( wresult ) ) { DEBUG( 4, ( "sync_eventlog_params: Failed to open key [%s] (%s)\n", path, win_errstr( wresult ) ) ); goto done; } status = dcerpc_winreg_query_dword(ctx, h, &key_hnd, "Retention", &uiRetention, &wresult); if (!NT_STATUS_IS_OK(status)) { DEBUG(4, ("Failed to query value \"Retention\": %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(wresult)) { DEBUG(4, ("Failed to query value \"Retention\": %s\n", win_errstr(wresult))); goto done; } status = dcerpc_winreg_query_dword(ctx, h, &key_hnd, "MaxSize", &uiMaxSize, &wresult); if (!NT_STATUS_IS_OK(status)) { DEBUG(4, ("Failed to query value \"Retention\": %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(wresult)) { DEBUG(4, ("Failed to query value \"MaxSize\": %s\n", win_errstr(wresult))); goto done; } tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize ); tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention ); ret = true; done: if (h != NULL) { WERROR ignore; if (is_valid_policy_hnd(&key_hnd)) { dcerpc_winreg_CloseKey(h, ctx, &key_hnd, &ignore); } if (is_valid_policy_hnd(&hive_hnd)) { dcerpc_winreg_CloseKey(h, ctx, &hive_hnd, &ignore); } } TALLOC_FREE(ctx); return ret; }
static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid, uint32 *rids, size_t num_rids, char **pdomain_name, char ***pnames, enum lsa_SidType **ptypes) { struct rpc_pipe_client *lsa_pipe; struct policy_handle lsa_policy; enum lsa_SidType *types = NULL; char *domain_name = NULL; char **names = NULL; TALLOC_CTX *tmp_ctx; NTSTATUS status, result; struct dcerpc_binding_handle *b = NULL; DEBUG(3,("sam_rids_to_names for %s\n", domain->name)); ZERO_STRUCT(lsa_policy); /* Paranoia check */ if (!sid_check_is_builtin(domain_sid) && !sid_check_is_domain(domain_sid) && !sid_check_is_unix_users(domain_sid) && !sid_check_is_unix_groups(domain_sid) && !sid_check_is_in_wellknown_domain(domain_sid)) { DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to " "lookup SID %s\n", sid_string_dbg(domain_sid))); return NT_STATUS_NONE_MAPPED; } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } b = lsa_pipe->binding_handle; status = rpc_rids_to_names(tmp_ctx, lsa_pipe, &lsa_policy, domain, domain_sid, rids, num_rids, &domain_name, &names, &types); if (!NT_STATUS_IS_OK(status)) { goto done; } if (pdomain_name) { *pdomain_name = talloc_move(mem_ctx, &domain_name); } if (ptypes) { *ptypes = talloc_move(mem_ctx, &types); } if (pnames) { *pnames = talloc_move(mem_ctx, &names); } done: if (b && is_valid_policy_hnd(&lsa_policy)) { dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); } TALLOC_FREE(tmp_ctx); return status; }
WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx, struct NetLocalGroupDel *r) { struct rpc_pipe_client *pipe_cli = NULL; NTSTATUS status, result; WERROR werr; struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle; struct dom_sid2 *domain_sid = NULL; struct dcerpc_binding_handle *b = NULL; if (!r->in.group_name) { return WERR_INVALID_PARAM; } ZERO_STRUCT(connect_handle); ZERO_STRUCT(builtin_handle); ZERO_STRUCT(domain_handle); ZERO_STRUCT(alias_handle); werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } b = pipe_cli->binding_handle; werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli, SAMR_ACCESS_LOOKUP_DOMAIN | SAMR_ACCESS_ENUM_DOMAINS, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &builtin_handle); if (!W_ERROR_IS_OK(werr)) { goto done; } status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &builtin_handle, r->in.group_name, SEC_STD_DELETE, &alias_handle); if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); } if (NT_STATUS_IS_OK(status)) { goto delete_alias; } werr = libnetapi_samr_open_domain(ctx, pipe_cli, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, SAMR_DOMAIN_ACCESS_CREATE_ALIAS | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &domain_handle, &domain_sid); if (!W_ERROR_IS_OK(werr)) { goto done; } status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &domain_handle, r->in.group_name, SEC_STD_DELETE, &alias_handle); if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); } if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } delete_alias: status = dcerpc_samr_DeleteDomAlias(b, talloc_tos(), &alias_handle, &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } ZERO_STRUCT(alias_handle); werr = WERR_OK; done: if (is_valid_policy_hnd(&alias_handle)) { dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result); } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); libnetapi_samr_close_connect_handle(ctx, &connect_handle); } return werr; }
static NTSTATUS cmd_lsa_query_secret(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; struct policy_handle handle, sec_handle; struct lsa_String name; struct lsa_DATA_BUF_PTR new_val; NTTIME new_mtime = 0; struct lsa_DATA_BUF_PTR old_val; NTTIME old_mtime = 0; DATA_BLOB session_key; DATA_BLOB new_blob = data_blob_null; DATA_BLOB old_blob = data_blob_null; char *new_secret, *old_secret; if (argc < 2) { printf("Usage: %s name\n", argv[0]); return NT_STATUS_OK; } status = rpccli_lsa_open_policy2(cli, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &handle); if (!NT_STATUS_IS_OK(status)) { return status; } init_lsa_String(&name, argv[1]); status = rpccli_lsa_OpenSecret(cli, mem_ctx, &handle, name, SEC_FLAG_MAXIMUM_ALLOWED, &sec_handle); if (!NT_STATUS_IS_OK(status)) { goto done; } ZERO_STRUCT(new_val); ZERO_STRUCT(old_val); status = rpccli_lsa_QuerySecret(cli, mem_ctx, &sec_handle, &new_val, &new_mtime, &old_val, &old_mtime); if (!NT_STATUS_IS_OK(status)) { goto done; } status = cli_get_session_key(mem_ctx, cli, &session_key); if (!NT_STATUS_IS_OK(status)) { goto done; } if (new_val.buf) { new_blob = data_blob_const(new_val.buf->data, new_val.buf->length); } if (old_val.buf) { old_blob = data_blob_const(old_val.buf->data, old_val.buf->length); } new_secret = sess_decrypt_string(mem_ctx, &new_blob, &session_key); old_secret = sess_decrypt_string(mem_ctx, &old_blob, &session_key); if (new_secret) { d_printf("new secret: %s\n", new_secret); } if (old_secret) { d_printf("old secret: %s\n", old_secret); } done: if (is_valid_policy_hnd(&sec_handle)) { rpccli_lsa_Close(cli, mem_ctx, &sec_handle); } if (is_valid_policy_hnd(&handle)) { rpccli_lsa_Close(cli, mem_ctx, &handle); } return status; }
static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx, struct NetLocalGroupAddMembers *add, struct NetLocalGroupDelMembers *del, struct NetLocalGroupSetMembers *set) { struct NetLocalGroupAddMembers *r = NULL; struct rpc_pipe_client *pipe_cli = NULL; struct rpc_pipe_client *lsa_pipe = NULL; NTSTATUS status, result; WERROR werr; struct lsa_String lsa_account_name; struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle; struct dom_sid2 *domain_sid = NULL; struct dom_sid *member_sids = NULL; int i = 0, k = 0; struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL; struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL; struct dom_sid *add_sids = NULL; struct dom_sid *del_sids = NULL; uint32_t num_add_sids = 0; uint32_t num_del_sids = 0; struct dcerpc_binding_handle *b = NULL; if ((!add && !del && !set) || (add && del && set)) { return WERR_INVALID_PARAM; } if (add) { r = add; } if (del) { r = (struct NetLocalGroupAddMembers *)del; } if (set) { r = (struct NetLocalGroupAddMembers *)set; } if (!r->in.group_name) { return WERR_INVALID_PARAM; } switch (r->in.level) { case 0: case 3: break; default: return WERR_UNKNOWN_LEVEL; } if (r->in.total_entries == 0 || !r->in.buffer) { return WERR_INVALID_PARAM; } ZERO_STRUCT(connect_handle); ZERO_STRUCT(builtin_handle); ZERO_STRUCT(domain_handle); ZERO_STRUCT(alias_handle); member_sids = talloc_zero_array(ctx, struct dom_sid, r->in.total_entries); W_ERROR_HAVE_NO_MEMORY(member_sids); switch (r->in.level) { case 0: info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer; for (i=0; i < r->in.total_entries; i++) { sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid); } break; case 3: info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer; break; default: break; } if (r->in.level == 3) { werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_lsarpc, &lsa_pipe); if (!W_ERROR_IS_OK(werr)) { goto done; } for (i=0; i < r->in.total_entries; i++) { status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe, info3[i].lgrmi3_domainandname, &member_sids[i]); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } TALLOC_FREE(lsa_pipe); } werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } b = pipe_cli->binding_handle; werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli, SAMR_ACCESS_LOOKUP_DOMAIN | SAMR_ACCESS_ENUM_DOMAINS, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &builtin_handle); if (!W_ERROR_IS_OK(werr)) { goto done; } init_lsa_String(&lsa_account_name, r->in.group_name); status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &builtin_handle, r->in.group_name, SAMR_ALIAS_ACCESS_ADD_MEMBER | SAMR_ALIAS_ACCESS_REMOVE_MEMBER | SAMR_ALIAS_ACCESS_GET_MEMBERS | SAMR_ALIAS_ACCESS_LOOKUP_INFO, &alias_handle); if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); } if (NT_STATUS_IS_OK(status)) { goto modify_membership; } werr = libnetapi_samr_open_domain(ctx, pipe_cli, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &domain_handle, &domain_sid); if (!W_ERROR_IS_OK(werr)) { goto done; } status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &domain_handle, r->in.group_name, SAMR_ALIAS_ACCESS_ADD_MEMBER | SAMR_ALIAS_ACCESS_REMOVE_MEMBER | SAMR_ALIAS_ACCESS_GET_MEMBERS | SAMR_ALIAS_ACCESS_LOOKUP_INFO, &alias_handle); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); } modify_membership: if (add) { for (i=0; i < r->in.total_entries; i++) { status = add_sid_to_array_unique(ctx, &member_sids[i], &add_sids, &num_add_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } if (del) { for (i=0; i < r->in.total_entries; i++) { status = add_sid_to_array_unique(ctx, &member_sids[i], &del_sids, &num_del_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } if (set) { struct lsa_SidArray current_sids; status = dcerpc_samr_GetMembersInAlias(b, talloc_tos(), &alias_handle, ¤t_sids, &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } /* add list */ for (i=0; i < r->in.total_entries; i++) { bool already_member = false; for (k=0; k < current_sids.num_sids; k++) { if (dom_sid_equal(&member_sids[i], current_sids.sids[k].sid)) { already_member = true; break; } } if (!already_member) { status = add_sid_to_array_unique(ctx, &member_sids[i], &add_sids, &num_add_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } /* del list */ for (k=0; k < current_sids.num_sids; k++) { bool keep_member = false; for (i=0; i < r->in.total_entries; i++) { if (dom_sid_equal(&member_sids[i], current_sids.sids[k].sid)) { keep_member = true; break; } } if (!keep_member) { status = add_sid_to_array_unique(ctx, current_sids.sids[k].sid, &del_sids, &num_del_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } } /* add list */ for (i=0; i < num_add_sids; i++) { status = dcerpc_samr_AddAliasMember(b, talloc_tos(), &alias_handle, &add_sids[i], &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } } /* del list */ for (i=0; i < num_del_sids; i++) { status = dcerpc_samr_DeleteAliasMember(b, talloc_tos(), &alias_handle, &del_sids[i], &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } } werr = WERR_OK; done: if (b && is_valid_policy_hnd(&alias_handle)) { dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result); } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); libnetapi_samr_close_connect_handle(ctx, &connect_handle); } return werr; }
WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx, struct NetLocalGroupAdd *r) { struct rpc_pipe_client *pipe_cli = NULL; NTSTATUS status, result; WERROR werr; struct lsa_String lsa_account_name; struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle; struct dom_sid2 *domain_sid = NULL; uint32_t rid; struct dcerpc_binding_handle *b = NULL; struct LOCALGROUP_INFO_0 *info0 = NULL; struct LOCALGROUP_INFO_1 *info1 = NULL; const char *alias_name = NULL; if (!r->in.buffer) { return WERR_INVALID_PARAM; } ZERO_STRUCT(connect_handle); ZERO_STRUCT(builtin_handle); ZERO_STRUCT(domain_handle); ZERO_STRUCT(alias_handle); switch (r->in.level) { case 0: info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer; alias_name = info0->lgrpi0_name; break; case 1: info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer; alias_name = info1->lgrpi1_name; break; default: werr = WERR_UNKNOWN_LEVEL; goto done; } werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } b = pipe_cli->binding_handle; werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli, SAMR_ACCESS_LOOKUP_DOMAIN | SAMR_ACCESS_ENUM_DOMAINS, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &builtin_handle); if (!W_ERROR_IS_OK(werr)) { goto done; } status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &builtin_handle, alias_name, SAMR_ALIAS_ACCESS_LOOKUP_INFO, &alias_handle); if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); } if (NT_STATUS_IS_OK(status)) { werr = WERR_ALIAS_EXISTS; goto done; } werr = libnetapi_samr_open_domain(ctx, pipe_cli, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, SAMR_DOMAIN_ACCESS_CREATE_ALIAS | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &domain_handle, &domain_sid); if (!W_ERROR_IS_OK(werr)) { goto done; } init_lsa_String(&lsa_account_name, alias_name); status = dcerpc_samr_CreateDomAlias(b, talloc_tos(), &domain_handle, &lsa_account_name, SEC_STD_DELETE | SAMR_ALIAS_ACCESS_SET_INFO, &alias_handle, &rid, &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } if (r->in.level == 1 && info1->lgrpi1_comment) { union samr_AliasInfo alias_info; init_lsa_String(&alias_info.description, info1->lgrpi1_comment); status = dcerpc_samr_SetAliasInfo(b, talloc_tos(), &alias_handle, ALIASINFODESCRIPTION, &alias_info, &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } } werr = WERR_OK; done: if (is_valid_policy_hnd(&alias_handle)) { dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result); } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); libnetapi_samr_close_connect_handle(ctx, &connect_handle); } return werr; }
WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx, struct NetLocalGroupGetInfo *r) { struct cli_state *cli = NULL; struct rpc_pipe_client *pipe_cli = NULL; NTSTATUS status; WERROR werr; struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle; struct dom_sid2 *domain_sid = NULL; union samr_AliasInfo *alias_info = NULL; uint32_t entries_read = 0; if (!r->in.group_name) { return WERR_INVALID_PARAM; } switch (r->in.level) { case 0: case 1: case 1002: break; default: return WERR_UNKNOWN_LEVEL; } ZERO_STRUCT(connect_handle); ZERO_STRUCT(builtin_handle); ZERO_STRUCT(domain_handle); ZERO_STRUCT(alias_handle); werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_samr.syntax_id, &cli, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli, SAMR_ACCESS_LOOKUP_DOMAIN | SAMR_ACCESS_ENUM_DOMAINS, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &builtin_handle); if (!W_ERROR_IS_OK(werr)) { goto done; } status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &builtin_handle, r->in.group_name, SAMR_ALIAS_ACCESS_LOOKUP_INFO, &alias_handle); if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); } if (NT_STATUS_IS_OK(status)) { goto query_alias; } werr = libnetapi_samr_open_domain(ctx, pipe_cli, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, SAMR_DOMAIN_ACCESS_CREATE_ALIAS | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &domain_handle, &domain_sid); if (!W_ERROR_IS_OK(werr)) { goto done; } status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &domain_handle, r->in.group_name, SAMR_ALIAS_ACCESS_LOOKUP_INFO, &alias_handle); if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); } if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } query_alias: status = rpccli_samr_QueryAliasInfo(pipe_cli, ctx, &alias_handle, ALIASINFOALL, &alias_info); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } werr = map_alias_info_to_buffer(ctx, r->in.group_name, &alias_info->all, r->in.level, &entries_read, r->out.buffer); done: if (!cli) { return werr; } if (is_valid_policy_hnd(&alias_handle)) { rpccli_samr_Close(pipe_cli, ctx, &alias_handle); } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); libnetapi_samr_close_connect_handle(ctx, &connect_handle); } return werr; }
bool svcctl_init_winreg(struct messaging_context *msg_ctx) { struct dcerpc_binding_handle *h = NULL; uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED; struct policy_handle hive_hnd, key_hnd; const char **service_list = lp_svcctl_list(); const char **subkeys = NULL; uint32_t num_subkeys = 0; char *key = NULL; uint32_t i; NTSTATUS status; WERROR result = WERR_OK; bool ok = false; TALLOC_CTX *tmp_ctx; tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return false; } DEBUG(3, ("Initialise the svcctl registry keys if needed.\n")); ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); key = talloc_strdup(tmp_ctx, TOP_LEVEL_SERVICES_KEY); if (key == NULL) { goto done; } result = regdb_open(); if (!W_ERROR_IS_OK(result)) { DEBUG(10, ("regdb_open failed: %s\n", win_errstr(result))); goto done; } result = regdb_transaction_start(); if (!W_ERROR_IS_OK(result)) { DEBUG(10, ("regdb_transaction_start failed: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_int_hklm_openkey(tmp_ctx, get_session_info_system(), msg_ctx, &h, key, false, access_mask, &hive_hnd, &key_hnd, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg: Could not open %s - %s\n", key, nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg: Could not open %s - %s\n", key, win_errstr(result))); goto done; } /* get all subkeys */ status = dcerpc_winreg_enum_keys(tmp_ctx, h, &key_hnd, &num_subkeys, &subkeys, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg: Could enum keys at %s - %s\n", key, nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg: Could enum keys at %s - %s\n", key, win_errstr(result))); goto done; } for (i = 0; builtin_svcs[i].servicename != NULL; i++) { uint32_t j; bool skip = false; for (j = 0; j < num_subkeys; j++) { if (strequal(subkeys[i], builtin_svcs[i].servicename)) { skip = true; } } if (skip) { continue; } ok = svcctl_add_service(tmp_ctx, h, &hive_hnd, key, access_mask, builtin_svcs[i].servicename); if (!ok) { goto done; } } for (i = 0; service_list && service_list[i]; i++) { uint32_t j; bool skip = false; for (j = 0; j < num_subkeys; j++) { if (strequal(subkeys[i], service_list[i])) { skip = true; } } if (skip) { continue; } ok = svcctl_add_service(tmp_ctx, h, &hive_hnd, key, access_mask, service_list[i]); if (is_valid_policy_hnd(&key_hnd)) { dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result); } ZERO_STRUCT(key_hnd); if (!ok) { goto done; } } done: if (is_valid_policy_hnd(&key_hnd)) { dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result); } if (ok) { result = regdb_transaction_commit(); if (!W_ERROR_IS_OK(result)) { DEBUG(10, ("regdb_transaction_commit failed: %s\n", win_errstr(result))); } } else { result = regdb_transaction_cancel(); if (!W_ERROR_IS_OK(result)) { DEBUG(10, ("regdb_transaction_cancel failed: %s\n", win_errstr(result))); } } regdb_close(); talloc_free(tmp_ctx); return ok; }
static bool svcctl_add_service(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *h, struct policy_handle *hive_hnd, const char *key, uint32_t access_mask, const char *name) { enum winreg_CreateAction action = REG_ACTION_NONE; struct security_descriptor *sd = NULL; struct policy_handle key_hnd; struct winreg_String wkey; struct winreg_String wkeyclass; char *description = NULL; char *dname = NULL; char *ipath = NULL; bool ok = false; uint32_t i; NTSTATUS status; WERROR result = WERR_OK; ZERO_STRUCT(key_hnd); ZERO_STRUCT(wkey); wkey.name = talloc_asprintf(mem_ctx, "%s\\%s", key, name); if (wkey.name == NULL) { goto done; } ZERO_STRUCT(wkeyclass); wkeyclass.name = ""; status = dcerpc_winreg_CreateKey(h, mem_ctx, hive_hnd, wkey, wkeyclass, 0, access_mask, NULL, &key_hnd, &action, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n", wkey.name, nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n", wkey.name, win_errstr(result))); goto done; } /* These values are hardcoded in all QueryServiceConfig() replies. I'm just storing them here for cosmetic purposes */ status = dcerpc_winreg_set_dword(mem_ctx, h, &key_hnd, "Start", SVCCTL_AUTO_START, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_dword(mem_ctx, h, &key_hnd, "Type", SERVICE_TYPE_WIN32_OWN_PROCESS, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_dword(mem_ctx, h, &key_hnd, "ErrorControl", SVCCTL_SVC_ERROR_NORMAL, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_sz(mem_ctx, h, &key_hnd, "ObjectName", "LocalSystem", &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } /* * Special considerations for internal services and the DisplayName * value. */ for (i = 0; builtin_svcs[i].servicename; i++) { if (strequal(name, builtin_svcs[i].servicename)) { ipath = talloc_asprintf(mem_ctx, "%s/%s/%s", get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR, builtin_svcs[i].daemon); description = talloc_strdup(mem_ctx, builtin_svcs[i].description); dname = talloc_strdup(mem_ctx, builtin_svcs[i].dispname); break; } } /* Default to an external service if we haven't found a match */ if (builtin_svcs[i].servicename == NULL) { struct rcinit_file_information *init_info = NULL; char *dispname = NULL; ipath = talloc_asprintf(mem_ctx, "%s/%s/%s", get_dyn_MODULESDIR(), SVCCTL_SCRIPT_DIR, name); /* lookup common unix display names */ dispname = svcctl_get_common_service_dispname(mem_ctx, name); dname = talloc_strdup(mem_ctx, dispname ? dispname : ""); /* get info from init file itself */ if (read_init_file(mem_ctx, name, &init_info)) { description = talloc_strdup(mem_ctx, init_info->description); } else { description = talloc_strdup(mem_ctx, "External Unix Service"); } } if (ipath == NULL || dname == NULL || description == NULL) { goto done; } status = dcerpc_winreg_set_sz(mem_ctx, h, &key_hnd, "DisplayName", dname, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_sz(mem_ctx, h, &key_hnd, "ImagePath", ipath, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } status = dcerpc_winreg_set_sz(mem_ctx, h, &key_hnd, "Description", description, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } sd = svcctl_gen_service_sd(mem_ctx); if (sd == NULL) { DEBUG(0, ("add_new_svc_name: Failed to create default " "sec_desc!\n")); goto done; } if (is_valid_policy_hnd(&key_hnd)) { dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result); } ZERO_STRUCT(key_hnd); ZERO_STRUCT(wkey); wkey.name = talloc_asprintf(mem_ctx, "%s\\%s\\Security", key, name); if (wkey.name == NULL) { result = WERR_NOMEM; goto done; } ZERO_STRUCT(wkeyclass); wkeyclass.name = ""; status = dcerpc_winreg_CreateKey(h, mem_ctx, hive_hnd, wkey, wkeyclass, 0, access_mask, NULL, &key_hnd, &action, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n", wkey.name, nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create key %s: %s\n", wkey.name, win_errstr(result))); goto done; } status = dcerpc_winreg_set_sd(mem_ctx, h, &key_hnd, "Security", sd, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_init_winreg_keys: Could not create value: %s\n", win_errstr(result))); goto done; } ok = true; done: if (is_valid_policy_hnd(&key_hnd)) { dcerpc_winreg_CloseKey(h, mem_ctx, &key_hnd, &result); } return ok; }
static WERROR cmd_drsuapi_writeaccountspn(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; WERROR werr; struct GUID bind_guid; struct policy_handle bind_handle; struct dcerpc_binding_handle *b = cli->binding_handle; struct drsuapi_DsNameString *spn_names = NULL; int i = 0; uint32_t level_out; union drsuapi_DsWriteAccountSpnRequest req; union drsuapi_DsWriteAccountSpnResult result; if (argc < 4) { printf("usage: %s [add|replace|delete] dn [spn_names]+\n", argv[0]); return WERR_OK; } req.req1.unknown1 = 0; /* Unused, must be 0 */ req.req1.object_dn = argv[2]; req.req1.count = argc - 3; if (strcmp(argv[1], "add") == 0) { req.req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD; } else if (strcmp(argv[1], "replace") == 0) { req.req1.operation = DRSUAPI_DS_SPN_OPERATION_REPLACE; } else if (strcmp(argv[1], "delete") == 0) { req.req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE; } else { printf("usage: %s [add|replace|delete] dn [spn_names]+\n", argv[0]); return WERR_OK; } spn_names = talloc_zero_array(mem_ctx, struct drsuapi_DsNameString, req.req1.count); W_ERROR_HAVE_NO_MEMORY(spn_names); for (i=0; i<req.req1.count; i++) { spn_names[i].str = argv[i + 3]; } req.req1.spn_names = spn_names; GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid); status = dcerpc_drsuapi_DsBind(b, mem_ctx, &bind_guid, NULL, &bind_handle, &werr); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (!W_ERROR_IS_OK(werr)) { return werr; } status = dcerpc_drsuapi_DsWriteAccountSpn(b, mem_ctx, &bind_handle, 1, &req, &level_out, &result, &werr); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto out; } if (!W_ERROR_IS_OK(werr)) { goto out; } out: if (is_valid_policy_hnd(&bind_handle)) { WERROR _werr; dcerpc_drsuapi_DsUnbind(b, mem_ctx, &bind_handle, &_werr); } return werr; }
WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx, struct NetLocalGroupSetInfo *r) { struct rpc_pipe_client *pipe_cli = NULL; NTSTATUS status, result; WERROR werr; struct lsa_String lsa_account_name; struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle; struct dom_sid2 *domain_sid = NULL; enum samr_AliasInfoEnum alias_level = 0; union samr_AliasInfo *alias_info = NULL; struct dcerpc_binding_handle *b = NULL; if (!r->in.group_name) { return WERR_INVALID_PARAM; } switch (r->in.level) { case 0: case 1: case 1002: break; default: return WERR_UNKNOWN_LEVEL; } ZERO_STRUCT(connect_handle); ZERO_STRUCT(builtin_handle); ZERO_STRUCT(domain_handle); ZERO_STRUCT(alias_handle); werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } b = pipe_cli->binding_handle; werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli, SAMR_ACCESS_LOOKUP_DOMAIN | SAMR_ACCESS_ENUM_DOMAINS, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &builtin_handle); if (!W_ERROR_IS_OK(werr)) { goto done; } init_lsa_String(&lsa_account_name, r->in.group_name); status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &builtin_handle, r->in.group_name, SAMR_ALIAS_ACCESS_SET_INFO, &alias_handle); if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); } if (NT_STATUS_IS_OK(status)) { goto set_alias; } werr = libnetapi_samr_open_domain(ctx, pipe_cli, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &domain_handle, &domain_sid); if (!W_ERROR_IS_OK(werr)) { goto done; } status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &domain_handle, r->in.group_name, SAMR_ALIAS_ACCESS_SET_INFO, &alias_handle); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); } set_alias: werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer, &alias_level, &alias_info); if (!W_ERROR_IS_OK(werr)) { goto done; } status = dcerpc_samr_SetAliasInfo(b, talloc_tos(), &alias_handle, alias_level, alias_info, &result); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (!NT_STATUS_IS_OK(result)) { werr = ntstatus_to_werror(result); goto done; } werr = WERR_OK; done: if (is_valid_policy_hnd(&alias_handle)) { dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result); } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); libnetapi_samr_close_connect_handle(ctx, &connect_handle); } return werr; }
static WERROR cmd_drsuapi_cracknames(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; WERROR werr; int i; struct GUID bind_guid; struct policy_handle bind_handle; struct dcerpc_binding_handle *b = cli->binding_handle; union drsuapi_DsNameCtr ctr; if (argc < 2) { printf("usage: %s name\n", argv[0]); return WERR_OK; } GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid); status = dcerpc_drsuapi_DsBind(b, mem_ctx, &bind_guid, NULL, &bind_handle, &werr); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (!W_ERROR_IS_OK(werr)) { return werr; } werr = cracknames(cli, mem_ctx, &bind_handle, DRSUAPI_DS_NAME_FORMAT_UNKNOWN, DRSUAPI_DS_NAME_FORMAT_FQDN_1779, 1, argv+1, &ctr); if (!W_ERROR_IS_OK(werr)) { goto out; } for (i=0; i < ctr.ctr1->count; i++) { printf("status: %d\n", ctr.ctr1->array[i].status); printf("dns_domain_name: %s\n", ctr.ctr1->array[i].dns_domain_name); printf("result_name: %s\n", ctr.ctr1->array[i].result_name); } out: if (is_valid_policy_hnd(&bind_handle)) { WERROR _werr; dcerpc_drsuapi_DsUnbind(b, mem_ctx, &bind_handle, &_werr); } return werr; }
/* Lookup group membership given a rid. */ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const struct dom_sid *group_sid, enum lsa_SidType type, uint32_t *pnum_names, struct dom_sid **psid_mem, char ***pnames, uint32_t **pname_types) { struct rpc_pipe_client *samr_pipe; struct policy_handle dom_pol; uint32_t num_names = 0; struct dom_sid *sid_mem = NULL; char **names = NULL; uint32_t *name_types = NULL; TALLOC_CTX *tmp_ctx; NTSTATUS status, result; struct dcerpc_binding_handle *b = NULL; DEBUG(3,("sam_lookup_groupmem\n")); ZERO_STRUCT(dom_pol); /* Paranoia check */ if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) { /* There's no groups, only aliases in BUILTIN */ return NT_STATUS_NO_SUCH_GROUP; } if (pnum_names) { pnum_names = 0; } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } b = samr_pipe->binding_handle; status = rpc_lookup_groupmem(tmp_ctx, samr_pipe, &dom_pol, domain->name, &domain->sid, group_sid, type, &num_names, &sid_mem, &names, &name_types); if (pnum_names) { *pnum_names = num_names; } if (pnames) { *pnames = talloc_move(mem_ctx, &names); } if (pname_types) { *pname_types = talloc_move(mem_ctx, &name_types); } if (psid_mem) { *psid_mem = talloc_move(mem_ctx, &sid_mem); } done: if (b && is_valid_policy_hnd(&dom_pol)) { dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); } TALLOC_FREE(tmp_ctx); return status; }
static NTSTATUS cmd_lsa_set_secret(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; struct policy_handle handle, sec_handle; struct lsa_String name; struct lsa_DATA_BUF new_val; struct lsa_DATA_BUF old_val; DATA_BLOB enc_key; DATA_BLOB session_key; if (argc < 3) { printf("Usage: %s name secret\n", argv[0]); return NT_STATUS_OK; } status = rpccli_lsa_open_policy2(cli, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &handle); if (!NT_STATUS_IS_OK(status)) { return status; } init_lsa_String(&name, argv[1]); status = rpccli_lsa_OpenSecret(cli, mem_ctx, &handle, name, SEC_FLAG_MAXIMUM_ALLOWED, &sec_handle); if (!NT_STATUS_IS_OK(status)) { goto done; } ZERO_STRUCT(new_val); ZERO_STRUCT(old_val); status = cli_get_session_key(mem_ctx, cli, &session_key); if (!NT_STATUS_IS_OK(status)) { goto done; } enc_key = sess_encrypt_string(argv[2], &session_key); new_val.length = enc_key.length; new_val.size = enc_key.length; new_val.data = enc_key.data; status = rpccli_lsa_SetSecret(cli, mem_ctx, &sec_handle, &new_val, NULL); if (!NT_STATUS_IS_OK(status)) { goto done; } done: if (is_valid_policy_hnd(&sec_handle)) { rpccli_lsa_Close(cli, mem_ctx, &sec_handle); } if (is_valid_policy_hnd(&handle)) { rpccli_lsa_Close(cli, mem_ctx, &handle); } return status; }
bool svcctl_set_secdesc(struct messaging_context *msg_ctx, const struct auth_session_info *session_info, const char *name, struct security_descriptor *sd) { struct dcerpc_binding_handle *h = NULL; uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED; struct policy_handle hive_hnd; struct policy_handle key_hnd = { 0, }; char *key = NULL; bool ok = false; TALLOC_CTX *tmp_ctx; NTSTATUS status; WERROR result = WERR_OK; tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return false; } key = talloc_asprintf(tmp_ctx, "%s\\%s", TOP_LEVEL_SERVICES_KEY, name); if (key == NULL) { goto done; } status = dcerpc_winreg_int_hklm_openkey(tmp_ctx, session_info, msg_ctx, &h, key, false, access_mask, &hive_hnd, &key_hnd, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n", key, nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n", key, win_errstr(result))); goto done; } if (is_valid_policy_hnd(&key_hnd)) { dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result); } { enum winreg_CreateAction action = REG_ACTION_NONE; struct winreg_String wkey = { 0, }; struct winreg_String wkeyclass; wkey.name = talloc_asprintf(tmp_ctx, "%s\\Security", key); if (wkey.name == NULL) { result = WERR_NOT_ENOUGH_MEMORY; goto done; } ZERO_STRUCT(wkeyclass); wkeyclass.name = ""; status = dcerpc_winreg_CreateKey(h, tmp_ctx, &hive_hnd, wkey, wkeyclass, 0, access_mask, NULL, &key_hnd, &action, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n", wkey.name, nt_errstr(status))); goto done; } if (!W_ERROR_IS_OK(result)) { DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n", wkey.name, win_errstr(result))); goto done; } status = dcerpc_winreg_set_sd(tmp_ctx, h, &key_hnd, "Security", sd, &result); if (!NT_STATUS_IS_OK(status)) { goto done; } if (!W_ERROR_IS_OK(result)) { goto done; } } ok = true; done: if (is_valid_policy_hnd(&key_hnd)) { dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result); } talloc_free(tmp_ctx); return ok; }