libcli/security Move source4/ privileges code into the common libcli/security
[abartlet/samba.git/.git] / libcli / security / privileges.c
index f4f3321198672fde501674ff63b80278bafab9d2..3919ce83805cd91c6832980d890d849206923fd3 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) Gerald (Jerry) Carter          2005
    Copyright (C) Michael Adam                  2007
    Copyright (C) Andrew Bartlett               2010
    Copyright (C) Gerald (Jerry) Carter          2005
    Copyright (C) Michael Adam                  2007
    Copyright (C) Andrew Bartlett               2010
+   Copyright (C) Andrew Tridgell                2004
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
  */
 
 #include "includes.h"
  */
 
 #include "includes.h"
+#include "libcli/security/privileges.h"
+#include "librpc/gen_ndr/security.h"
+
+/* The use of strcasecmp here is safe, all the comparison strings are ASCII */
+#undef strcasecmp
 
 const uint64_t se_priv_all         = SE_ALL_PRIVS;
 static const uint64_t se_priv_end  = SE_END;
 
 const uint64_t se_priv_all         = SE_ALL_PRIVS;
 static const uint64_t se_priv_end  = SE_END;
@@ -446,3 +452,286 @@ bool privilege_set_to_se_priv( uint64_t *privilege_mask, struct lsa_PrivilegeSet
 
        return true;
 }
 
        return true;
 }
+
+static const struct {
+       enum sec_privilege privilege;
+       uint64_t privilege_mask;
+       const char *name;
+       const char *display_name;
+} privilege_names[] = {
+       {SEC_PRIV_SECURITY,
+        SE_SECURITY,
+        "SeSecurityPrivilege",
+       "System security"},
+
+       {SEC_PRIV_BACKUP,
+        SE_BACKUP,
+        "SeBackupPrivilege",
+        "Backup files and directories"},
+
+       {SEC_PRIV_RESTORE,
+        SE_RESTORE,
+        "SeRestorePrivilege",
+       "Restore files and directories"},
+
+       {SEC_PRIV_SYSTEMTIME,
+        SE_SYSTEMTIME,
+        "SeSystemtimePrivilege",
+       "Set the system clock"},
+
+       {SEC_PRIV_SHUTDOWN,
+        SE_SHUTDOWN,
+        "SeShutdownPrivilege",
+       "Shutdown the system"},
+
+       {SEC_PRIV_REMOTE_SHUTDOWN,
+        SE_REMOTE_SHUTDOWN,
+        "SeRemoteShutdownPrivilege",
+       "Shutdown the system remotely"},
+
+       {SEC_PRIV_TAKE_OWNERSHIP,
+        SE_TAKE_OWNERSHIP,
+        "SeTakeOwnershipPrivilege",
+       "Take ownership of files and directories"},
+
+       {SEC_PRIV_DEBUG,
+        SE_DEBUG,
+        "SeDebugPrivilege",
+       "Debug processes"},
+
+       {SEC_PRIV_SYSTEM_ENVIRONMENT,
+        SE_SYSTEM_ENVIRONMENT,
+        "SeSystemEnvironmentPrivilege",
+       "Modify system environment"},
+
+       {SEC_PRIV_SYSTEM_PROFILE,
+        SE_SYSTEM_PROFILE,
+        "SeSystemProfilePrivilege",
+       "Profile the system"},
+
+       {SEC_PRIV_PROFILE_SINGLE_PROCESS,
+        SE_PROFILE_SINGLE_PROCESS,
+        "SeProfileSingleProcessPrivilege",
+       "Profile one process"},
+
+       {SEC_PRIV_INCREASE_BASE_PRIORITY,
+        SE_INCREASE_BASE_PRIORITY,
+        "SeIncreaseBasePriorityPrivilege",
+        "Increase base priority"},
+
+       {SEC_PRIV_LOAD_DRIVER,
+        SE_LOAD_DRIVER,
+        "SeLoadDriverPrivilege",
+       "Load drivers"},
+
+       {SEC_PRIV_CREATE_PAGEFILE,
+        SE_CREATE_PAGEFILE,
+        "SeCreatePagefilePrivilege",
+       "Create page files"},
+
+       {SEC_PRIV_INCREASE_QUOTA,
+        SE_INCREASE_QUOTA,
+        "SeIncreaseQuotaPrivilege",
+       "Increase quota"},
+
+       {SEC_PRIV_CHANGE_NOTIFY,
+        SE_CHANGE_NOTIFY,
+        "SeChangeNotifyPrivilege",
+       "Register for change notify"},
+
+       {SEC_PRIV_UNDOCK,
+        SE_UNDOCK,
+        "SeUndockPrivilege",
+       "Undock devices"},
+
+       {SEC_PRIV_MANAGE_VOLUME,
+        SE_MANAGE_VOLUME,
+        "SeManageVolumePrivilege",
+       "Manage system volumes"},
+
+       {SEC_PRIV_IMPERSONATE,
+        SE_IMPERSONATE,
+        "SeImpersonatePrivilege",
+       "Impersonate users"},
+
+       {SEC_PRIV_CREATE_GLOBAL,
+        SE_CREATE_GLOBAL,
+        "SeCreateGlobalPrivilege",
+       "Create global"},
+
+       {SEC_PRIV_ENABLE_DELEGATION,
+        SE_ENABLE_DELEGATION,
+        "SeEnableDelegationPrivilege",
+       "Enable Delegation"},
+
+       {SEC_PRIV_INTERACTIVE_LOGON,
+        SE_INTERACTIVE_LOGON,
+        "SeInteractiveLogonRight",
+       "Interactive logon"},
+
+       {SEC_PRIV_NETWORK_LOGON,
+        SE_NETWORK_LOGON,
+        "SeNetworkLogonRight",
+       "Network logon"},
+
+       {SEC_PRIV_REMOTE_INTERACTIVE_LOGON,
+        SE_REMOTE_INTERACTIVE_LOGON,
+        "SeRemoteInteractiveLogonRight",
+       "Remote Interactive logon"},
+
+       {SEC_PRIV_MACHINE_ACCOUNT,
+        SE_MACHINE_ACCOUNT,
+        "SeMachineAccountPrivilege",
+        "Add workstations to domain"},
+
+       /* These last 3 are Samba only */
+       {SEC_PRIV_PRINT_OPERATOR,
+        SE_PRINT_OPERATOR,
+        "SePrintOperatorPrivilege",
+        "Manage printers"},
+
+       {SEC_PRIV_ADD_USERS,
+        SE_ADD_USERS,
+        "SeAddUsersPrivilege",
+        "Add users and groups to the domain"},
+
+       {SEC_PRIV_DISK_OPERATOR,
+        SE_DISK_OPERATOR,
+        "SeDiskOperatorPrivilege",
+        "Manage disk shares"},
+};
+
+
+/*
+  map a privilege id to the wire string constant
+*/
+const char *sec_privilege_name(enum sec_privilege privilege)
+{
+       int i;
+       for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
+               if (privilege_names[i].privilege == privilege) {
+                       return privilege_names[i].name;
+               }
+       }
+       return NULL;
+}
+
+/*
+  map a privilege id to a privilege display name. Return NULL if not found
+
+  TODO: this should use language mappings
+*/
+const char *sec_privilege_display_name(enum sec_privilege privilege, uint16_t *language)
+{
+       int i;
+       if (privilege < 1 || privilege > 64) {
+               return NULL;
+       }
+       for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
+               if (privilege_names[i].privilege == privilege) {
+                       return privilege_names[i].display_name;
+               }
+       }
+       return NULL;
+}
+
+/*
+  map a privilege name to a privilege id. Return -1 if not found
+*/
+enum sec_privilege sec_privilege_id(const char *name)
+{
+       int i;
+       for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
+               if (strcasecmp(privilege_names[i].name, name) == 0) {
+                       return privilege_names[i].privilege;
+               }
+       }
+       return -1;
+}
+
+/*
+  map a privilege name to a privilege id. Return -1 if not found
+*/
+enum sec_privilege sec_privilege_from_mask(uint64_t mask)
+{
+       int i;
+       for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
+               if (privilege_names[i].privilege_mask == mask) {
+                       return privilege_names[i].privilege;
+               }
+       }
+       return -1;
+}
+
+/*
+  map a privilege name to a privilege id. Return -1 if not found
+*/
+enum sec_privilege sec_privilege_from_index(int idx)
+{
+       if (idx >= 0 && idx<ARRAY_SIZE(privilege_names)) {
+               return privilege_names[idx].privilege;
+       }
+       return -1;
+}
+
+
+/*
+  return a privilege mask given a privilege id
+*/
+static uint64_t sec_privilege_mask(enum sec_privilege privilege)
+{
+       int i;
+       for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
+               if (privilege_names[i].privilege == privilege) {
+                       return privilege_names[i].privilege_mask;
+               }
+       }
+
+       return 0;
+}
+
+
+/*
+  return true if a security_token has a particular privilege bit set
+*/
+bool security_token_has_privilege(const struct security_token *token, enum sec_privilege privilege)
+{
+       uint64_t mask;
+
+       mask = sec_privilege_mask(privilege);
+       if (mask == 0) {
+               return false;
+       }
+
+       if (token->privilege_mask & mask) {
+               return true;
+       }
+       return false;
+}
+
+/*
+  set a bit in the privilege mask
+*/
+void security_token_set_privilege(struct security_token *token, enum sec_privilege privilege)
+{
+       /* Relies on the fact that an invalid privilage will return 0, so won't change this */
+       token->privilege_mask |= sec_privilege_mask(privilege);
+}
+
+void security_token_debug_privileges(int dbg_lev, const struct security_token *token)
+{
+       DEBUGADD(dbg_lev, (" Privileges (0x%16llX):\n",
+                           (unsigned long long) token->privilege_mask));
+
+       if (token->privilege_mask) {
+               int i = 0;
+               uint64_t mask;
+               for (mask = 1; mask != 0; mask = mask << 1) {
+                       if (token->privilege_mask & mask) {
+                               enum sec_privilege privilege = sec_privilege_from_mask(mask);
+                               DEBUGADD(dbg_lev, ("  Privilege[%3lu]: %s\n", (unsigned long)i++,
+                                       sec_privilege_name(privilege)));
+                       }
+               }
+       }
+}