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