WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx, struct NetJoinDomain *r) { struct rpc_pipe_client *pipe_cli = NULL; struct wkssvc_PasswordBuffer *encrypted_password = NULL; NTSTATUS status; WERROR werr; unsigned int old_timeout = 0; struct dcerpc_binding_handle *b; DATA_BLOB session_key; if (IS_DC) { return WERR_NERR_SETUPDOMAINCONTROLLER; } werr = libnetapi_open_pipe(ctx, r->in.server, &ndr_table_wkssvc, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } b = pipe_cli->binding_handle; if (r->in.password) { status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } encode_wkssvc_join_password_buffer(ctx, r->in.password, &session_key, &encrypted_password); } old_timeout = rpccli_set_timeout(pipe_cli, 600000); status = dcerpc_wkssvc_NetrJoinDomain2(b, talloc_tos(), r->in.server, r->in.domain, r->in.account_ou, r->in.account, encrypted_password, r->in.join_flags, &werr); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } done: if (pipe_cli && old_timeout) { rpccli_set_timeout(pipe_cli, old_timeout); } return werr; }
static NTSTATUS cmd_lsa_retrieve_private_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; struct policy_handle handle; struct lsa_String name; struct lsa_DATA_BUF *val; DATA_BLOB session_key; DATA_BLOB blob = data_blob_null; char *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]); ZERO_STRUCT(val); status = rpccli_lsa_RetrievePrivateData(cli, mem_ctx, &handle, &name, &val); 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 (val) { blob = data_blob_const(val->data, val->length); } secret = sess_decrypt_string(mem_ctx, &blob, &session_key); if (secret) { d_printf("secret: %s\n", secret); } done: if (is_valid_policy_hnd(&handle)) { rpccli_lsa_Close(cli, mem_ctx, &handle); } return status; }
static NTSTATUS cmd_lsa_store_private_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; struct policy_handle handle; struct lsa_String name; struct lsa_DATA_BUF val; DATA_BLOB session_key; DATA_BLOB enc_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]); ZERO_STRUCT(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); val.length = enc_key.length; val.size = enc_key.length; val.data = enc_key.data; status = rpccli_lsa_StorePrivateData(cli, mem_ctx, &handle, &name, &val); if (!NT_STATUS_IS_OK(status)) { goto done; } done: if (is_valid_policy_hnd(&handle)) { rpccli_lsa_Close(cli, mem_ctx, &handle); } return status; }
WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx, struct NetGetJoinableOUs *r) { struct rpc_pipe_client *pipe_cli = NULL; struct wkssvc_PasswordBuffer *encrypted_password = NULL; NTSTATUS status; WERROR werr; struct dcerpc_binding_handle *b; DATA_BLOB session_key; werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_wkssvc, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } b = pipe_cli->binding_handle; if (r->in.password) { status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } encode_wkssvc_join_password_buffer(ctx, r->in.password, &session_key, &encrypted_password); } status = dcerpc_wkssvc_NetrGetJoinableOus2(b, talloc_tos(), r->in.server_name, r->in.domain, r->in.account, encrypted_password, r->out.ou_count, r->out.ous, &werr); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } done: 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 cmd_drsuapi_getncchanges(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status; WERROR werr; struct policy_handle bind_handle; struct dcerpc_binding_handle *b = cli->binding_handle; struct GUID bind_guid; struct drsuapi_DsBindInfoCtr bind_info; struct drsuapi_DsBindInfo28 info28; const char *nc_dn = NULL; DATA_BLOB session_key; uint32_t level = 8; bool single = false; uint32_t level_out = 0; union drsuapi_DsGetNCChangesRequest req; union drsuapi_DsGetNCChangesCtr ctr; struct drsuapi_DsReplicaObjectIdentifier nc; struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL; struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL; uint32_t out_level = 0; int y; uint32_t supported_extensions = 0; uint32_t replica_flags = DRSUAPI_DRS_WRIT_REP | DRSUAPI_DRS_INIT_SYNC | DRSUAPI_DRS_PER_SYNC | DRSUAPI_DRS_GET_ANC | DRSUAPI_DRS_NEVER_SYNCED; if (argc > 3) { printf("usage: %s [naming_context_or_object_dn [single]]\n", argv[0]); return WERR_OK; } if (argc >= 2) { nc_dn = argv[1]; } if (argc == 3) { if (strequal(argv[2], "single")) { single = true; } else { printf("warning: ignoring unknown argument '%s'\n", argv[2]); } } ZERO_STRUCT(info28); ZERO_STRUCT(req); GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid); info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7; info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT; info28.site_guid = GUID_zero(); info28.pid = 0; info28.repl_epoch = 0; bind_info.length = 28; bind_info.info.info28 = info28; status = dcerpc_drsuapi_DsBind(b, mem_ctx, &bind_guid, &bind_info, &bind_handle, &werr); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (!W_ERROR_IS_OK(werr)) { return werr; } if (bind_info.length == 24) { supported_extensions = bind_info.info.info24.supported_extensions; } else if (bind_info.length == 28) { supported_extensions = bind_info.info.info28.supported_extensions; } else if (bind_info.length == 32) { supported_extensions = bind_info.info.info32.supported_extensions; } else if (bind_info.length == 48) { supported_extensions = bind_info.info.info48.supported_extensions; } else if (bind_info.length == 52) { supported_extensions = bind_info.info.info52.supported_extensions; } if (!nc_dn) { union drsuapi_DsNameCtr crack_ctr; const char *name; name = talloc_asprintf(mem_ctx, "%s\\", lp_workgroup()); W_ERROR_HAVE_NO_MEMORY(name); werr = cracknames(cli, mem_ctx, &bind_handle, DRSUAPI_DS_NAME_FORMAT_UNKNOWN, DRSUAPI_DS_NAME_FORMAT_FQDN_1779, 1, &name, &crack_ctr); if (!W_ERROR_IS_OK(werr)) { return werr; } if (crack_ctr.ctr1->count != 1) { return WERR_NO_SUCH_DOMAIN; } if (crack_ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { return WERR_NO_SUCH_DOMAIN; } nc_dn = talloc_strdup(mem_ctx, crack_ctr.ctr1->array[0].result_name); W_ERROR_HAVE_NO_MEMORY(nc_dn); printf("using: %s\n", nc_dn); } nc.dn = nc_dn; nc.guid = GUID_zero(); nc.sid = (struct dom_sid) {0}; if (supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) { level = 8; req.req8.naming_context = &nc; req.req8.replica_flags = replica_flags; req.req8.max_object_count = 402; req.req8.max_ndr_size = 402116; if (single) { req.req8.extended_op = DRSUAPI_EXOP_REPL_OBJ; } } else { level = 5; req.req5.naming_context = &nc; req.req5.replica_flags = replica_flags; req.req5.max_object_count = 402; req.req5.max_ndr_size = 402116; if (single) { req.req5.extended_op = DRSUAPI_EXOP_REPL_OBJ; } } for (y=0; ;y++) { if (level == 8) { DEBUG(1,("start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",y, (long long)req.req8.highwatermark.tmp_highest_usn, (long long)req.req8.highwatermark.highest_usn)); } status = dcerpc_drsuapi_DsGetNCChanges(b, mem_ctx, &bind_handle, level, &req, &level_out, &ctr, &werr); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); printf("Failed to get NC Changes: %s", get_friendly_nt_error_msg(status)); goto out; } if (!W_ERROR_IS_OK(werr)) { printf("Failed to get NC Changes: %s", get_friendly_werror_msg(werr)); goto out; } if (level_out == 1) { out_level = 1; ctr1 = &ctr.ctr1; } else if (level_out == 2 && ctr.ctr2.mszip1.ts) { out_level = 1; ctr1 = &ctr.ctr2.mszip1.ts->ctr1; } status = cli_get_session_key(mem_ctx, cli, &session_key); if (!NT_STATUS_IS_OK(status)) { printf("Failed to get Session Key: %s", nt_errstr(status)); return ntstatus_to_werror(status); } if (out_level == 1) { DEBUG(1,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y, (long long)ctr1->new_highwatermark.tmp_highest_usn, (long long)ctr1->new_highwatermark.highest_usn)); #if 0 libnet_dssync_decrypt_attributes(mem_ctx, &session_key, ctr1->first_object); #endif if (ctr1->more_data) { req.req5.highwatermark = ctr1->new_highwatermark; continue; } } if (level_out == 6) { out_level = 6; ctr6 = &ctr.ctr6; } else if (level_out == 7 && ctr.ctr7.level == 6 && ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP && ctr.ctr7.ctr.mszip6.ts) { out_level = 6; ctr6 = &ctr.ctr7.ctr.mszip6.ts->ctr6; } else if (level_out == 7 && ctr.ctr7.level == 6 && ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_XPRESS && ctr.ctr7.ctr.xpress6.ts) { out_level = 6; ctr6 = &ctr.ctr7.ctr.xpress6.ts->ctr6; } if (out_level == 6) { DEBUG(1,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y, (long long)ctr6->new_highwatermark.tmp_highest_usn, (long long)ctr6->new_highwatermark.highest_usn)); #if 0 libnet_dssync_decrypt_attributes(mem_ctx, &session_key, ctr6->first_object); #endif if (ctr6->more_data) { req.req8.highwatermark = ctr6->new_highwatermark; continue; } } break; } out: return werr; } /* List of commands exported by this module */ struct cmd_set drsuapi_commands[] = { { "DRSUAPI" }, { "dscracknames", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_cracknames, &ndr_table_drsuapi, NULL, "Crack Name", "" }, { "dsgetdcinfo", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_getdcinfo, &ndr_table_drsuapi, NULL, "Get Domain Controller Info", "" }, { "dsgetncchanges", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_getncchanges, &ndr_table_drsuapi, NULL, "Get NC Changes", "" }, { "dswriteaccountspn", RPC_RTYPE_WERROR, NULL, cmd_drsuapi_writeaccountspn, &ndr_table_drsuapi, NULL, "Write Account SPN", "" }, { NULL } };
static NTSTATUS connect_and_get_info(TALLOC_CTX *mem_ctx, struct net_context *net_ctx, struct cli_state **cli, struct rpc_pipe_client **pipe_hnd, struct policy_handle *pol_hnd, struct dom_data *dom_data, DATA_BLOB *session_key) { NTSTATUS status; NTSTATUS result; status = net_make_ipc_connection_ex(net_ctx, NULL, NULL, NULL, NET_FLAGS_PDC, cli); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to connect to [%s] with error [%s]\n", net_ctx->opt_host, nt_errstr(status))); return status; } status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc.syntax_id, pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to initialise lsa pipe with error [%s]\n", nt_errstr(status))); return status; } status = dcerpc_lsa_open_policy2((*pipe_hnd)->binding_handle, mem_ctx, (*pipe_hnd)->srv_name_slash, false, (LSA_POLICY_VIEW_LOCAL_INFORMATION | LSA_POLICY_TRUST_ADMIN | LSA_POLICY_CREATE_SECRET), pol_hnd, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to open policy handle with error [%s]\n", nt_errstr(status))); return status; } if (!NT_STATUS_IS_OK(result)) { DEBUG(0, ("lsa_open_policy2 with error [%s]\n", nt_errstr(result))); return result; } status = get_domain_info(mem_ctx, (*pipe_hnd)->binding_handle, pol_hnd, dom_data); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("get_domain_info failed with error [%s].\n", nt_errstr(status))); return status; } status = cli_get_session_key(mem_ctx, *pipe_hnd, session_key); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Error getting session_key of LSA pipe. Error was %s\n", nt_errstr(status))); return status; } return NT_STATUS_OK; }