~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/passdb/machine_sid.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
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)
 
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)
 
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)
 
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) 
 
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)
 
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)
 
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
}