From c727866172b5abb1cab0913eb78f3f1d58fcb9aa Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 15 Jan 2005 02:20:30 +0000 Subject: 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) --- source3/lib/privileges.c | 77 ++++++++++++++++++++++++----- source3/rpc_parse/parse_lsa.c | 8 +-- source3/rpc_server/srv_lsa.c | 66 ++++++++++++++++++++++++- source3/rpc_server/srv_lsa_nt.c | 107 ++++++++++++++++++++++++++++++++++++++++ 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 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; ipol = *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; icount; 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; icount; 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 } }; + -- cgit