static void test_sysdb_handle_original_uuid(void **state) { int ret; struct sysdb_attrs *src_attrs; struct sysdb_attrs *dest_attrs; const char *guid; uint8_t bin_guid[] = AD_GUID_BIN; struct ldb_val guid_val = {bin_guid, 16}; ret = sysdb_handle_original_uuid(NULL, NULL, NULL, NULL, NULL); assert_int_equal(ret, ENOENT); src_attrs = sysdb_new_attrs(NULL); assert_non_null(src_attrs); dest_attrs = sysdb_new_attrs(NULL); assert_non_null(dest_attrs); ret = sysdb_handle_original_uuid("xyz", src_attrs, "abc", dest_attrs, "def"); assert_int_equal(ret, ENOENT); ret = sysdb_attrs_add_val(src_attrs, "GUID", &guid_val); assert_int_equal(ret, EOK); ret = sysdb_attrs_add_string(src_attrs, "UUID", IPA_UUID); assert_int_equal(ret, EOK); ret = sysdb_handle_original_uuid(NULL, src_attrs, "GUID", dest_attrs, "def"); assert_int_equal(ret, ENOENT); ret = sysdb_handle_original_uuid("objectGUID", NULL, "GUID", dest_attrs, "def"); assert_int_equal(ret, EINVAL); ret = sysdb_handle_original_uuid("objectGUID", src_attrs, "GUID", dest_attrs, "def"); assert_int_equal(ret, EOK); ret = sysdb_attrs_get_string(dest_attrs, "def", &guid); assert_int_equal(ret, EOK); assert_string_equal(guid, AD_GUID); ret = sysdb_handle_original_uuid("ipaUniqueID", src_attrs, "UUID", dest_attrs, "ghi"); assert_int_equal(ret, EOK); ret = sysdb_attrs_get_string(dest_attrs, "ghi", &guid); assert_int_equal(ret, EOK); assert_string_equal(guid, IPA_UUID); talloc_free(src_attrs); src_attrs = sysdb_new_attrs(NULL); assert_non_null(src_attrs); /* check objectGUID with length other than 16 */ ret = sysdb_attrs_add_string(src_attrs, "GUID", IPA_UUID); assert_int_equal(ret, EOK); ret = sysdb_handle_original_uuid("objectGUID", src_attrs, "GUID", dest_attrs, "jkl"); assert_int_equal(ret, EOK); ret = sysdb_attrs_get_string(dest_attrs, "jkl", &guid); assert_int_equal(ret, EOK); assert_string_equal(guid, IPA_UUID); talloc_free(src_attrs); talloc_free(dest_attrs); }
errno_t sysdb_store_ssh_host(struct sysdb_ctx *sysdb, struct sss_domain_info *domain, const char *name, const char *alias, time_t now, struct sysdb_attrs *attrs) { TALLOC_CTX *tmp_ctx; errno_t ret, sret; bool in_transaction = false; const char *search_attrs[] = { SYSDB_NAME_ALIAS, NULL }; bool new_alias; struct ldb_message *host = NULL; struct ldb_message_element *el; unsigned int i; DEBUG(SSSDBG_TRACE_FUNC, ("Storing host %s\n", name)); tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } ret = sysdb_transaction_start(sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); goto done; } in_transaction = true; ret = sysdb_get_ssh_host(tmp_ctx, sysdb, domain, name, search_attrs, &host); if (ret != EOK && ret != ENOENT) { goto done; } ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, SYSDB_SSH_HOST_OC); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not set object class [%d]: %s\n", ret, strerror(ret))); goto done; } ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not set name attribute [%d]: %s\n", ret, strerror(ret))); goto done; } if (alias) { new_alias = true; /* copy aliases from the existing entry */ if (host) { el = ldb_msg_find_element(host, SYSDB_NAME_ALIAS); if (el) { for (i = 0; i < el->num_values; i++) { if (strcmp((char *)el->values[i].data, alias) == 0) { new_alias = false; } ret = sysdb_attrs_add_val(attrs, SYSDB_NAME_ALIAS, &el->values[i]); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias %s [%d]: %s\n", el->values[i].data, ret, strerror(ret))); goto done; } } } } /* add alias only if it is not already present */ if (new_alias) { ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, alias); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias %s [%d]: %s\n", alias, ret, strerror(ret))); goto done; } } } /* make sure sshPublicKey is present when modifying an existing host */ if (host) { ret = sysdb_attrs_get_el(attrs, SYSDB_SSH_PUBKEY, &el); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not get sysdb sshPublicKey [%d]: %s\n", ret, strerror(ret))); goto done; } } ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not set sysdb lastUpdate [%d]: %s\n", ret, strerror(ret))); goto done; } ret = sysdb_update_ssh_host(sysdb, domain, name, attrs); if (ret != EOK) { goto done; } ret = sysdb_transaction_commit(sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n")); goto done; } in_transaction = false; ret = EOK; done: if (in_transaction) { sret = sysdb_transaction_cancel(sysdb); if (sret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n")); } } talloc_free(tmp_ctx); return ret; }
int sdap_parse_entry(TALLOC_CTX *memctx, struct sdap_handle *sh, struct sdap_msg *sm, struct sdap_attr_map *map, int attrs_num, struct sysdb_attrs **_attrs, char **_dn, bool disable_range_retrieval) { struct sysdb_attrs *attrs; BerElement *ber = NULL; struct berval **vals; struct ldb_val v; char *str; int lerrno; int a, i, ret; const char *name; bool store; bool base64; char *base_attr; char *dn = NULL; uint32_t range_offset; TALLOC_CTX *tmp_ctx = talloc_new(NULL); if (!tmp_ctx) return ENOMEM; lerrno = 0; ret = ldap_set_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); if (ret != LDAP_OPT_SUCCESS) { DEBUG(1, ("ldap_set_option failed [%s], ignored.\n", sss_ldap_err2string(ret))); } attrs = sysdb_new_attrs(tmp_ctx); if (!attrs) { ret = ENOMEM; goto done; } str = ldap_get_dn(sh->ldap, sm->msg); if (!str) { ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); DEBUG(1, ("ldap_get_dn failed: %d(%s)\n", lerrno, sss_ldap_err2string(lerrno))); ret = EIO; goto done; } DEBUG(9, ("OriginalDN: [%s].\n", str)); ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, str); if (ret) goto done; if (_dn) { dn = talloc_strdup(tmp_ctx, str); if (!dn) { ret = ENOMEM; ldap_memfree(str); goto done; } } ldap_memfree(str); if (map) { vals = ldap_get_values_len(sh->ldap, sm->msg, "objectClass"); if (!vals) { DEBUG(1, ("Unknown entry type, no objectClasses found!\n")); ret = EINVAL; goto done; } for (i = 0; vals[i]; i++) { /* the objectclass is always the first name in the map */ if (strncasecmp(map[0].name, vals[i]->bv_val, vals[i]->bv_len) == 0) { /* ok it's an entry of the right type */ break; } } if (!vals[i]) { DEBUG(1, ("objectClass not matching: %s\n", map[0].name)); ldap_value_free_len(vals); ret = EINVAL; goto done; } ldap_value_free_len(vals); } str = ldap_first_attribute(sh->ldap, sm->msg, &ber); if (!str) { ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); DEBUG(lerrno == LDAP_SUCCESS ? SSSDBG_TRACE_INTERNAL : SSSDBG_MINOR_FAILURE, ("Entry has no attributes [%d(%s)]!?\n", lerrno, sss_ldap_err2string(lerrno))); if (map) { ret = EINVAL; goto done; } } while (str) { base64 = false; ret = sdap_parse_range(tmp_ctx, str, &base_attr, &range_offset, disable_range_retrieval); switch(ret) { case EAGAIN: /* This attribute contained range values and needs more to * be retrieved */ /* TODO: return the set of attributes that need additional retrieval * For now, we'll continue below and treat it as regular values. */ /* FALLTHROUGH */ case ECANCELED: /* FALLTHROUGH */ case EOK: break; default: DEBUG(SSSDBG_MINOR_FAILURE, ("Could not determine if attribute [%s] was ranged\n", str)); goto done; } if (map) { for (a = 1; a < attrs_num; a++) { /* check if this attr is valid with the chosen schema */ if (!map[a].name) continue; /* check if it is an attr we are interested in */ if (strcasecmp(base_attr, map[a].name) == 0) break; } /* interesting attr */ if (a < attrs_num) { store = true; name = map[a].sys_name; if (strcmp(name, SYSDB_SSH_PUBKEY) == 0) { base64 = true; } } else { store = false; name = NULL; } } else { name = base_attr; store = true; } if (ret == ECANCELED) { ret = EOK; store = false; } if (store) { vals = ldap_get_values_len(sh->ldap, sm->msg, str); if (!vals) { ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); if (lerrno != LDAP_SUCCESS) { DEBUG(1, ("LDAP Library error: %d(%s)", lerrno, sss_ldap_err2string(lerrno))); ret = EIO; goto done; } DEBUG(5, ("Attribute [%s] has no values, skipping.\n", str)); } else { if (!vals[0]) { DEBUG(1, ("Missing value after ldap_get_values() ??\n")); ret = EINVAL; goto done; } for (i = 0; vals[i]; i++) { if (vals[i]->bv_len == 0) { DEBUG(SSSDBG_MINOR_FAILURE, ("Value of attribute [%s] is empty. " "Skipping this value.\n", str)); continue; } if (base64) { v.data = (uint8_t *)sss_base64_encode(attrs, (uint8_t *)vals[i]->bv_val, vals[i]->bv_len); if (!v.data) { ret = ENOMEM; goto done; } v.length = strlen((const char *)v.data); } else { v.data = (uint8_t *)vals[i]->bv_val; v.length = vals[i]->bv_len; } ret = sysdb_attrs_add_val(attrs, name, &v); if (ret) goto done; } ldap_value_free_len(vals); } } ldap_memfree(str); str = ldap_next_attribute(sh->ldap, sm->msg, ber); } ber_free(ber, 0); ber = NULL; ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); if (lerrno) { DEBUG(1, ("LDAP Library error: %d(%s)", lerrno, sss_ldap_err2string(lerrno))); ret = EIO; goto done; } *_attrs = talloc_steal(memctx, attrs); if (_dn) *_dn = talloc_steal(memctx, dn); ret = EOK; done: if (ber) ber_free(ber, 0); talloc_free(tmp_ctx); return ret; }