XRootD
Loading...
Searching...
No Matches
XrdCmsLogin.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d C m s L o g i n . c c */
4/* */
5/* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* All Rights Reserved */
7/* Produced by Andrew Hanushevsky for Stanford University under contract */
8/* DE-AC02-76-SFO0515 with the Department of Energy */
9/* */
10/* This file is part of the XRootD software suite. */
11/* */
12/* XRootD is free software: you can redistribute it and/or modify it under */
13/* the terms of the GNU Lesser General Public License as published by the */
14/* Free Software Foundation, either version 3 of the License, or (at your */
15/* option) any later version. */
16/* */
17/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20/* License for more details. */
21/* */
22/* You should have received a copy of the GNU Lesser General Public License */
23/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25/* */
26/* The copyright holder's institutional names and contributor's names may not */
27/* be used to endorse or promote products derived from this software without */
28/* specific prior written permission of the institution or contributor. */
29/******************************************************************************/
30
31#include <netinet/in.h>
32#include <unistd.h>
33
35
36#include "Xrd/XrdLink.hh"
37
39#include "XrdCms/XrdCmsLogin.hh"
41#include "XrdCms/XrdCmsTalk.hh"
43#include "XrdCms/XrdCmsTrace.hh"
44
45#include "XrdOuc/XrdOucPup.hh"
46
47#include "XrdSys/XrdSysError.hh"
49
50using namespace XrdCms;
51
52/******************************************************************************/
53/* Public: A d m i t */
54/******************************************************************************/
55
57 const char *sid, const char *envP)
58{
59 CmsRRHdr myHdr;
60 CmsLoginData myData;
61 const char *eText, *Token;
62 int myDlen, Toksz;
63
64// Get complete request
65//
66 if ((eText = XrdCmsTalk::Attend(Link, myHdr, myBuff, myBlen, myDlen)))
67 return Emsg(Link, eText, 0);
68
69// If we need to do authentication, do so now
70//
71 if ((Token = XrdCmsSecurity::getToken(Toksz, Link->AddrInfo()))
72 && !XrdCmsSecurity::Authenticate(Link, Token, Toksz)) return 0;
73
74// Fiddle with the login data structures
75//
76 Data.SID = Data.Paths = Data.ifList = Data.envCGI = 0;
77 memset(&myData, 0, sizeof(myData));
78 myData.Mode = Data.Mode;
79 myData.HoldTime = Data.HoldTime;
80 myData.Version = Data.Version = kYR_Version;
81
82// Decode the data pointers ans grab the login data
83//
84 if (!Parser.Parse(&Data, myBuff, myBuff+myDlen))
85 return Emsg(Link, "invalid login data", 0);
86
87// Check if this node is blacklisted
88//
89 if (!(Data.Mode & CmsLoginData::kYR_director))
90 {static const int rbsz = 1024;
91 char *rbP, rbuff[rbsz];
92 int rc;
93 rbP = (myData.Version <= Data.Version ? rbuff : 0);
94 rc = XrdCmsBlackList::Present(Link->Host(), 0, rbP, rbsz);
95 if (rc > 0) return SendErrorBL(Link, rbuff, rc);
96 else if (rc < 0) return SendErrorBL(Link);
97 }
98
99// Fill out additional information if the client can accept it
100//
101 if (myData.Version <= Data.Version)
102 {myData.SID = (kXR_char *)sid;
103 myData.envCGI = (kXR_char *)envP;
104 }
105
106// Send off login reply
107//
108 return (sendData(Link, myData) ? 0 : 1);
109}
110
111/******************************************************************************/
112/* Private: E m s g */
113/******************************************************************************/
114
115int XrdCmsLogin::Emsg(XrdLink *Link, const char *msg, int ecode)
116{
117 Say.Emsg("Login", Link->Name(), "login failed;", msg);
118 return ecode;
119}
120
121/******************************************************************************/
122/* Public: L o g i n */
123/******************************************************************************/
124
125int XrdCmsLogin::Login(XrdLink *Link, CmsLoginData &Data, int timeout)
126{
127 CmsRRHdr LIHdr;
128 char WorkBuff[4096], *hList, *wP = WorkBuff;
129 int n, dataLen;
130
131// We can accept permanent redirects so indicate this
132//
134
135// Send the data and immediately clear the data structure of pointers
136//
137 n = sendData(Link, Data);
138 Data.Paths = Data.SID = Data.envCGI = 0;
139 if (n) return kYR_EINVAL;
140
141// Get the response.
142//
143 if ((n = Link->RecvAll((char *)&LIHdr, sizeof(LIHdr), timeout)) < 0)
144 return Emsg(Link, (n == -ETIMEDOUT ? "timed out" : "rejected"));
145
146// Receive and decode the response. We apparently have protocol version 2.
147//
148 if ((dataLen = static_cast<int>(ntohs(LIHdr.datalen))))
149 {if (dataLen > (int)sizeof(WorkBuff))
150 return Emsg(Link, "login reply too long");
151 if (Link->RecvAll(WorkBuff, dataLen, timeout) < 0)
152 return Emsg(Link, "login receive error");
153 }
154
155// Check if we are being asked to identify ourselves
156//
157 if (LIHdr.rrCode == kYR_xauth)
158 {if (!XrdCmsSecurity::Identify(Link, LIHdr, WorkBuff, sizeof(WorkBuff)))
159 return kYR_EINVAL;
160 dataLen = static_cast<int>(ntohs(LIHdr.datalen));
161 if (dataLen > (int)sizeof(WorkBuff))
162 return Emsg(Link, "login reply too long");
163 }
164
165// The response can also be a login redirect (i.e., a try request).
166//
167 if (!(Data.Mode & CmsLoginData::kYR_director)
168 && LIHdr.rrCode == kYR_try)
169 {if (!XrdOucPup::Unpack(&wP, wP+dataLen, &hList, n))
170 return Emsg(Link, "malformed try host data");
171 Data.Paths = (kXR_char *)strdup(n ? hList : "");
174 return kYR_redirect;
175 }
176
177// Process error reply
178//
179 if (LIHdr.rrCode == kYR_error)
180 {unsigned int eRC;
181 if (dataLen < (int)sizeof(kXR_unt32)+8)
182 return Emsg(Link, "invalid error reply");
183 Emsg(Link, WorkBuff+sizeof(kXR_unt32));
184 memcpy(&eRC, WorkBuff, sizeof(eRC));
185 eRC = ntohl(eRC);
186 return (eRC == kYR_EPERM ? -1 : kYR_EINVAL);
187 }
188
189// Process normal reply
190//
191 if (LIHdr.rrCode != kYR_login
192 || !Parser.Parse(&Data, WorkBuff, WorkBuff+dataLen))
193 return Emsg(Link, "invalid login response");
194
195// Copy any strings that we are exporting
196//
197 if (Data.SID) Data.SID = (kXR_char *)strdup((const char *)Data.SID);
198 if (Data.envCGI) Data.envCGI = (kXR_char *)strdup((const char *)Data.envCGI);
199 return 0;
200}
201
202/******************************************************************************/
203/* Private: s e n d D a t a */
204/******************************************************************************/
205
206int XrdCmsLogin::sendData(XrdLink *Link, CmsLoginData &Data)
207{
208 static const int xNum = 20;
209
210 int n, iovcnt, iovnum;
211 char Work[xNum*12];
212 struct iovec Liov[xNum];
213 CmsRRHdr Resp={0, kYR_login, 0, 0};
214 static const int iovmax = XrdSys::getIovMax();
215
216// Pack the response (ignore the auth token for now)
217//
218 if (!(iovcnt=Parser.Pack(kYR_login,&Liov[1],&Liov[xNum],(char *)&Data,Work)))
219 return Emsg(Link, "too much login data");
220
221// Complete I/O vector
222//
223 Resp.datalen = Data.Size;
224 Liov[0].iov_base = (char *)&Resp;
225 Liov[0].iov_len = sizeof(Resp);
226
227// Send off the data *break it up to IOV_MAX chunks, mostly for Solaris)
228//
229 n = 0; iovcnt++;
230 if (iovcnt <= iovmax) Link->Send(Liov, iovcnt);
231 else while(iovcnt > 0)
232 {iovnum = (iovcnt > iovmax ? iovmax : iovcnt);
233 Link->Send(&Liov[n], iovnum);
234 n += iovmax; iovcnt -= iovmax;
235 }
236
237// Return success
238//
239 return 0;
240}
241
242/******************************************************************************/
243/* Private: S e n d E r r o r B L */
244/******************************************************************************/
245
246int XrdCmsLogin::SendErrorBL(XrdLink *Link)
247{
248 struct {CmsResponse rInfo;
249 char rText[512];
250 } rData;
251 const char *hName = Link->AddrInfo()->Name("???");
252 int n;
253
254// Format the message
255//
256 n = snprintf(rData.rText, sizeof(rData.rText), "%s is blacklisted.", hName)
257 + sizeof(rData.rInfo.Val) + 1;
258
259// Construct response
260//
261 rData.rInfo.Hdr.streamid = 0;
262 rData.rInfo.Hdr.rrCode = kYR_error;
263 rData.rInfo.Hdr.modifier = 0;
264 rData.rInfo.Hdr.datalen = htons(n);
265 rData.rInfo.Val = htonl(static_cast<unsigned int>(kYR_EPERM));
266
267// Send off the data
268//
269 Link->Send((const char *)&rData, n + sizeof(CmsRRHdr));
270 return Emsg(Link, "blacklisted", 0);
271}
272
273/******************************************************************************/
274
275int XrdCmsLogin::SendErrorBL(XrdLink *Link, char *rbuff, int rblen)
276{
277 CmsRRHdr Rsp = {0, kYR_try, CmsTryRequest::kYR_permtop, htons((unsigned short int)rblen)};
278 struct iovec iov[2] = {{(char *)&Rsp, sizeof(Rsp)},
279 {rbuff, static_cast<size_t>(rblen)}};
280 char msgbuff[2048];
281
282// Send off the data
283//
284 Link->Send(iov, 2, sizeof(Rsp) + rblen);
285
286// Compose the right message
287//
288 snprintf(msgbuff, sizeof(msgbuff), "blacklisted; redirected to %s",
289 rbuff+sizeof(short));
290 return Emsg(Link, msgbuff, 0);
291}
unsigned int kXR_unt32
Definition XPtypes.hh:90
unsigned char kXR_char
Definition XPtypes.hh:65
static int Present(const char *hName, XrdOucTList *bList=0, char *rbuff=0, int rblen=0)
int Admit(XrdLink *Link, XrdCms::CmsLoginData &Data, const char *sid, const char *envP)
static int Login(XrdLink *Link, XrdCms::CmsLoginData &Data, int timeout=-1)
static int Pack(int rnum, struct iovec *iovP, struct iovec *iovE, char *Base, char *Work)
int Parse(XrdCms::CmsLoginData *Data, const char *Aps, const char *Apt)
static const char * getToken(int &size, XrdNetAddrInfo *endPoint)
static int Authenticate(XrdLink *Link, const char *Token, int tlen)
static int Identify(XrdLink *Link, XrdCms::CmsRRHdr &inHdr, char *authBuff, int abLen)
static const char * Attend(XrdLink *Link, XrdCms::CmsRRHdr &Hdr, char *buff, int blen, int &rlen, int tmo=5000)
Definition XrdCmsTalk.cc:46
const char * Name(const char *eName=0, const char **eText=0)
static int Unpack(char **buff, const char *bend, char **data, int &dlen)
Definition XrdOucPup.cc:250
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
static const unsigned char kYR_Version
Definition YProtocol.hh:80
kXR_unt16 datalen
Definition YProtocol.hh:86
@ kYR_EINVAL
Definition YProtocol.hh:153
@ kYR_EPERM
Definition YProtocol.hh:151
kXR_char modifier
Definition YProtocol.hh:85
XrdCmsParser Parser
@ kYR_redirect
Definition YProtocol.hh:143
@ kYR_error
Definition YProtocol.hh:142
XrdSysError Say
kXR_char rrCode
Definition YProtocol.hh:84
@ kYR_xauth
Definition YProtocol.hh:117
@ kYR_login
Definition YProtocol.hh:90
int getIovMax()