root/source3/passdb/machine_sid.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. read_sid_from_file
  2. generate_random_sid
  3. pdb_generate_sam_sid
  4. get_global_sam_sid
  5. reset_global_sam_sid
  6. sid_check_is_domain
  7. sid_check_is_in_our_domain

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    Password and authentication handling
   4    Copyright (C) Jeremy Allison                 1996-2002
   5    Copyright (C) Andrew Tridgell                2002
   6    Copyright (C) Gerald (Jerry) Carter          2000
   7    Copyright (C) Stefan (metze) Metzmacher      2002
   8       
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13    
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18    
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 
  25 /* NOTE! the global_sam_sid is the SID of our local SAM. This is only
  26    equal to the domain SID when we are a DC, otherwise its our
  27    workstation SID */
  28 static DOM_SID *global_sam_sid=NULL;
  29 
  30 #undef DBGC_CLASS
  31 #define DBGC_CLASS DBGC_PASSDB
  32 
  33 /****************************************************************************
  34  Read a SID from a file. This is for compatibility with the old MACHINE.SID
  35  style of SID storage
  36 ****************************************************************************/
  37 
  38 static bool read_sid_from_file(const char *fname, DOM_SID *sid)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40         char **lines;
  41         int numlines;
  42         bool ret;
  43 
  44         lines = file_lines_load(fname, &numlines,0, NULL);
  45         
  46         if (!lines || numlines < 1) {
  47                 if (lines) TALLOC_FREE(lines);
  48                 return False;
  49         }
  50         
  51         ret = string_to_sid(sid, lines[0]);
  52         TALLOC_FREE(lines);
  53         return ret;
  54 }
  55 
  56 /*
  57   generate a random sid - used to build our own sid if we don't have one
  58 */
  59 static void generate_random_sid(DOM_SID *sid)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61         int i;
  62         uchar raw_sid_data[12];
  63 
  64         memset((char *)sid, '\0', sizeof(*sid));
  65         sid->sid_rev_num = 1;
  66         sid->id_auth[5] = 5;
  67         sid->num_auths = 0;
  68         sid->sub_auths[sid->num_auths++] = 21;
  69 
  70         generate_random_buffer(raw_sid_data, 12);
  71         for (i = 0; i < 3; i++)
  72                 sid->sub_auths[sid->num_auths++] = IVAL(raw_sid_data, i*4);
  73 }
  74 
  75 /****************************************************************************
  76  Generate the global machine sid.
  77 ****************************************************************************/
  78 
  79 static DOM_SID *pdb_generate_sam_sid(void)
     /* [<][>][^][v][top][bottom][index][help] */
  80 {
  81         DOM_SID domain_sid;
  82         char *fname = NULL;
  83         DOM_SID *sam_sid;
  84         
  85         if(!(sam_sid=SMB_MALLOC_P(DOM_SID)))
  86                 return NULL;
  87 
  88         if ( IS_DC ) {
  89                 if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
  90                         sid_copy(sam_sid, &domain_sid);
  91                         return sam_sid;
  92                 }
  93         }
  94 
  95         if (secrets_fetch_domain_sid(global_myname(), sam_sid)) {
  96 
  97                 /* We got our sid. If not a pdc/bdc, we're done. */
  98                 if ( !IS_DC )
  99                         return sam_sid;
 100 
 101                 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
 102 
 103                         /* No domain sid and we're a pdc/bdc. Store it */
 104 
 105                         if (!secrets_store_domain_sid(lp_workgroup(), sam_sid)) {
 106                                 DEBUG(0,("pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc.\n"));
 107                                 SAFE_FREE(sam_sid);
 108                                 return NULL;
 109                         }
 110                         return sam_sid;
 111                 }
 112 
 113                 if (!sid_equal(&domain_sid, sam_sid)) {
 114 
 115                         /* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */
 116 
 117                         DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n"));
 118                         if (!secrets_store_domain_sid(global_myname(), &domain_sid)) {
 119                                 DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC.\n"));
 120                                 SAFE_FREE(sam_sid);
 121                                 return NULL;
 122                         }
 123                         return sam_sid;
 124                 }
 125 
 126                 return sam_sid;
 127                 
 128         }
 129 
 130         /* check for an old MACHINE.SID file for backwards compatibility */
 131         if (asprintf(&fname, "%s/MACHINE.SID", lp_private_dir()) == -1) {
 132                 SAFE_FREE(sam_sid);
 133                 return NULL;
 134         }
 135 
 136         if (read_sid_from_file(fname, sam_sid)) {
 137                 /* remember it for future reference and unlink the old MACHINE.SID */
 138                 if (!secrets_store_domain_sid(global_myname(), sam_sid)) {
 139                         DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n"));
 140                         SAFE_FREE(fname);
 141                         SAFE_FREE(sam_sid);
 142                         return NULL;
 143                 }
 144                 unlink(fname);
 145                 if ( !IS_DC ) {
 146                         if (!secrets_store_domain_sid(lp_workgroup(), sam_sid)) {
 147                                 DEBUG(0,("pdb_generate_sam_sid: Failed to store domain SID from file.\n"));
 148                                 SAFE_FREE(fname);
 149                                 SAFE_FREE(sam_sid);
 150                                 return NULL;
 151                         }
 152                 }
 153 
 154                 /* Stored the old sid from MACHINE.SID successfully.*/
 155                 SAFE_FREE(fname);
 156                 return sam_sid;
 157         }
 158 
 159         SAFE_FREE(fname);
 160 
 161         /* we don't have the SID in secrets.tdb, we will need to
 162            generate one and save it */
 163         generate_random_sid(sam_sid);
 164 
 165         if (!secrets_store_domain_sid(global_myname(), sam_sid)) {
 166                 DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n"));
 167                 SAFE_FREE(sam_sid);
 168                 return NULL;
 169         }
 170         if ( IS_DC ) {
 171                 if (!secrets_store_domain_sid(lp_workgroup(), sam_sid)) {
 172                         DEBUG(0,("pdb_generate_sam_sid: Failed to store generated domain SID.\n"));
 173                         SAFE_FREE(sam_sid);
 174                         return NULL;
 175                 }
 176         }
 177 
 178         return sam_sid;
 179 }   
 180 
 181 /* return our global_sam_sid */
 182 DOM_SID *get_global_sam_sid(void)
     /* [<][>][^][v][top][bottom][index][help] */
 183 {
 184         struct db_context *db;
 185 
 186         if (global_sam_sid != NULL)
 187                 return global_sam_sid;
 188         
 189         /*
 190          * memory for global_sam_sid is allocated in
 191          * pdb_generate_sam_sid() as needed
 192          *
 193          * Note: this is garded by a transaction
 194          *       to prevent races on startup which
 195          *       can happen with some dbwrap backends
 196          */
 197 
 198         db = secrets_db_ctx();
 199         if (!db) {
 200                 smb_panic("could not open secrets db");
 201         }
 202 
 203         if (db->transaction_start(db) != 0) {
 204                 smb_panic("could not start transaction on secrets db");
 205         }
 206 
 207         if (!(global_sam_sid = pdb_generate_sam_sid())) {
 208                 db->transaction_cancel(db);
 209                 smb_panic("could not generate a machine SID");
 210         }
 211 
 212         if (db->transaction_commit(db) != 0) {
 213                 smb_panic("could not start commit secrets db");
 214         }
 215 
 216         return global_sam_sid;
 217 }
 218 
 219 /** 
 220  * Force get_global_sam_sid to requery the backends 
 221  */
 222 void reset_global_sam_sid(void) 
     /* [<][>][^][v][top][bottom][index][help] */
 223 {
 224         SAFE_FREE(global_sam_sid);
 225 }
 226 
 227 /*****************************************************************
 228  Check if the SID is our domain SID (S-1-5-21-x-y-z).
 229 *****************************************************************/  
 230 
 231 bool sid_check_is_domain(const DOM_SID *sid)
     /* [<][>][^][v][top][bottom][index][help] */
 232 {
 233         return sid_equal(sid, get_global_sam_sid());
 234 }
 235 
 236 /*****************************************************************
 237  Check if the SID is our domain SID (S-1-5-21-x-y-z).
 238 *****************************************************************/  
 239 
 240 bool sid_check_is_in_our_domain(const DOM_SID *sid)
     /* [<][>][^][v][top][bottom][index][help] */
 241 {
 242         DOM_SID dom_sid;
 243         uint32 rid;
 244 
 245         sid_copy(&dom_sid, sid);
 246         sid_split_rid(&dom_sid, &rid);
 247         return sid_check_is_domain(&dom_sid);
 248 }

/* [<][>][^][v][top][bottom][index][help] */