summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-01-15 02:20:30 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:53:53 -0500
commitc727866172b5abb1cab0913eb78f3f1d58fcb9aa (patch)
treee590044485bc3bcbd732e47dcdcd40fa28b90cd4
parent2c33c41b0c98ee36f5c9b6a368deb1192360fd5b (diff)
downloadsamba-c727866172b5abb1cab0913eb78f3f1d58fcb9aa.tar.gz
samba-c727866172b5abb1cab0913eb78f3f1d58fcb9aa.tar.xz
samba-c727866172b5abb1cab0913eb78f3f1d58fcb9aa.zip
r4742: add server support for lsa_add/remove_account_rights() and fix some parsing bugs related to that code
(This used to be commit 7bf1312287cc1ec6b97917ba25fc60d6db09f26c)
-rw-r--r--source3/lib/privileges.c77
-rw-r--r--source3/rpc_parse/parse_lsa.c8
-rw-r--r--source3/rpc_server/srv_lsa.c66
-rw-r--r--source3/rpc_server/srv_lsa_nt.c107
-rw-r--r--source3/rpcclient/cmd_lsarpc.c7
5 files changed, 247 insertions, 18 deletions
diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c
index f35d16f30f4..09a868fc277 100644
--- a/source3/lib/privileges.c
+++ b/source3/lib/privileges.c
@@ -87,24 +87,25 @@ typedef struct priv_sid_list {
Retrieve the privilege mask (set) for a given SID
****************************************************************************/
-static uint32 get_privileges( const DOM_SID *sid )
+static uint32 get_privileges( const DOM_SID *sid, uint32 *mask )
{
TDB_CONTEXT *tdb = get_account_pol_tdb();
fstring keystr;
uint32 priv_mask;
if ( !tdb )
- return 0;
+ return False;
fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) );
if ( !tdb_fetch_uint32( tdb, keystr, &priv_mask ) ) {
DEBUG(3,("get_privileges: No privileges assigned to SID [%s]\n",
sid_string_static(sid)));
- return 0;
+ return False;
}
- return priv_mask;
+ *mask = priv_mask;
+ return True;
}
/***************************************************************************
@@ -241,13 +242,11 @@ void get_privileges_for_sids(PRIVILEGE_SET *privset, DOM_SID *slist, int scount)
int i;
for ( i=0; i<scount; i++ ) {
- priv_mask = get_privileges( &slist[i] );
-
/* don't add unless we actually have a privilege assigned */
- if ( priv_mask == 0 )
+ if ( !get_privileges( &slist[i], &priv_mask ) )
continue;
-
+
DEBUG(5,("get_privileges_for_sids: sid = %s, privilege mask = 0x%x\n",
sid_string_static(&slist[i]), priv_mask));
@@ -350,9 +349,10 @@ BOOL grant_privilege(const DOM_SID *sid, uint32 priv_mask)
{
uint32 old_mask, new_mask;
- old_mask = get_privileges( sid );
-
- new_mask = old_mask | priv_mask;
+ if ( get_privileges( sid, &old_mask ) )
+ new_mask = old_mask | priv_mask;
+ else
+ new_mask = priv_mask;
DEBUG(10,("grant_privilege: %s, orig priv set = 0x%x, new privilege set = 0x%x\n",
sid_string_static(sid), old_mask, new_mask ));
@@ -360,6 +360,25 @@ BOOL grant_privilege(const DOM_SID *sid, uint32 priv_mask)
return set_privileges( sid, new_mask );
}
+/*********************************************************************
+ Add a privilege based on its name
+*********************************************************************/
+
+BOOL grant_privilege_by_name(DOM_SID *sid, const char *name)
+{
+ int i;
+
+ for ( i = 0; privs[i].se_priv != SE_END; i++ ) {
+ if ( strequal(privs[i].name, name) ) {
+ return grant_privilege( sid, privs[i].se_priv );
+ }
+ }
+
+ DEBUG(3, ("grant_privilege_by_name: No Such Privilege Found (%s)\n", name));
+
+ return False;
+}
+
/***************************************************************************
Remove privilege from sid
****************************************************************************/
@@ -368,7 +387,10 @@ BOOL revoke_privilege(const DOM_SID *sid, uint32 priv_mask)
{
uint32 old_mask, new_mask;
- old_mask = get_privileges( sid );
+ if ( get_privileges( sid, &old_mask ) )
+ new_mask = old_mask | priv_mask;
+ else
+ new_mask = priv_mask;
new_mask = old_mask & ~priv_mask;
@@ -378,6 +400,25 @@ BOOL revoke_privilege(const DOM_SID *sid, uint32 priv_mask)
return set_privileges( sid, new_mask );
}
+/*********************************************************************
+ Add a privilege based on its name
+*********************************************************************/
+
+BOOL revoke_privilege_by_name(DOM_SID *sid, const char *name)
+{
+ int i;
+
+ for ( i = 0; privs[i].se_priv != SE_END; i++ ) {
+ if ( strequal(privs[i].name, name) ) {
+ return revoke_privilege( sid, privs[i].se_priv );
+ }
+ }
+
+ DEBUG(3, ("revoke_privilege_by_name: No Such Privilege Found (%s)\n", name));
+
+ return False;
+}
+
/***************************************************************************
Retrieve the SIDs assigned to a given privilege
****************************************************************************/
@@ -560,3 +601,15 @@ int count_all_privileges( void )
return count;
}
+/*******************************************************************
+*******************************************************************/
+
+BOOL is_privileged_sid( DOM_SID *sid )
+{
+ int mask;
+
+ /* check if the lookup succeeds */
+
+ return get_privileges( sid, &mask );
+}
+
diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c
index 20ccc39ce07..a4a3917d2e1 100644
--- a/source3/rpc_parse/parse_lsa.c
+++ b/source3/rpc_parse/parse_lsa.c
@@ -2359,7 +2359,7 @@ void init_q_add_acct_rights(LSA_Q_ADD_ACCT_RIGHTS *q_q,
q_q->pol = *hnd;
init_dom_sid2(&q_q->sid, sid);
init_unistr2_array(&q_q->rights, count, rights);
- q_q->count = 5;
+ q_q->count = count;
}
@@ -2377,7 +2377,7 @@ BOOL lsa_io_q_add_acct_rights(const char *desc, LSA_Q_ADD_ACCT_RIGHTS *q_q, prs_
if(!smb_io_dom_sid2("sid", &q_q->sid, ps, depth))
return False;
- if(!prs_uint32("count", ps, depth, &q_q->rights.count))
+ if(!prs_uint32("count", ps, depth, &q_q->count))
return False;
if(!smb_io_unistr2_array("rights", &q_q->rights, ps, depth))
@@ -2417,7 +2417,7 @@ void init_q_remove_acct_rights(LSA_Q_REMOVE_ACCT_RIGHTS *q_q,
init_dom_sid2(&q_q->sid, sid);
q_q->removeall = removeall;
init_unistr2_array(&q_q->rights, count, rights);
- q_q->count = 5;
+ q_q->count = count;
}
@@ -2438,7 +2438,7 @@ BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *q_q
if(!prs_uint32("removeall", ps, depth, &q_q->removeall))
return False;
- if(!prs_uint32("count", ps, depth, &q_q->rights.count))
+ if(!prs_uint32("count", ps, depth, &q_q->count))
return False;
if(!smb_io_unistr2_array("rights", &q_q->rights, ps, depth))
diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c
index 63e74ec8911..e2506775342 100644
--- a/source3/rpc_server/srv_lsa.c
+++ b/source3/rpc_server/srv_lsa.c
@@ -642,7 +642,69 @@ static BOOL api_lsa_query_secobj(pipes_struct *p)
}
/***************************************************************************
- api_lsa_query_dnsdomainfo
+ api_lsa_add_acct_rights
+ ***************************************************************************/
+
+static BOOL api_lsa_add_acct_rights(pipes_struct *p)
+{
+ LSA_Q_ADD_ACCT_RIGHTS q_u;
+ LSA_R_ADD_ACCT_RIGHTS r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!lsa_io_q_add_acct_rights("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_add_acct_rights: failed to unmarshall LSA_Q_ADD_ACCT_RIGHTS.\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_add_acct_rights(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!lsa_io_r_add_acct_rights("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_add_acct_rights: Failed to marshall LSA_R_ADD_ACCT_RIGHTS.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/***************************************************************************
+ api_lsa_remove_acct_rights
+ ***************************************************************************/
+
+static BOOL api_lsa_remove_acct_rights(pipes_struct *p)
+{
+ LSA_Q_REMOVE_ACCT_RIGHTS q_u;
+ LSA_R_REMOVE_ACCT_RIGHTS r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!lsa_io_q_remove_acct_rights("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_remove_acct_rights: failed to unmarshall LSA_Q_REMOVE_ACCT_RIGHTS.\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_remove_acct_rights(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!lsa_io_r_remove_acct_rights("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_remove_acct_rights: Failed to marshall LSA_R_REMOVE_ACCT_RIGHTS.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/***************************************************************************
+ api_lsa_query_info2
***************************************************************************/
static BOOL api_lsa_query_info2(pipes_struct *p)
@@ -697,6 +759,8 @@ static struct api_struct api_lsa_cmds[] =
{ "LSA_SETSYSTEMACCOUNT", LSA_SETSYSTEMACCOUNT, api_lsa_setsystemaccount },
{ "LSA_ADDPRIVS" , LSA_ADDPRIVS , api_lsa_addprivs },
{ "LSA_REMOVEPRIVS" , LSA_REMOVEPRIVS , api_lsa_removeprivs },
+ { "LSA_ADDACCTRIGHTS" , LSA_ADDACCTRIGHTS , api_lsa_add_acct_rights },
+ { "LSA_REMOVEACCTRIGHTS", LSA_REMOVEACCTRIGHTS, api_lsa_remove_acct_rights },
{ "LSA_QUERYSECOBJ" , LSA_QUERYSECOBJ , api_lsa_query_secobj },
/* be careful of the adding of new RPC's. See commentrs below about
ADS DC capabilities */
diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c
index 328f409cf36..d5bddef739a 100644
--- a/source3/rpc_server/srv_lsa_nt.c
+++ b/source3/rpc_server/srv_lsa_nt.c
@@ -1237,6 +1237,8 @@ NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUER
return r_u->status;
}
+/***************************************************************************
+ ***************************************************************************/
NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_INFO2 *r_u)
{
@@ -1297,3 +1299,108 @@ NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_I
return r_u->status;
}
+
+/***************************************************************************
+ ***************************************************************************/
+
+NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R_ADD_ACCT_RIGHTS *r_u)
+{
+ struct lsa_info *info = NULL;
+ int i = 0;
+ DOM_SID sid;
+ fstring privname;
+ UNISTR2_ARRAY *uni_privnames = &q_u->rights;
+
+
+ /* find the connection policy handle. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ return NT_STATUS_INVALID_HANDLE;
+
+ /* check to see if the pipe_user is a Domain Admin since
+ account_pol.tdb was already opened as root, this is all we have */
+
+ if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ return NT_STATUS_ACCESS_DENIED;
+
+ /* according to an NT4 PDC, you can add privileges to SIDs even without
+ call_lsa_create_account() first. And you can use any arbitrary SID. */
+
+ sid_copy( &sid, &q_u->sid.sid );
+
+ /* just a little sanity check */
+
+ if ( q_u->count != uni_privnames->count ) {
+ DEBUG(0,("_lsa_add_acct_rights: count != number of UNISTR2 elements!\n"));
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ for ( i=0; i<q_u->count; i++ ) {
+ unistr2_to_ascii( privname, &uni_privnames->strings[i].string, sizeof(fstring)-1 );
+
+ /* only try to add non-null strings */
+
+ if ( *privname && !grant_privilege_by_name( &sid, privname ) ) {
+ DEBUG(2,("_lsa_add_acct_rights: Failed to add privilege [%s]\n", privname ));
+ return NT_STATUS_NO_SUCH_PRIVILEGE;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, LSA_R_REMOVE_ACCT_RIGHTS *r_u)
+{
+ struct lsa_info *info = NULL;
+ int i = 0;
+ DOM_SID sid;
+ fstring privname;
+ UNISTR2_ARRAY *uni_privnames = &q_u->rights;
+
+
+ /* find the connection policy handle. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ return NT_STATUS_INVALID_HANDLE;
+
+ /* check to see if the pipe_user is a Domain Admin since
+ account_pol.tdb was already opened as root, this is all we have */
+
+ if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ return NT_STATUS_ACCESS_DENIED;
+
+ /* according to an NT4 PDC, you can add privileges to SIDs even without
+ call_lsa_create_account() first. And you can use any arbitrary SID. */
+
+ sid_copy( &sid, &q_u->sid.sid );
+
+ if ( q_u->removeall ) {
+ if ( !revoke_privilege( &sid, SE_ALL_PRIVS ) )
+ return NT_STATUS_ACCESS_DENIED;
+
+ return NT_STATUS_OK;
+ }
+
+ /* just a little sanity check */
+
+ if ( q_u->count != uni_privnames->count ) {
+ DEBUG(0,("_lsa_add_acct_rights: count != number of UNISTR2 elements!\n"));
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ for ( i=0; i<q_u->count; i++ ) {
+ unistr2_to_ascii( privname, &uni_privnames->strings[i].string, sizeof(fstring)-1 );
+
+ /* only try to add non-null strings */
+
+ if ( *privname && !revoke_privilege_by_name( &sid, privname ) ) {
+ DEBUG(2,("_lsa_remove_acct_rights: Failed to add privilege [%s]\n", privname ));
+ return NT_STATUS_NO_SUCH_PRIVILEGE;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c
index a07d38ca60d..419ddb47349 100644
--- a/source3/rpcclient/cmd_lsarpc.c
+++ b/source3/rpcclient/cmd_lsarpc.c
@@ -750,9 +750,13 @@ struct cmd_set lsarpc_commands[] = {
{ "enumprivs", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privilege, NULL, PI_LSARPC, "Enumerate privileges", "" },
{ "getdispname", RPC_RTYPE_NTSTATUS, cmd_lsa_get_dispname, NULL, PI_LSARPC, "Get the privilege name", "" },
{ "lsaenumsid", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_sids, NULL, PI_LSARPC, "Enumerate the LSA SIDS", "" },
- { "lsacreateaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_create_account, NULL, PI_LSARPC, "Create a new lsa account", "" },
+ { "lsacreateaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_create_account, NULL, PI_LSARPC, "Create a new lsa account", "" },
{ "lsaenumprivsaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privsaccounts, NULL, PI_LSARPC, "Enumerate the privileges of an SID", "" },
{ "lsaenumacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_acct_rights, NULL, PI_LSARPC, "Enumerate the rights of an SID", "" },
+#if 0
+ { "lsaaddpriv", RPC_RTYPE_NTSTATUS, cmd_lsa_add_priv, NULL, PI_LSARPC, "Assign a privilege to a SID", "" },
+ { "lsadelpriv", RPC_RTYPE_NTSTATUS, cmd_lsa_del_priv, NULL, PI_LSARPC, "Revoke a privilege from a SID", "" },
+#endif
{ "lsaaddacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_add_acct_rights, NULL, PI_LSARPC, "Add rights to an account", "" },
{ "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, PI_LSARPC, "Remove rights from an account", "" },
{ "lsalookupprivvalue", RPC_RTYPE_NTSTATUS, cmd_lsa_lookupprivvalue, NULL, PI_LSARPC, "Get a privilege value given its name", "" },
@@ -760,3 +764,4 @@ struct cmd_set lsarpc_commands[] = {
{ NULL }
};
+