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