Removed version number from file header.
[samba.git] / source3 / passdb / machine_sid.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Jeremy Allison                 1996-1998
5    Copyright (C) Luke Kenneth Casson Leighton   1996-1998
6    Copyright (C) Gerald (Jerry) Carter          2000
7       
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 /****************************************************************************
26  Read the machine SID from a file.
27 ****************************************************************************/
28
29 static BOOL read_sid_from_file(int fd, char *sid_file)
30 {
31   fstring fline;
32
33   memset(fline, '\0', sizeof(fline));
34
35   if(read(fd, fline, sizeof(fline) -1 ) < 0) {
36     DEBUG(0,("unable to read file %s. Error was %s\n",
37            sid_file, strerror(errno) ));
38     return False;
39   }
40
41   /*
42    * Convert to the machine SID.
43    */
44
45   fline[sizeof(fline)-1] = '\0';
46   if(!string_to_sid( &global_sam_sid, fline)) {
47     DEBUG(0,("unable to generate machine SID.\n"));
48     return False;
49   }
50
51   return True;
52 }
53
54 /****************************************************************************
55  Generate the global machine sid. Look for the MACHINE.SID file first, if
56  not found then look in smb.conf and use it to create the MACHINE.SID file.
57  Note this function will be replaced soon. JRA.
58 ****************************************************************************/
59
60 BOOL pdb_generate_sam_sid(void)
61 {
62         int fd;
63         pstring sid_file;
64         fstring sid_string;
65         SMB_STRUCT_STAT st;
66         BOOL overwrite_bad_sid = False;
67
68         generate_wellknown_sids();
69
70         pstrcpy(sid_file, lp_private_dir());
71
72         if (!directory_exist(sid_file, NULL)) {
73                 if (mkdir(sid_file, 0700) != 0) {
74                         DEBUG(0,("can't create private directory %s : %s\n",
75                                  sid_file, strerror(errno)));
76                         return False;
77                 }
78         }
79
80         pstrcat(sid_file, "/MACHINE.SID");
81     
82         if((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
83                 DEBUG(0,("unable to open or create file %s. Error was %s\n",
84                          sid_file, strerror(errno) ));
85                 return False;
86         } 
87   
88         /*
89          * Check if the file contains data.
90          */
91         
92         if(sys_fstat( fd, &st) < 0) {
93                 DEBUG(0,("unable to stat file %s. Error was %s\n",
94                          sid_file, strerror(errno) ));
95                 close(fd);
96                 return False;
97         } 
98   
99         if(st.st_size > 0) {
100                 /*
101                  * We have a valid SID - read it.
102                  */
103                 if(!read_sid_from_file( fd, sid_file)) {
104                         DEBUG(0,("unable to read file %s. Error was %s\n",
105                                  sid_file, strerror(errno) ));
106                         close(fd);
107                         return False;
108                 }
109
110                 /*
111                  * JRA. Reversed the sense of this test now that I have
112                  * actually done this test *personally*. One more reason
113                  * to never trust third party information you have not
114                  * independently verified.... sigh. JRA.
115                  */
116
117                 if(global_sam_sid.num_auths > 0 && global_sam_sid.sub_auths[0] == 0x21) {
118                         /*
119                          * Fix and re-write...
120                          */
121                         overwrite_bad_sid = True;
122                         global_sam_sid.sub_auths[0] = 21;
123                         DEBUG(5,("pdb_generate_sam_sid: Old (incorrect) sid id_auth of hex 21 \
124 detected - re-writing to be decimal 21 instead.\n" ));
125                         sid_to_string(sid_string, &global_sam_sid);
126                         if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) {
127                                 DEBUG(0,("unable to seek file file %s. Error was %s\n",
128                                          sid_file, strerror(errno) ));
129                                 close(fd);
130                                 return False;
131                         }
132                 } else {
133                         close(fd);
134                         return True;
135                 }
136         } else {
137                 /*
138                  * The file contains no data - we need to generate our
139                  * own sid.
140                  * Generate the new sid data & turn it into a string.
141                  */
142                 int i;
143                 uchar raw_sid_data[12];
144                 DOM_SID mysid;
145
146                 memset((char *)&mysid, '\0', sizeof(DOM_SID));
147                 mysid.sid_rev_num = 1;
148                 mysid.id_auth[5] = 5;
149                 mysid.num_auths = 0;
150                 mysid.sub_auths[mysid.num_auths++] = 21;
151
152                 generate_random_buffer( raw_sid_data, 12, True);
153                 for( i = 0; i < 3; i++)
154                         mysid.sub_auths[mysid.num_auths++] = IVAL(raw_sid_data, i*4);
155
156                 sid_to_string(sid_string, &mysid);
157         } 
158         
159         fstrcat(sid_string, "\n");
160         
161         /*
162          * Ensure our new SID is valid.
163          */
164         
165         if(!string_to_sid( &global_sam_sid, sid_string)) {
166                 DEBUG(0,("unable to generate machine SID.\n"));
167                 return False;
168         } 
169   
170         /*
171          * Do an exclusive blocking lock on the file.
172          */
173         
174         if(!do_file_lock( fd, 60, F_WRLCK)) {
175                 DEBUG(0,("unable to lock file %s. Error was %s\n",
176                          sid_file, strerror(errno) ));
177                 close(fd);
178                 return False;
179         } 
180  
181         if(!overwrite_bad_sid) {
182                 /*
183                  * At this point we have a blocking lock on the SID
184                  * file - check if in the meantime someone else wrote
185                  * SID data into the file. If so - they were here first,
186                  * use their data.
187                  */
188         
189                 if(sys_fstat( fd, &st) < 0) {
190                         DEBUG(0,("unable to stat file %s. Error was %s\n",
191                                  sid_file, strerror(errno) ));
192                         close(fd);
193                         return False;
194                 } 
195   
196                 if(st.st_size > 0) {
197                         /*
198                          * Unlock as soon as possible to reduce
199                          * contention on the exclusive lock.
200                          */ 
201                         do_file_lock( fd, 60, F_UNLCK);
202                 
203                         /*
204                          * We have a valid SID - read it.
205                          */
206                 
207                         if(!read_sid_from_file( fd, sid_file)) {
208                                 DEBUG(0,("unable to read file %s. Error was %s\n",
209                                          sid_file, strerror(errno) ));
210                                 close(fd);
211                                 return False;
212                         }
213                         close(fd);
214                         return True;
215                 } 
216         }
217         
218         /*
219          * The file is still empty and we have an exlusive lock on it,
220          * or we're fixing an earlier mistake.
221          * Write out out SID data into the file.
222          */
223
224         /*
225          * Use chmod here as some (strange) UNIX's don't
226          * have fchmod. JRA.
227          */     
228
229         if(chmod(sid_file, 0644) < 0) {
230                 DEBUG(0,("unable to set correct permissions on file %s. \
231 Error was %s\n", sid_file, strerror(errno) ));
232                 do_file_lock( fd, 60, F_UNLCK);
233                 close(fd);
234                 return False;
235         } 
236         
237         if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
238                 DEBUG(0,("unable to write file %s. Error was %s\n",
239                          sid_file, strerror(errno) ));
240                 do_file_lock( fd, 60, F_UNLCK);
241                 close(fd);
242                 return False;
243         } 
244         
245         /*
246          * Unlock & exit.
247          */
248         
249         do_file_lock( fd, 60, F_UNLCK);
250         close(fd);
251         return True;
252 }   
253
254