2000-11-14 02:03:34 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-11-14 02:03:34 +03:00
Password and authentication handling
2002-03-12 05:26:33 +03:00
Copyright ( C ) Jeremy Allison 1996 - 2002
Copyright ( C ) Andrew Tridgell 2002
2000-11-14 02:03:34 +03:00
Copyright ( C ) Gerald ( Jerry ) Carter 2000
2002-07-15 14:35:28 +04:00
Copyright ( C ) Stefan ( metze ) Metzmacher 2002
2010-02-05 17:43:26 +03:00
2000-11-14 02:03:34 +03:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2000-11-14 02:03:34 +03:00
( at your option ) any later version .
2010-02-05 17:43:26 +03:00
2000-11-14 02:03:34 +03:00
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 .
2010-02-05 17:43:26 +03:00
2000-11-14 02:03:34 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-11-14 02:03:34 +03:00
*/
# include "includes.h"
2011-10-18 00:00:45 +04:00
# include "passdb/machine_sid.h"
2010-08-05 04:25:37 +04:00
# include "secrets.h"
2011-07-07 19:42:08 +04:00
# include "dbwrap/dbwrap.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2000-11-14 02:03:34 +03:00
2002-07-15 14:35:28 +04:00
/* NOTE! the global_sam_sid is the SID of our local SAM. This is only
equal to the domain SID when we are a DC , otherwise its our
workstation SID */
2010-05-21 05:25:01 +04:00
static struct dom_sid * global_sam_sid = NULL ;
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_PASSDB
2002-03-10 04:44:21 +03:00
2000-11-14 02:03:34 +03:00
/****************************************************************************
2002-03-10 04:44:21 +03:00
Read a SID from a file . This is for compatibility with the old MACHINE . SID
style of SID storage
2000-11-14 02:03:34 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
2010-05-21 05:25:01 +04:00
static bool read_sid_from_file ( const char * fname , struct dom_sid * sid )
2000-11-14 02:03:34 +03:00
{
2002-03-10 04:44:21 +03:00
char * * lines ;
int numlines ;
2007-10-19 04:40:25 +04:00
bool ret ;
2000-11-14 02:03:34 +03:00
2008-10-12 19:34:43 +04:00
lines = file_lines_load ( fname , & numlines , 0 , NULL ) ;
2010-02-05 17:43:26 +03:00
2002-03-10 04:44:21 +03:00
if ( ! lines | | numlines < 1 ) {
2010-02-05 17:53:19 +03:00
TALLOC_FREE ( lines ) ;
2002-03-10 04:44:21 +03:00
return False ;
}
2010-02-05 17:43:26 +03:00
2002-03-10 04:44:21 +03:00
ret = string_to_sid ( sid , lines [ 0 ] ) ;
2008-10-12 19:34:43 +04:00
TALLOC_FREE ( lines ) ;
2002-03-10 04:44:21 +03:00
return ret ;
}
2000-11-14 02:03:34 +03:00
2002-03-10 04:44:21 +03:00
/*
generate a random sid - used to build our own sid if we don ' t have one
*/
2010-05-21 05:25:01 +04:00
static void generate_random_sid ( struct dom_sid * sid )
2002-03-10 04:44:21 +03:00
{
int i ;
uchar raw_sid_data [ 12 ] ;
2010-02-05 17:55:14 +03:00
ZERO_STRUCTP ( sid ) ;
2002-03-10 04:44:21 +03:00
sid - > sid_rev_num = 1 ;
sid - > id_auth [ 5 ] = 5 ;
sid - > num_auths = 0 ;
sid - > sub_auths [ sid - > num_auths + + ] = 21 ;
2004-07-14 08:36:01 +04:00
generate_random_buffer ( raw_sid_data , 12 ) ;
2002-03-10 04:44:21 +03:00
for ( i = 0 ; i < 3 ; i + + )
sid - > sub_auths [ sid - > num_auths + + ] = IVAL ( raw_sid_data , i * 4 ) ;
2000-11-14 02:03:34 +03:00
}
/****************************************************************************
2002-03-10 04:44:21 +03:00
Generate the global machine sid .
2000-11-14 02:03:34 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-12 05:26:33 +03:00
2010-05-21 05:25:01 +04:00
static struct dom_sid * pdb_generate_sam_sid ( void )
2000-11-14 02:03:34 +03:00
{
2010-05-21 05:25:01 +04:00
struct dom_sid domain_sid ;
2002-03-10 04:44:21 +03:00
char * fname = NULL ;
2010-05-21 05:25:01 +04:00
struct dom_sid * sam_sid ;
2010-02-05 17:43:26 +03:00
2010-05-21 05:25:01 +04:00
if ( ! ( sam_sid = SMB_MALLOC_P ( struct dom_sid ) ) )
2004-02-26 01:01:02 +03:00
return NULL ;
2000-11-14 02:03:34 +03:00
2005-06-14 22:31:06 +04:00
if ( IS_DC ) {
2003-04-21 18:09:03 +04:00
if ( secrets_fetch_domain_sid ( lp_workgroup ( ) , & domain_sid ) ) {
2004-02-26 01:01:02 +03:00
sid_copy ( sam_sid , & domain_sid ) ;
return sam_sid ;
2003-04-21 18:09:03 +04:00
}
}
2011-06-09 09:31:03 +04:00
if ( secrets_fetch_domain_sid ( lp_netbios_name ( ) , sam_sid ) ) {
2002-03-12 05:26:33 +03:00
/* We got our sid. If not a pdc/bdc, we're done. */
2005-06-14 22:31:06 +04:00
if ( ! IS_DC )
2004-02-26 01:01:02 +03:00
return sam_sid ;
2002-03-12 05:26:33 +03:00
2002-09-25 19:19:00 +04:00
if ( ! secrets_fetch_domain_sid ( lp_workgroup ( ) , & domain_sid ) ) {
2002-03-12 05:26:33 +03:00
/* No domain sid and we're a pdc/bdc. Store it */
2004-02-26 01:01:02 +03:00
if ( ! secrets_store_domain_sid ( lp_workgroup ( ) , sam_sid ) ) {
2002-03-12 05:26:33 +03:00
DEBUG ( 0 , ( " pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc. \n " ) ) ;
2004-02-26 01:01:02 +03:00
SAFE_FREE ( sam_sid ) ;
return NULL ;
2002-03-12 05:26:33 +03:00
}
2004-02-26 01:01:02 +03:00
return sam_sid ;
2002-03-12 05:26:33 +03:00
}
2010-08-26 17:48:50 +04:00
if ( ! dom_sid_equal ( & domain_sid , sam_sid ) ) {
2002-03-12 05:26:33 +03:00
2003-04-21 18:09:03 +04:00
/* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */
2002-03-12 05:26:33 +03:00
DEBUG ( 0 , ( " pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc. \n " ) ) ;
2011-06-09 09:31:03 +04:00
if ( ! secrets_store_domain_sid ( lp_netbios_name ( ) , & domain_sid ) ) {
2003-04-21 18:09:03 +04:00
DEBUG ( 0 , ( " pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC. \n " ) ) ;
2004-02-26 01:01:02 +03:00
SAFE_FREE ( sam_sid ) ;
return NULL ;
2002-03-12 05:26:33 +03:00
}
2004-02-26 01:01:02 +03:00
return sam_sid ;
2002-03-12 05:26:33 +03:00
}
2004-02-26 01:01:02 +03:00
return sam_sid ;
2002-03-10 04:44:21 +03:00
}
2000-11-14 02:03:34 +03:00
2002-03-10 04:44:21 +03:00
/* check for an old MACHINE.SID file for backwards compatibility */
2008-02-25 17:24:49 +03:00
if ( asprintf ( & fname , " %s/MACHINE.SID " , lp_private_dir ( ) ) = = - 1 ) {
SAFE_FREE ( sam_sid ) ;
return NULL ;
}
2002-03-12 05:26:33 +03:00
2004-02-26 01:01:02 +03:00
if ( read_sid_from_file ( fname , sam_sid ) ) {
2002-03-10 04:44:21 +03:00
/* remember it for future reference and unlink the old MACHINE.SID */
2011-06-09 09:31:03 +04:00
if ( ! secrets_store_domain_sid ( lp_netbios_name ( ) , sam_sid ) ) {
2002-03-12 05:26:33 +03:00
DEBUG ( 0 , ( " pdb_generate_sam_sid: Failed to store SID from file. \n " ) ) ;
SAFE_FREE ( fname ) ;
2004-02-26 01:01:02 +03:00
SAFE_FREE ( sam_sid ) ;
return NULL ;
2002-03-12 05:26:33 +03:00
}
unlink ( fname ) ;
2005-06-14 22:31:06 +04:00
if ( ! IS_DC ) {
2004-02-26 01:01:02 +03:00
if ( ! secrets_store_domain_sid ( lp_workgroup ( ) , sam_sid ) ) {
2002-03-12 05:26:33 +03:00
DEBUG ( 0 , ( " pdb_generate_sam_sid: Failed to store domain SID from file. \n " ) ) ;
SAFE_FREE ( fname ) ;
2004-02-26 01:01:02 +03:00
SAFE_FREE ( sam_sid ) ;
return NULL ;
2002-03-12 05:26:33 +03:00
}
2000-11-14 02:03:34 +03:00
}
2002-04-02 11:45:19 +04:00
2002-07-15 14:35:28 +04:00
/* Stored the old sid from MACHINE.SID successfully.*/
2002-04-02 11:45:19 +04:00
SAFE_FREE ( fname ) ;
2004-02-26 01:01:02 +03:00
return sam_sid ;
2000-11-14 02:03:34 +03:00
}
2002-03-12 05:26:33 +03:00
SAFE_FREE ( fname ) ;
2002-03-10 04:44:21 +03:00
/* we don't have the SID in secrets.tdb, we will need to
generate one and save it */
2004-02-26 01:01:02 +03:00
generate_random_sid ( sam_sid ) ;
2000-11-14 02:03:34 +03:00
2011-06-09 09:31:03 +04:00
if ( ! secrets_store_domain_sid ( lp_netbios_name ( ) , sam_sid ) ) {
2002-03-12 05:26:33 +03:00
DEBUG ( 0 , ( " pdb_generate_sam_sid: Failed to store generated machine SID. \n " ) ) ;
2004-02-26 01:01:02 +03:00
SAFE_FREE ( sam_sid ) ;
return NULL ;
2002-03-12 05:26:33 +03:00
}
2005-06-14 22:31:06 +04:00
if ( IS_DC ) {
2004-02-26 01:01:02 +03:00
if ( ! secrets_store_domain_sid ( lp_workgroup ( ) , sam_sid ) ) {
2002-03-12 05:26:33 +03:00
DEBUG ( 0 , ( " pdb_generate_sam_sid: Failed to store generated domain SID. \n " ) ) ;
2004-02-26 01:01:02 +03:00
SAFE_FREE ( sam_sid ) ;
return NULL ;
2002-03-12 05:26:33 +03:00
}
}
2004-02-26 01:01:02 +03:00
return sam_sid ;
2000-11-14 02:03:34 +03:00
}
2002-07-15 14:35:28 +04:00
/* return our global_sam_sid */
2010-05-21 05:25:01 +04:00
struct dom_sid * get_global_sam_sid ( void )
2002-07-15 14:35:28 +04:00
{
2008-04-01 13:02:01 +04:00
struct db_context * db ;
2002-07-15 14:35:28 +04:00
if ( global_sam_sid ! = NULL )
return global_sam_sid ;
2010-02-05 17:43:26 +03:00
2008-04-01 13:02:01 +04:00
/*
* memory for global_sam_sid is allocated in
* pdb_generate_sam_sid ( ) as needed
*
* Note : this is garded by a transaction
* to prevent races on startup which
* can happen with some dbwrap backends
*/
db = secrets_db_ctx ( ) ;
if ( ! db ) {
smb_panic ( " could not open secrets db " ) ;
}
2011-08-25 02:36:05 +04:00
if ( dbwrap_transaction_start ( db ) ! = 0 ) {
2008-04-01 13:02:01 +04:00
smb_panic ( " could not start transaction on secrets db " ) ;
}
2002-07-15 14:35:28 +04:00
2004-02-26 01:01:02 +03:00
if ( ! ( global_sam_sid = pdb_generate_sam_sid ( ) ) ) {
2011-08-25 02:36:05 +04:00
dbwrap_transaction_cancel ( db ) ;
2007-06-16 01:58:49 +04:00
smb_panic ( " could not generate a machine SID " ) ;
2003-06-18 12:42:04 +04:00
}
2004-02-26 01:01:02 +03:00
2011-08-25 02:36:05 +04:00
if ( dbwrap_transaction_commit ( db ) ! = 0 ) {
2008-04-01 13:02:01 +04:00
smb_panic ( " could not start commit secrets db " ) ;
}
2002-07-15 14:35:28 +04:00
return global_sam_sid ;
}
2004-02-08 14:05:34 +03:00
/**
* Force get_global_sam_sid to requery the backends
*/
2004-02-09 17:43:18 +03:00
void reset_global_sam_sid ( void )
2004-02-08 14:05:34 +03:00
{
SAFE_FREE ( global_sam_sid ) ;
}
2005-12-03 21:34:13 +03:00
/*****************************************************************
2012-07-12 17:55:21 +04:00
Check if the SID is our sam SID ( S - 1 - 5 - 21 - x - y - z ) .
2005-12-03 21:34:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-07-12 17:55:21 +04:00
bool sid_check_is_our_sam ( const struct dom_sid * sid )
2005-12-03 21:34:13 +03:00
{
2010-08-26 17:48:50 +04:00
return dom_sid_equal ( sid , get_global_sam_sid ( ) ) ;
2005-12-03 21:34:13 +03:00
}
/*****************************************************************
Check if the SID is our domain SID ( S - 1 - 5 - 21 - x - y - z ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-07-12 18:00:59 +04:00
bool sid_check_is_in_our_sam ( const struct dom_sid * sid )
2005-12-03 21:34:13 +03:00
{
2010-05-21 05:25:01 +04:00
struct dom_sid dom_sid ;
2005-12-03 21:34:13 +03:00
sid_copy ( & dom_sid , sid ) ;
2011-03-10 18:19:17 +03:00
sid_split_rid ( & dom_sid , NULL ) ;
2012-07-12 17:55:21 +04:00
return sid_check_is_our_sam ( & dom_sid ) ;
2005-12-03 21:34:13 +03:00
}