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