From c8549363f49ac9ea818bd782319e57154764992f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 19 Mar 2004 14:31:09 +0000 Subject: add privileges support to ldapsam too (This used to be commit d940a2f77377dd1560cea4c782823cf9cd97a3aa) --- source3/include/smbldap.h | 4 + source3/lib/privileges.c | 2 +- source3/lib/smbldap.c | 10 ++ source3/param/loadparm.c | 11 ++ source3/passdb/pdb_ldap.c | 317 +++++++++++++++++++++++++++++++++++++++++ source3/utils/net_privileges.c | 45 +++--- 6 files changed, 361 insertions(+), 28 deletions(-) diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h index 68a2c00afe..119479f218 100644 --- a/source3/include/smbldap.h +++ b/source3/include/smbldap.h @@ -38,6 +38,7 @@ #define LDAP_OBJ_IDPOOL "sambaUnixIdPool" #define LDAP_OBJ_IDMAP_ENTRY "sambaIdmapEntry" #define LDAP_OBJ_SID_ENTRY "sambaSidEntry" +#define LDAP_OBJ_PRIVILEGE "sambaPrivilege" #define LDAP_OBJ_ACCOUNT "account" #define LDAP_OBJ_POSIXACCOUNT "posixAccount" @@ -49,6 +50,7 @@ #define LDAP_ATTRIBUTE_SID "sambaSID" #define LDAP_ATTRIBUTE_UIDNUMBER "uidNumber" #define LDAP_ATTRIBUTE_GIDNUMBER "gidNumber" +#define LDAP_ATTRIBUTE_SID_LIST "sambaSIDList" /* attribute map table indexes */ @@ -93,6 +95,7 @@ #define LDAP_ATTR_MUNGED_DIAL 37 #define LDAP_ATTR_BAD_PASSWORD_TIME 38 #define LDAP_ATTR_MOD_TIMESTAMP 39 +#define LDAP_ATTR_SID_LIST 40 typedef struct _attrib_map_entry { int attrib; @@ -106,6 +109,7 @@ extern ATTRIB_MAP_ENTRY attrib_map_v22[]; extern ATTRIB_MAP_ENTRY attrib_map_v30[]; extern ATTRIB_MAP_ENTRY dominfo_attr_list[]; extern ATTRIB_MAP_ENTRY groupmap_attr_list[]; +extern ATTRIB_MAP_ENTRY privilege_attr_list[]; extern ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[]; extern ATTRIB_MAP_ENTRY idpool_attr_list[]; extern ATTRIB_MAP_ENTRY sidmap_attr_list[]; diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c index cd888b6513..ce647f02cd 100644 --- a/source3/lib/privileges.c +++ b/source3/lib/privileges.c @@ -33,7 +33,7 @@ PRIVS privs[] = { {SE_ASSIGN_PRIMARY_TOKEN, "SeAssignPrimaryTokenPrivilege", "Assign Primary Token"}, {SE_LOCK_MEMORY, "SeLockMemoryPrivilege", "Lock Memory"}, {SE_INCREASE_QUOTA, "SeIncreaseQuotaPrivilege", "Increase Quota"}, - {SE_UNSOLICITED_INPUT, "eUnsolicitedInputPrivilege", "Unsolicited Input"}, + {SE_UNSOLICITED_INPUT, "SeUnsolicitedInputPrivilege", "Unsolicited Input"}, {SE_MACHINE_ACCOUNT, "SeMachineAccountPrivilege", "Can add Machine Accounts to the Domain"}, {SE_TCB, "SeTcbPrivilege", "TCB"}, {SE_SECURITY, "SeSecurityPrivilege", "Security Privilege"}, diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 20c2163cde..c2dcd905ea 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -155,6 +155,16 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { { LDAP_ATTR_LIST_END, NULL } }; +/* privileges */ + +ATTRIB_MAP_ENTRY privilege_attr_list[] = { + { LDAP_ATTR_CN, "sambaPrivName" }, + { LDAP_ATTR_SID_LIST, LDAP_ATTRIBUTE_SID_LIST }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_LIST_END, NULL } +}; + /********************************************************************** perform a simple table lookup and return the attribute name **********************************************************************/ diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index a72f7f878b..b5372188de 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -224,6 +224,7 @@ typedef struct char *szLdapUserSuffix; char *szLdapIdmapSuffix; char *szLdapGroupSuffix; + char *szLdapPrivilegeSuffix; #ifdef WITH_LDAP_SAMCONFIG int ldap_port; char *szLdapServer; @@ -1074,6 +1075,7 @@ static struct parm_struct parm_table[] = { {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED}, {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, NULL, NULL, FLAG_ADVANCED}, {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, NULL, NULL, FLAG_ADVANCED}, + {"ldap privilege suffix", P_STRING, P_GLOBAL, &Globals.szLdapPrivilegeSuffix, NULL, NULL, FLAG_ADVANCED}, {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, FLAG_ADVANCED}, {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED}, {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED}, @@ -1471,6 +1473,7 @@ static void init_globals(void) string_set(&Globals.szLdapUserSuffix, ""); string_set(&Globals.szLdapGroupSuffix, ""); string_set(&Globals.szLdapIdmapSuffix, ""); + string_set(&Globals.szLdapPrivilegeSuffix, ""); string_set(&Globals.szLdapAdminDn, ""); Globals.ldap_ssl = LDAP_SSL_ON; @@ -2961,6 +2964,14 @@ char *lp_ldap_idmap_suffix(void) return lp_string(Globals.szLdapSuffix); } +char *lp_ldap_privilege_suffix(void) +{ + if (Globals.szLdapPrivilegeSuffix[0]) + return append_ldap_suffix(Globals.szLdapPrivilegeSuffix); + + return lp_string(Globals.szLdapSuffix); +} + /*************************************************************************** ***************************************************************************/ diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 2141f2a3f1..da5bfbecbb 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -2329,6 +2329,318 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, return NT_STATUS_OK; } +/********************************************************************** + Privileges related functions + *********************************************************************/ + +static NTSTATUS ldapsam_modify_sid_list_for_privilege(struct pdb_methods *my_methods, const char *privname, const DOM_SID *sid, int ldap_op) +{ + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + LDAPMessage *entry = NULL; + LDAPMod **mods = NULL; + fstring sid_str; + fstring filter; + char **attr_list, *dn; + int rc, i; + + if ((sid == NULL) || (!sid_to_string(sid_str, sid))) { + DEBUG(3, ("ldapsam_modify_sid_list_for_privilege: Invalid SID\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + pstr_sprintf(filter, "(&(objectclass=%s)(sambaPrivName=%s))", LDAP_OBJ_PRIVILEGE, privname); + attr_list = get_attr_list(privilege_attr_list); + rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_privilege_suffix(), + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &ldap_state->result); + free_attr_list(attr_list); + + + if (rc != LDAP_SUCCESS) { + DEBUG(0, ("ldapsam_modify_sid_list_for_privilege: LDAP search failed: %s\n", ldap_err2string(rc))); + DEBUG(3, ("ldapsam_modify_sid_list_for_privilege: Query was: %s, %s\n", lp_ldap_privilege_suffix(), filter)); + ldap_msgfree(ldap_state->result); + ldap_state->result = NULL; + goto done; + } + + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, ldap_state->result) == 0) { + /* if the privilege does not exist and we are adding then + * create it */ + if (ldap_op == LDAP_MOD_ADD) { + + DEBUG(3, ("Privilege not found on ldap tree, creating a new entry\n")); + if (asprintf(&dn, "sambaPrivName=%s,%s", privname, lp_ldap_privilege_suffix()) < 0) { + DEBUG(0, ("ldapsam_modify_sid_list_for_privilege: Out of memory\n")); + goto done; + } + + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaPrivName", privname); + + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_PRIVILEGE); + + rc = smbldap_add(ldap_state->smbldap_state, dn, mods); + + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(1, + ("ldapsam_modify_sid_list_for_privilege:" + "Failed to add privilege (%s) dn= %s with: %s\n\t%s\n", + privname, + dn, ldap_err2string(rc), + ld_error ? ld_error : "unknown") + ); + + SAFE_FREE(ld_error); + goto done; + } + + pstr_sprintf(filter, "(&(objectclass=%s)(sambaPrivName=%s))", LDAP_OBJ_PRIVILEGE, privname); + attr_list = get_attr_list(privilege_attr_list); + rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_privilege_suffix(), + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &ldap_state->result); + free_attr_list(attr_list); + + if (rc != LDAP_SUCCESS) { + DEBUG(0, ("ldapsam_modify_sid_list_for_privilege: LDAP search failed: %s\n", ldap_err2string(rc))); + DEBUG(3, ("ldapsam_modify_sid_list_for_privilege: Query was: %s, %s\n", lp_ldap_privilege_suffix(), filter)); + ldap_msgfree(ldap_state->result); + ldap_state->result = NULL; + goto done; + } + } else { + goto done; + } + } + /* entry found */ + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result); + + /* retrieve the dn */ + dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + if (!dn) { + goto done; + } + + /* prepare the modification */ + smbldap_set_mod(&mods, ldap_op, "sambaSIDList", sid_str); + + /* modify the privilege */ + rc = smbldap_modify(ldap_state->smbldap_state, dn, mods); + + /* free used structures */ + ldap_mods_free(mods, True); + + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(1, + ("ldapsam_modify_sid_list_for_privilege:" + "Failed to %s sid for privilege (%s) dn= %s with: %s\n\t%s\n", + (ldap_op == LDAP_MOD_ADD) ? "add" : "remove", + privname, + dn, ldap_err2string(rc), + ld_error ? ld_error : "unknown") + ); + SAFE_FREE(ld_error); + goto done; + } + + ret = NT_STATUS_OK; + +done: + return ret; +} + +static NTSTATUS ldapsam_add_sid_to_privilege(struct pdb_methods *my_methods, const char *privname, const DOM_SID *sid) +{ + return ldapsam_modify_sid_list_for_privilege(my_methods, privname, sid, LDAP_MOD_ADD); +} + +static NTSTATUS ldapsam_remove_sid_from_privilege(struct pdb_methods *my_methods, const char *privname, const DOM_SID *sid) +{ + return ldapsam_modify_sid_list_for_privilege(my_methods, privname, sid, LDAP_MOD_DELETE); +} + +static NTSTATUS ldapsam_get_privilege_set(struct pdb_methods *my_methods, NT_USER_TOKEN *token, PRIVILEGE_SET *privset) +{ + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + LDAPMessage *entry = NULL; + fstring sid_str; + fstring filter; + char **sid_list; + char **attr_list; + int rc, i; + + sid_list = (char **)malloc(sizeof(char *) * (token->num_sids + 1)); + for (i = 0; i < token->num_sids; i++) { + sid_to_string(sid_str, &token->user_sids[i]); + sid_list[i] = strdup(sid_str); + if ( ! sid_list[i]) { + ret = NT_STATUS_NO_MEMORY; + goto done; + } + } + sid_list[i] = NULL; + + pstr_sprintf(filter, "(objectclass=%s)", LDAP_OBJ_PRIVILEGE); + attr_list = get_attr_list(privilege_attr_list); + rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_privilege_suffix(), + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &ldap_state->result); + free_attr_list(attr_list); + + if (rc != LDAP_SUCCESS) { + DEBUG(0, ("ldapsam_get_privilege_set: LDAP search failed: %s\n", ldap_err2string(rc))); + DEBUG(3, ("ldapsam_get_privilege_set: Query was: %s, %s\n", lp_ldap_privilege_suffix(), filter)); + ldap_msgfree(ldap_state->result); + ldap_state->result = NULL; + goto done; + } + + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, ldap_state->result) == 0) { + DEBUG(3, ("ldapsam_get_privilege_set: No privileges in ldap tree\n")); + ret = NT_STATUS_OK; + goto done; + } + + DEBUG(2, ("ldapsam_get_privilege_set: %d entries in the base!\n", + ldap_count_entries(ldap_state->smbldap_state->ldap_struct, ldap_state->result))); + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result); + + while (entry != NULL) { + char **values = NULL; + + for(i=0; sid_list[i] != NULL; i++) { + char *c, *s; + pstring privname; + int j; + + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "sambaPrivName", privname, sizeof(pstring))) { + goto loop; + } + + if ((values = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID_LIST)) == NULL) { + DEBUG(10, ("ldapsam_get_privilege_set: SID List not found skipping privilege\n")); + goto loop; + } + + j = 0; + while (values[j] != 0) { + if (strcmp(values[j], sid_list[i]) == 0) { + DEBUG(10, ("sid [%s] found in users sid list\n", sid_list[i])); + DEBUG(10, ("adding privilege [%s] to the users privilege list\n", privname)); + add_privilege_by_name(privset, privname); + goto loop; + } + j++; + } + + if (values) { + ldap_value_free(values); + values = NULL; + } + } + loop: + if (values) { + ldap_value_free(values); + } + + entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct, entry); + } + + ret = NT_STATUS_OK; + +done: + i = 0; + while (sid_list[i]) { + free(sid_list[i]); + i++; + } + free(sid_list); + + return ret; +} + +static NTSTATUS ldapsam_get_privilege_entry(struct pdb_methods *my_methods, const char *privname, + char **sid_list) +{ + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + LDAPMessage *entry = NULL; + fstring sid_str; + fstring filter; + char **attr_list, **values; + int rc, i, len; + + *sid_list = NULL; + pstr_sprintf(filter, "(&(objectclass=%s)(sambaPrivName=%s))", LDAP_OBJ_PRIVILEGE, privname); + attr_list = get_attr_list(privilege_attr_list); + rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_privilege_suffix(), + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &ldap_state->result); + free_attr_list(attr_list); + + if (rc != LDAP_SUCCESS) { + DEBUG(0, ("ldapsam_get_privilege_entry: LDAP search failed: %s\n", ldap_err2string(rc))); + DEBUG(3, ("ldapsam_get_privilege_entry: Query was: %s, %s\n", lp_ldap_privilege_suffix(), filter)); + ldap_msgfree(ldap_state->result); + ldap_state->result = NULL; + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, ldap_state->result) == 0) { + DEBUG(3, ("ldapsam_get_privilege_entry: No such privilege (%s) in ldap tree\n", privname)); + goto done; + } + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result); + + if ((values = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID_LIST)) == NULL) { + DEBUG(10, ("ldapsam_get_privilege_entry: SID List not found skipping privilege\n")); + ret = NT_STATUS_OK; + goto done; + } + + for (i = 0, len = 0; values[i] != 0; i++ ) { + len = len + strlen(values[i]) + 1; + } + + *sid_list = (char *)malloc(len); + if ((*sid_list) == NULL) { + DEBUG(0, ("ldapsam_get_privilege_entry: Out of memory!\n")); + ldap_value_free(values); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + (*sid_list)[0] = '\0'; + + for (i = 0; values[i] != 0; i++ ) { + if (i != 0) { + strlcat(*sid_list, ",", len); + } + DEBUG(0, ("sid_list = [%s]\n", *sid_list)); + DEBUG(0, ("values = [%s]\n", values[i])); + DEBUG(0, ("len = [%d]\n", len)); + strlcat(*sid_list, values[i], len); + DEBUG(0, ("sid_list = [%s]\n", *sid_list)); + } + + ldap_value_free(values); + ret = NT_STATUS_OK; +done: + return ret; +} + + /********************************************************************** Housekeeping *********************************************************************/ @@ -2382,6 +2694,11 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry; (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping; + (*pdb_method)->add_sid_to_privilege = ldapsam_add_sid_to_privilege; + (*pdb_method)->remove_sid_from_privilege = ldapsam_remove_sid_from_privilege; + (*pdb_method)->get_privilege_set = ldapsam_get_privilege_set; + (*pdb_method)->get_privilege_entry = ldapsam_get_privilege_entry; + /* TODO: Setup private data and free */ ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(*ldap_state)); diff --git a/source3/utils/net_privileges.c b/source3/utils/net_privileges.c index 2e8bfe0c83..62f2da33ee 100644 --- a/source3/utils/net_privileges.c +++ b/source3/utils/net_privileges.c @@ -69,13 +69,13 @@ static void print_priv_entry(const char *privname, const char *description, cons return; } - if (!description) - d_printf("%s\n", privname); - else { - d_printf("%s\n", privname); + d_printf("%s\n", privname); + + if (description) { d_printf("\tdescription: %s\n", description); - d_printf("\tSIDS: %s\n", sid_list); } + + d_printf("\tSIDS: %s\n", sid_list); } /********************************************************* @@ -83,17 +83,13 @@ static void print_priv_entry(const char *privname, const char *description, cons **********************************************************/ static int net_priv_list(int argc, const char **argv) { - BOOL long_list = False; fstring privname = ""; fstring sid_string = ""; int i; /* get the options */ for ( i=0; i