diff options
author | Gerald Carter <jerry@samba.org> | 2005-01-15 02:20:30 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:53:53 -0500 |
commit | c727866172b5abb1cab0913eb78f3f1d58fcb9aa (patch) | |
tree | e590044485bc3bcbd732e47dcdcd40fa28b90cd4 /source3 | |
parent | 2c33c41b0c98ee36f5c9b6a368deb1192360fd5b (diff) | |
download | samba-c727866172b5abb1cab0913eb78f3f1d58fcb9aa.tar.gz samba-c727866172b5abb1cab0913eb78f3f1d58fcb9aa.tar.bz2 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)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/lib/privileges.c | 77 | ||||
-rw-r--r-- | source3/rpc_parse/parse_lsa.c | 8 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa.c | 66 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa_nt.c | 107 | ||||
-rw-r--r-- | source3/rpcclient/cmd_lsarpc.c | 7 |
5 files changed, 247 insertions, 18 deletions
diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c index f35d16f30f..09a868fc27 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 20ccc39ce0..a4a3917d2e 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 63e74ec891..e250677534 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 328f409cf3..d5bddef739 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 a07d38ca60..419ddb4734 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 } }; + |