mirror of
https://github.com/samba-team/samba.git
synced 2025-01-15 23:24:37 +03:00
0f14ae46f3
Andrew Bartlett (This used to be commit 099151cdabd40e724b36482c0ffc169d231146d2)
392 lines
12 KiB
C
392 lines
12 KiB
C
/*
|
|
Unix SMB/CIFS implementation.
|
|
Samba utility functions
|
|
Copyright (C) Andrew Tridgell 1992-1998
|
|
Copyright (C) Luke Kenneth Caseson Leighton 1998-1999
|
|
Copyright (C) Jeremy Allison 1999
|
|
Copyright (C) Stefan (metze) Metzmacher 2002
|
|
Copyright (C) Simo Sorce 2002
|
|
|
|
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 2 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, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
|
|
/*
|
|
* Some useful sids
|
|
*/
|
|
|
|
struct dom_sid *global_sid_World_Domain; /* Everyone domain */
|
|
struct dom_sid *global_sid_World; /* Everyone */
|
|
struct dom_sid *global_sid_Creator_Owner_Domain; /* Creator Owner domain */
|
|
struct dom_sid *global_sid_NT_Authority; /* NT Authority */
|
|
struct dom_sid *global_sid_System; /* System */
|
|
struct dom_sid *global_sid_NULL; /* NULL sid */
|
|
struct dom_sid *global_sid_Authenticated_Users; /* All authenticated rids */
|
|
struct dom_sid *global_sid_Network; /* Network rids */
|
|
|
|
struct dom_sid *global_sid_Creator_Owner; /* Creator Owner */
|
|
struct dom_sid *global_sid_Creator_Group; /* Creator Group */
|
|
struct dom_sid *global_sid_Anonymous; /* Anonymous login */
|
|
|
|
struct dom_sid *global_sid_Builtin; /* Local well-known domain */
|
|
struct dom_sid *global_sid_Builtin_Administrators; /* Builtin administrators */
|
|
struct dom_sid *global_sid_Builtin_Users; /* Builtin users */
|
|
struct dom_sid *global_sid_Builtin_Guests; /* Builtin guest users */
|
|
struct dom_sid *global_sid_Builtin_Power_Users; /* Builtin power users */
|
|
struct dom_sid *global_sid_Builtin_Account_Operators; /* Builtin account operators */
|
|
struct dom_sid *global_sid_Builtin_Server_Operators; /* Builtin server operators */
|
|
struct dom_sid *global_sid_Builtin_Print_Operators; /* Builtin print operators */
|
|
struct dom_sid *global_sid_Builtin_Backup_Operators; /* Builtin backup operators */
|
|
struct dom_sid *global_sid_Builtin_Replicator; /* Builtin replicator */
|
|
|
|
#define SECURITY_NULL_SID_AUTHORITY 0
|
|
#define SECURITY_WORLD_SID_AUTHORITY 1
|
|
#define SECURITY_LOCAL_SID_AUTHORITY 2
|
|
#define SECURITY_CREATOR_SID_AUTHORITY 3
|
|
#define SECURITY_NT_AUTHORITY 5
|
|
|
|
/****************************************************************************
|
|
Lookup string names for SID types.
|
|
****************************************************************************/
|
|
|
|
static const struct {
|
|
enum SID_NAME_USE sid_type;
|
|
const char *string;
|
|
} sid_name_type[] = {
|
|
{SID_NAME_USER, "User"},
|
|
{SID_NAME_DOM_GRP, "Domain Group"},
|
|
{SID_NAME_DOMAIN, "Domain"},
|
|
{SID_NAME_ALIAS, "Local Group"},
|
|
{SID_NAME_WKN_GRP, "Well-known Group"},
|
|
{SID_NAME_DELETED, "Deleted Account"},
|
|
{SID_NAME_INVALID, "Invalid Account"},
|
|
{SID_NAME_UNKNOWN, "UNKNOWN"},
|
|
|
|
{SID_NAME_USE_NONE, NULL}
|
|
};
|
|
|
|
const char *sid_type_lookup(uint32 sid_type)
|
|
{
|
|
int i = 0;
|
|
|
|
/* Look through list */
|
|
while(sid_name_type[i].sid_type != 0) {
|
|
if (sid_name_type[i].sid_type == sid_type)
|
|
return sid_name_type[i].string;
|
|
i++;
|
|
}
|
|
|
|
/* Default return */
|
|
return "SID *TYPE* is INVALID";
|
|
}
|
|
|
|
/****************************************************************************
|
|
Creates some useful well known sids
|
|
****************************************************************************/
|
|
|
|
void generate_wellknown_sids(void)
|
|
{
|
|
static BOOL initialised = False;
|
|
static TALLOC_CTX *mem_ctx;
|
|
|
|
if (initialised)
|
|
return;
|
|
|
|
mem_ctx = talloc_init("Well known groups, global static context");
|
|
if (!mem_ctx)
|
|
return;
|
|
|
|
/* SECURITY_NULL_SID_AUTHORITY */
|
|
global_sid_NULL = dom_sid_parse_talloc(mem_ctx, "S-1-0-0");
|
|
|
|
/* SECURITY_WORLD_SID_AUTHORITY */
|
|
global_sid_World_Domain = dom_sid_parse_talloc(mem_ctx, "S-1-1");
|
|
global_sid_World = dom_sid_parse_talloc(mem_ctx, "S-1-1-0");
|
|
|
|
/* SECURITY_CREATOR_SID_AUTHORITY */
|
|
global_sid_Creator_Owner_Domain = dom_sid_parse_talloc(mem_ctx, "S-1-3");
|
|
global_sid_Creator_Owner = dom_sid_parse_talloc(mem_ctx, "S-1-3-0");
|
|
global_sid_Creator_Group = dom_sid_parse_talloc(mem_ctx, "S-1-3-1");
|
|
|
|
/* SECURITY_NT_AUTHORITY */
|
|
global_sid_NT_Authority = dom_sid_parse_talloc(mem_ctx, "S-1-5");
|
|
global_sid_Network = dom_sid_parse_talloc(mem_ctx, "S-1-5-2");
|
|
global_sid_Anonymous = dom_sid_parse_talloc(mem_ctx, "S-1-5-7");
|
|
global_sid_Authenticated_Users = dom_sid_parse_talloc(mem_ctx, "S-1-5-11");
|
|
global_sid_System = dom_sid_parse_talloc(mem_ctx, "S-1-5-18");
|
|
|
|
/* SECURITY_BUILTIN_DOMAIN_RID */
|
|
global_sid_Builtin = dom_sid_parse_talloc(mem_ctx, "S-1-5-32");
|
|
global_sid_Builtin_Administrators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-544");
|
|
global_sid_Builtin_Users = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-545");
|
|
global_sid_Builtin_Guests = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-546");
|
|
global_sid_Builtin_Power_Users = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-547");
|
|
global_sid_Builtin_Account_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-548");
|
|
global_sid_Builtin_Server_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-549");
|
|
global_sid_Builtin_Print_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-550");
|
|
global_sid_Builtin_Backup_Operators = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-551");
|
|
global_sid_Builtin_Replicator = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-552");
|
|
|
|
initialised = True;
|
|
}
|
|
|
|
/**************************************************************************
|
|
Splits a name of format \DOMAIN\name or name into its two components.
|
|
Sets the DOMAIN name to lp_netbios_name() if it has not been specified.
|
|
***************************************************************************/
|
|
|
|
void split_domain_name(const char *fullname, char *domain, char *name)
|
|
{
|
|
pstring full_name;
|
|
const char *sep;
|
|
char *p;
|
|
|
|
sep = lp_winbind_separator();
|
|
|
|
*domain = *name = '\0';
|
|
|
|
if (fullname[0] == sep[0] || fullname[0] == '\\')
|
|
fullname++;
|
|
|
|
pstrcpy(full_name, fullname);
|
|
p = strchr_m(full_name+1, '\\');
|
|
if (!p) p = strchr_m(full_name+1, sep[0]);
|
|
|
|
if (p != NULL) {
|
|
*p = 0;
|
|
fstrcpy(domain, full_name);
|
|
fstrcpy(name, p+1);
|
|
} else {
|
|
fstrcpy(domain, lp_netbios_name());
|
|
fstrcpy(name, full_name);
|
|
}
|
|
|
|
DEBUG(10,("split_domain_name:name '%s' split into domain :'%s' and user :'%s'\n",
|
|
fullname, domain, name));
|
|
}
|
|
|
|
/*****************************************************************
|
|
Convert a SID to an ascii string.
|
|
*****************************************************************/
|
|
|
|
char *sid_to_string(fstring sidstr_out, const struct dom_sid *sid)
|
|
{
|
|
char *tmp_string;
|
|
TALLOC_CTX *mem_ctx;
|
|
if (!(mem_ctx = talloc_init("sid_to_string temp context"))) {
|
|
return NULL;
|
|
}
|
|
|
|
tmp_string = dom_sid_string(mem_ctx, sid);
|
|
if (!tmp_string)
|
|
return NULL;
|
|
|
|
fstrcpy(sidstr_out, tmp_string);
|
|
return sidstr_out;
|
|
}
|
|
|
|
/*****************************************************************
|
|
Removes the last rid from the end of a sid
|
|
*****************************************************************/
|
|
|
|
BOOL sid_split_rid(struct dom_sid *sid, uint32 *rid)
|
|
{
|
|
if (sid->num_auths > 0) {
|
|
sid->num_auths--;
|
|
if (rid)
|
|
*rid = sid->sub_auths[sid->num_auths];
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
/*****************************************************************
|
|
Return the last rid from the end of a sid
|
|
*****************************************************************/
|
|
|
|
BOOL sid_peek_rid(const struct dom_sid *sid, uint32 *rid)
|
|
{
|
|
if (!sid || !rid)
|
|
return False;
|
|
|
|
if (sid->num_auths > 0) {
|
|
*rid = sid->sub_auths[sid->num_auths - 1];
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
/*****************************************************************
|
|
Return the last rid from the end of a sid
|
|
and check the sid against the exp_dom_sid
|
|
*****************************************************************/
|
|
|
|
BOOL sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid *sid, uint32 *rid)
|
|
{
|
|
if (!exp_dom_sid || !sid || !rid)
|
|
return False;
|
|
|
|
|
|
if (sid_compare_domain(exp_dom_sid, sid)!=0){
|
|
*rid=(-1);
|
|
return False;
|
|
}
|
|
|
|
return sid_peek_rid(sid, rid);
|
|
}
|
|
|
|
/*****************************************************************
|
|
Compare the auth portion of two sids.
|
|
*****************************************************************/
|
|
|
|
static int sid_compare_auth(const struct dom_sid *sid1, const struct dom_sid *sid2)
|
|
{
|
|
int i;
|
|
|
|
if (sid1 == sid2)
|
|
return 0;
|
|
if (!sid1)
|
|
return -1;
|
|
if (!sid2)
|
|
return 1;
|
|
|
|
if (sid1->sid_rev_num != sid2->sid_rev_num)
|
|
return sid1->sid_rev_num - sid2->sid_rev_num;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
if (sid1->id_auth[i] != sid2->id_auth[i])
|
|
return sid1->id_auth[i] - sid2->id_auth[i];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************
|
|
Compare two sids.
|
|
*****************************************************************/
|
|
|
|
int sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2)
|
|
{
|
|
int i;
|
|
|
|
if (sid1 == sid2)
|
|
return 0;
|
|
if (!sid1)
|
|
return -1;
|
|
if (!sid2)
|
|
return 1;
|
|
|
|
/* Compare most likely different rids, first: i.e start at end */
|
|
if (sid1->num_auths != sid2->num_auths)
|
|
return sid1->num_auths - sid2->num_auths;
|
|
|
|
for (i = sid1->num_auths-1; i >= 0; --i)
|
|
if (sid1->sub_auths[i] != sid2->sub_auths[i])
|
|
return sid1->sub_auths[i] - sid2->sub_auths[i];
|
|
|
|
return sid_compare_auth(sid1, sid2);
|
|
}
|
|
|
|
/*****************************************************************
|
|
See if 2 SIDs are in the same domain
|
|
this just compares the leading sub-auths
|
|
*****************************************************************/
|
|
|
|
int sid_compare_domain(const struct dom_sid *sid1, const struct dom_sid *sid2)
|
|
{
|
|
int n, i;
|
|
|
|
n = MIN(sid1->num_auths, sid2->num_auths);
|
|
|
|
for (i = n-1; i >= 0; --i)
|
|
if (sid1->sub_auths[i] != sid2->sub_auths[i])
|
|
return sid1->sub_auths[i] - sid2->sub_auths[i];
|
|
|
|
return sid_compare_auth(sid1, sid2);
|
|
}
|
|
|
|
/*****************************************************************
|
|
Compare two sids.
|
|
*****************************************************************/
|
|
|
|
BOOL sid_equal(const struct dom_sid *sid1, const struct dom_sid *sid2)
|
|
{
|
|
return sid_compare(sid1, sid2) == 0;
|
|
}
|
|
/*****************************************************************
|
|
Write a sid out into on-the-wire format.
|
|
*****************************************************************/
|
|
|
|
BOOL sid_linearize(char *outbuf, size_t len, const struct dom_sid *sid)
|
|
{
|
|
size_t i;
|
|
|
|
if (len < sid_size(sid))
|
|
return False;
|
|
|
|
SCVAL(outbuf,0,sid->sid_rev_num);
|
|
SCVAL(outbuf,1,sid->num_auths);
|
|
memcpy(&outbuf[2], sid->id_auth, 6);
|
|
for(i = 0; i < sid->num_auths; i++)
|
|
SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]);
|
|
|
|
return True;
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
Calculates size of a sid.
|
|
*****************************************************************/
|
|
|
|
size_t sid_size(const struct dom_sid *sid)
|
|
{
|
|
if (sid == NULL)
|
|
return 0;
|
|
|
|
return sid->num_auths * sizeof(uint32) + 8;
|
|
}
|
|
|
|
/*****************************************************************
|
|
Return the binary string representation of a DOM_SID.
|
|
Caller must free.
|
|
*****************************************************************/
|
|
|
|
char *sid_binstring(const struct dom_sid *sid)
|
|
{
|
|
char *buf, *s;
|
|
int len = sid_size(sid);
|
|
buf = malloc(len);
|
|
if (!buf)
|
|
return NULL;
|
|
sid_linearize(buf, len, sid);
|
|
s = binary_string(buf, len);
|
|
free(buf);
|
|
return s;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Check if ACE has OBJECT type.
|
|
********************************************************************/
|
|
BOOL sec_ace_object(uint8 type)
|
|
{
|
|
if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
|
|
type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
|
|
type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
|
|
type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|