Changes from APPLIANCE_HEAD:
[ira/wip.git] / source3 / smbd / groupname.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Groupname handling
5    Copyright (C) Jeremy Allison 1998.
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifdef USING_GROUPNAME_MAP
23
24 #include "includes.h"
25 extern int DEBUGLEVEL;
26 extern DOM_SID global_sam_sid;
27
28
29 /**************************************************************************
30  Groupname map functionality. The code loads a groupname map file and
31  (currently) loads it into a linked list. This is slow and memory
32  hungry, but can be changed into a more efficient storage format
33  if the demands on it become excessive.
34 ***************************************************************************/
35
36 typedef struct groupname_map {
37    ubi_slNode next;
38
39    char *windows_name;
40    DOM_SID windows_sid;
41    char *unix_name;
42    gid_t unix_gid;
43 } groupname_map_entry;
44
45 static ubi_slList groupname_map_list;
46
47 /**************************************************************************
48  Delete all the entries in the groupname map list.
49 ***************************************************************************/
50
51 static void delete_groupname_map_list(void)
52 {
53   groupname_map_entry *gmep;
54
55   while((gmep = (groupname_map_entry *)ubi_slRemHead( &groupname_map_list )) != NULL) {
56     if(gmep->windows_name)
57       free(gmep->windows_name);
58     if(gmep->unix_name)
59       free(gmep->unix_name);
60     free((char *)gmep);
61   }
62 }
63
64 /**************************************************************************
65  Load a groupname map file. Sets last accessed timestamp.
66 ***************************************************************************/
67
68 void load_groupname_map(void)
69 {
70   static time_t groupmap_file_last_modified = (time_t)0;
71   static BOOL initialized = False;
72   char *groupname_map_file = lp_groupname_map();
73   SMB_STRUCT_STAT st;
74   char **lines;
75   int i;
76   groupname_map_entry *new_ep;
77
78   if(!initialized) {
79     ubi_slInitList( &groupname_map_list );
80     initialized = True;
81   }
82
83   if (!*groupname_map_file)
84     return;
85
86   if(sys_stat(groupname_map_file, &st) != 0) {
87     DEBUG(0, ("load_groupname_map: Unable to stat file %s. Error was %s\n",
88                groupname_map_file, strerror(errno) ));
89     return;
90   }
91
92   /*
93    * Check if file has changed.
94    */
95   if( st.st_mtime <= groupmap_file_last_modified)
96     return;
97
98   groupmap_file_last_modified = st.st_mtime;
99
100   /*
101    * Load the file.
102    */
103
104   lines = file_lines_load(groupname_map_file,NULL,False);
105   if (!lines) {
106     DEBUG(0,("load_groupname_map: can't open groupname map %s. Error was %s\n",
107           groupname_map_file, strerror(errno)));
108     return;
109   }
110   file_lines_slashcont(lines);
111
112   /*
113    * Throw away any previous list.
114    */
115   delete_groupname_map_list();
116
117   DEBUG(4,("load_groupname_map: Scanning groupname map %s\n",groupname_map_file));
118
119   for (i=0; lines[i]; i++) {
120     pstring unixname;
121     pstring windows_name;
122     gid_t gid;
123     DOM_SID tmp_sid;
124     char *s = lines[i];
125
126     DEBUG(10,("load_groupname_map: Read line |%s|\n", s));
127
128     if (!*s || strchr("#;",*s))
129       continue;
130
131     if(!next_token(&s,unixname, "\t\n\r=", sizeof(unixname)))
132       continue;
133
134     if(!next_token(&s,windows_name, "\t\n\r=", sizeof(windows_name)))
135       continue;
136
137     trim_string(unixname, " ", " ");
138     trim_string(windows_name, " ", " ");
139
140     if (!*windows_name)
141       continue;
142
143     if(!*unixname)
144       continue;
145
146     DEBUG(5,("load_groupname_map: unixname = %s, windowsname = %s.\n",
147              unixname, windows_name));
148
149     /*
150      * Attempt to get the unix gid_t for this name.
151      */
152
153         if ((gid = nametogid(unixname)) == (gid_t)-1)
154       DEBUG(0,("load_groupname_map: nametogid for group %s failed.\
155 Error was %s.\n", unixname, strerror(errno) ));
156       continue;
157     }
158
159     /*
160      * Now map to an NT SID.
161      */
162
163     if(!lookup_wellknown_sid_from_name(windows_name, &tmp_sid)) {
164       /*
165        * It's not a well known name, convert the UNIX gid_t
166        * to a rid within this domain SID.
167        */
168       tmp_sid = global_sam_sid;
169       tmp_sid.sub_auths[tmp_sid.num_auths++] = 
170                     pdb_gid_to_group_rid(gid);
171     }
172
173     /*
174      * Create the list entry and add it onto the list.
175      */
176
177     if((new_ep = (groupname_map_entry *)malloc( sizeof(groupname_map_entry) ))== NULL) {
178       DEBUG(0,("load_groupname_map: malloc fail for groupname_map_entry.\n"));
179       fclose(fp);
180       return;
181     } 
182
183     new_ep->unix_gid = gid;
184     new_ep->windows_sid = tmp_sid;
185     new_ep->windows_name = strdup( windows_name );
186     new_ep->unix_name = strdup( unixname );
187
188     if(new_ep->windows_name == NULL || new_ep->unix_name == NULL) {
189       DEBUG(0,("load_groupname_map: malloc fail for names in groupname_map_entry.\n"));
190       fclose(fp);
191       if(new_ep->windows_name != NULL)
192         free(new_ep->windows_name);
193       if(new_ep->unix_name != NULL)
194         free(new_ep->unix_name);
195       free((char *)new_ep);
196       file_lines_free(lines);
197       return;
198     }
199     memset((char *)&new_ep->next, '\0', sizeof(new_ep->next) );
200
201     ubi_slAddHead( &groupname_map_list, (ubi_slNode *)new_ep);
202   }
203
204   DEBUG(10,("load_groupname_map: Added %ld entries to groupname map.\n",
205             ubi_slCount(&groupname_map_list)));
206            
207   file_lines_free(lines);
208 }
209
210 /***********************************************************
211  Lookup a SID entry by gid_t.
212 ************************************************************/
213
214 void map_gid_to_sid( gid_t gid, DOM_SID *psid)
215 {
216   groupname_map_entry *gmep;
217
218   /*
219    * Initialize and load if not already loaded.
220    */
221   load_groupname_map();
222
223   for( gmep = (groupname_map_entry *)ubi_slFirst( &groupname_map_list);
224        gmep; gmep = (groupname_map_entry *)ubi_slNext( gmep )) {
225
226     if( gmep->unix_gid == gid) {
227       *psid = gmep->windows_sid;
228       DEBUG(7,("map_gid_to_sid: Mapping unix group %s to windows group %s.\n",
229                gmep->unix_name, gmep->windows_name ));
230       return;
231     }
232   }
233
234   /*
235    * If there's no map, convert the UNIX gid_t
236    * to a rid within this domain SID.
237    */
238   *psid = global_sam_sid;
239   psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid);
240
241   return;
242 }
243 #else /* USING_GROUPNAME_MAP */
244  void load_groupname_map(void) {;}
245 #endif /* USING_GROUPNAME_MAP */