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