Line data Source code
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 : #include "lib/util/util_file.h" 25 : #include "passdb/machine_sid.h" 26 : #include "secrets.h" 27 : #include "dbwrap/dbwrap.h" 28 : #include "../libcli/security/security.h" 29 : 30 : /* NOTE! the global_sam_sid is the SID of our local SAM. This is only 31 : equal to the domain SID when we are a DC, otherwise its our 32 : workstation SID */ 33 : static struct dom_sid *global_sam_sid=NULL; 34 : 35 : #undef DBGC_CLASS 36 : #define DBGC_CLASS DBGC_PASSDB 37 : 38 : /**************************************************************************** 39 : Read a SID from a file. This is for compatibility with the old MACHINE.SID 40 : style of SID storage 41 : ****************************************************************************/ 42 : 43 20 : static bool read_sid_from_file(const char *fname, struct dom_sid *sid) 44 : { 45 2 : char **lines; 46 2 : int numlines; 47 2 : bool ret; 48 : 49 20 : lines = file_lines_load(fname, &numlines,0, NULL); 50 : 51 20 : if (!lines || numlines < 1) { 52 20 : TALLOC_FREE(lines); 53 20 : return False; 54 : } 55 : 56 0 : ret = string_to_sid(sid, lines[0]); 57 0 : TALLOC_FREE(lines); 58 0 : return ret; 59 : } 60 : 61 : /* 62 : generate a random sid - used to build our own sid if we don't have one 63 : */ 64 20 : static void generate_random_sid(struct dom_sid *sid) 65 : { 66 2 : int i; 67 2 : uchar raw_sid_data[12]; 68 : 69 20 : *sid = (struct dom_sid) { 70 : .sid_rev_num = 1, 71 : .id_auth[5] = 5, 72 : }; 73 : 74 20 : sid->sub_auths[sid->num_auths++] = 21; 75 : 76 20 : generate_random_buffer(raw_sid_data, 12); 77 82 : for (i = 0; i < 3; i++) 78 60 : sid->sub_auths[sid->num_auths++] = IVAL(raw_sid_data, i*4); 79 20 : } 80 : 81 : /**************************************************************************** 82 : Generate the global machine sid. 83 : ****************************************************************************/ 84 : 85 1668 : static struct dom_sid *pdb_generate_sam_sid(void) 86 : { 87 17 : struct dom_sid domain_sid; 88 1668 : char *fname = NULL; 89 17 : struct dom_sid *sam_sid; 90 : 91 1668 : if(!(sam_sid=SMB_MALLOC_P(struct dom_sid))) 92 0 : return NULL; 93 : 94 1668 : if ( IS_DC ) { 95 816 : if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { 96 801 : sid_copy(sam_sid, &domain_sid); 97 801 : return sam_sid; 98 : } 99 : } 100 : 101 867 : if (secrets_fetch_domain_sid(lp_netbios_name(), sam_sid)) { 102 : 103 : /* We got our sid. If not a pdc/bdc, we're done. */ 104 847 : if ( !IS_DC ) 105 830 : return sam_sid; 106 : 107 15 : if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { 108 : 109 : /* No domain sid and we're a pdc/bdc. Store it */ 110 : 111 15 : if (!secrets_store_domain_sid(lp_workgroup(), sam_sid)) { 112 0 : DEBUG(0,("pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc.\n")); 113 0 : SAFE_FREE(sam_sid); 114 0 : return NULL; 115 : } 116 14 : return sam_sid; 117 : } 118 : 119 0 : if (!dom_sid_equal(&domain_sid, sam_sid)) { 120 : 121 : /* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */ 122 : 123 0 : DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n")); 124 0 : if (!secrets_store_domain_sid(lp_netbios_name(), &domain_sid)) { 125 0 : DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC.\n")); 126 0 : SAFE_FREE(sam_sid); 127 0 : return NULL; 128 : } 129 0 : return sam_sid; 130 : } 131 : 132 0 : return sam_sid; 133 : } 134 : 135 : /* check for an old MACHINE.SID file for backwards compatibility */ 136 20 : if (asprintf(&fname, "%s/MACHINE.SID", lp_private_dir()) == -1) { 137 0 : SAFE_FREE(sam_sid); 138 0 : return NULL; 139 : } 140 : 141 20 : if (read_sid_from_file(fname, sam_sid)) { 142 : /* remember it for future reference and unlink the old MACHINE.SID */ 143 0 : if (!secrets_store_domain_sid(lp_netbios_name(), sam_sid)) { 144 0 : DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n")); 145 0 : SAFE_FREE(fname); 146 0 : SAFE_FREE(sam_sid); 147 0 : return NULL; 148 : } 149 0 : unlink(fname); 150 0 : if ( !IS_DC ) { 151 0 : if (!secrets_store_domain_sid(lp_workgroup(), sam_sid)) { 152 0 : DEBUG(0,("pdb_generate_sam_sid: Failed to store domain SID from file.\n")); 153 0 : SAFE_FREE(fname); 154 0 : SAFE_FREE(sam_sid); 155 0 : return NULL; 156 : } 157 : } 158 : 159 : /* Stored the old sid from MACHINE.SID successfully.*/ 160 0 : SAFE_FREE(fname); 161 0 : return sam_sid; 162 : } 163 : 164 20 : SAFE_FREE(fname); 165 : 166 : /* we don't have the SID in secrets.tdb, we will need to 167 : generate one and save it */ 168 20 : generate_random_sid(sam_sid); 169 : 170 20 : if (!secrets_store_domain_sid(lp_netbios_name(), sam_sid)) { 171 0 : DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n")); 172 0 : SAFE_FREE(sam_sid); 173 0 : return NULL; 174 : } 175 20 : if ( IS_DC ) { 176 0 : if (!secrets_store_domain_sid(lp_workgroup(), sam_sid)) { 177 0 : DEBUG(0,("pdb_generate_sam_sid: Failed to store generated domain SID.\n")); 178 0 : SAFE_FREE(sam_sid); 179 0 : return NULL; 180 : } 181 : } 182 : 183 18 : return sam_sid; 184 : } 185 : 186 : /* return our global_sam_sid */ 187 653123 : struct dom_sid *get_global_sam_sid(void) 188 : { 189 1536 : struct db_context *db; 190 : 191 653123 : if (global_sam_sid != NULL) 192 649936 : return global_sam_sid; 193 : 194 : /* 195 : * memory for global_sam_sid is allocated in 196 : * pdb_generate_sam_sid() as needed 197 : * 198 : * Note: this is guarded by a transaction 199 : * to prevent races on startup which 200 : * can happen with some dbwrap backends 201 : */ 202 : 203 1668 : db = secrets_db_ctx(); 204 1668 : if (!db) { 205 0 : smb_panic("could not open secrets db"); 206 : } 207 : 208 1668 : if (dbwrap_transaction_start(db) != 0) { 209 0 : smb_panic("could not start transaction on secrets db"); 210 : } 211 : 212 1668 : if (!(global_sam_sid = pdb_generate_sam_sid())) { 213 0 : dbwrap_transaction_cancel(db); 214 0 : smb_panic("could not generate a machine SID"); 215 : } 216 : 217 1668 : if (dbwrap_transaction_commit(db) != 0) { 218 0 : smb_panic("could not start commit secrets db"); 219 : } 220 : 221 1668 : return global_sam_sid; 222 : } 223 : 224 : /** 225 : * Force get_global_sam_sid to requery the backends 226 : */ 227 487 : void reset_global_sam_sid(void) 228 : { 229 487 : SAFE_FREE(global_sam_sid); 230 487 : } 231 : 232 : /***************************************************************** 233 : Check if the SID is our sam SID (S-1-5-21-x-y-z). 234 : *****************************************************************/ 235 : 236 191585 : bool sid_check_is_our_sam(const struct dom_sid *sid) 237 : { 238 191585 : return dom_sid_equal(sid, get_global_sam_sid()); 239 : } 240 : 241 : /***************************************************************** 242 : Check if the SID is our domain SID (S-1-5-21-x-y-z). 243 : *****************************************************************/ 244 : 245 125864 : bool sid_check_is_in_our_sam(const struct dom_sid *sid) 246 : { 247 325 : struct dom_sid dom_sid; 248 : 249 125864 : sid_copy(&dom_sid, sid); 250 125864 : sid_split_rid(&dom_sid, NULL); 251 125864 : return sid_check_is_our_sam(&dom_sid); 252 : }