XRootD
XrdSecProtocolpwd Class Reference

#include <XrdSecProtocolpwd.hh>

+ Inheritance diagram for XrdSecProtocolpwd:
+ Collaboration diagram for XrdSecProtocolpwd:

Public Member Functions

 XrdSecProtocolpwd (int opts, const char *hname, XrdNetAddrInfo &endPoint, const char *parms=0)
 
virtual ~XrdSecProtocolpwd ()
 
int Authenticate (XrdSecCredentials *cred, XrdSecParameters **parms, XrdOucErrInfo *einfo=0)
 
void Delete ()
 Delete the protocol object. DO NOT use C++ delete() on this object. More...
 
XrdSecCredentialsgetCredentials (XrdSecParameters *parm=0, XrdOucErrInfo *einfo=0)
 
- Public Member Functions inherited from XrdSecProtocol
 XrdSecProtocol (const char *pName)
 Constructor. More...
 
virtual int Decrypt (const char *inbuff, int inlen, XrdSecBuffer **outbuff)
 
virtual int Encrypt (const char *inbuff, int inlen, XrdSecBuffer **outbuff)
 
virtual int getKey (char *buff=0, int size=0)
 
virtual bool needTLS ()
 Check if this protocol requires TLS to properly function. More...
 
virtual int setKey (char *buff, int size)
 
virtual int Sign (const char *inbuff, int inlen, XrdSecBuffer **outbuff)
 
virtual int Verify (const char *inbuff, int inlen, const char *sigbuff, int siglen)
 

Static Public Member Functions

static XrdOucTraceEnableTracing ()
 
static char * Init (pwdOptions o, XrdOucErrInfo *erp)
 
static void PrintTimeStat ()
 

Additional Inherited Members

- Public Attributes inherited from XrdSecProtocol
XrdSecEntity Entity
 
- Protected Member Functions inherited from XrdSecProtocol
virtual ~XrdSecProtocol ()
 Destructor (prevents use of direct delete). More...
 

Detailed Description

Definition at line 285 of file XrdSecProtocolpwd.hh.

Constructor & Destructor Documentation

◆ XrdSecProtocolpwd()

XrdSecProtocolpwd::XrdSecProtocolpwd ( int  opts,
const char *  hname,
XrdNetAddrInfo endPoint,
const char *  parms = 0 
)

Definition at line 252 of file XrdSecProtocolpwd.cc.

