r4742: add server support for lsa_add/remove_account_rights() and fix some parsing...
authorGerald Carter <jerry@samba.org>
Sat, 15 Jan 2005 02:20:30 +0000 (02:20 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:53:53 +0000 (10:53 -0500)
source/lib/privileges.c
source/rpc_parse/parse_lsa.c
source/rpc_server/srv_lsa.c
source/rpc_server/srv_lsa_nt.c
source/rpcclient/cmd_lsarpc.c

index f35d16f30f4777cd3a83531ae24137479d3c33b0..09a868fc277079ff95778b99c3bc7c4b893afffb 100644 (file)
@@ -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 );
+}
+
index 20ccc39ce0737d361bd07715c105de6fea34210c..a4a3917d2e16995dc2a37947688d887342791236 100644 (file)
@@ -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))
index 63e74ec89110544119655b68f4965334095d36f2..e250677534231d7430959e114ce879abb0904cfe 100644 (file)
@@ -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                                               */
index 328f409cf36c16cc6871acb02491ff18059f994f..d5bddef739a95a02c0ce3227ce374f5d509b5c8a 100644 (file)
@@ -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;
+}
+
+
index a07d38ca60d1724d1021d326a0093f47531fdd95..419ddb473498513cf291d11f947e6a7933f9f32d 100644 (file)
@@ -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 }
 };
+