00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdAccGroupsCVSID = "$Id: XrdAccGroups.cc 38011 2011-02-08 18:35:57Z ganis $";
00014
00015 #include <unistd.h>
00016 #include <ctype.h>
00017 #include <errno.h>
00018 #include <limits.h>
00019 #include <netdb.h>
00020 #include <pwd.h>
00021 #include <string.h>
00022 #include <strings.h>
00023 #include <sys/param.h>
00024 #include <sys/types.h>
00025
00026 #include "XrdSys/XrdSysHeaders.hh"
00027 #include "XrdAcc/XrdAccCapability.hh"
00028 #include "XrdAcc/XrdAccGroups.hh"
00029 #include "XrdAcc/XrdAccPrivs.hh"
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 XrdAccGroups XrdAccGroupMaster;
00047
00048
00049
00050
00051
00052 struct XrdAccGroupArgs {const char *user;
00053 const char *host;
00054 int gtabi;
00055 const char *Gtab[NGROUPS_MAX];
00056 };
00057
00058
00059
00060
00061
00062 XrdAccGroups::XrdAccGroups()
00063 {
00064
00065
00066
00067 retrancnt = 0;
00068 HaveGroups = 0;
00069 HaveNetGroups = 0;
00070 options = No_Group_Opt;
00071 domain = 0;
00072 LifeTime = 60*60*12;
00073 }
00074
00075
00076
00077
00078
00079 char *XrdAccGroups::AddName(const XrdAccGroupType gtype, const char *name)
00080 {
00081 char *np;
00082 XrdOucHash<char> *hp;
00083
00084
00085
00086 if (gtype == XrdAccNetGroup) {hp = &NetGroup_Names; HaveNetGroups = 1;}
00087 else {hp = &Group_Names; HaveGroups = 1;}
00088
00089
00090
00091 Group_Name_Context.Lock();
00092
00093
00094
00095
00096 if (!(np = hp->Find(name)))
00097 {hp->Add(name, 0, 0, Hash_data_is_key);
00098 if (!(np = hp->Find(name)))
00099 cerr <<"XrdAccGroups: Unable to add group " <<name <<endl;
00100 }
00101
00102
00103
00104 Group_Name_Context.UnLock();
00105 return np;
00106 }
00107
00108
00109
00110
00111
00112 char *XrdAccGroups::FindName(const XrdAccGroupType gtype, const char *name)
00113 {
00114 char *np;
00115
00116
00117
00118 Group_Name_Context.Lock();
00119
00120
00121
00122 if (gtype == XrdAccNetGroup) np = NetGroup_Names.Find(name);
00123 else np = Group_Names.Find(name);
00124
00125
00126
00127 Group_Name_Context.UnLock();
00128 return np;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 XrdAccGroupList *XrdAccGroups::Groups(const char *user)
00138 {
00139 struct group *gr;
00140 struct passwd *pw;
00141 char **cp;
00142 XrdAccGroupList *glist;
00143 int gtabi;
00144 char *Gtab[NGROUPS_MAX];
00145
00146
00147
00148 if (!HaveGroups) return (XrdAccGroupList *)0;
00149
00150
00151
00152
00153
00154
00155 Group_Cache_Context.Lock();
00156 if ((glist = Group_Cache.Find(user)))
00157 {if (glist->First()) glist = new XrdAccGroupList(*glist);
00158 else glist = 0;
00159 Group_Cache_Context.UnLock();
00160 return glist;
00161 }
00162 Group_Cache_Context.UnLock();
00163
00164
00165
00166
00167
00168 Group_Build_Context.Lock();
00169 if ( (pw = getpwnam(user)) == NULL)
00170 {Group_Build_Context.UnLock();
00171 return (XrdAccGroupList *)0;
00172 }
00173
00174
00175
00176
00177
00178 gtabi = addGroup(user, pw->pw_gid, 0, Gtab, 0);
00179
00180
00181
00182
00183 if (!(options & Primary_Only))
00184 {
00185 setgrent() ;
00186 while ((gr = getgrent()))
00187 {
00188 if (pw->pw_gid == gr->gr_gid) continue;
00189 for (cp = gr->gr_mem; cp && *cp; cp++)
00190 if (strcmp(*cp, user) == 0)
00191 gtabi = addGroup(user, gr->gr_gid,
00192 Dotran(gr->gr_gid,gr->gr_name),
00193 Gtab, gtabi);
00194 }
00195 endgrent();
00196 }
00197
00198
00199
00200 Group_Build_Context.UnLock();
00201
00202
00203
00204 glist = new XrdAccGroupList(gtabi, (const char **)Gtab);
00205
00206
00207
00208 Group_Cache_Context.Lock();
00209 Group_Cache.Add(user, glist, LifeTime);
00210 Group_Cache_Context.UnLock();
00211
00212
00213
00214 if (!gtabi) return (XrdAccGroupList *)0;
00215 return new XrdAccGroupList(gtabi, (const char **)Gtab);
00216 }
00217
00218
00219
00220
00221
00222 XrdAccGroupList *XrdAccGroups::NetGroups(const char *user, const char *host)
00223 {
00224 XrdAccGroupList *glist;
00225 int i, j;
00226 char uh_key[MAXHOSTNAMELEN+96];
00227 struct XrdAccGroupArgs GroupTab;
00228 int XrdAccCheckNetGroup(const char *netgroup, char *key, void *Arg);
00229
00230
00231
00232 if (!HaveNetGroups) return (XrdAccGroupList *)0;
00233
00234
00235
00236 i = strlen(user); j = strlen(host);
00237 if (i+j+2 > (int)sizeof(uh_key)) return (XrdAccGroupList *)0;
00238 strcpy(uh_key, user);
00239 uh_key[i] = '@';
00240 strcpy(&uh_key[i+1], host);
00241
00242
00243
00244
00245
00246 NetGroup_Cache_Context.Lock();
00247 if ((glist = NetGroup_Cache.Find(uh_key)))
00248 {if (glist->First()) glist = new XrdAccGroupList(*glist);
00249 else glist = 0;
00250 NetGroup_Cache_Context.UnLock();
00251 return glist;
00252 }
00253 NetGroup_Cache_Context.UnLock();
00254
00255
00256
00257 GroupTab.user = user;
00258 GroupTab.host = host;
00259 GroupTab.gtabi = 0;
00260 Group_Name_Context.Lock();
00261 NetGroup_Names.Apply(XrdAccCheckNetGroup, (void *)&GroupTab);
00262 Group_Name_Context.UnLock();
00263
00264
00265
00266 glist = new XrdAccGroupList(GroupTab.gtabi,
00267 (const char **)GroupTab.Gtab);
00268
00269
00270
00271 NetGroup_Cache_Context.Lock();
00272 NetGroup_Cache.Add((const char *)uh_key, glist, LifeTime);
00273 NetGroup_Cache_Context.UnLock();
00274
00275
00276
00277 if (!GroupTab.gtabi) return (XrdAccGroupList *)0;
00278 return new XrdAccGroupList(GroupTab.gtabi,
00279 (const char **)GroupTab.Gtab);
00280 }
00281
00282
00283
00284
00285
00286 void XrdAccGroups::PurgeCache()
00287 {
00288
00289
00290
00291 Group_Cache_Context.Lock();
00292 Group_Cache.Purge();
00293 Group_Cache_Context.UnLock();
00294
00295
00296
00297 NetGroup_Cache_Context.Lock();
00298 NetGroup_Cache.Purge();
00299 NetGroup_Cache_Context.UnLock();
00300 }
00301
00302
00303
00304
00305
00306 int XrdAccGroups::Retran(const gid_t gid)
00307 {
00308 if ((int)gid < 0) retrancnt = 0;
00309 else {if (retrancnt > (int)(sizeof(retrangid)/sizeof(gid_t))) return -1;
00310 retrangid[retrancnt++] = gid;
00311 }
00312 return 0;
00313 }
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 int XrdAccGroups::addGroup(const char *user, const gid_t gid, char *gname,
00324 char **Gtab, int gtabi)
00325 {
00326 char *gp;
00327
00328
00329
00330
00331
00332 if (gtabi >= NGROUPS_MAX)
00333 {if (gtabi == NGROUPS_MAX)
00334 cerr <<"XrdAccGroups: More than " <<gtabi <<"groups for " <<user <<endl;
00335 return gtabi;
00336 }
00337
00338
00339
00340
00341 if (!gname || !gname[0])
00342 {struct group *gp;
00343 if ((gp = getgrgid(gid)) == NULL) return gtabi;
00344 else gname = gp->gr_name;
00345 }
00346
00347
00348
00349
00350
00351 if (!(gp = Group_Names.Find(gname)) ) return gtabi;
00352
00353
00354
00355 Gtab[gtabi++] = gp;
00356 return gtabi;
00357 }
00358
00359
00360
00361
00362
00363 char *XrdAccGroups::Dotran(const gid_t gid, char *gname)
00364 {
00365 int i;
00366
00367
00368
00369
00370 for (i = 0; i < retrancnt; i++) if (retrangid[i] == gid) return (char *)0;
00371 return gname;
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 int XrdAccCheckNetGroup(const char *netgroup, char *key, void *Arg)
00383 {
00384 struct XrdAccGroupArgs *grp = static_cast<struct XrdAccGroupArgs *>(Arg);
00385
00386
00387
00388 if (innetgr(netgroup, (const char *)grp->host, (const char *)grp->user,
00389 XrdAccGroupMaster.Domain()))
00390 {if (grp->gtabi >= NGROUPS_MAX)
00391 {if (grp->gtabi == NGROUPS_MAX)
00392 cerr <<"XrdAccGroups: More than " <<grp->gtabi <<"netgroups for " <<grp->user <<endl;
00393 return 1;
00394 }
00395
00396
00397
00398
00399 grp->Gtab[grp->gtabi] = netgroup; grp->gtabi++;
00400 }
00401 return 0;
00402 }