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 92 : static bool read_sid_from_file(const char *fname, struct dom_sid *sid)
43 : {
44 : char **lines;
45 : int numlines;
46 : bool ret;
47 :
48 92 : lines = file_lines_load(fname, &numlines,0, NULL);
49 :
50 92 : if (!lines || numlines < 1) {
51 92 : TALLOC_FREE(lines);
52 92 : 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 92 : static void generate_random_sid(struct dom_sid *sid)
64 : {
65 : int i;
66 : uchar raw_sid_data[12];
67 :
68 92 : *sid = (struct dom_sid) {
69 : .sid_rev_num = 1,
70 : .id_auth[5] = 5,
71 : };
72 :
73 92 : sid->sub_auths[sid->num_auths++] = 21;
74 :
75 92 : generate_random_buffer(raw_sid_data, 12);
76 368 : for (i = 0; i < 3; i++)
77 276 : sid->sub_auths[sid->num_auths++] = IVAL(raw_sid_data, i*4);
78 92 : }
79 :
80 : /****************************************************************************
81 : Generate the global machine sid.
82 : ****************************************************************************/
83 :
84 1016 : static struct dom_sid *pdb_generate_sam_sid(void)
85 : {
86 : struct dom_sid domain_sid;
87 1016 : char *fname = NULL;
88 : struct dom_sid *sam_sid;
89 :
90 1016 : if(!(sam_sid=SMB_MALLOC_P(struct dom_sid)))
91 0 : return NULL;
92 :
93 1016 : if ( IS_DC ) {
94 185 : if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
95 183 : sid_copy(sam_sid, &domain_sid);
96 183 : return sam_sid;
97 : }
98 : }
99 :
100 833 : 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 741 : if ( !IS_DC )
104 739 : return sam_sid;
105 :
106 2 : if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
107 :
108 : /* No domain sid and we're a pdc/bdc. Store it */
109 :
110 2 : 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 2 : 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 92 : if (asprintf(&fname, "%s/MACHINE.SID", lp_private_dir()) == -1) {
136 0 : SAFE_FREE(sam_sid);
137 0 : return NULL;
138 : }
139 :
140 92 : 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 92 : 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 92 : generate_random_sid(sam_sid);
168 :
169 92 : 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 92 : 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 92 : return sam_sid;
183 : }
184 :
185 : /* return our global_sam_sid */
186 68564 : struct dom_sid *get_global_sam_sid(void)
187 : {
188 : struct db_context *db;
189 :
190 68564 : if (global_sam_sid != NULL)
191 67548 : 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 1016 : db = secrets_db_ctx();
203 1016 : if (!db) {
204 0 : smb_panic("could not open secrets db");
205 : }
206 :
207 1016 : if (dbwrap_transaction_start(db) != 0) {
208 0 : smb_panic("could not start transaction on secrets db");
209 : }
210 :
211 1016 : 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 1016 : if (dbwrap_transaction_commit(db) != 0) {
217 0 : smb_panic("could not start commit secrets db");
218 : }
219 :
220 1016 : return global_sam_sid;
221 : }
222 :
223 : /**
224 : * Force get_global_sam_sid to requery the backends
225 : */
226 167 : void reset_global_sam_sid(void)
227 : {
228 167 : SAFE_FREE(global_sam_sid);
229 167 : }
230 :
231 : /*****************************************************************
232 : Check if the SID is our sam SID (S-1-5-21-x-y-z).
233 : *****************************************************************/
234 :
235 40620 : bool sid_check_is_our_sam(const struct dom_sid *sid)
236 : {
237 40620 : 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 14246 : bool sid_check_is_in_our_sam(const struct dom_sid *sid)
245 : {
246 : struct dom_sid dom_sid;
247 :
248 14246 : sid_copy(&dom_sid, sid);
249 14246 : sid_split_rid(&dom_sid, NULL);
250 14246 : return sid_check_is_our_sam(&dom_sid);
251 : }
|