Add const.
[samba.git] / source3 / 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
25 /**************************************************************************
26  Groupname map functionality. The code loads a groupname map file and
27  (currently) loads it into a linked list. This is slow and memory
28  hungry, but can be changed into a more efficient storage format
29  if the demands on it become excessive.
30 ***************************************************************************/
31
32 typedef struct groupname_map {
33    ubi_slNode next;
34
35    char *windows_name;
36    DOM_SID windows_sid;
37    char *unix_name;
38    gid_t unix_gid;
39 } groupname_map_entry;
40
41 static ubi_slList groupname_map_list;
42
43 /**************************************************************************
44  Delete all the entries in the groupname map list.
45 ***************************************************************************/
46
47 static void delete_groupname_map_list(void)
48 {
49   groupname_map_entry *gmep;
50
51   while((gmep = (groupname_map_entry *)ubi_slRemHead( &groupname_map_list )) != NULL) {
52     SAFE_FREE(gmep->windows_name);
53     SAFE_FREE(gmep->unix_name);
54     SAFE_FREE(gmep);
55   }
56 }
57
58 /**************************************************************************
59  Load a groupname map file. Sets last accessed timestamp.
60 ***************************************************************************/
61
62 void load_groupname_map(void)
63 {
64   static time_t groupmap_file_last_modified = (time_t)0;
65   static BOOL initialized = False;
66   char *groupname_map_file = lp_groupname_map();
67   SMB_STRUCT_STAT st;
68   char **lines;
69   int i;
70   groupname_map_entry *new_ep;
71
72   if(!initialized) {
73     ubi_slInitList( &groupname_map_list );
74     initialized = True;
75   }
76
77   if (!*groupname_map_file)
78     return;
79
80   if(sys_stat(groupname_map_file, &st) != 0) {
81     DEBUG(0, ("load_groupname_map: Unable to stat file %s. Error was %s\n",
82                groupname_map_file, strerror(errno) ));
83     return;
84   }
85
86   /*
87    * Check if file has changed.
88    */
89   if( st.st_mtime <= groupmap_file_last_modified)
90     return;
91
92   groupmap_file_last_modified = st.st_mtime;
93
94   /*
95    * Load the file.
96    */
97
98   lines = file_lines_load(groupname_map_file,NULL,False);
99   if (!lines) {
100     DEBUG(0,("load_groupname_map: can't open groupname map %s. Error was %s\n",
101           groupname_map_file, strerror(errno)));
102     return;
103   }
104   file_lines_slashcont(lines);
105
106   /*
107    * Throw away any previous list.
108    */
109   delete_groupname_map_list();
110
111   DEBUG(4,("load_groupname_map: Scanning groupname map %s\n",groupname_map_file));
112
113   for (i=0; lines[i]; i++) {
114     pstring unixname;
115     pstring windows_name;
116     gid_t gid;
117     DOM_SID tmp_sid;
118     char *s = lines[i];
119
120     DEBUG(10,("load_groupname_map: Read line |%s|\n", s));
121
122     if (!*s || strchr_m("#;",*s))
123       continue;
124
125     if(!next_token(&s,unixname, "\t\n\r=", sizeof(unixname)))
126       continue;
127
128     if(!next_token(&s,windows_name, "\t\n\r=", sizeof(windows_name)))
129       continue;
130
131     trim_string(unixname, " ", " ");
132     trim_string(windows_name, " ", " ");
133
134     if (!*windows_name)
135       continue;
136
137     if(!*unixname)
138       continue;
139
140     DEBUG(5,("load_groupname_map: unixname = %s, windowsname = %s.\n",
141              unixname, windows_name));
142
143     /*
144      * Attempt to get the unix gid_t for this name.
145      */
146
147         if ((gid = nametogid(unixname)) == (gid_t)-1)
148       DEBUG(0,("load_groupname_map: nametogid for group %s failed.\
149 Error was %s.\n", unixname, strerror(errno) ));
150       continue;
151     }
152
153     /*
154      * Now map to an NT SID.
155      */
156
157     if(!lookup_wellknown_sid_from_name(windows_name, &tmp_sid)) {
158       /*
159        * It's not a well known name, convert the UNIX gid_t
160        * to a rid within this domain SID.
161        */
162       sid_copy(&tmp_sid,get_global_sam_sid());
163       tmp_sid.sub_auths[tmp_sid.num_auths++] = 
164                     pdb_gid_to_group_rid(gid);
165     }
166
167     /*
168      * Create the list entry and add it onto the list.
169      */
170
171     if((new_ep = (groupname_map_entry *)malloc( sizeof(groupname_map_entry) ))== NULL) {
172       DEBUG(0,("load_groupname_map: malloc fail for groupname_map_entry.\n"));
173       fclose(fp);
174       return;
175     } 
176
177     new_ep->unix_gid = gid;
178     new_ep->windows_sid = tmp_sid;
179     new_ep->windows_name = strdup( windows_name );
180     new_ep->unix_name = strdup( unixname );
181
182     if(new_ep->windows_name == NULL || new_ep->unix_name == NULL) {
183       DEBUG(0,("load_groupname_map: malloc fail for names in groupname_map_entry.\n"));
184       fclose(fp);
185       SAFE_FREE(new_ep->windows_name);
186       SAFE_FREE(new_ep->unix_name);
187       SAFE_FREE(new_ep);
188       file_lines_free(lines);
189       return;
190     }
191     memset((char *)&new_ep->next, '\0', sizeof(new_ep->next) );
192
193     ubi_slAddHead( &groupname_map_list, (ubi_slNode *)new_ep);
194   }
195
196   DEBUG(10,("load_groupname_map: Added %ld entries to groupname map.\n",
197             ubi_slCount(&groupname_map_list)));
198            
199   file_lines_free(lines);
200 }
201
202 /***********************************************************
203  Lookup a SID entry by gid_t.
204 ************************************************************/
205
206 void map_gid_to_sid( gid_t gid, DOM_SID *psid)
207 {
208   groupname_map_entry *gmep;
209
210   /*
211    * Initialize and load if not already loaded.
212    */
213   load_groupname_map();
214
215   for( gmep = (groupname_map_entry *)ubi_slFirst( &groupname_map_list);
216        gmep; gmep = (groupname_map_entry *)ubi_slNext( gmep )) {
217
218     if( gmep->unix_gid == gid) {
219       *psid = gmep->windows_sid;
220       DEBUG(7,("map_gid_to_sid: Mapping unix group %s to windows group %s.\n",
221                gmep->unix_name, gmep->windows_name ));
222       return;
223     }
224   }
225
226   /*
227    * If there's no map, convert the UNIX gid_t
228    * to a rid within this domain SID.
229    */
230   sid_copy(psid,get_global_sam_sid());
231   psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid);
232
233   return;
234 }
235 #else /* USING_GROUPNAME_MAP */
236  void load_groupname_map(void) {;}
237 #endif /* USING_GROUPNAME_MAP */