00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdCmsLoginCVSID = "$Id: XrdCmsLogin.cc 38011 2011-02-08 18:35:57Z ganis $";
00014
00015 #include <netinet/in.h>
00016
00017 #include "XProtocol/YProtocol.hh"
00018
00019 #include "Xrd/XrdLink.hh"
00020
00021 #include "XrdCms/XrdCmsLogin.hh"
00022 #include "XrdCms/XrdCmsParser.hh"
00023 #include "XrdCms/XrdCmsTalk.hh"
00024 #include "XrdCms/XrdCmsSecurity.hh"
00025 #include "XrdCms/XrdCmsTrace.hh"
00026
00027 #include "XrdOuc/XrdOucPup.hh"
00028
00029 #include "XrdSys/XrdSysError.hh"
00030 #include "XrdSys/XrdSysPthread.hh"
00031
00032 using namespace XrdCms;
00033
00034
00035
00036
00037
00038 int XrdCmsLogin::Admit(XrdLink *Link, CmsLoginData &Data)
00039 {
00040 CmsRRHdr myHdr;
00041 CmsLoginData myData;
00042 const char *eText, *Token;
00043 int myDlen, Toksz;
00044
00045
00046
00047 if ((eText = XrdCmsTalk::Attend(Link, myHdr, myBuff, myBlen, myDlen)))
00048 return Emsg(Link, eText, 0);
00049
00050
00051
00052 if ((Token = XrdCmsSecurity::getToken(Toksz, Link->Host()))
00053 && !XrdCmsSecurity::Authenticate(Link, Token, Toksz)) return 0;
00054
00055
00056
00057 Data.SID = Data.Paths = 0;
00058 memset(&myData, 0, sizeof(myData));
00059 myData.Mode = Data.Mode;
00060 myData.HoldTime = Data.HoldTime;
00061 myData.Version = Data.Version = kYR_Version;
00062
00063
00064
00065 if (!Parser.Parse(&Data, myBuff, myBuff+myDlen))
00066 return Emsg(Link, "invalid login data", 0);
00067
00068
00069
00070 if ((Token = XrdCmsSecurity::getToken(Toksz, Link->Host())))
00071 if (!XrdCmsSecurity::Authenticate(Link, Token, Toksz)) return 0;
00072
00073
00074
00075 return (sendData(Link, myData) ? 0 : 1);
00076 }
00077
00078
00079
00080
00081
00082 int XrdCmsLogin::Emsg(XrdLink *Link, const char *msg, int ecode)
00083 {
00084 Say.Emsg("Login", Link->Name(), "login failed;", msg);
00085 return ecode;
00086 }
00087
00088
00089
00090
00091
00092 int XrdCmsLogin::Login(XrdLink *Link, CmsLoginData &Data, int timeout)
00093 {
00094 CmsRRHdr LIHdr;
00095 char WorkBuff[4096], *hList, *wP = WorkBuff;
00096 int n, dataLen;
00097
00098
00099
00100 if (sendData(Link, Data)) return kYR_EINVAL;
00101
00102
00103
00104 if ((n = Link->RecvAll((char *)&LIHdr, sizeof(LIHdr), timeout)) < 0)
00105 return Emsg(Link, (n == -ETIMEDOUT ? "timed out" : "rejected"));
00106
00107
00108
00109 if ((dataLen = static_cast<int>(ntohs(LIHdr.datalen))))
00110 {if (dataLen > (int)sizeof(WorkBuff))
00111 return Emsg(Link, "login reply too long");
00112 if (Link->RecvAll(WorkBuff, dataLen, timeout) < 0)
00113 return Emsg(Link, "login receive error");
00114 }
00115
00116
00117
00118 if (LIHdr.rrCode == kYR_xauth)
00119 {if (!XrdCmsSecurity::Identify(Link, LIHdr, WorkBuff, sizeof(WorkBuff)))
00120 return kYR_EINVAL;
00121 dataLen = static_cast<int>(ntohs(LIHdr.datalen));
00122 if (dataLen > (int)sizeof(WorkBuff))
00123 return Emsg(Link, "login reply too long");
00124 }
00125
00126
00127
00128 if (!(Data.Mode & CmsLoginData::kYR_director)
00129 && LIHdr.rrCode == kYR_try)
00130 {if (!XrdOucPup::Unpack(&wP, wP+dataLen, &hList, n))
00131 return Emsg(Link, "malformed try host data");
00132 Data.Paths = (kXR_char *)strdup(n ? hList : "");
00133 return kYR_redirect;
00134 }
00135
00136
00137
00138 if (LIHdr.rrCode == kYR_error)
00139 return (dataLen < (int)sizeof(kXR_unt32)+8
00140 ? Emsg(Link, "invalid error reply")
00141 : Emsg(Link, WorkBuff+sizeof(kXR_unt32)));
00142
00143
00144
00145 if (LIHdr.rrCode != kYR_login
00146 || !Parser.Parse(&Data, WorkBuff, WorkBuff+dataLen))
00147 return Emsg(Link, "invalid login response");
00148 return 0;
00149 }
00150
00151
00152
00153
00154
00155 int XrdCmsLogin::sendData(XrdLink *Link, CmsLoginData &Data)
00156 {
00157 static const int xNum = 16;
00158
00159 int iovcnt;
00160 char Work[xNum*12];
00161 struct iovec Liov[xNum];
00162 CmsRRHdr Resp={0, kYR_login, 0, 0};
00163
00164
00165
00166 if (!(iovcnt=Parser.Pack(kYR_login,&Liov[1],&Liov[xNum],(char *)&Data,Work)))
00167 return Emsg(Link, "too much login reply data");
00168
00169
00170
00171 Resp.datalen = Data.Size;
00172 Liov[0].iov_base = (char *)&Resp;
00173 Liov[0].iov_len = sizeof(Resp);
00174
00175
00176
00177 Link->Send(Liov, iovcnt+1);
00178
00179
00180
00181 return 0;
00182 }