00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdAccConfigCVSID = "$Id: XrdAccConfig.cc 24468 2008-06-22 16:47:03Z ganis $";
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <unistd.h>
00024 #include <ctype.h>
00025 #include <fcntl.h>
00026 #include <strings.h>
00027 #include <stdio.h>
00028 #include <time.h>
00029 #include <sys/param.h>
00030 #include <sys/stat.h>
00031 #include <sys/types.h>
00032
00033 #include "XrdOuc/XrdOucLock.hh"
00034 #include "XrdOuc/XrdOucEnv.hh"
00035 #include "XrdSys/XrdSysError.hh"
00036 #include "XrdSys/XrdSysHeaders.hh"
00037 #include "XrdOuc/XrdOucStream.hh"
00038 #include "XrdAcc/XrdAccAccess.hh"
00039 #include "XrdAcc/XrdAccAudit.hh"
00040 #include "XrdAcc/XrdAccConfig.hh"
00041 #include "XrdAcc/XrdAccGroups.hh"
00042 #include "XrdAcc/XrdAccCapability.hh"
00043
00044
00045
00046
00047
00048
00049
00050
00051 XrdAccConfig XrdAccConfiguration;
00052
00053
00054
00055
00056
00057 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(Config,Eroute);
00058
00059 #define TS_Str(x,m) if (!strcmp(x,var)) {free(m); m = strdup(val); return 0;}
00060
00061 #define TS_Chr(x,m) if (!strcmp(x,var)) {m = val[0]; return 0;}
00062
00063 #define TS_Bit(x,m,v) if (!strcmp(x,var)) {m |= v; return 0;}
00064
00065 #define ACC_PGO 0x0001
00066
00067
00068
00069
00070
00071
00072
00073
00074 void *XrdAccConfig_Refresh( void *start_data )
00075 {
00076 XrdSysError *Eroute = (XrdSysError *)start_data;
00077
00078
00079
00080 struct timespec naptime = {(time_t)XrdAccConfiguration.AuthRT, 0};
00081
00082
00083
00084 while(1)
00085 {nanosleep(&naptime, 0); XrdAccConfiguration.ConfigDB(1, *Eroute);}
00086 return (void *)0;
00087 }
00088
00089
00090
00091
00092
00093 XrdAccConfig::XrdAccConfig()
00094 {
00095
00096
00097
00098 dbpath = strdup("/opt/xrd/etc/Authfile");
00099 Database = 0;
00100 Authorization = 0;
00101
00102
00103
00104 ConfigDefaults();
00105 }
00106
00107
00108
00109
00110
00111 int XrdAccConfig::Configure(XrdSysError &Eroute, const char *cfn) {
00112
00113
00114
00115
00116
00117
00118
00119 char *var;
00120 int retc, NoGo = 0, Cold = (Database == 0);
00121 pthread_t reftid;
00122
00123
00124
00125 Eroute.Say("++++++ Authorization system initialization started.");
00126
00127
00128
00129 if (!(Authorization = new XrdAccAccess(&Eroute))
00130 || (NoGo = ConfigFile(Eroute, cfn))
00131 || (NoGo = ConfigDB(0, Eroute)))
00132 {if (Authorization) {delete Authorization, Authorization = 0;}
00133 NoGo = 1;
00134 }
00135
00136
00137
00138 if (Cold && !NoGo)
00139 {if ((retc=XrdSysThread::Run(&reftid,XrdAccConfig_Refresh,(void *)&Eroute)))
00140 Eroute.Emsg("ConfigDB",retc,"start refresh thread.");
00141 }
00142
00143
00144
00145 var = (NoGo > 0 ? (char *)"failed." : (char *)"completed.");
00146 Eroute.Say("------ Authorization system initialization ", var);
00147 return (NoGo > 0);
00148 }
00149
00150
00151
00152
00153
00154 int XrdAccConfig::ConfigDB(int Warm, XrdSysError &Eroute)
00155 {
00156
00157
00158
00159
00160
00161
00162
00163 char buff[128];
00164 int retc, anum = 0, NoGo = 0;
00165 struct XrdAccAccess_Tables tabs;
00166 XrdOucLock cdb_Lock(&Config_Context);
00167
00168
00169
00170 if (!Database) NoGo = !(Database = XrdAccAuthDBObject(&Eroute));
00171 else if (Warm && !Database->Changed(dbpath)) return 0;
00172
00173
00174
00175 if (!Database || !Database->Open(Eroute, dbpath)) return 1;
00176
00177
00178
00179 if (!(tabs.G_Hash = new XrdOucHash<XrdAccCapability>()) ||
00180 !(tabs.H_Hash = new XrdOucHash<XrdAccCapability>()) ||
00181 !(tabs.N_Hash = new XrdOucHash<XrdAccCapability>()) ||
00182 !(tabs.T_Hash = new XrdOucHash<XrdAccCapability>()) ||
00183 !(tabs.U_Hash = new XrdOucHash<XrdAccCapability>()) )
00184 {Eroute.Emsg("ConfigDB","Insufficient storage for id tables.");
00185 Database->Close(); return 1;
00186 }
00187
00188
00189
00190 while((retc = ConfigDBrec(Eroute, tabs))) {NoGo |= retc < 0; anum++;}
00191 snprintf(buff, sizeof(buff), "%d auth entries processed in ", anum);
00192 Eroute.Say("Config ", buff, dbpath);
00193
00194
00195
00196 if (!Database->Close() || NoGo) return 1;
00197
00198
00199
00200 if (!tabs.G_Hash->Num()) {delete tabs.G_Hash; tabs.G_Hash=0;}
00201 if (!tabs.H_Hash->Num()) {delete tabs.H_Hash; tabs.H_Hash=0;}
00202 if (!tabs.N_Hash->Num()) {delete tabs.N_Hash; tabs.N_Hash=0;}
00203 if (!tabs.T_Hash->Num()) {delete tabs.T_Hash; tabs.T_Hash=0;}
00204 if (!tabs.U_Hash->Num()) {delete tabs.U_Hash; tabs.U_Hash=0;}
00205 Authorization->SwapTabs(tabs);
00206
00207
00208
00209 return NoGo;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219 int XrdAccConfig::ConfigFile(XrdSysError &Eroute, const char *ConfigFN) {
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 char *var;
00230 int cfgFD, retc, NoGo = 0, recs = 0;
00231 XrdOucEnv myEnv;
00232 XrdOucStream Config(&Eroute, getenv("XRDINSTANCE"), &myEnv, "=====> ");
00233
00234
00235
00236 if( !ConfigFN || !*ConfigFN)
00237 {Eroute.Emsg("Config", "Authorization configuration file not specified.");
00238 return 1;
00239 }
00240
00241
00242
00243 if (!strcmp(ConfigFN, "none"))
00244 {Eroute.Emsg("Config", "Authorization system deactivated.");
00245 return -1;
00246 }
00247
00248
00249
00250 if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
00251 {Eroute.Emsg("Config", errno, "open config file", ConfigFN);
00252 return 1;
00253 }
00254 Eroute.Emsg("Config","Authorization system using configuration in",ConfigFN);
00255
00256
00257
00258 ConfigDefaults(); Config.Attach(cfgFD); Config.Tabs(0);
00259 while((var = Config.GetMyFirstWord()))
00260 {if (!strncmp(var, "acc.", 2))
00261 {recs++;
00262 if (ConfigXeq(var+4, Config, Eroute)) {Config.Echo(); NoGo = 1;}
00263 }
00264 }
00265
00266
00267
00268 if ((retc = Config.LastError()))
00269 NoGo = Eroute.Emsg("Config",-retc,"read config file",ConfigFN);
00270 else {char buff[128];
00271 snprintf(buff, sizeof(buff),
00272 "%d authorization directives processed in ", recs);
00273 Eroute.Say("Config ", buff, ConfigFN);
00274 }
00275 Config.Close();
00276
00277
00278
00279 if (options & ACC_PGO) GroupMaster.SetOptions(Primary_Only);
00280
00281
00282
00283 return NoGo;
00284 }
00285
00286
00287
00288
00289
00290 void XrdAccConfig::ConfigDefaults()
00291 {
00292 AuthRT = 60*60*12;
00293 options = 0;
00294 }
00295
00296
00297
00298
00299
00300 int XrdAccConfig::ConfigXeq(char *var, XrdOucStream &Config, XrdSysError &Eroute)
00301 {
00302
00303
00304
00305 TS_Xeq("audit", xaud);
00306 TS_Xeq("authdb", xdbp);
00307 TS_Xeq("authrefresh", xart);
00308 TS_Xeq("gidlifetime", xglt);
00309 TS_Xeq("gidretran", xgrt);
00310 TS_Xeq("nisdomain", xnis);
00311 TS_Bit("pgo", options, ACC_PGO);
00312
00313
00314
00315 Eroute.Emsg("Config", "unknown directive", var);
00316 Config.Echo();
00317 return 1;
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 int XrdAccConfig::xaud(XrdOucStream &Config, XrdSysError &Eroute)
00338 {
00339 static struct auditopts {const char *opname; int opval;} audopts[] =
00340 {
00341 {"deny", (int)audit_deny},
00342 {"grant", (int)audit_grant}
00343 };
00344 int i, audval = 0, numopts = sizeof(audopts)/sizeof(struct auditopts);
00345 char *val;
00346
00347 val = Config.GetWord();
00348 if (!val || !val[0])
00349 {Eroute.Emsg("Config", "audit option not specified"); return 1;}
00350 while (val && val[0])
00351 {if (!strcmp(val, "none")) audval = (int)audit_none;
00352 else for (i = 0; i < numopts; i++)
00353 {if (!strcmp(val, audopts[i].opname))
00354 {audval |= audopts[i].opval; break;}
00355 if (i >= numopts)
00356 {Eroute.Emsg("Config","invalid audit option -",val);
00357 return 1;
00358 }
00359 }
00360 val = Config.GetWord();
00361 }
00362 Authorization->Auditor->setAudit((XrdAccAudit_Options)audval);
00363 return 0;
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 int XrdAccConfig::xart(XrdOucStream &Config, XrdSysError &Eroute)
00380 {
00381 char *val;
00382 int reft;
00383
00384 val = Config.GetWord();
00385 if (!val || !val[0])
00386 {Eroute.Emsg("Config","authrefresh value not specified");return 1;}
00387 if (XrdOuca2x::a2tm(Eroute,"authrefresh value",val,&reft,60))
00388 return 1;
00389 AuthRT = reft;
00390 return 0;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 int XrdAccConfig::xdbp(XrdOucStream &Config, XrdSysError &Eroute)
00407 {
00408 char *val;
00409
00410 val = Config.GetWord();
00411 if (!val || !val[0])
00412 {Eroute.Emsg("Config","authdb path not specified");return 1;}
00413 dbpath = strdup(val);
00414 return 0;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 int XrdAccConfig::xglt(XrdOucStream &Config, XrdSysError &Eroute)
00431 {
00432 char *val;
00433 int reft;
00434
00435 val = Config.GetWord();
00436 if (!val || !val[0])
00437 {Eroute.Emsg("Config","gidlifetime value not specified");return 1;}
00438 if (XrdOuca2x::a2tm(Eroute,"gidlifetime value",val,&reft,60))
00439 return 1;
00440 GroupMaster.SetLifetime(reft);
00441 return 0;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 int XrdAccConfig::xgrt(XrdOucStream &Config, XrdSysError &Eroute)
00459 {
00460 char *val;
00461 int gid;
00462
00463 val = Config.GetWord();
00464 if (!val || !val[0])
00465 {Eroute.Emsg("Config","gidretran value not specified"); return 1;}
00466
00467 while (val && val[0])
00468 {if (XrdOuca2x::a2i(Eroute, "gid", val, &gid, 0)) return 1;
00469 if (GroupMaster.Retran((gid_t)gid) < 0)
00470 {Eroute.Emsg("Config", "to many gidretran gid's"); return 1;}
00471 val = Config.GetWord();
00472 }
00473 return 0;
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 int XrdAccConfig::xnis(XrdOucStream &Config, XrdSysError &Eroute)
00490 {
00491 char *val;
00492
00493 val = Config.GetWord();
00494 if (!val || !val[0])
00495 {Eroute.Emsg("Config","nisdomain value not specified");return 1;}
00496 GroupMaster.SetDomain(strdup(val));
00497 return 0;
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507 int XrdAccConfig::ConfigDBrec(XrdSysError &Eroute,
00508 struct XrdAccAccess_Tables &tabs)
00509 {
00510
00511
00512 enum DB_RecType { Group_ID = 'g',
00513 Host_ID = 'h',
00514 Netgrp_ID = 'n',
00515 Set_ID = 's',
00516 Template_ID = 't',
00517 User_ID = 'u',
00518 No_ID = 0
00519 };
00520 char *authid, rtype, *atype, *path, *privs;
00521 int alluser = 0, anyuser = 0, domname = 0, NoGo = 0;
00522 DB_RecType rectype;
00523 XrdOucHash<XrdAccCapability> *hp;
00524 XrdAccGroupType gtype = XrdAccNoGroup;
00525 XrdAccPrivCaps xprivs;
00526 XrdAccCapability mycap((char *)"", xprivs), *currcap, *lastcap = &mycap;
00527 XrdAccCapName *ncp;
00528
00529
00530
00531 if (!(rtype = Database->getRec(&authid))) return 0;
00532 rectype = (DB_RecType)rtype;
00533
00534
00535
00536 switch(rectype)
00537 {case Group_ID: hp = tabs.G_Hash; atype = (char *)"group";
00538 gtype=XrdAccUnixGroup;
00539 break;
00540 case Host_ID: hp = tabs.H_Hash; atype = (char *)"host";
00541 domname = (authid[0] == '.');
00542 break;
00543 case Set_ID: hp = 0; atype = (char *)"set";
00544 break;
00545 case Netgrp_ID: hp = tabs.N_Hash; atype = (char *)"netgrp";
00546 gtype=XrdAccNetGroup;
00547 break;
00548 case Template_ID: hp = tabs.T_Hash; atype = (char *)"template";
00549 break;
00550 case User_ID: hp = tabs.U_Hash; atype = (char *)"user";
00551 alluser = (authid[0] == '*' && !authid[1]);
00552 anyuser = (authid[0] == '=' && !authid[1]);
00553 break;
00554 default: hp = 0;
00555 break;
00556 }
00557
00558
00559
00560 if (!hp) {char badtype[2] = {rtype, '\0'};
00561 Eroute.Emsg("ConfigXeq", "Invalid id type -", badtype);
00562 return -1;
00563 }
00564
00565
00566
00567 if ((domname && tabs.D_List && tabs.D_List->Find((const char *)authid))
00568 || (alluser && tabs.Z_List) || (anyuser && tabs.X_List) || hp->Find(authid))
00569 {Eroute.Emsg("ConfigXeq", "duplicate id -", authid);
00570 return -1;
00571 }
00572
00573
00574
00575 if (gtype) GroupMaster.AddName(gtype, (const char *)authid);
00576
00577
00578
00579 while(1) {NoGo = 0;
00580 if (!Database->getPP(&path, &privs)) break;
00581 if (!path) continue;
00582 NoGo = 1;
00583 if (*path != '/')
00584 {if ((currcap = tabs.T_Hash->Find(path)))
00585 currcap = new XrdAccCapability(currcap);
00586 else {Eroute.Emsg("ConfigXeq", "Missing template -", path);
00587 break;
00588 }
00589 } else {
00590 if (!privs)
00591 {Eroute.Emsg("ConfigXeq", "Missing privs for path", path);
00592 break;
00593 }
00594 if (!PrivsConvert(privs, xprivs))
00595 {Eroute.Emsg("ConfigXeq", "Invalid privs -", privs);
00596 break;
00597 }
00598 currcap = new XrdAccCapability(path, xprivs);
00599 }
00600 lastcap->Add(currcap);
00601 lastcap = currcap;
00602 }
00603
00604
00605
00606 if (NoGo) return -1;
00607
00608
00609
00610 if (!mycap.Next())
00611 {Eroute.Emsg("ConfigXeq", "no capabilities specified for", authid);
00612 return -1;
00613 }
00614
00615
00616
00617 if (domname)
00618 {if (!(ncp = new XrdAccCapName(authid, mycap.Next())))
00619 {Eroute.Emsg("ConfigXeq","unable to add id",authid); return -1;}
00620 if (tabs.E_List) tabs.E_List->Add(ncp);
00621 else tabs.D_List = ncp;
00622 tabs.E_List = ncp;
00623 }
00624 else if (anyuser) tabs.X_List = mycap.Next();
00625 else if (alluser) tabs.Z_List = mycap.Next();
00626 else hp->Add(authid, mycap.Next());
00627
00628
00629
00630 mycap.Add((XrdAccCapability *)0);
00631 return 1;
00632 }
00633
00634
00635
00636
00637
00638 int XrdAccConfig::PrivsConvert(char *privs, XrdAccPrivCaps &ctab)
00639 {
00640 int i = 0;
00641 XrdAccPrivs ptab[] = {XrdAccPriv_None, XrdAccPriv_None};
00642
00643
00644
00645 while(*privs)
00646 {switch((XrdAccPrivSpec)(*privs))
00647 {case All_Priv:
00648 ptab[i] = (XrdAccPrivs)(ptab[i]|XrdAccPriv_All);
00649 break;
00650 case Delete_Priv:
00651 ptab[i] = (XrdAccPrivs)(ptab[i]|XrdAccPriv_Delete);
00652 break;
00653 case Insert_Priv:
00654 ptab[i] = (XrdAccPrivs)(ptab[i]|XrdAccPriv_Insert);
00655 break;
00656 case Lock_Priv:
00657 ptab[i] = (XrdAccPrivs)(ptab[i]|XrdAccPriv_Lock);
00658 break;
00659 case Lookup_Priv:
00660 ptab[i] = (XrdAccPrivs)(ptab[i]|XrdAccPriv_Lookup);
00661 break;
00662 case Rename_Priv:
00663 ptab[i] = (XrdAccPrivs)(ptab[i]|XrdAccPriv_Rename);
00664 break;
00665 case Read_Priv:
00666 ptab[i] = (XrdAccPrivs)(ptab[i]|XrdAccPriv_Read);
00667 break;
00668 case Write_Priv:
00669 ptab[i] = (XrdAccPrivs)(ptab[i]|XrdAccPriv_Write);
00670 break;
00671 case Neg_Priv: if (i) return 0; i++; break;
00672 default: return 0;
00673 }
00674 privs++;
00675 }
00676 ctab.pprivs = ptab[0]; ctab.nprivs = ptab[1];
00677 return 1;
00678 }