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