static NTSTATUS tcp_ldap_rootdse(void *data, TALLOC_CTX *mem_ctx, struct cldap_search *io) { struct ldap_connection *conn = talloc_get_type(data, struct ldap_connection); struct ldap_message *msg, *result; struct ldap_request *req; int i; NTSTATUS status; msg = new_ldap_message(mem_ctx); if (!msg) { return NT_STATUS_NO_MEMORY; } msg->type = LDAP_TAG_SearchRequest; msg->r.SearchRequest.basedn = ""; msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE; msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER; msg->r.SearchRequest.timelimit = 0; msg->r.SearchRequest.sizelimit = 0; msg->r.SearchRequest.attributesonly = false; msg->r.SearchRequest.tree = ldb_parse_tree(msg, io->in.filter); msg->r.SearchRequest.num_attributes = str_list_length(io->in.attributes); msg->r.SearchRequest.attributes = io->in.attributes; req = ldap_request_send(conn, msg); if (req == NULL) { printf("Could not setup ldap search\n"); return NT_STATUS_UNSUCCESSFUL; } ZERO_STRUCT(io->out); for (i = 0; i < 2; ++i) { status = ldap_result_n(req, i, &result); if (!NT_STATUS_IS_OK(status)) { return status; } switch (result->type) { case LDAP_TAG_SearchResultEntry: if (i != 0) { return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); } io->out.response = &result->r.SearchResultEntry; break; case LDAP_TAG_SearchResultDone: io->out.result = &result->r.SearchResultDone; if (io->out.result->resultcode != LDAP_SUCCESS) { return NT_STATUS_LDAP(io->out.result->resultcode); } return NT_STATUS_OK; default: return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); } } return NT_STATUS_OK; }
static NTSTATUS unbecomeDC_ldap_move_computer(struct libnet_UnbecomeDC_state *s) { int ret; struct ldb_result *r; struct ldb_dn *basedn; struct ldb_dn *old_dn; struct ldb_dn *new_dn; static const char *_1_1_attrs[] = { "1.1", NULL }; basedn = ldb_dn_new_fmt(s, s->ldap.ldb, "<WKGUID=aa312825768811d1aded00c04fd8d5cd,%s>", s->domain.dn_str); NT_STATUS_HAVE_NO_MEMORY(basedn); ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_BASE, _1_1_attrs, "(objectClass=*)"); talloc_free(basedn); if (ret != LDB_SUCCESS) { return NT_STATUS_LDAP(ret); } else if (r->count != 1) { talloc_free(r); return NT_STATUS_INVALID_NETWORK_RESPONSE; } old_dn = ldb_dn_new(r, s->ldap.ldb, s->dest_dsa.computer_dn_str); NT_STATUS_HAVE_NO_MEMORY(old_dn); new_dn = r->msgs[0]->dn; if (!ldb_dn_add_child_fmt(new_dn, "CN=%s", s->dest_dsa.netbios_name)) { talloc_free(r); return NT_STATUS_NO_MEMORY; } if (ldb_dn_compare(old_dn, new_dn) == 0) { /* we don't need to rename if the old and new dn match */ talloc_free(r); return NT_STATUS_OK; } ret = ldb_rename(s->ldap.ldb, old_dn, new_dn); if (ret != LDB_SUCCESS) { talloc_free(r); return NT_STATUS_LDAP(ret); } s->dest_dsa.computer_dn_str = ldb_dn_alloc_linearized(s, new_dn); NT_STATUS_HAVE_NO_MEMORY(s->dest_dsa.computer_dn_str); talloc_free(r); return NT_STATUS_OK; }
static NTSTATUS unbecomeDC_ldap_computer_object(struct libnet_UnbecomeDC_state *s) { int ret; struct ldb_result *r; struct ldb_dn *basedn; static const char *attrs[] = { "distinguishedName", "userAccountControl", NULL }; basedn = ldb_dn_new(s, s->ldap.ldb, s->domain.dn_str); NT_STATUS_HAVE_NO_MEMORY(basedn); ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_SUBTREE, attrs, "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))", s->dest_dsa.netbios_name); talloc_free(basedn); if (ret != LDB_SUCCESS) { return NT_STATUS_LDAP(ret); } else if (r->count != 1) { talloc_free(r); return NT_STATUS_INVALID_NETWORK_RESPONSE; } s->dest_dsa.computer_dn_str = ldb_msg_find_attr_as_string(r->msgs[0], "distinguishedName", NULL); if (!s->dest_dsa.computer_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE; talloc_steal(s, s->dest_dsa.computer_dn_str); s->dest_dsa.user_account_control = ldb_msg_find_attr_as_uint(r->msgs[0], "userAccountControl", 0); talloc_free(r); return NT_STATUS_OK; }
/* do a rough conversion between ads error codes and NT status codes we'll need to fill this in more */ NTSTATUS ads_ntstatus(ADS_STATUS status) { switch (status.error_type) { case ENUM_ADS_ERROR_NT: return status.err.nt_status; case ENUM_ADS_ERROR_SYSTEM: return map_nt_error_from_unix(status.err.rc); #ifdef HAVE_LDAP case ENUM_ADS_ERROR_LDAP: if (status.err.rc == LDAP_SUCCESS) { return NT_STATUS_OK; } return NT_STATUS_LDAP(status.err.rc); #endif #ifdef HAVE_KRB5 case ENUM_ADS_ERROR_KRB5: return krb5_to_nt_status(status.err.rc); #endif default: break; } if (ADS_ERR_OK(status)) { return NT_STATUS_OK; } return NT_STATUS_UNSUCCESSFUL; }
static NTSTATUS get_ldapi_ctx(TALLOC_CTX *mem_ctx, struct tldap_context **pld) { struct tldap_context *ld; struct sockaddr_un addr; char *sockaddr; int fd; NTSTATUS status; int res; sockaddr = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi", lp_private_dir()); if (sockaddr == NULL) { DEBUG(10, ("talloc failed\n")); return NT_STATUS_NO_MEMORY; } ZERO_STRUCT(addr); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, sockaddr, sizeof(addr.sun_path)); TALLOC_FREE(sockaddr); status = open_socket_out((struct sockaddr_storage *)(void *)&addr, 0, 0, &fd); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Could not connect to %s: %s\n", addr.sun_path, nt_errstr(status))); return status; } set_blocking(fd, false); ld = tldap_context_create(mem_ctx, fd); if (ld == NULL) { close(fd); return NT_STATUS_NO_MEMORY; } res = tldap_fetch_rootdse(ld); if (res != TLDAP_SUCCESS) { DEBUG(10, ("tldap_fetch_rootdse failed: %s\n", tldap_errstr(talloc_tos(), ld, res))); TALLOC_FREE(ld); return NT_STATUS_LDAP(res); } *pld = ld; return NT_STATUS_OK;; }
static NTSTATUS unbecomeDC_ldap_modify_computer(struct libnet_UnbecomeDC_state *s) { int ret; struct ldb_message *msg; uint32_t user_account_control = UF_WORKSTATION_TRUST_ACCOUNT; unsigned int i; /* as the value is already as we want it to be, we're done */ if (s->dest_dsa.user_account_control == user_account_control) { return NT_STATUS_OK; } /* make a 'modify' msg, and only for serverReference */ msg = ldb_msg_new(s); NT_STATUS_HAVE_NO_MEMORY(msg); msg->dn = ldb_dn_new(msg, s->ldap.ldb, s->dest_dsa.computer_dn_str); NT_STATUS_HAVE_NO_MEMORY(msg->dn); ret = samdb_msg_add_uint(s->ldap.ldb, msg, msg, "userAccountControl", user_account_control); if (ret != LDB_SUCCESS) { talloc_free(msg); return NT_STATUS_NO_MEMORY; } /* mark all the message elements (should be just one) as LDB_FLAG_MOD_REPLACE */ for (i=0;i<msg->num_elements;i++) { msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; } ret = ldb_modify(s->ldap.ldb, msg); talloc_free(msg); if (ret != LDB_SUCCESS) { return NT_STATUS_LDAP(ret); } s->dest_dsa.user_account_control = user_account_control; return NT_STATUS_OK; }
static NTSTATUS unbecomeDC_ldap_rootdse(struct libnet_UnbecomeDC_state *s) { int ret; struct ldb_result *r; struct ldb_dn *basedn; static const char *attrs[] = { "defaultNamingContext", "configurationNamingContext", NULL }; basedn = ldb_dn_new(s, s->ldap.ldb, NULL); NT_STATUS_HAVE_NO_MEMORY(basedn); ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_BASE, attrs, "(objectClass=*)"); talloc_free(basedn); if (ret != LDB_SUCCESS) { return NT_STATUS_LDAP(ret); } else if (r->count != 1) { talloc_free(r); return NT_STATUS_INVALID_NETWORK_RESPONSE; } s->domain.dn_str = ldb_msg_find_attr_as_string(r->msgs[0], "defaultNamingContext", NULL); if (!s->domain.dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE; talloc_steal(s, s->domain.dn_str); s->forest.config_dn_str = ldb_msg_find_attr_as_string(r->msgs[0], "configurationNamingContext", NULL); if (!s->forest.config_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE; talloc_steal(s, s->forest.config_dn_str); s->dest_dsa.server_dn_str = talloc_asprintf(s, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s", s->dest_dsa.netbios_name, s->dest_dsa.site_name, s->forest.config_dn_str); NT_STATUS_HAVE_NO_MEMORY(s->dest_dsa.server_dn_str); talloc_free(r); return NT_STATUS_OK; }
static NTSTATUS mymachinepw(uint8_t pwd[16]) { TALLOC_CTX *frame = talloc_stackframe(); struct tldap_context *ld = NULL; struct tldap_message *rootdse, **msg; const char *attrs[1] = { "unicodePwd" }; char *default_nc, *myname; int rc, num_msg; DATA_BLOB pwdblob; NTSTATUS status; status = get_ldapi_ctx(talloc_tos(), &ld); if (!NT_STATUS_IS_OK(status)) { goto fail; } rootdse = tldap_rootdse(ld); if (rootdse == NULL) { DEBUG(10, ("Could not get rootdse\n")); status = NT_STATUS_INTERNAL_ERROR; goto fail; } default_nc = tldap_talloc_single_attribute( rootdse, "defaultNamingContext", talloc_tos()); if (default_nc == NULL) { DEBUG(10, ("Could not get defaultNamingContext\n")); status = NT_STATUS_NO_MEMORY; goto fail; } DEBUG(10, ("default_nc = %s\n", default_nc)); myname = talloc_asprintf_strupper_m(talloc_tos(), "%s$", global_myname()); if (myname == NULL) { DEBUG(10, ("talloc failed\n")); status = NT_STATUS_NO_MEMORY; goto fail; } rc = tldap_search_fmt( ld, default_nc, TLDAP_SCOPE_SUB, attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg, "(&(sAMAccountName=%s)(objectClass=computer))", myname); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("Could not retrieve our account: %s\n", tldap_errstr(talloc_tos(), ld, rc))); status = NT_STATUS_LDAP(rc); goto fail; } num_msg = talloc_array_length(msg); if (num_msg != 1) { DEBUG(10, ("Got %d accounts, expected one\n", num_msg)); status = NT_STATUS_INTERNAL_DB_CORRUPTION; goto fail; } if (!tldap_get_single_valueblob(msg[0], "unicodePwd", &pwdblob)) { char *dn = NULL; tldap_entry_dn(msg[0], &dn); DEBUG(10, ("No unicodePwd attribute in %s\n", dn ? dn : "<unknown DN>")); status = NT_STATUS_INTERNAL_DB_CORRUPTION; goto fail; } if (pwdblob.length != 16) { DEBUG(10, ("Password hash hash has length %d, expected 16\n", (int)pwdblob.length)); status = NT_STATUS_INTERNAL_DB_CORRUPTION; goto fail; } memcpy(pwd, pwdblob.data, 16); fail: TALLOC_FREE(frame); return status; }