254  : XrdSecProtocol("pwd")
255 {
256  // Default constructor
257  EPNAME("XrdSecProtocolpwd");
258 
259  if (QTRACE(Authen)) { PRINT("constructing: "<<this); }
260 
261  // Create instance of the handshake vars
262  if ((hs = new pwdHSVars())) {
263  // Update time stamp
264  hs->TimeStamp = time(0);
265  // Local handshake variables
266  hs->CryptoMod = ""; // crypto module in use
267  hs->User = ""; // remote username
268  hs->Tag.resize(256); // tag for credentials
269  hs->RemVers = -1; // Version run by remote counterpart
270  hs->CF = 0; // crypto factory
271  hs->Hcip = 0; // handshake cipher
272  hs->Rcip = 0; // reference cipher
273  hs->ID = ""; // Handshake ID (dummy for clients)
274  hs->Cref = 0; // Cache reference
275  hs->Pent = 0; // Pointer to relevant file entry
276  hs->RtagOK = 0; // Rndm tag checked / not checked
277  hs->Tty = (isatty(0) == 0 || isatty(1) == 0) ? 0 : 1;
278  hs->Step = 0; // Current step
279  hs->LastStep = 0; // Step required at previous iteration
280  } else {
281  PRINT("could not create handshake vars object");
282  }
283 
284  // Used by servers to store forwarded credentials
285  clientCreds = 0;
286 
287  // Save host name and address
288  if (hname) {
289  Entity.host = strdup(hname);
290  } else {
291  NOTIFY("warning: host name undefined");
292  }
293  epAddr = endPoint;
294  Entity.addrInfo = &epAddr;
295  // Init client name
296  CName[0] = '?'; CName[1] = '\0';
297 
298  //
299  // Notify, if required
300  DEBUG("constructing: host: "<<hname);
301  DEBUG("p: "<<XrdSecPROTOIDENT<<", plen: "<<XrdSecPROTOIDLEN);
302  //
303  // basic settings
304  options = opts;
305 
306  //
307  // Mode specific initializations
308  if (Server) {
309  srvMode = 1;
310  DEBUG("mode: server");
311  } else {
312  srvMode = 0;
313  DEBUG("mode: client");
314  if (AutoLogin > 0) {
315  DEBUG("using autologin file: "<<PFAlog.Name());
316  if (AutoLogin > 1) {
317  DEBUG("running in update-autologin mode");
318  }
319  }
320  if (VeriSrv > 0) {
321  DEBUG("server verification ON");
322  } else {
323  DEBUG("server verification OFF");
324  }
325  // Decode received buffer
326  if (parms) {
327  XrdOucString p("&P=pwd,");
328  p += parms;
329  hs->Parms = new XrdSutBuffer(p.c_str(), p.length());
330  }
331  }
332 
333  // We are done
334  String vers = Version;
335  vers.insert('.',vers.length()-2);
336  vers.insert('.',vers.length()-5);
337  DEBUG("object created: v"<<vers.c_str());
338 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define QTRACE(act)
Definition: XrdCmsTrace.hh:49
#define PRINT(y)
#define XrdSecPROTOIDLEN
#define XrdSecPROTOIDENT
static const kXR_int32 Version
#define NOTIFY(y)
struct myOpts opts
void insert(const int i, int start=-1)
const char * c_str() const
int length() const
void resize(int lmx=0)
XrdNetAddrInfo * addrInfo
Entity's connection details.
Definition: XrdSecEntity.hh:80
char * host
Entity's host name dnr dependent.
Definition: XrdSecEntity.hh:70
XrdSecEntity Entity
XrdSecProtocol(const char *pName)
Constructor.
const char * Name() const
Definition: XrdSutPFile.hh:168
XrdCryptoCipher * Hcip
XrdCryptoCipher * Rcip
XrdCryptoFactory * CF
XrdSutPFEntry * Pent
XrdSutPFEntry * Cref
XrdSutBuffer * Parms

References XrdSecEntity::addrInfo, XrdOucString::c_str(), pwdHSVars::CF, pwdHSVars::Cref, pwdHSVars::CryptoMod, DEBUG, XrdSecProtocol::Entity, EPNAME, pwdHSVars::Hcip, XrdSecEntity::host, pwdHSVars::ID, XrdOucString::insert(), pwdHSVars::LastStep, XrdOucString::length(), XrdSutPFile::Name(), NOTIFY, opts, pwdHSVars::Parms, pwdHSVars::Pent, PRINT, QTRACE, pwdHSVars::Rcip, pwdHSVars::RemVers, XrdOucString::resize(), pwdHSVars::RtagOK, pwdHSVars::Step, pwdHSVars::Tag, pwdHSVars::TimeStamp, pwdHSVars::Tty, pwdHSVars::User, Version, XrdSecPROTOIDENT, and XrdSecPROTOIDLEN.

+ Here is the call graph for this function:

◆ ~XrdSecProtocolpwd()

virtual XrdSecProtocolpwd::~XrdSecProtocolpwd ( )
inlinevirtual

Definition at line 298 of file XrdSecProtocolpwd.hh.

298 {} // Delete() does it all

Member Function Documentation

◆ Authenticate()

int XrdSecProtocolpwd::Authenticate ( XrdSecCredentials cred,
XrdSecParameters **  parms,
XrdOucErrInfo einfo = 0 
)
virtual

Authenticate a client.

Parameters
credCredentials supplied by the client.
parmsPlace where the address of additional authentication data is to be placed for another autrhentication handshake.
einfoThe error information object where error messages should be placed. The messages are returned to the client. Should einfo be null, messages should be written to stderr.
Returns
> 0 -> parms present (more authentication needed) = 0 -> Entity present (authentication suceeded) < 0 -> einfo present (error has occurred)

Implements XrdSecProtocol.

Definition at line 1169 of file XrdSecProtocolpwd.cc.

1172 {
1173  //
1174  // Check if we have any credentials or if no credentials really needed.
1175  // In either case, use host name as client name
1176  EPNAME("Authenticate");
1177 
1178  //
1179  // If cred buffer is two small or empty assume host protocol
1180  if (cred->size <= (int)XrdSecPROTOIDLEN || !cred->buffer) {
1181  strncpy(Entity.prot, "host", sizeof(Entity.prot));
1182  return 0;
1183  }
1184 
1185  // Handshake vars container must be initialized at this point
1186  if (!hs)
1187  return ErrS(String("none"),ei,0,0,0,kPWErrError,
1188  "handshake var container missing",
1189  "protocol initialization problems");
1190  hs->ErrMsg = "";
1191  //
1192  // Update time stamp
1193  hs->TimeStamp = time(0);
1194 
1195  //
1196  // ID of this handshaking
1197  hs->ID = Entity.tident;
1198  DEBUG("handshaking ID: " << hs->ID);
1199 
1200  // Local vars
1201  int i = 0;
1202  int kS_rc = kpST_more;
1203  int rc = 0;
1204  int entst = 0;
1205  int nextstep = 0;
1206  int ctype = kpCT_normal;
1207  char *bpub = 0, *bpid = 0;
1208  int lpub = 0;
1209  const char *stepstr = 0;
1210  String Message;
1211  String CryptList;
1212  String Host;
1213  String SrvPuKExp;
1214  String Salt;
1215  String RndmTag;
1216  String ClntMsg(256);
1217  // Buffer related
1218  XrdSutBuffer *bpar = 0; // Global buffer
1219  XrdSutBuffer *bmai = 0; // Main buffer
1220  XrdSutBucket *bck = 0; // Generic bucket
1221  // The local status info
1222  pwdStatus_t SessionSt = { 0, 0, 0};
1223 
1224  //
1225  // Unlocks automatically returning
1226  XrdSysMutexHelper pwdGuard(&pwdContext);
1227  //
1228  // Decode received buffer
1229  if (!(bpar = new XrdSutBuffer((const char *)cred->buffer,cred->size)))
1230  return ErrS(hs->ID,ei,0,0,0,kPWErrDecodeBuffer,"global",stepstr);
1231  //
1232  // Check protocol ID name
1233  if (strcmp(bpar->GetProtocol(),XrdSecPROTOIDENT))
1234  return ErrS(hs->ID,ei,bpar,bmai,0,kPWErrBadProtocol,stepstr);
1235  //
1236  // The step indicates what we are supposed to do
1237  hs->Step = bpar->GetStep();
1238  stepstr = ClientStepStr(hs->Step);
1239  // Dump, if requested
1240  if (QTRACE(Dump)) {
1241  bpar->Dump(stepstr);
1242  }
1243 
1244  //
1245  // Find first crypto module to be used
1246  if (ParseCrypto(bpar) != 0)
1247  return ErrS(hs->ID,ei,bpar,0,0,kPWErrLoadCrypto,stepstr);
1248  //
1249  // Parse input buffer
1250  if (ParseServerInput(bpar, &bmai, ClntMsg) == -1) {
1251  PRINT(ClntMsg);
1252  return ErrS(hs->ID,ei,bpar,bmai,0,kPWErrParseBuffer,ClntMsg.c_str(),stepstr);
1253  }
1254  //
1255  // Get handshake status
1256  if ((bck = bmai->GetBucket(kXRS_status))) {
1257  int pst = 0;
1258  memcpy(&pst,bck->buffer,sizeof(pwdStatus_t));
1259  pst = ntohl(pst);
1260  memcpy(&SessionSt, &pst, sizeof(pwdStatus_t));
1261  bmai->Deactivate(kXRS_status);
1262  } else {
1263  NOTIFY("no bucket kXRS_status found in main buffer");
1264  }
1265  hs->Tty = SessionSt.options & kOptsClntTty;
1266  //
1267  // Client name
1268  unsigned int ulen = hs->User.length();
1269  ulen = (ulen > sizeof(CName)-1) ? sizeof(CName)-1 : ulen;
1270  if (ulen)
1271  strcpy(CName, hs->User.c_str());
1272  // And set link to entity
1273  Entity.name = strdup(CName);
1274 
1275  //
1276  // Version
1277  DEBUG("version run by client: "<< hs->RemVers);
1278  //
1279  // Dump, if requested
1280  if (QTRACE(Dump)) {
1281  bmai->Dump("main IN");
1282  }
1283  //
1284  // Check random challenge
1285  if (!CheckRtag(bmai, ClntMsg))
1286  return ErrS(hs->ID,ei,bpar,bmai,0,kPWErrBadRndmTag,stepstr,ClntMsg.c_str());
1287  //
1288  // Check also host / time stamp (it will be done only if really neede)
1289  if (!CheckTimeStamp(bmai, TimeSkew, ClntMsg))
1290  return ErrS(hs->ID,ei,bpar,bmai,0,kPWErrBadRndmTag,stepstr,ClntMsg.c_str());
1291  //
1292  // Now action depens on the step
1293  bool savecreds = (SessionSt.options & kOptsExpCred);
1294  switch (hs->Step) {
1295 
1296  case kXPC_verifysrv:
1297  //
1298  // Client required us to sign a random challenge: this is done
1299  // in AddSerialized, so nothing to do here
1300  nextstep = kXPS_signedrtag;
1301  break;
1302 
1303  case kXPC_signedrtag:
1304  //
1305  // Client signed the random challenge we sent: if we are here,
1306  // everything was fine
1307  kS_rc = kpST_ok;
1308  nextstep = kXPS_none;
1309  break;
1310 
1311  case kXPC_failureack:
1312  //
1313  // Client acknowledged failure
1314  kS_rc = kpST_error;
1315  nextstep = kXPS_none;
1316  break;
1317 
1318  case kXPC_autoreg:
1319  //
1320  // Client has lost the key or requested auto-registration: we
1321  // check the username: if it has a good entry or it is allowed
1322  // to auto-register (the check is done in QueryUser) we send
1323  // the public part of the key; otherwise we fail
1324  rc = QueryUser(entst, ClntMsg);
1325  if (rc < 0 || (entst == kPFE_disabled))
1326  return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrBadCreds,
1327  DefError.c_str(),stepstr);
1328  //
1329  // We have to send the public key
1330  for (i = 0; i < ncrypt; i++) {
1331  if (refcip[i]) {
1332  //
1333  // Extract buffer with public info for the cipher agreement
1334  if (!(bpub = refcip[i]->Public(lpub)))
1335  return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrNoPublic,
1336  "session",stepstr);
1337  bpid = new char[lpub+5];
1338  if (bpid) {
1339  char cid[5] = {0};
1340  sprintf(cid,"%d",cryptID[i]);
1341  memcpy(bpid,cid,5);
1342  memcpy(bpid+5, bpub, lpub);
1343  //
1344  // Add it to the global list
1345  if (bmai->AddBucket(bpid,lpub+5,kXRS_puk) != 0)
1346  return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrAddBucket,
1347  "main",stepstr);
1348  } else
1349  return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrError,
1350  "out-of-memory",stepstr);
1351  SafeDelArray(bpub); // bpid is taken by the bucket
1352  }
1353  }
1354  // client should now go through a complete login
1355  nextstep = kXPS_puk;
1356  break;
1357 
1358  case kXPC_normal:
1359  case kXPC_creds:
1360 if (hs->Step == kXPC_normal)
1361  {
1362  //
1363  // Complete login sequence: check user and creds
1364  if (QueryUser(entst,ClntMsg) != 0)
1365  return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrBadCreds,
1366  ": user ",hs->User.c_str(),stepstr);
1367  // Nothing to do, if disabled
1368  if (entst == kPFE_disabled)
1369  return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrBadCreds,
1370  ": user ",hs->User.c_str(),stepstr);
1371 
1372  if (entst == kPFE_expired || entst == kPFE_onetime) {
1373  // New credentials should asked upon success first check
1374  SessionSt.options |= kOptsExpCred;
1375  }
1376  if (entst == kPFE_crypt) {
1377  // User credentials are either in crypt form (private or
1378  // system ones) or of AFS type; in case of failure
1379  // this flag allows the client to send the right creds
1380  // at next iteration
1381  if (ClntMsg.beginswith("afs:")) {
1382  SessionSt.options |= kOptsAFSPwd;
1383  } else
1384  SessionSt.options |= kOptsCrypPwd;
1385  // Reset the message
1386  ClntMsg = "";
1387  }
1388  // Creds, if any, should be checked, unles we allow auto-registration
1389  savecreds = (entst != kPFE_allowed) ? 0 : 1;
1390  }
1391 
1392 // case kXPC_creds: (falls into here from _normal)
1393  //
1394  // Final login sequence: extract and check creds
1395  // Extract credentials from main buffer
1396  if (!(bck = bmai->GetBucket(kXRS_creds))) {
1397  //
1398  // If credentials are missing, require them
1399  kS_rc = kpST_more;
1400  nextstep = kXPS_credsreq;
1401  break;
1402  }
1403  //
1404  // If we required new credentials at previous step, just save them
1405  if (savecreds) {
1406  if (SaveCreds(bck) != 0) {
1407  ClntMsg = "Warning: could not correctly update credentials database";
1408  }
1409  kS_rc = kpST_ok;
1410  nextstep = kXPS_none;
1411  bmai->Deactivate(kXRS_creds);
1412  break;
1413  }
1414  //
1415  // Credential type
1416  ctype = kpCT_normal;
1417  if (SessionSt.options & kOptsCrypPwd)
1418  ctype = kpCT_crypt;
1419  else if (SessionSt.options & kOptsAFSPwd) {
1420  ctype = kpCT_afs;
1421  String afsInfo;
1422  XrdSutBucket *bafs = bmai->GetBucket(kXRS_afsinfo);
1423  if (bafs)
1424  bafs->ToString(afsInfo);
1425  if (afsInfo == "c")
1426  ctype = kpCT_afsenc;
1427  }
1428  //
1429  // Check credentials
1430  if (!CheckCreds(bck, ctype)) {
1431  //
1432  // Count temporary failures
1433  (hs->Cref->cnt)++;
1434  // Reset expired credentials flag
1435  SessionSt.options &= ~kOptsExpCred;
1436  // Repeat if not too many attempts
1437  ClntMsg = DefError;
1438  if (hs->Cref->cnt < MaxPrompts) {
1439  // Set next step to credential request
1440  nextstep = kXPS_credsreq;
1441  kS_rc = kpST_more;
1442  // request again creds
1443  if (hs->Pent->status == kPFE_crypt) {
1444  SessionSt.ctype = kpCT_crypt;
1445  if (ctype == kpCT_afs || ctype == kpCT_afsenc) {
1446  SessionSt.ctype = kpCT_afs;
1447  String afsinfo = hs->ErrMsg;
1448  bmai->UpdateBucket(afsinfo, kXRS_afsinfo);
1449  }
1450  ClntMsg = "";
1451  } else {
1452  SessionSt.ctype = kpCT_normal;
1453  ClntMsg = "insufficient credentials";
1454  }
1455  } else {
1456  // We communicate failure
1457  kS_rc = kpST_more;
1458  nextstep = kXPS_failure;
1459  // Count failures
1460  (hs->Pent->cnt)++;
1461  // Count failures
1462  hs->Pent->mtime = (kXR_int32)time(0);
1463  // Flush cache content to source file
1464  XrdSysPrivGuard priv(getuid(), getgid());
1465  if (priv.Valid()) {
1466  if (cacheAdmin.Flush() != 0) {
1467  PRINT("WARNING: some problem flushing to admin"
1468  " file after updating "<<hs->Pent->name);
1469  }
1470  }
1471  }
1472  } else {
1473  // Reset counter for temporary failures
1474  hs->Cref->cnt = 0;
1475  // Reset counter in file if needed
1476  if (hs->Pent->cnt > 0) {
1477  hs->Pent->cnt = 0;
1478  // Count failures
1479  hs->Pent->mtime = (kXR_int32)time(0);
1480  // Flush cache content to source file
1481  XrdSysPrivGuard priv(getuid(), getgid());
1482  if (priv.Valid()) {
1483  if (cacheAdmin.Flush() != 0) {
1484  PRINT("WARNING: some problem flushing to admin"
1485  " file after updating "<<hs->Pent->name);
1486  }
1487  }
1488  }
1489  kS_rc = kpST_ok;
1490  nextstep = kXPS_none;
1491  if (SessionSt.options & kOptsExpCred ||
1492  // Client requested a pwd change
1493  SessionSt.options & kOptsChngPwd) {
1494  kS_rc = kpST_more;
1495  nextstep = kXPS_credsreq;
1496  if (SessionSt.options & kOptsExpCred) {
1497  ClntMsg = "Credentials expired";
1498  } else if (SessionSt.options & kOptsChngPwd) {
1499  ClntMsg = "Password change requested";
1500  }
1501  // request new creds
1502  SessionSt.ctype = kpCT_new;
1503  // So we can save at next round
1504  SessionSt.options |= kOptsExpCred;
1505  }
1506  // Create buffer to keep the credentials, if required
1507  if (KeepCreds) {
1508  int sz = bck->size+5;
1509  char *buf = (char *) malloc(sz);
1510  if (buf) {
1511  memcpy(buf, "&pwd", 4);
1512  buf[4] = 0;
1513  memcpy(buf+5, bck->buffer, bck->size);
1514  // Put in hex
1515  char *out = new char[2*sz+1];
1516  XrdSutToHex(buf, sz, out);
1517  // Cleanup any existing info
1518  SafeDelete(clientCreds);
1519  clientCreds = new XrdSecCredentials(out, 2*sz+1);
1520  }
1521  }
1522  // Export creds to a file, if required
1523  if (FileExpCreds.length() > 0) {
1524  if (ExportCreds(bck) != 0)
1525  PRINT("WARNING: some problem exporting creds to file;"
1526  " template is :"<<FileExpCreds);
1527  }
1528  }
1529  // We will not use again these credentials
1530  bmai->Deactivate(kXRS_creds);
1531 
1532  break;
1533 
1534  default:
1535  return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrBadOpt, stepstr);
1536  }
1537 
1538  //
1539  // If strong signature checking is required add random tag
1540  if (kS_rc == kpST_ok) {
1541  if (VeriClnt == 2 && !(hs->RtagOK)) {
1542  // Send only the random tag to sign
1543  nextstep = kXPS_rtag;
1544  kS_rc = kpST_more;
1545  }
1546  }
1547 
1548  //
1549  // If we need additional info but the client caa not reply, just fail
1550  if (kS_rc == kpST_more && !(hs->Tty)) {
1551  PRINT("client cannot reply to additional request: failure");
1552  // Deactivate everything
1553  bpar->Deactivate(-1);
1554  bmai->Deactivate(-1);
1555  kS_rc = kpST_error;
1556  }
1557  //
1558  if (kS_rc == kpST_more) {
1559  //
1560  // Add message to client
1561  if (ClntMsg.length() > 0)
1562  if (bmai->AddBucket(ClntMsg,kXRS_message) != 0) {
1563  PRINT("problems adding bucket with message for client");
1564  }
1565  //
1566  // We set some options in the option field of a pwdStatus_t structure
1567  int *pst = (int *) new char[sizeof(pwdStatus_t)];
1568  memcpy(pst,&SessionSt,sizeof(pwdStatus_t));
1569  *pst = htonl(*pst);
1570  if (bmai->AddBucket((char *)pst,sizeof(pwdStatus_t), kXRS_status) != 0) {
1571  PRINT("problems adding bucket kXRS_status");
1572  }
1573  //
1574  // Serialize, encrypt and add to the global list
1575  if (AddSerialized('s', nextstep, hs->ID,
1576  bpar, bmai, kXRS_main, hs->Hcip) != 0)
1577  return ErrS(hs->ID,ei,bpar,bmai,0, kPWErrSerialBuffer,
1578  "main / session cipher",stepstr);
1579  //
1580  // Serialize the global buffer
1581  char *bser = 0;
1582  int nser = bpar->Serialized(&bser,'f');
1583  //
1584  // Dump, if requested
1585  if (QTRACE(Dump)) {
1586  bpar->Dump(ServerStepStr(bpar->GetStep()));
1587  bmai->Dump("Main OUT");
1588  }
1589  //
1590  // Create buffer for client
1591  *parms = new XrdSecParameters(bser,nser);
1592  } else {
1593  //
1594  // Cleanup handshake vars
1595  SafeDelete(hs);
1596  }
1597  //
1598  // We may release the buffers now
1599  REL2(bpar,bmai);
1600  //
1601  // All done
1602  return kS_rc;
1603 }
int kXR_int32
Definition: XPtypes.hh:89
XrdSecBuffer XrdSecParameters
XrdSecBuffer XrdSecCredentials
#define SafeDelete(x)
#define REL2(x, y)
XrdOucString String
#define SafeDelArray(x)
static const short kOptsChngPwd
static const short kOptsExpCred
static const char * ServerStepStr(int ksrv)
static const short kOptsAFSPwd
static const short kOptsCrypPwd
static const short kOptsClntTty
static const char * ClientStepStr(int kclt)
@ kPWErrParseBuffer
@ kPWErrBadOpt
@ kPWErrBadCreds
@ kPWErrSerialBuffer
@ kPWErrNoPublic
@ kPWErrBadProtocol
@ kPWErrLoadCrypto
@ kPWErrBadRndmTag
@ kPWErrDecodeBuffer
@ kPWErrError
@ kPWErrAddBucket
@ kpST_ok
@ kpST_more
@ kpST_error
@ kXPC_failureack
@ kXPC_autoreg
@ kXPC_signedrtag
@ kXPC_normal
@ kXPC_creds
@ kXPC_verifysrv
@ kpCT_afs
@ kpCT_normal
@ kpCT_new
@ kpCT_crypt
@ kpCT_afsenc
@ kXPS_puk
@ kXPS_credsreq
@ kXPS_failure
@ kXPS_none
@ kXPS_signedrtag
@ kXPS_rtag
XrdOucString CryptList
int XrdSutToHex(const char *in, int lin, char *out)
Definition: XrdSutAux.cc:241
@ kXRS_afsinfo
Definition: XrdSutAux.hh:84
@ kXRS_message
Definition: XrdSutAux.hh:68
@ kXRS_puk
Definition: XrdSutAux.hh:61
@ kXRS_status
Definition: XrdSutAux.hh:72
@ kXRS_main
Definition: XrdSutAux.hh:58
@ kXRS_creds
Definition: XrdSutAux.hh:67
@ kPFE_allowed
@ kPFE_disabled
@ kPFE_onetime
@ kPFE_expired
@ kPFE_crypt
const char * tident
Trace identifier always preset.
Definition: XrdSecEntity.hh:81
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
Definition: XrdSecEntity.hh:67
char * name
Entity's name.
Definition: XrdSecEntity.hh:69
kXR_int32 size
Definition: XrdSutBucket.hh:47
void ToString(XrdOucString &s)
int AddBucket(char *bp=0, int sz=0, int ty=0)
Definition: XrdSutBuffer.hh:59
int UpdateBucket(const char *bp, int sz, int ty)
int Serialized(char **buffer, char opt='n')
void Dump(const char *stepstr=0, bool all=false)
int GetStep() const
Definition: XrdSutBuffer.hh:89
XrdSutBucket * GetBucket(kXR_int32 type, const char *tag=0)
const char * GetProtocol() const
Definition: XrdSutBuffer.hh:88
void Deactivate(kXR_int32 type)
int Flush(const char *pfname=0)
kXR_int32 mtime
char * buffer
Pointer to the buffer.
int size
Size of the buffer or length of data in the buffer.

References XrdSutBuffer::AddBucket(), XrdOucString::beginswith(), XrdSecBuffer::buffer, XrdSutBucket::buffer, XrdOucString::c_str(), ClientStepStr(), XrdSutPFEntry::cnt, pwdHSVars::Cref, CryptList, pwdStatus_t::ctype, XrdSutBuffer::Deactivate(), DEBUG, XrdSutBuffer::Dump(), XrdSecProtocol::Entity, EPNAME, pwdHSVars::ErrMsg, XrdSutPFCache::Flush(), XrdSutBuffer::GetBucket(), XrdSutBuffer::GetProtocol(), XrdSutBuffer::GetStep(), pwdHSVars::Hcip, pwdHSVars::ID, kOptsAFSPwd, kOptsChngPwd, kOptsClntTty, kOptsCrypPwd, kOptsExpCred, kpCT_afs, kpCT_afsenc, kpCT_crypt, kpCT_new, kpCT_normal, kPFE_allowed, kPFE_crypt, kPFE_disabled, kPFE_expired, kPFE_onetime, kpST_error, kpST_more, kpST_ok, kPWErrAddBucket, kPWErrBadCreds, kPWErrBadOpt, kPWErrBadProtocol, kPWErrBadRndmTag, kPWErrDecodeBuffer, kPWErrError, kPWErrLoadCrypto, kPWErrNoPublic, kPWErrParseBuffer, kPWErrSerialBuffer, kXPC_autoreg, kXPC_creds, kXPC_failureack, kXPC_normal, kXPC_signedrtag, kXPC_verifysrv, kXPS_credsreq, kXPS_failure, kXPS_none, kXPS_puk, kXPS_rtag, kXPS_signedrtag, kXRS_afsinfo, kXRS_creds, kXRS_main, kXRS_message, kXRS_puk, kXRS_status, XrdOucString::length(), XrdSutPFEntry::mtime, XrdSecEntity::name, XrdSutPFEntry::name, ncrypt, NOTIFY, pwdStatus_t::options, ParseCrypto(), pwdHSVars::Pent, PRINT, XrdSecEntity::prot, QTRACE, REL2, pwdHSVars::RemVers, pwdHSVars::RtagOK, SafeDelArray, SafeDelete, XrdSutBuffer::Serialized(), ServerStepStr(), XrdSecBuffer::size, XrdSutBucket::size, XrdSutPFEntry::status, pwdHSVars::Step, XrdSecEntity::tident, pwdHSVars::TimeStamp, XrdSutBucket::ToString(), pwdHSVars::Tty, XrdSutBuffer::UpdateBucket(), pwdHSVars::User, XrdSysPrivGuard::Valid(), XrdSecPROTOIDENT, XrdSecPROTOIDLEN, and XrdSutToHex().

+ Here is the call graph for this function:

◆ Delete()

void XrdSecProtocolpwd::Delete ( )
virtual

Delete the protocol object. DO NOT use C++ delete() on this object.

Implements XrdSecProtocol.

Definition at line 854 of file XrdSecProtocolpwd.cc.

855 {
856  // Deletes the protocol
857  if (Entity.host) free(Entity.host);
858  // Cleanup the handshake variables, if still there
859  SafeDelete(hs);
860  delete this;
861 }

References XrdSecProtocol::Entity, XrdSecEntity::host, and SafeDelete.

◆ EnableTracing()

XrdOucTrace * XrdSecProtocolpwd::EnableTracing ( )
static

Definition at line 1609 of file XrdSecProtocolpwd.cc.

1610 {
1611  // Initiate error logging and tracing
1612 
1613  eDest.logger(&Logger);
1614  PWDTrace = new XrdOucTrace(&eDest);
1615  return PWDTrace;
1616 }
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:141

References eDest, XrdGlobal::Logger, and XrdSysError::logger().

Referenced by XrdSecProtocolpwdInit().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getCredentials()

XrdSecCredentials * XrdSecProtocolpwd::getCredentials ( XrdSecParameters parm = 0,
XrdOucErrInfo einfo = 0 
)
virtual

Generate client credentials to be used in the authentication process.

Parameters
parmPointer to the information returned by the server either in the initial login response or the authmore response.
einfoThe error information object where error messages should be placed. The messages are returned to the client. Should einfo be null, messages should be written to stderr.
Returns
Success: Pointer to credentials to sent to the server. The caller is responsible for deleting the object. Failure: Null pointer with einfo, if supplied, containing the reason for the failure.

Implements XrdSecProtocol.

Definition at line 870 of file XrdSecProtocolpwd.cc.

872 {
873  // Query client for the password; remote username and host
874  // are specified in 'parm'. File '.rootnetrc' is checked.
875  EPNAME("getCredentials");
876 
877  // If we are a server the only reason to be here is to get the forwarded
878  // or saved client credentials
879  if (srvMode) {
880  XrdSecCredentials *creds = 0;
881  if (clientCreds) {
882  // Duplicate the buffer (otherwise it will get deleted ...)
883  int sz = clientCreds->size;
884  char *nbuf = (char *) malloc(sz);
885  if (nbuf) {
886  memcpy(nbuf, clientCreds->buffer, sz);
887  creds = new XrdSecCredentials(nbuf, sz);
888  }
889  }
890  return creds;
891  }
892 
893  // Handshake vars conatiner must be initialized at this point
894  if (!hs)
895  return ErrC(ei,0,0,0,kPWErrError,
896  "handshake var container missing","getCredentials");
897  hs->ErrMsg = "";
898 
899  //
900  // Nothing to do if buffer is empty and not filled during construction
901  if ((!parm && !hs->Parms) || (parm && (!(parm->buffer) || parm->size <= 0)))
902  return ErrC(ei,0,0,0,kPWErrNoBuffer,"missing parameters","getCredentials");
903 
904  // Count interations
905  (hs->Iter)++;
906 
907  // Update time stamp
908  hs->TimeStamp = time(0);
909 
910  // Local vars
911  int nextstep = 0;
912  const char *stepstr = 0;
913  kXR_int32 status = 0;
914  char *bpub = 0;
915  int lpub = 0;
916  String CryptList = "";
917  String Host = "";
918  String RemID = "";
919  String Emsg;
920  String specID = "";
921  // Buffer / Bucket related
922  XrdSutBucket *bck = 0;
923  XrdSutBuffer *bpar = 0; // Global buffer
924  XrdSutBuffer *bmai = 0; // Main buffer
925  // Session status
926  pwdStatus_t SessionSt;
927  memset(&SessionSt,0,sizeof(SessionSt));
928 
929  //
930  // Unlocks automatically returning
931  XrdSysMutexHelper pwdGuard(&pwdContext);
932  //
933  // Decode received buffer
934  bpar = hs->Parms;
935  if (!bpar && !(bpar = new XrdSutBuffer((const char *)parm->buffer,parm->size)))
936  return ErrC(ei,0,0,0,kPWErrDecodeBuffer,"global",stepstr);
937  // Ownership has been transferred
938  hs->Parms = 0;
939  //
940  // Check protocol ID name
941  if (strcmp(bpar->GetProtocol(),XrdSecPROTOIDENT))
942  return ErrC(ei,bpar,bmai,0,kPWErrBadProtocol,stepstr);
943  //
944  // The step indicates what we are supposed to do
945  hs->Step = (bpar->GetStep()) ? bpar->GetStep() : kXPS_init;
946  stepstr = ServerStepStr(hs->Step);
947  // Dump, if requested
948  if (QTRACE(Dump)) {
949  bpar->Dump(stepstr);
950  }
951  //
952  // Find first crypto module to be used
953  if (ParseCrypto(bpar) != 0)
954  return ErrC(ei,bpar,0,0,kPWErrLoadCrypto,stepstr);
955  //
956  // Parse input buffer
957  if (ParseClientInput(bpar, &bmai, Emsg) == -1) {
958  PRINT(Emsg);
959  return ErrC(ei,bpar,bmai,0,kPWErrParseBuffer,Emsg.c_str(),stepstr);
960  }
961  //
962  // Version
963  DEBUG("version run by server: "<< hs->RemVers);
964  //
965  // Dump what we got
966  if (QTRACE(Dump)) {
967  bmai->Dump("Main IN");
968  }
969  //
970  // Print server messages, if any
971  if (hs->Iter > 1) {
972  bmai->Message();
973  bmai->Deactivate(kXRS_message);
974  }
975  //
976  // Check random challenge
977  if (!CheckRtag(bmai, Emsg))
978  return ErrC(ei,bpar,bmai,0,kPWErrBadRndmTag,Emsg.c_str(),stepstr);
979 
980  //
981  // Get the status bucket, if any
982  if ((bck = bmai->GetBucket(kXRS_status))) {
983  int pst = 0;
984  memcpy(&pst,bck->buffer,sizeof(pwdStatus_t));
985  pst = ntohl(pst);
986  memcpy(&SessionSt, &pst, sizeof(pwdStatus_t));
987  bmai->Deactivate(kXRS_status);
988  } else {
989  SessionSt.ctype = kpCT_normal;
990  }
991  //
992  // Now action depens on the step
993  nextstep = kXPC_none;
994  switch (hs->Step) {
995 
996  case kXPS_init: // The following 3 cases may fall through
997  case kXPS_puk:
998  case kXPS_signedrtag: // (after kXRC_verifysrv)
999 if (hs->Step == kXPS_init)
1000  {
1001  //
1002  // Add bucket with cryptomod to the global list
1003  // (This must be always visible from now on)
1004  if (bpar->AddBucket(hs->CryptoMod,kXRS_cryptomod) != 0)
1005  return ErrC(ei,bpar,bmai,0,
1007  //
1008  // Add bucket with our version to the main list
1009  if (bmai->MarshalBucket(kXRS_version,(kXR_int32)(Version)) != 0)
1010  return ErrC(ei,bpar,bmai,0, kPWErrCreateBucket,
1011  XrdSutBuckStr(kXRS_version),"(main list)",stepstr);
1012  //
1013  // We set some options in the option field of a pwdStatus_t structure
1014  if (hs->Tty || (AutoLogin > 0))
1015  SessionSt.options = kOptsClntTty;
1016  }
1017 // case kXPS_puk:
1018 if ((hs->Step == kXPS_init) || (hs->Step == kXPS_puk))
1019  {
1020  // After auto-reg request, server puk have been saved in ParseClientInput:
1021  // we need to start a full normal login now
1022 
1023  //
1024  // If we have a session cipher we extract the public part
1025  // and add to the main packet for transmission to server
1026  if (hs->Hcip) {
1027  //
1028  // Extract buffer with public info for the cipher agreement
1029  if (!(bpub = hs->Hcip->Public(lpub)))
1030  return ErrC(ei,bpar,bmai,0,
1031  kPWErrNoPublic,"session",stepstr);
1032  //
1033  // Add it to the global list
1034  if (bpar->UpdateBucket(bpub,lpub,kXRS_puk) != 0)
1035  return ErrC(ei,bpar,bmai,0, kPWErrAddBucket,
1036  XrdSutBuckStr(kXRS_puk),"global",stepstr);
1037  SafeDelArray(bpub);
1038  //
1039  // If we are requiring server verification of puk ownership
1040  // we are done for this step
1041  if (VeriSrv == 1) {
1042  nextstep = kXPC_verifysrv;
1043  break;
1044  }
1045  }
1046  }
1047 // case kXPS_signedrtag: // (after kXRC_verifysrv)
1048  //
1049  // Add the username
1050  if (hs->User.length()) {
1051  if (bmai->AddBucket(hs->User,kXRS_user) != 0)
1052  return ErrC(ei,bpar,bmai,0, kPWErrDuplicateBucket,
1053  XrdSutBuckStr(kXRS_user),stepstr);
1054  } else
1055  return ErrC(ei,bpar,bmai,0, kPWErrNoUser,stepstr);
1056 
1057  //
1058  // If we do not have a session cipher, the only thing we can
1059  // try is auto-registration
1060  if (!(hs->Hcip)) {
1061  nextstep = kXPC_autoreg;
1062  break;
1063  }
1064 
1065  //
1066  // Normal attempt: add credentials
1067  status = kpCT_normal;
1068  if (hs->SysPwd == 1)
1069  status = kpCT_crypt;
1070  if (hs->SysPwd == 2)
1071  status = kpCT_afs;
1072  if (!(bck = QueryCreds(bmai, (AutoLogin > 0), status)))
1073  return ErrC(ei,bpar,bmai,0, kPWErrQueryCreds,
1074  hs->Tag.c_str(),stepstr);
1075  bmai->AddBucket(bck);
1076  //
1077  // Tell the server we want to change the password, if so
1078  if (hs->Pent->status == kPFE_onetime)
1079  SessionSt.options |= kOptsChngPwd;
1080  //
1081  nextstep = kXPC_normal;
1082  break;
1083 
1084  case kXPS_credsreq:
1085  //
1086  // If this is not the first time, during the handshake, that
1087  // we query credentials, any save buffer must insufficient,
1088  // so invalidate it
1089  if (hs->Pent)
1090  hs->Pent->cnt = 1;
1091  //
1092  // Server requires additional credentials: the status bucket
1093  // tells us what she wants exactly
1094  status = SessionSt.ctype;
1095  if (!(bck = QueryCreds(bmai, 0, status)))
1096  return ErrC(ei,bpar,bmai,0, kPWErrQueryCreds,
1097  hs->Tag.c_str(),stepstr);
1098  bmai->AddBucket(bck);
1099  //
1100  nextstep = kXPC_creds;
1101  break;
1102 
1103  case kXPS_failure:
1104  //
1105  // Failure: invalidate cache
1106  hs->Pent->buf1.SetBuf();
1107  hs->Pent->buf2.SetBuf();
1108  //
1109  nextstep = kXPC_failureack;
1110  break;
1111 
1112  case kXPS_newpuk:
1113  //
1114  // New server puk have been saved in ParseClientInput: we
1115  // just need to sign the random tag
1116  case kXPS_rtag:
1117  //
1118  // Not much to do: the random tag is signed in AddSerialized
1119  nextstep = kXPC_signedrtag;
1120  break;
1121 
1122  default:
1123  return ErrC(ei,bpar,bmai,0, kPWErrBadOpt,stepstr);
1124  }
1125  //
1126  // Add / Update status
1127  int *pst = (int *) new char[sizeof(pwdStatus_t)];
1128  memcpy(pst,&SessionSt,sizeof(pwdStatus_t));
1129  *pst = htonl(*pst);
1130  if (bmai->AddBucket((char *)pst,sizeof(pwdStatus_t), kXRS_status) != 0) {
1131  PRINT("problems adding bucket kXRS_status");
1132  }
1133  //
1134  // Serialize and encrypt
1135  if (AddSerialized('c', nextstep, hs->ID,
1136  bpar, bmai, kXRS_main, hs->Hcip) != 0)
1137  return ErrC(ei,bpar,bmai,0,
1138  kPWErrSerialBuffer,"main",stepstr);
1139  //
1140  // Serialize the global buffer
1141  char *bser = 0;
1142  int nser = bpar->Serialized(&bser,'f');
1143 
1144  if (QTRACE(Dump)) {
1145  bpar->Dump(ClientStepStr(bpar->GetStep()));
1146  bmai->Dump("Main OUT");
1147  }
1148  //
1149  // We may release the buffers now
1150  REL2(bpar,bmai);
1151  //
1152  // Return serialized buffer
1153  if (nser > 0) {
1154  DEBUG("returned " << nser <<" bytes of credentials");
1155  return new XrdSecCredentials(bser, nser);
1156  } else {
1157  DEBUG("problems with final serialization");
1158  return (XrdSecCredentials *)0;
1159  }
1160 }
@ kPWErrNoBuffer
@ kPWErrQueryCreds
@ kPWErrDuplicateBucket
@ kPWErrNoUser
@ kPWErrCreateBucket
@ kXPC_none
@ kXPS_init
@ kXPS_newpuk
const char * XrdSutBuckStr(int kbck)
Definition: XrdSutAux.cc:121
@ kXRS_user
Definition: XrdSutAux.hh:65
@ kXRS_version
Definition: XrdSutAux.hh:71
@ kXRS_cryptomod
Definition: XrdSutAux.hh:57
virtual char * Public(int &lpub)
void Message(const char *prepose=0)
kXR_int32 MarshalBucket(kXR_int32 type, kXR_int32 code)
void SetBuf(const char *b=0, kXR_int32 l=0)
XrdSutPFBuf buf1
XrdSutPFBuf buf2
Generic structure to pass security information back and forth.

References XrdSutBuffer::AddBucket(), XrdSutPFEntry::buf1, XrdSutPFEntry::buf2, XrdSecBuffer::buffer, XrdSutBucket::buffer, XrdOucString::c_str(), ClientStepStr(), XrdSutPFEntry::cnt, CryptList, pwdHSVars::CryptoMod, pwdStatus_t::ctype, XrdSutBuffer::Deactivate(), DEBUG, XrdSutBuffer::Dump(), EPNAME, pwdHSVars::ErrMsg, XrdSutBuffer::GetBucket(), XrdSutBuffer::GetProtocol(), XrdSutBuffer::GetStep(), pwdHSVars::Hcip, pwdHSVars::ID, pwdHSVars::Iter, kOptsChngPwd, kOptsClntTty, kpCT_afs, kpCT_crypt, kpCT_normal, kPFE_onetime, kPWErrAddBucket, kPWErrBadOpt, kPWErrBadProtocol, kPWErrBadRndmTag, kPWErrCreateBucket, kPWErrDecodeBuffer, kPWErrDuplicateBucket, kPWErrError, kPWErrLoadCrypto, kPWErrNoBuffer, kPWErrNoPublic, kPWErrNoUser, kPWErrParseBuffer, kPWErrQueryCreds, kPWErrSerialBuffer, kXPC_autoreg, kXPC_creds, kXPC_failureack, kXPC_none, kXPC_normal, kXPC_signedrtag, kXPC_verifysrv, kXPS_credsreq, kXPS_failure, kXPS_init, kXPS_newpuk, kXPS_puk, kXPS_rtag, kXPS_signedrtag, kXRS_cryptomod, kXRS_main, kXRS_message, kXRS_puk, kXRS_status, kXRS_user, kXRS_version, XrdOucString::length(), XrdSutBuffer::MarshalBucket(), XrdSutBuffer::Message(), pwdStatus_t::options, pwdHSVars::Parms, ParseCrypto(), pwdHSVars::Pent, PRINT, XrdCryptoCipher::Public(), QTRACE, REL2, pwdHSVars::RemVers, SafeDelArray, XrdSutBuffer::Serialized(), ServerStepStr(), XrdSutPFBuf::SetBuf(), XrdSecBuffer::size, XrdSutPFEntry::status, pwdHSVars::Step, pwdHSVars::SysPwd, pwdHSVars::Tag, pwdHSVars::TimeStamp, pwdHSVars::Tty, XrdSutBuffer::UpdateBucket(), pwdHSVars::User, Version, XrdSecPROTOIDENT, and XrdSutBuckStr().

+ Here is the call graph for this function:

◆ Init()

char * XrdSecProtocolpwd::Init ( pwdOptions  o,
XrdOucErrInfo erp 
)
static

Definition at line 341 of file XrdSecProtocolpwd.cc.

342 {
343  // Static method to the configure the static part of the protocol
344  // Called once by XrdSecProtocolpwdInit
345  EPNAME("Init");
346  XrdSutPFCacheRef pfeRef;
347  char *Parms = 0;
348  //
349  // Debug an tracing
350  Debug = (opt.debug > -1) ? opt.debug : Debug;
351 
352  // We must have the tracing object at this point
353  // (initialized in XrdSecProtocolgsiInit)
354  if (!pwdTrace) {
355  ErrF(erp,kPWErrInit,"tracing object (pwdTrace) not initialized! cannot continue");
356  return Parms;
357  }
358 
359  // Set debug mask ... also for auxilliary libs
360  int trace = 0, traceSut = 0, traceCrypto = 0;
361  if (Debug >= 3) {
362  trace = cryptoTRACE_Dump;
363  traceSut = sutTRACE_Dump;
364  traceCrypto = cryptoTRACE_Dump;
365  PWDTrace->What = TRACE_ALL;
366  } else if (Debug >= 2) {
367  trace = cryptoTRACE_Debug;
368  traceSut = sutTRACE_Debug;
369  traceCrypto = cryptoTRACE_Debug;
370  PWDTrace->What = TRACE_Debug;
371  PWDTrace->What |= TRACE_Authen;
372  } else if (Debug >= 1) {
373  trace = cryptoTRACE_Debug;
374  traceSut = sutTRACE_Notify;
375  traceCrypto = cryptoTRACE_Notify;
376  PWDTrace->What = TRACE_Debug;
377  }
378 
379  // ... also for auxilliary libs
380  XrdSutSetTrace(traceSut);
381  XrdCryptoSetTrace(traceCrypto);
382 
383  // Get user info
384  struct passwd *pw;
385  XrdSysPwd thePwd(getuid(), &pw);
386 
387  if (!pw) {
388  PRINT("no user info available - invalid ");
389  ErrF(erp, kPWErrInit, "could not get user info from pwuid");
390  return Parms;
391  }
392 
393  //
394  // Operation mode
395  Server = (opt.mode == 's');
396 
397  //
398  // Directory with admin pwd files
399  bool argdir = 0;
400  String infodir(512);
401  if (opt.dir) {
402  infodir = opt.dir;
403  // Expand
404  if (XrdSutExpand(infodir) != 0) {
405  PRINT("cannot expand "<<opt.dir);
406  infodir = "";
407  }
408  argdir = 1;
409  } else {
410  // use default dir $(HOME)/.<prefix>
411  infodir = XrdSutHome();
412  infodir += ("/." + Prefix);
413  }
414  if (!infodir.endswith("/")) infodir += "/";
415  //
416  // If defined, check existence of the infodir and admin file
417  if (infodir.length()) {
418  // Acquire the privileges, if needed
419  XrdSysPrivGuard priv(pw->pw_uid, pw->pw_gid);
420  if (priv.Valid()) {
421  struct stat st;
422  if (stat(infodir.c_str(),&st) == -1) {
423  if (errno == ENOENT) {
424  if (argdir) {
425  DEBUG("infodir non existing: "<<infodir.c_str());
426  } else {
427  DEBUG("creating infodir: "<<infodir.c_str());
428  if (XrdSutMkdir(infodir.c_str(),0777) != 0) {
429  DEBUG("cannot create infodir (errno: "<<errno<<")");
430  infodir = "";
431  argdir = 0;
432  }
433  }
434  } else {
435  DEBUG("cannot stat infodir "<<infodir<<" (errno: "<<errno<<")");
436  infodir = "";
437  argdir = 0;
438  }
439  }
440  }
441  }
442  DEBUG("using infodir: "<<infodir.c_str());
443 
444  //
445  // Server specific options
446  if (Server) {
447  //
448  // Auto registration
449  AutoReg = (opt.areg > -1) ? opt.areg : AutoReg;
450  //
451  // Client verification level
452  VeriClnt = (opt.vericlnt > -1) ? opt.vericlnt : VeriClnt;
453  //
454  // Whether to check pwd files in users' $HOME
455  UserPwd = (opt.upwd > -1) ? opt.upwd : UserPwd;
456  //
457  // Whether to check system pwd files (if allowed)
458  SysPwd = (opt.syspwd > -1) ? opt.syspwd : SysPwd;
459  if (SysPwd) {
460  // Make sure this setting makes sense
461  if (pw) {
462 #ifdef HAVE_SHADOWPW
463  // Acquire the privileges, if needed
464  XrdSysPrivGuard priv((uid_t) 0, (gid_t) 0);
465  if (priv.Valid()) {
466  // System V Rel 4 style shadow passwords
467  struct spwd *spw = getspnam(pw->pw_name);
468  if (!spw) {
469  SysPwd = 0;
470  DEBUG("no privileges to access shadow passwd file");
471  }
472  } else {
473  DEBUG("problems acquiring credentials"
474  " to access the system password file");
475  }
476 #else
477  // Normal passwd file
478  if (!pw->pw_passwd &&
479  (pw->pw_passwd && strlen(pw->pw_passwd) <= 1)) {
480  SysPwd = 0;
481  DEBUG("no privileges to access system passwd file");
482  }
483 #endif
484  } else
485  SysPwd = 0;
486  }
487  //
488  // Credential lifetime
489  LifeCreds = (opt.lifecreds > -1) ? opt.lifecreds : LifeCreds;
490  //
491  // Max number of failures
492  MaxFailures = (opt.maxfailures > -1) ? opt.maxfailures : MaxFailures;
493 
494  //
495  // If defined, check existence of the infodir and admin file
496  if (infodir.length()) {
497  // Acquire the privileges, if needed
498  XrdSysPrivGuard priv(pw->pw_uid, pw->pw_gid);
499  if (priv.Valid()) {
500  struct stat st;
501  //
502  // Define admin file and check its existence
503  FileAdmin = infodir + AdminRef;
504  if (stat(FileAdmin.c_str(),&st) == -1) {
505  if (errno == ENOENT) {
506  PRINT("FileAdmin non existing: "<<FileAdmin.c_str());
507  } else {
508  PRINT("cannot stat FileAdmin (errno: "<<errno<<")");
509  }
510  FileAdmin = "";
511  if (UserPwd == 0 && !SysPwd) {
512  PRINT("no passwd info available - invalid ");
513  ErrF(erp,kPWErrInit,"could not find a valid password file");
514  return Parms;
515  }
516  }
517  if (FileAdmin.length() > 0) {
518  //
519  // Load server ID
520  PFAdmin.Init(FileAdmin.c_str(),0);
521  if (PFAdmin.IsValid()) {
522  //
523  // Init cache for admin file
524  if (cacheAdmin.Load(FileAdmin.c_str()) != 0) {
525  PRINT("problems init cache for file admin ");
526  ErrF(erp,kPWErrError,"initializing cache for file admin");
527  return Parms;
528  }
529  if (QTRACE(Authen)) { cacheAdmin.Dump(); }
530  XrdSutPFEntry *ent = cacheAdmin.Get(pfeRef, "+++SrvID");
531  if (ent)
532  {SrvID.insert(ent->buf1.buf, 0, ent->buf1.len);
533  pfeRef.UnLock();
534  }
535  ent = cacheAdmin.Get(pfeRef, "+++SrvEmail");
536  if (ent)
537  SrvEmail.insert(ent->buf1.buf, 0, ent->buf1.len);
538  // Default error message
539  DefError += SrvEmail;
540  pfeRef.UnLock();
541  }
542  DEBUG("server ID: "<<SrvID);
543  DEBUG("contact e-mail: "<<SrvEmail);
544  }
545  }
546  } else if (UserPwd == 0 && !SysPwd) {
547  PRINT("no passwd info available - invalid ");
548  ErrF(erp,kPWErrError,"could not find a valid password file");
549  return Parms;
550  }
551  //
552  // Init cache for user pwd information
553  if (UserPwd > 0 || SysPwd) {
554  if (cacheUser.Init(100) != 0) {
555  PRINT("problems init cache for user pwd info"
556  " - passwd files in user accounts will not be used");
557  UserPwd = 0;
558  }
559  }
560 
561  //
562  // List of crypto modules
563  String cryptlist = opt.clist ? (const char *)(opt.clist) : DefCrypto;
564 
565  //
566  // Load crypto modules
567  XrdSutPFEntry ent;
568  XrdCryptoFactory *cf = 0;
569  String clist = cryptlist;
570  if (clist.length()) {
571  String ncpt = "";
572  int from = 0;
573  while ((from = clist.tokenize(ncpt, from, '|')) != -1) {
574  if (ncpt.length() > 0) {
575  // Try loading
576  if ((cf = XrdCryptoFactory::GetCryptoFactory(ncpt.c_str()))) {
577  // Add it to the list
578  cryptID[ncrypt] = cf->ID();
579  cryptName[ncrypt].insert(cf->Name(),0,strlen(cf->Name())+1);
580  cf->SetTrace(trace);
581  // Ref cipher
582  String ptag("+++SrvPuk_");
583  ptag += cf->ID();
584  if (FileAdmin.length() > 0) {
585  // Acquire the privileges, if needed
586  XrdSysPrivGuard priv(pw->pw_uid, pw->pw_gid);
587  if (priv.Valid()) {
588  if (PFAdmin.ReadEntry(ptag.c_str(),ent) <= 0) {
589  PRINT("ref cipher for module "<<ncpt<<" missing: disable");
590  cryptlist.erase(ncpt);
591  } else {
592  XrdSutBucket bck;
593  bck.SetBuf(ent.buf1.buf,ent.buf1.len);
594  if (!(refcip[ncrypt] = cf->Cipher(&bck))) {
595  PRINT("ref cipher for module "<<ncpt<<
596  " cannot be instantiated : disable");
597  cryptlist.erase(ncpt);
598  } else {
599  ncrypt++;
600  if (ncrypt >= XrdCryptoMax) {
601  PRINT("max number of crypto modules ("
602  << XrdCryptoMax <<") reached ");
603  break;
604  }
605  }
606  }
607  }
608  }
609  } else {
610  PRINT("cannot instantiate crypto factory "<<ncpt);
611  }
612  }
613  }
614  }
615 
616  //
617  // We need at least one valid crypto module
618  if (ncrypt <= 0) {
619  PRINT("could not find any valid crypto module");
620  ErrF(erp,kPWErrInit,"could not find any valid crypto module");
621  return Parms;
622  }
623 
624  //
625  // users' pwd information
626  if (UserPwd > 0) {
627  FileUser = ("/" + UserRef);
628  if (opt.udir) {
629  FileUser.insert(opt.udir,0);
630  if (FileUser[0] != '/') FileUser.insert('/',0);
631  } else {
632  // Use default $(HOME)/.<Prefix>
633  FileUser.insert(Prefix,0);
634  FileUser.insert("/.",0);
635  }
636  //
637  // Crypt-hash file name, if requested
638  if (opt.cpass) {
639  UserPwd = 2;
640  FileCrypt = opt.cpass;
641  if (FileCrypt[0] != '/') FileCrypt.insert('/',0);
642  }
643  }
644 
645  //
646  // Whether to save client creds
647  KeepCreds = (opt.keepcreds > -1) ? opt.keepcreds : KeepCreds;
648  if (KeepCreds > 0)
649  NOTIFY("Exporting client creds to internal buffer");
650 
651  //
652  // Whether to export client creds to a file
653  FileExpCreds = (opt.expcreds) ? opt.expcreds : FileExpCreds;
654  if (FileExpCreds.length() > 0) {
655  // Export format
656  FmtExpCreds = opt.expfmt;
657  const char *efmts[4] = {"PFile", "hex", "raw", "raw/nokeyword"};
658  NOTIFY("Exporting client creds (fmt:"<<efmts[FmtExpCreds]<<") to files "<<FileExpCreds);
659  }
660 
661  //
662  // Priority option field
663  String popt = "";
664  if (SysPwd) {
665  popt += "sys";
666  }
667 
668  //
669  // Parms in the form: &P=pwd,c:<cryptomod>,v:<version>,id:<srvid>
670  Parms = new char[cryptlist.length()+3+12+SrvID.length()+5+popt.length()+3];
671  if (Parms) {
672  if (popt.length() > 0)
673  sprintf(Parms,"v:%d,id:%s,c:%s,po:%s",
674  Version,SrvID.c_str(),cryptlist.c_str(),popt.c_str());
675  else
676  sprintf(Parms,"v:%d,id:%s,c:%s",
677  Version,SrvID.c_str(),cryptlist.c_str());
678  } else {
679  PRINT("no system resources for 'Parms'");
680  ErrF(erp,kPWErrInit,"no system resources for 'Parms'");
681  }
682 
683  // Some notification
684  NOTIFY("using FileAdmin: "<<FileAdmin);
685  NOTIFY("server ID: "<<SrvID);
686  NOTIFY("contact e-mail: "<<SrvEmail);
687  NOTIFY("auto-registration mode: "<<AutoReg);
688  NOTIFY("verify client mode: "<<VeriClnt);
689  NOTIFY("available crypto modules: "<<cryptlist);
690  if (UserPwd > 0) {
691  NOTIFY("using private pwd files: $(HOME)"<<FileUser);
692  if (UserPwd > 1) {
693  NOTIFY("using private crypt-hash files: $(HOME)"<<FileCrypt);
694  }
695  }
696  if (SysPwd) {
697  NOTIFY("using system pwd information");
698  }
699  if (KeepCreds) {
700  NOTIFY("client credentials will be kept");
701  }
702  }
703 
704  //
705  // Client specific options
706  if (!Server) {
707  //
708  // Server verification level
709  VeriSrv = (opt.verisrv > -1) ? opt.verisrv : VeriSrv;
710  //
711  // Server puks file
712  FileSrvPuk = "";
713  if (opt.srvpuk) {
714  FileSrvPuk = opt.srvpuk;
715  if (XrdSutExpand(FileSrvPuk) != 0) {
716  PRINT("cannot expand "<<opt.srvpuk);
717  FileSrvPuk = "";
718  }
719  }
720  //
721  // If not defined, use default
722  if (FileSrvPuk.length() <= 0 && infodir.length() > 0)
723  FileSrvPuk = infodir + SrvPukRef;
724 
725  if (FileSrvPuk.length() > 0) {
726  kXR_int32 openmode = 0;
727  struct stat st;
728  //
729  if (stat(FileSrvPuk.c_str(),&st) == -1) {
730  if (errno == ENOENT) {
731  PRINT("server public key file "<<FileSrvPuk<<" non existing: creating");
732  openmode = kPFEcreate;
733  // Make sure that the dir path exists
734  XrdOucString dir = FileSrvPuk;
735  dir.erase(dir.rfind('/')+1);
736  DEBUG("asserting dir: "<<dir);
737  if (XrdSutMkdir(dir.c_str(),0777) != 0) {
738  PRINT("cannot create dir for srvpuk(errno: "<<errno<<")");
739  ErrF(erp,kPWErrInit,"cannot create dir for server public key file- exit");
740  return Parms;
741  }
742  } else {
743  PRINT("cannot stat server public key file (errno: "<<errno<<")");
744  FileSrvPuk = "";
745  PRINT("server public key file invalid - exit");
746  ErrF(erp,kPWErrInit,"server public key file invalid - exit");
747  return Parms;
748  }
749  }
750  //
751  // Load server ID
752  PFSrvPuk.Init(FileSrvPuk.c_str(),openmode);
753  if (PFSrvPuk.IsValid()) {
754  //
755  // Init cache for server puk file
756  if (cacheSrvPuk.Load(FileSrvPuk.c_str()) != 0) {
757  PRINT("problems init cache for server public key file ");
758  ErrF(erp,kPWErrError,"initializing cache for server public key file ");
759  return Parms;
760  }
761  if (QTRACE(Authen)) { cacheSrvPuk.Dump(); }
762  } else {
763  PRINT("server public key file invalid ");
764  ErrF(erp,kPWErrInit,"server public key file invalid");
765  return Parms;
766  }
767  } else {
768  PRINT("server public key file undefined");
769  ErrF(erp,kPWErrInit,"server public key file undefined");
770  return Parms;
771  }
772 
773  //
774  // Whether to search for autologin information
775  AutoLogin = (opt.alog > -1) ? opt.alog : AutoLogin;
776  NOTIFY("AutoLogin level: "<<AutoLogin);
777  //
778  // Max number of re-prompts (for inconsistent inputs)
779  MaxPrompts = (opt.maxprompts > -1) ? opt.maxprompts : MaxPrompts;
780  //
781  // Attach autologin file name, if requested
782  if (AutoLogin > 0) {
783  bool filefound = 0;
784  String fnrc(256);
785  if (opt.alogfile) {
786  fnrc = opt.alogfile;
787  if (XrdSutExpand(fnrc) != 0) {
788  PRINT("cannot expand "<<opt.alogfile);
789  fnrc = "";
790  }
791  }
792  //
793  // If file name not specified ...
794  if (fnrc.length() <= 0)
795  // use default
796  fnrc = infodir + NetRcRef;
797 
798  if (fnrc.length() > 0) {
799  kXR_int32 openmode = 0;
800  struct stat st;
801  if (stat(fnrc.c_str(),&st) == -1) {
802  if (errno == ENOENT) {
803  PRINT("Autologin file "<<fnrc<<" non existing: creating");
804  openmode = kPFEcreate;
805  } else {
806  PRINT("cannot stat autologin file (errno: "<<errno<<")");
807  PRINT("switching off auto-login");
808  AutoLogin = 0;
809  }
810  }
811 
812  if (AutoLogin > 0) {
813  // Attach to file
814  PFAlog.Init(fnrc.c_str(),openmode);
815  if (PFAlog.IsValid()) {
816  // Init cache for autologin file
817  if (cacheAlog.Load(fnrc.c_str()) == 0) {
818  if (QTRACE(Authen)) { cacheAlog.Dump(); }
819  filefound =1;
820  } else {
821  PRINT("problems init cache for autologin file");
822  }
823  } else {
824  PRINT("problems attaching-to / creating autologin file");
825  }
826  }
827  }
828  //
829  // Notify if not found
830  if (!filefound) {
831  NOTIFY("could not init properly autologin - switch off ");
832  AutoLogin = 0;
833  }
834  }
835  //
836  // Notify if not found
837  if (AutoLogin <= 0) {
838  // Init anyhow cache to cache information during session
839  if (cacheAlog.Init(100) != 0) {
840  PRINT("problems init cache for user temporary autolog");
841  }
842  }
843  // We are done
844  Parms = (char *)"";
845  }
846 
847  // We are done
848  return Parms;
849 }
#define TRACE_Debug
Definition: XrdCmsTrace.hh:37
void XrdCryptoSetTrace(kXR_int32 trace)
Definition: XrdCryptoAux.cc:49
#define cryptoTRACE_Notify
Definition: XrdCryptoAux.hh:49
#define cryptoTRACE_Dump
Definition: XrdCryptoAux.hh:47
#define cryptoTRACE_Debug
Definition: XrdCryptoAux.hh:48
int stat(const char *path, struct stat *buf)
#define XrdCryptoMax
static String NetRcRef
XrdOucTrace * pwdTrace
static String SrvPukRef
static String UserRef
static String Prefix
static String AdminRef
@ kPWErrInit
#define TRACE_Authen
Definition: XrdSecTrace.hh:62
int ncrypt
XrdOucString DefCrypto
XrdOucString SrvID
int XrdSutExpand(XrdOucString &path)
Definition: XrdSutAux.cc:366
const char * XrdSutHome()
Definition: XrdSutAux.cc:465
int XrdSutMkdir(const char *dir, unsigned int mode, const char *opt)
Definition: XrdSutAux.cc:493
void XrdSutSetTrace(kXR_int32 trace)
Definition: XrdSutAux.cc:93
#define sutTRACE_Notify
Definition: XrdSutAux.hh:100
#define sutTRACE_Debug
Definition: XrdSutAux.hh:99
#define sutTRACE_Dump
Definition: XrdSutAux.hh:98
#define kPFEcreate
Definition: XrdSutPFile.hh:59
if(Avsz)
#define TRACE_ALL
Definition: XrdTrace.hh:35
virtual void SetTrace(kXR_int32 trace)
char * Name() const
virtual XrdCryptoCipher * Cipher(const char *t, int l=0)
static XrdCryptoFactory * GetCryptoFactory(const char *factoryname)
int erase(int start=0, int size=0)
int rfind(const char c, int start=STR_NPOS)
int tokenize(XrdOucString &tok, int from, char del=':')
int SetBuf(const char *nb=0, int ns=0)
kXR_int32 len
int Init(int capacity=100, bool lock=1)
void Dump(const char *msg=0)
int Load(const char *pfname)
bool IsValid() const
Definition: XrdSutPFile.hh:170
kXR_int32 ReadEntry(const char *name, XrdSutPFEntry &ent, int opt=0)
Definition: XrdSutPFile.cc:909
bool Init(const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
Definition: XrdSutPFile.cc:236

References AdminRef, pwdOptions::alog, pwdOptions::alogfile, pwdOptions::areg, XrdSutPFBuf::buf, XrdSutPFEntry::buf1, XrdOucString::c_str(), XrdCryptoFactory::Cipher(), pwdOptions::clist, pwdOptions::cpass, cryptoTRACE_Debug, cryptoTRACE_Dump, cryptoTRACE_Notify, DEBUG, pwdOptions::debug, DefCrypto, pwdOptions::dir, XrdSutPFCache::Dump(), XrdOucString::endswith(), EPNAME, XrdOucString::erase(), pwdOptions::expcreds, pwdOptions::expfmt, XrdCryptoFactory::GetCryptoFactory(), XrdCryptoFactory::ID(), if(), XrdSutPFile::Init(), XrdSutPFCache::Init(), XrdOucString::insert(), XrdSutPFile::IsValid(), pwdOptions::keepcreds, kPFEcreate, kPWErrError, kPWErrInit, XrdSutPFBuf::len, XrdOucString::length(), pwdOptions::lifecreds, XrdSutPFCache::Load(), pwdOptions::maxfailures, pwdOptions::maxprompts, pwdOptions::mode, XrdCryptoFactory::Name(), ncrypt, NetRcRef, NOTIFY, Prefix, PRINT, pwdTrace, QTRACE, XrdSutPFile::ReadEntry(), XrdOucString::rfind(), XrdSutBucket::SetBuf(), XrdCryptoFactory::SetTrace(), SrvID, pwdOptions::srvpuk, SrvPukRef, stat(), sutTRACE_Debug, sutTRACE_Dump, sutTRACE_Notify, pwdOptions::syspwd, XrdOucString::tokenize(), TRACE_ALL, TRACE_Authen, TRACE_Debug, pwdOptions::udir, XrdSutPFCacheRef::UnLock(), pwdOptions::upwd, UserRef, XrdSysPrivGuard::Valid(), pwdOptions::vericlnt, pwdOptions::verisrv, Version, XrdOucTrace::What, XrdCryptoMax, XrdCryptoSetTrace(), XrdSutExpand(), XrdSutHome(), XrdSutMkdir(), and XrdSutSetTrace().

Referenced by XrdSecProtocolpwdInit().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PrintTimeStat()

static void XrdSecProtocolpwd::PrintTimeStat ( )
static

The documentation for this class was generated from the following files: