r25040: Add "net sam rights"
authorVolker Lendecke <vlendec@samba.org>
Sat, 8 Sep 2007 20:30:51 +0000 (20:30 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:30:36 +0000 (12:30 -0500)
Not strictly in the SAM, but close enough. This command acts directly on
the local tdb, no running smbd required

This also changes the root-only check to a warning
(This used to be commit 0c5657b5eff60e3c52de8fbb4ce9346d0341854c)

source3/lib/privileges.c
source3/lib/util_sid.c
source3/utils/net_sam.c

index 34bca18b20269199916c39fb7915e92316d6a12d..b2e145e819cb0ff71f7f4fb72e1ccd9e2a9033d2 100644 (file)
@@ -31,6 +31,7 @@ typedef struct {
 } SID_LIST;
 
 typedef struct {
+       TALLOC_CTX *mem_ctx;
        SE_PRIV privilege;
        SID_LIST sids;
 } PRIV_SID_LIST;
@@ -183,7 +184,8 @@ static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *s
                return 0;
        }
 
-       if (!add_sid_to_array( NULL, &sid, &priv->sids.list, &priv->sids.count )) {
+       if (!add_sid_to_array( priv->mem_ctx, &sid, &priv->sids.list,
+                              &priv->sids.count )) {
                return 0;
        }
        
@@ -217,6 +219,35 @@ NTSTATUS privilege_enumerate_accounts(DOM_SID **sids, int *num_sids)
        return NT_STATUS_OK;
 }
 
+/*********************************************************************
+ Retrieve list of SIDs granted a particular privilege
+*********************************************************************/
+
+NTSTATUS privilege_enum_sids(const SE_PRIV *mask, TALLOC_CTX *mem_ctx,
+                            DOM_SID **sids, int *num_sids)
+{
+       TDB_CONTEXT *tdb = get_account_pol_tdb();
+       PRIV_SID_LIST priv;
+
+       if (!tdb) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       ZERO_STRUCT(priv);
+
+       se_priv_copy(&priv.privilege, mask);
+       priv.mem_ctx = mem_ctx;
+
+       tdb_traverse( tdb, priv_traverse_fn, &priv);
+
+       /* give the memory away; caller will free */
+
+       *sids      = priv.sids.list;
+       *num_sids  = priv.sids.count;
+
+       return NT_STATUS_OK;
+}
+
 /***************************************************************************
  Add privilege to sid
 ****************************************************************************/
index 7c6fc9b217cdd5ed9aaea20e25c12447f7f8ced3..85cb96bd6043fa8ffce6bcb03a3db1571712f6ca 100644 (file)
@@ -207,6 +207,13 @@ const char *sid_string_static(const DOM_SID *sid)
        return sid_str;
 }
 
+char *sid_string_tos(const DOM_SID *sid)
+{
+       fstring sid_str;
+       sid_to_string(sid_str, sid);
+       return talloc_strdup(talloc_tos(), sid_str);
+}
+
 /*****************************************************************
  Convert a string to a SID. Returns True on success, False on fail.
 *****************************************************************/  
index 056bd6a0ccfdf6867c57996e0a8fa1fcc7c7832c..8f6ccffc51e81e5d1fe82da77e9c23c708691d50 100644 (file)
@@ -504,6 +504,138 @@ static int net_sam_policy(int argc, const char **argv)
         return net_run_function2(argc, argv, "net sam policy", func);
 }
 
+extern PRIVS privs[];
+
+static int net_sam_rights_list(int argc, const char **argv)
+{
+       SE_PRIV mask;
+
+       if (argc > 1) {
+               d_fprintf(stderr, "usage: net sam rights list [name]\n");
+               return -1;
+       }
+
+       if (argc == 0) {
+               int i;
+               int num = count_all_privileges();
+
+               for (i=0; i<num; i++) {
+                       d_printf("%s\n", privs[i].name);
+               }
+               return 0;
+       }
+
+       if (se_priv_from_name(argv[0], &mask)) {
+               DOM_SID *sids;
+               int i, num_sids;
+               NTSTATUS status;
+
+               status = privilege_enum_sids(&mask, talloc_tos(),
+                                            &sids, &num_sids);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_fprintf(stderr, "Could not list rights: %s\n",
+                                 nt_errstr(status));
+                       return -1;
+               }
+
+               for (i=0; i<num_sids; i++) {
+                       const char *dom, *name;
+                       enum lsa_SidType type;
+
+                       if (lookup_sid(talloc_tos(), &sids[i], &dom, &name,
+                                      &type)) {
+                               d_printf("%s\\%s\n", dom, name);
+                       }
+                       else {
+                               d_printf("%s\n", sid_string_tos(&sids[i]));
+                       }
+               }
+               return 0;
+       }
+
+       return -1;
+}
+
+static int net_sam_rights_grant(int argc, const char **argv)
+{
+       DOM_SID sid;
+       enum lsa_SidType type;
+       const char *dom, *name;
+       SE_PRIV mask;
+
+       if (argc != 2) {
+               d_fprintf(stderr, "usage: net sam rights grant <name> "
+                         "<right>\n");
+               return -1;
+       }
+
+       if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &dom, &name, &sid, &type)) {
+               d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+               return -1;
+       }
+
+       if (!se_priv_from_name(argv[1], &mask)) {
+               d_fprintf(stderr, "%s unknown\n", argv[1]);
+               return -1;
+       }
+
+       if (!grant_privilege(&sid, &mask)) {
+               d_fprintf(stderr, "Could not grant privilege\n");
+               return -1;
+       }
+
+       d_printf("Granted %s to %s\\%s\n", argv[1], dom, name);
+       return 0;
+}
+
+static int net_sam_rights_revoke(int argc, const char **argv)
+{
+       DOM_SID sid;
+       enum lsa_SidType type;
+       const char *dom, *name;
+       SE_PRIV mask;
+
+       if (argc != 2) {
+               d_fprintf(stderr, "usage: net sam rights revoke <name> "
+                         "<right>\n");
+               return -1;
+       }
+
+       if (!lookup_name(talloc_tos(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &dom, &name, &sid, &type)) {
+               d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+               return -1;
+       }
+
+       if (!se_priv_from_name(argv[1], &mask)) {
+               d_fprintf(stderr, "%s unknown\n", argv[1]);
+               return -1;
+       }
+
+       if (!revoke_privilege(&sid, &mask)) {
+               d_fprintf(stderr, "Could not revoke privilege\n");
+               return -1;
+       }
+
+       d_printf("Revoked %s from %s\\%s\n", argv[1], dom, name);
+       return 0;
+}
+
+static int net_sam_rights(int argc, const char **argv)
+{
+       struct functable2 func[] = {
+               { "list", net_sam_rights_list,
+                 "List possible user rights" },
+               { "grant", net_sam_rights_grant,
+                 "Grant a right" },
+               { "revoke", net_sam_rights_revoke,
+                 "Revoke a right" },
+               { NULL }
+       };
+        return net_run_function2(argc, argv, "net sam rights", func);
+}
+
 /*
  * Map a unix group to a domain group
  */
@@ -1521,6 +1653,8 @@ int net_sam(int argc, const char **argv)
                  "Set details of a SAM account" },
                { "policy", net_sam_policy,
                  "Set account policies" },
+               { "rights", net_sam_rights,
+                 "Manipulate user privileges" },
 #ifdef HAVE_LDAP
                { "provision", net_sam_provision,
                  "Provision a clean User Database" },
@@ -1528,11 +1662,9 @@ int net_sam(int argc, const char **argv)
                { NULL, NULL, NULL }
        };
 
-       /* we shouldn't have silly checks like this */
        if (getuid() != 0) {
-               d_fprintf(stderr, "You must be root to edit the SAM "
-                         "directly.\n");
-               return -1;
+               d_fprintf(stderr, "You are not root, most things won't "
+                         "work\n");
        }
        
        return net_run_function2(argc, argv, "net sam", func);