📄 hdb-ldb.c
字号:
krb5_set_error_string(context, "strupper_talloc: out of memory"); return ENOMEM; } ret = krb5_copy_principal(context, principal, &alloc_principal); if (ret) { return ret; } free(alloc_principal->name.name_string.val[1]); alloc_principal->name.name_string.val[1] = strdup(realm_fixed); talloc_free(realm_fixed); if (!alloc_principal->name.name_string.val[1]) { krb5_set_error_string(context, "LDB_fetch: strdup() failed!"); return ENOMEM; } principal = alloc_principal; realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msg[0], "nCName", NULL); } else { /* we should lookup trusted domains */ return HDB_ERR_NOENTRY; } realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msg[0], "nCName", NULL); ret = LDB_lookup_principal(context, (struct ldb_context *)db->hdb_db, mem_ctx, principal, HDB_LDB_ENT_TYPE_KRBTGT, realm_dn, &msg); if (ret != 0) { krb5_warnx(context, "LDB_fetch: could not find principal in DB"); krb5_set_error_string(context, "LDB_fetch: could not find principal in DB"); return ret; } ret = LDB_message2entry(context, db, mem_ctx, principal, HDB_LDB_ENT_TYPE_KRBTGT, msg[0], realm_ref_msg[0], entry_ex); if (ret != 0) { krb5_warnx(context, "LDB_fetch: message2entry failed"); } return ret;}static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, TALLOC_CTX *mem_ctx, krb5_const_principal principal, unsigned flags, hdb_entry_ex *entry_ex){ krb5_error_code ret; const char *realm; struct ldb_message **msg = NULL; struct ldb_message **realm_ref_msg = NULL; struct ldb_dn *partitions_basedn = samdb_partitions_dn(db->hdb_db, mem_ctx); if (principal->name.name_string.len >= 2) { /* 'normal server' case */ int ldb_ret; NTSTATUS nt_status; struct ldb_dn *user_dn, *domain_dn; char *principal_string; ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &principal_string); if (ret != 0) { return ret; } /* At this point we may find the host is known to be * in a different realm, so we should generate a * referral instead */ nt_status = crack_service_principal_name((struct ldb_context *)db->hdb_db, mem_ctx, principal_string, &user_dn, &domain_dn); free(principal_string); if (!NT_STATUS_IS_OK(nt_status)) { return HDB_ERR_NOENTRY; } ldb_ret = gendb_search_dn((struct ldb_context *)db->hdb_db, mem_ctx, user_dn, &msg, user_attrs); if (ldb_ret != 1) { return HDB_ERR_NOENTRY; } ldb_ret = gendb_search((struct ldb_context *)db->hdb_db, mem_ctx, partitions_basedn, &realm_ref_msg, realm_ref_attrs, "ncName=%s", ldb_dn_get_linearized(domain_dn)); if (ldb_ret != 1) { return HDB_ERR_NOENTRY; } } else { struct ldb_dn *realm_dn; /* server as client principal case, but we must not lookup userPrincipalNames */ realm = krb5_principal_get_realm(context, principal); ret = LDB_lookup_realm(context, (struct ldb_context *)db->hdb_db, mem_ctx, realm, &realm_ref_msg); if (ret != 0) { return HDB_ERR_NOENTRY; } realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msg[0], "nCName", NULL); ret = LDB_lookup_principal(context, (struct ldb_context *)db->hdb_db, mem_ctx, principal, HDB_LDB_ENT_TYPE_SERVER, realm_dn, &msg); if (ret != 0) { return ret; } } ret = LDB_message2entry(context, db, mem_ctx, principal, HDB_LDB_ENT_TYPE_SERVER, msg[0], realm_ref_msg[0], entry_ex); if (ret != 0) { krb5_warnx(context, "LDB_fetch: message2entry failed"); } return ret;} static krb5_error_code LDB_fetch(krb5_context context, HDB *db, krb5_const_principal principal, unsigned flags, hdb_entry_ex *entry_ex){ krb5_error_code ret = HDB_ERR_NOENTRY; TALLOC_CTX *mem_ctx = talloc_named(db, 0, "LDB_fetch context"); if (!mem_ctx) { krb5_set_error_string(context, "LDB_fetch: talloc_named() failed!"); return ENOMEM; } if (flags & HDB_F_GET_CLIENT) { ret = LDB_fetch_client(context, db, mem_ctx, principal, flags, entry_ex); if (ret != HDB_ERR_NOENTRY) goto done; } if (flags & HDB_F_GET_SERVER) { ret = LDB_fetch_server(context, db, mem_ctx, principal, flags, entry_ex); if (ret != HDB_ERR_NOENTRY) goto done; ret = LDB_fetch_krbtgt(context, db, mem_ctx, principal, flags, entry_ex); if (ret != HDB_ERR_NOENTRY) goto done; } if (flags & HDB_F_GET_KRBTGT) { ret = LDB_fetch_krbtgt(context, db, mem_ctx, principal, flags, entry_ex); if (ret != HDB_ERR_NOENTRY) goto done; }done: talloc_free(mem_ctx); return ret;}static krb5_error_code LDB_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry){ return HDB_ERR_DB_INUSE;}static krb5_error_code LDB_remove(krb5_context context, HDB *db, krb5_const_principal principal){ return HDB_ERR_DB_INUSE;}struct hdb_ldb_seq { struct ldb_context *ctx; int index; int count; struct ldb_message **msgs; struct ldb_message **realm_ref_msgs;};static krb5_error_code LDB_seq(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry){ krb5_error_code ret; struct hdb_ldb_seq *priv = (struct hdb_ldb_seq *)db->hdb_dbc; TALLOC_CTX *mem_ctx; hdb_entry_ex entry_ex; memset(&entry_ex, '\0', sizeof(entry_ex)); if (!priv) { return HDB_ERR_NOENTRY; } mem_ctx = talloc_named(priv, 0, "LDB_seq context"); if (!mem_ctx) { krb5_set_error_string(context, "LDB_seq: talloc_named() failed!"); return ENOMEM; } if (priv->index < priv->count) { ret = LDB_message2entry(context, db, mem_ctx, NULL, HDB_LDB_ENT_TYPE_ANY, priv->msgs[priv->index++], priv->realm_ref_msgs[0], entry); } else { ret = HDB_ERR_NOENTRY; } if (ret != 0) { talloc_free(priv); db->hdb_dbc = NULL; } else { talloc_free(mem_ctx); } return ret;}static krb5_error_code LDB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry){ struct ldb_context *ldb_ctx = (struct ldb_context *)db->hdb_db; struct hdb_ldb_seq *priv = (struct hdb_ldb_seq *)db->hdb_dbc; char *realm; struct ldb_dn *realm_dn = NULL; struct ldb_result *res = NULL; struct ldb_message **realm_ref_msgs = NULL; krb5_error_code ret; TALLOC_CTX *mem_ctx; int lret; if (priv) { talloc_free(priv); db->hdb_dbc = NULL; } priv = (struct hdb_ldb_seq *) talloc(db, struct hdb_ldb_seq); if (!priv) { krb5_set_error_string(context, "talloc: out of memory"); return ENOMEM; } priv->ctx = ldb_ctx; priv->index = 0; priv->msgs = NULL; priv->realm_ref_msgs = NULL; priv->count = 0; mem_ctx = talloc_named(priv, 0, "LDB_firstkey context"); if (!mem_ctx) { krb5_set_error_string(context, "LDB_firstkey: talloc_named() failed!"); return ENOMEM; } ret = krb5_get_default_realm(context, &realm); if (ret != 0) { talloc_free(priv); return ret; } ret = LDB_lookup_realm(context, (struct ldb_context *)db->hdb_db, mem_ctx, realm, &realm_ref_msgs); free(realm); if (ret != 0) { talloc_free(priv); krb5_warnx(context, "LDB_firstkey: could not find realm\n"); return HDB_ERR_NOENTRY; } realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msgs[0], "nCName", NULL); priv->realm_ref_msgs = talloc_steal(priv, realm_ref_msgs); lret = ldb_search(ldb_ctx, realm_dn, LDB_SCOPE_SUBTREE, "(objectClass=user)", user_attrs, &res); if (lret != LDB_SUCCESS) { talloc_free(priv); return HDB_ERR_NOENTRY; } priv->count = res->count; priv->msgs = talloc_steal(priv, res->msgs); talloc_free(res); db->hdb_dbc = priv; ret = LDB_seq(context, db, flags, entry); if (ret != 0) { talloc_free(priv); db->hdb_dbc = NULL; } else { talloc_free(mem_ctx); } return ret;}static krb5_error_code LDB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry){ return LDB_seq(context, db, flags, entry);}static krb5_error_code LDB_destroy(krb5_context context, HDB *db){ talloc_free(db); return 0;}/* This interface is to be called by the KDC, which is expecting Samba * calling conventions. It is also called by a wrapper * (hdb_ldb_create) from the kpasswdd -> krb5 -> keytab_hdb -> hdb * code */NTSTATUS kdc_hdb_ldb_create(TALLOC_CTX *mem_ctx, struct event_context *ev_ctx, struct loadparm_context *lp_ctx, krb5_context context, struct HDB **db, const char *arg){ NTSTATUS nt_status; struct auth_session_info *session_info; *db = talloc(mem_ctx, HDB); if (!*db) { krb5_set_error_string(context, "malloc: out of memory"); return NT_STATUS_NO_MEMORY; } (*db)->hdb_master_key_set = 0; (*db)->hdb_db = NULL; nt_status = auth_system_session_info(*db, lp_ctx, &session_info); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } /* The idea here is very simple. Using Kerberos to * authenticate the KDC to the LDAP server is higly likely to * be circular. * * In future we may set this up to use EXERNAL and SSL * certificates, for now it will almost certainly be NTLMSSP */ cli_credentials_set_kerberos_state(session_info->credentials, CRED_DONT_USE_KERBEROS); /* Setup the link to LDB */ (*db)->hdb_db = samdb_connect(*db, ev_ctx, lp_ctx, session_info); if ((*db)->hdb_db == NULL) { DEBUG(1, ("hdb_ldb_create: Cannot open samdb for KDC backend!")); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } (*db)->hdb_dbc = NULL; (*db)->hdb_open = LDB_open; (*db)->hdb_close = LDB_close; (*db)->hdb_fetch = LDB_fetch; (*db)->hdb_store = LDB_store; (*db)->hdb_remove = LDB_remove; (*db)->hdb_firstkey = LDB_firstkey; (*db)->hdb_nextkey = LDB_nextkey; (*db)->hdb_lock = LDB_lock; (*db)->hdb_unlock = LDB_unlock; (*db)->hdb_rename = LDB_rename; /* we don't implement these, as we are not a lockable database */ (*db)->hdb__get = NULL; (*db)->hdb__put = NULL; /* kadmin should not be used for deletes - use other tools instead */ (*db)->hdb__del = NULL; (*db)->hdb_destroy = LDB_destroy; return NT_STATUS_OK;}krb5_error_code hdb_ldb_create(krb5_context context, struct HDB **db, const char *arg){ NTSTATUS nt_status; /* The global kdc_mem_ctx and kdc_lp_ctx, Disgusting, ugly hack, but it means one less private hook */ nt_status = kdc_hdb_ldb_create(kdc_mem_ctx, event_context_find(kdc_mem_ctx), kdc_lp_ctx, context, db, arg); if (NT_STATUS_IS_OK(nt_status)) { return 0; } return EINVAL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -