/* Authors: Sumit Bose Copyright (C) 2013 Red Hat Translate well-known SIDs to domains and names 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 the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "util/util.h" #include "util/strtonum.h" /* Well-Known SIDs are documented in section 2.4.2.4 "Well-Known SID * Structures" of the "[MS-DTYP]: Windows Data Types" document. */ #define DOM_SID_PREFIX "S-1-5-21-" #define DOM_SID_PREFIX_LEN (sizeof(DOM_SID_PREFIX) - 1) #define BUILTIN_SID_PREFIX "S-1-5-32-" #define BUILTIN_SID_PREFIX_LEN (sizeof(BUILTIN_SID_PREFIX) - 1) #define BUILTIN_DOM_NAME "BUILTIN" #define NT_SID_PREFIX "S-1-5-" #define NT_SID_PREFIX_LEN (sizeof(NT_SID_PREFIX) - 1) #define NT_DOM_NAME "NT AUTHORITY" #define SPECIAL_SID_PREFIX "S-1-" #define SPECIAL_SID_PREFIX_LEN (sizeof(SPECIAL_SID_PREFIX) - 1) #define NULL_DOM_NAME "NULL AUTHORITY" #define WORLD_DOM_NAME "WORLD AUTHORITY" #define LOCAL_DOM_NAME "LOCAL AUTHORITY" #define CREATOR_DOM_NAME "CREATOR AUTHORITY" #define NT_MAP_ENTRY(rid, name) {rid, NT_SID_PREFIX #rid, name} #define BUILTIN_MAP_ENTRY(rid, name) {rid, BUILTIN_SID_PREFIX #rid, name} #define SPECIAL_MAP_ENTRY(id_auth, rid, dom, name) \ {(48 + id_auth), (48 + rid), SPECIAL_SID_PREFIX #id_auth "-" #rid, dom, name} struct rid_sid_name { uint32_t rid; const char *sid; const char *name; }; struct special_map { const char id_auth; char rid; const char *sid; const char *dom; const char *name; }; struct rid_sid_name builtin_map[] = { BUILTIN_MAP_ENTRY(544, "Administrators"), BUILTIN_MAP_ENTRY(545, "Users"), BUILTIN_MAP_ENTRY(546, "Guests"), BUILTIN_MAP_ENTRY(547, "Power Users"), BUILTIN_MAP_ENTRY(548, "Account Operators"), BUILTIN_MAP_ENTRY(549, "Server Operators"), BUILTIN_MAP_ENTRY(550, "Print Operators"), BUILTIN_MAP_ENTRY(551, "Backup Operators"), BUILTIN_MAP_ENTRY(552, "Replicator"), BUILTIN_MAP_ENTRY(554, "Pre-Windows 2000 Compatible Access"), BUILTIN_MAP_ENTRY(555, "Remote Desktop Users"), BUILTIN_MAP_ENTRY(556, "Network Configuration Operators"), BUILTIN_MAP_ENTRY(557, "Incoming Forest Trust Builders"), BUILTIN_MAP_ENTRY(558, "Performance Monitor Users"), BUILTIN_MAP_ENTRY(559, "Performance Log Users"), BUILTIN_MAP_ENTRY(560, "Windows Authorization Access Group"), BUILTIN_MAP_ENTRY(561, "Terminal Server License Servers"), BUILTIN_MAP_ENTRY(562, "Distributed COM Users"), BUILTIN_MAP_ENTRY(568, "IIS_IUSRS"), BUILTIN_MAP_ENTRY(569, "Cryptographic Operators"), BUILTIN_MAP_ENTRY(573, "Event Log Readers"), BUILTIN_MAP_ENTRY(574, "Certificate Service DCOM Access"), BUILTIN_MAP_ENTRY(575, "RDS Remote Access Servers"), BUILTIN_MAP_ENTRY(576, "RDS Endpoint Servers"), BUILTIN_MAP_ENTRY(577, "RDS Management Servers"), BUILTIN_MAP_ENTRY(578, "Hyper-V Admins"), BUILTIN_MAP_ENTRY(579, "Access Control Assistance OPS"), BUILTIN_MAP_ENTRY(580, "Remote Management Users"), {UINT32_MAX, NULL, NULL} }; struct rid_sid_name nt_map[] = { NT_MAP_ENTRY(1, "DIALUP"), NT_MAP_ENTRY(2, "NETWORK"), NT_MAP_ENTRY(3, "BATCH"), NT_MAP_ENTRY(4, "INTERACTIVE"), NT_MAP_ENTRY(6, "SERVICE"), NT_MAP_ENTRY(7, "ANONYMOUS LOGON"), NT_MAP_ENTRY(8, "PROXY"), NT_MAP_ENTRY(9, "ENTERPRISE DOMAIN CONTROLLERS"), NT_MAP_ENTRY(10, "SELF"), NT_MAP_ENTRY(11, "Authenticated Users"), NT_MAP_ENTRY(12, "RESTRICTED"), NT_MAP_ENTRY(13, "TERMINAL SERVER USER"), NT_MAP_ENTRY(14, "REMOTE INTERACTIVE LOGON"), NT_MAP_ENTRY(15, "This Organization"), NT_MAP_ENTRY(17, "IUSR"), NT_MAP_ENTRY(18, "SYSTEM"), NT_MAP_ENTRY(19, "LOCAL SERVICE"), NT_MAP_ENTRY(20, "NETWORK SERVICE"), {UINT32_MAX, NULL, NULL} }; /* The code to handle the SIDs of the Null, World, Local and Creator * Authorities (id_auth=0,1,2,3 respectively) is optimized to handle only * single digit id_auth and rid. */ struct special_map sp_map[] = { SPECIAL_MAP_ENTRY(0, 0, NULL_DOM_NAME, "NULL SID"), SPECIAL_MAP_ENTRY(1, 0, WORLD_DOM_NAME, "Everyone"), SPECIAL_MAP_ENTRY(2, 0, LOCAL_DOM_NAME, "LOCAL"), SPECIAL_MAP_ENTRY(2, 1, LOCAL_DOM_NAME, "CONSOLE LOGON"), SPECIAL_MAP_ENTRY(3, 0, CREATOR_DOM_NAME, "CREATOR OWNER"), SPECIAL_MAP_ENTRY(3, 1, CREATOR_DOM_NAME, "CREATOR GROUP"), SPECIAL_MAP_ENTRY(3, 2, CREATOR_DOM_NAME, "CREATOR OWNER SERVER"), SPECIAL_MAP_ENTRY(3, 3, CREATOR_DOM_NAME, "CREATOR GROUP SERVER"), SPECIAL_MAP_ENTRY(3, 4, CREATOR_DOM_NAME, "OWNER RIGHTS"), SPECIAL_MAP_ENTRY(18,1, "ASSERTED IDENTITY", "AUTHENTICATION ASSERTION"), SPECIAL_MAP_ENTRY(18,2, "ASSERTED IDENTITY", "SERVICE ASSERTION"), {'\0', '\0', NULL, NULL, NULL} }; static errno_t handle_special_sids(const char *sid, const char **dom, const char **name) { size_t c; if (!isdigit(sid[SPECIAL_SID_PREFIX_LEN]) || sid[SPECIAL_SID_PREFIX_LEN + 1] != '-' || !isdigit(sid[SPECIAL_SID_PREFIX_LEN + 2]) || sid[SPECIAL_SID_PREFIX_LEN + 3] != '\0' ) { return EINVAL; } for (c = 0; sp_map[c].name != NULL; c++) { if (sid[SPECIAL_SID_PREFIX_LEN] == sp_map[c].id_auth && sid[SPECIAL_SID_PREFIX_LEN + 2] == sp_map[c].rid) { *name = sp_map[c].name; *dom = sp_map[c].dom; return EOK; } } return EINVAL; } static errno_t handle_special_names(const char *dom, const char *name, const char **sid) { size_t c; for (c = 0; sp_map[c].name != NULL; c++) { if (strcmp(name, sp_map[c].name) == 0 && strcmp(dom, sp_map[c].dom) == 0) { *sid = sp_map[c].sid; return EOK; } } return EINVAL; } static errno_t handle_rid_to_name_map(const char *sid, size_t prefix_len, struct rid_sid_name *map, const char* dom_name, const char **dom, const char **name) { uint32_t rid; char *endptr; size_t c; errno = 0; rid = (uint32_t) strtouint32(sid + prefix_len, &endptr, 10); if (errno != 0 || *endptr != '\0') { return EINVAL; } for (c = 0; map[c].name != NULL; c++) { if (rid == map[c].rid) { *name = map[c].name; *dom = dom_name; return EOK; } } return EINVAL; } static errno_t handle_name_to_sid_map(const char *name, struct rid_sid_name *map, const char **sid) { size_t c; for (c = 0; map[c].name != NULL; c++) { if (strcmp(name, map[c].name) == 0) { *sid = map[c].sid; return EOK; } } return EINVAL; } static errno_t handle_nt_sids(const char *sid, const char **dom, const char **name) { return handle_rid_to_name_map(sid, NT_SID_PREFIX_LEN, nt_map, NT_DOM_NAME, dom, name); } static errno_t handle_nt_names(const char *name, const char **sid) { return handle_name_to_sid_map(name, nt_map, sid); } static errno_t handle_builtin_sids(const char *sid, const char **dom, const char **name) { return handle_rid_to_name_map(sid, BUILTIN_SID_PREFIX_LEN, builtin_map, BUILTIN_DOM_NAME, dom, name); } static errno_t handle_builtin_names(const char *name, const char **sid) { return handle_name_to_sid_map(name, builtin_map, sid); } errno_t well_known_sid_to_name(const char *sid, const char **dom, const char **name) { int ret; if (sid == NULL || dom == NULL || name == NULL) { return EINVAL; } if (strncmp(sid, DOM_SID_PREFIX, DOM_SID_PREFIX_LEN) == 0) { ret = ENOENT; } else if (strncmp(sid, BUILTIN_SID_PREFIX, BUILTIN_SID_PREFIX_LEN) == 0) { ret = handle_builtin_sids(sid, dom, name); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "handle_builtin_sids failed.\n"); } } else if (strncmp(sid, NT_SID_PREFIX, NT_SID_PREFIX_LEN) == 0) { ret = handle_nt_sids(sid, dom, name); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "handle_nt_sids failed.\n"); } } else if (strncmp(sid, SPECIAL_SID_PREFIX, SPECIAL_SID_PREFIX_LEN) == 0) { ret = handle_special_sids(sid, dom, name); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "handle_special_sids failed.\n"); } } else { ret = EINVAL; } return ret; } errno_t name_to_well_known_sid(const char *dom, const char *name, const char **sid) { int ret; if (sid == NULL || dom == NULL || name == NULL) { return EINVAL; } if (strcmp(dom, NT_DOM_NAME) == 0) { ret = handle_nt_names(name, sid); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "handle_nt_name failed.\n"); } } else if (strcmp(dom, BUILTIN_DOM_NAME) == 0) { ret = handle_builtin_names(name, sid); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "handle_builtin_name failed.\n"); } } else if (strcmp(dom, NULL_DOM_NAME) == 0 || strcmp(dom, WORLD_DOM_NAME) == 0 || strcmp(dom, LOCAL_DOM_NAME) == 0 || strcmp(dom, CREATOR_DOM_NAME) == 0) { ret = handle_special_names(dom, name, sid); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "handle_special_name failed.\n"); } } else { ret = ENOENT; } return ret; }