00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <sys/types.h>
00013 #include <sys/socket.h>
00014 #include <errno.h>
00015 #include <fcntl.h>
00016 #include <poll.h>
00017 #include <stdio.h>
00018 #include <unistd.h>
00019
00020 #include "XrdOuc/XrdOucErrInfo.hh"
00021 #include "XrdSec/XrdSecTLayer.hh"
00022 #include "XrdSys/XrdSysHeaders.hh"
00023
00024
00025
00026
00027
00028
00029
00030 const char XrdSecTLayer::TLayerRR::endData;
00031 const char XrdSecTLayer::TLayerRR::xfrData;
00032
00033
00034
00035
00036
00037 XrdSecTLayer::XrdSecTLayer(const char *pName, Initiator who1st)
00038 : XrdSecProtocol(pName),
00039 secTid(0), mySem(0), Starter(who1st), myFD(-1), urFD(-1),
00040 Tmax(275), Tcur(0), eCode(0), eText(0)
00041 {
00042
00043
00044
00045 memset((void *)&Hdr, 0, sizeof(Hdr));
00046 strncpy(Hdr.protName,pName,sizeof(Hdr.protName)-1);
00047 }
00048
00049
00050
00051
00052
00053
00054
00055
00056 XrdSecCredentials *XrdSecTLayer::getCredentials(XrdSecParameters *parm,
00057 XrdOucErrInfo *einfo)
00058 {
00059 char Buff[dataSz];
00060 int Blen = 0, wrLen = 0;
00061 char *bP, Req = TLayerRR::xfrData;
00062
00063
00064
00065 eDest = einfo;
00066 if (!parm)
00067 {if (!bootUp(isClient)) return 0;
00068 if (Starter == isServer)
00069 {Hdr.protCode = TLayerRR::xfrData;
00070 bP = (char *)malloc(hdrSz);
00071 memcpy(bP, (char *)&Hdr, hdrSz);
00072 return new XrdSecCredentials(bP, hdrSz);
00073 }
00074 } else {
00075 if (parm->size < hdrSz)
00076 {secError("Invalid parms length", EPROTO);
00077 return 0;
00078 }
00079 Req = ((TLayerRR *)parm->buffer)->protCode;
00080 wrLen= parm->size - hdrSz;
00081 }
00082
00083
00084
00085
00086
00087 switch(Req)
00088 {case TLayerRR::xfrData:
00089 if (wrLen > 0 && write(myFD, parm->buffer+hdrSz, wrLen) < 0)
00090 {secError("Socket write failed", errno); return 0;}
00091 Blen = Read(myFD, Buff, dataSz);
00092 if (Blen < 0 && (Blen != -EPIPE) && (Blen != -ECONNRESET))
00093 {secError("Socket read failed", -Blen); return 0;}
00094 break;
00095 case TLayerRR::endData:
00096 if (myFD < 0) {secError("Protocol violation", EPROTO); return 0;}
00097 Blen = -1;
00098 break;
00099 default: secError("Unknown parms request", EINVAL); return 0;
00100 }
00101
00102
00103
00104
00105
00106 if (Blen < 0) {if (!secDone()) return 0;
00107 Blen = 0; Hdr.protCode = TLayerRR::endData;}
00108 else if (Blen || wrLen) {Tcur = 0; Hdr.protCode = TLayerRR::xfrData;}
00109 else if (++Tcur <= Tmax) Hdr.protCode = TLayerRR::xfrData;
00110 else {Tcur = 0; Hdr.protCode = TLayerRR::endData;}
00111
00112
00113
00114 bP = (char *)malloc(hdrSz+Blen);
00115 memcpy(bP, (char *)&Hdr, hdrSz);
00116 if (Blen) memcpy(bP+hdrSz, Buff, Blen);
00117 return new XrdSecCredentials(bP, hdrSz+Blen);
00118 }
00119
00120
00121
00122
00123
00124 int XrdSecTLayer::Authenticate (XrdSecCredentials *cred,
00125 XrdSecParameters **parms,
00126 XrdOucErrInfo *einfo)
00127 {
00128 char Buff[dataSz];
00129 int Blen = 0, wrLen;
00130 char *bP, Req;
00131
00132
00133
00134 eDest = einfo;
00135 if (myFD < 0 && !bootUp(isServer)) return -1;
00136
00137
00138
00139 if (cred->size < hdrSz) {secError("Invalid credentials",EBADMSG); return -1;}
00140 Req = ((TLayerRR *)cred->buffer)->protCode;
00141 wrLen= cred->size - hdrSz;
00142
00143
00144
00145
00146
00147 switch(Req)
00148 {case TLayerRR::xfrData:
00149 if (wrLen > 0 && write(myFD, cred->buffer+hdrSz, wrLen) < 0)
00150 {secError("Socket write failed", errno); return -1;}
00151 Blen = Read(myFD, Buff, dataSz);
00152 if (Blen < 0 && (Blen != -EPIPE) && (Blen != -ECONNRESET))
00153 {secError("Socket read failed", -Blen); return 0;}
00154 break;
00155 case TLayerRR::endData: return (secDone() ? 0 : -1);
00156 default: secError("Unknown parms request", EINVAL); return -1;
00157 }
00158
00159
00160
00161
00162
00163
00164 if (Blen < 0) {Blen = 0; Hdr.protCode = TLayerRR::endData;}
00165 else if (Blen || wrLen) {Tcur = 0; Hdr.protCode = TLayerRR::xfrData;}
00166 else if (++Tcur <= Tmax) Hdr.protCode = TLayerRR::xfrData;
00167 else {Tcur = 0; Hdr.protCode = TLayerRR::endData;}
00168
00169
00170
00171 bP = (char *)malloc(hdrSz+Blen);
00172 memcpy(bP, (char *)&Hdr, hdrSz);
00173 if (Blen) memcpy(bP+hdrSz, Buff, Blen);
00174 *parms = new XrdSecParameters(bP, hdrSz+Blen);
00175
00176 return 1;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 void *XrdSecTLayerBootUp(void *carg)
00188 {XrdSecTLayer *tP = (XrdSecTLayer *)carg;
00189 tP->secXeq();
00190 return (void *)0;
00191 }
00192
00193
00194
00195 int XrdSecTLayer::bootUp(Initiator whoami)
00196 {
00197 int sv[2];
00198
00199
00200
00201 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
00202 {secError("Unable to create socket pair", errno); return 0;}
00203 myFD = sv[0]; urFD = sv[1];
00204 Responder = whoami;
00205
00206
00207
00208 fcntl(myFD, F_SETFD, FD_CLOEXEC);
00209 fcntl(urFD, F_SETFD, FD_CLOEXEC);
00210
00211
00212
00213 if (XrdSysThread::Run(&secTid,XrdSecTLayerBootUp,(void *)this, XRDSYSTHREAD_HOLD))
00214 {int rc = errno;
00215 close(myFD); myFD = -1;
00216 close(urFD); urFD = -1;
00217 secError("Unable to create thread", rc);
00218 return 0;
00219 }
00220
00221
00222
00223 return 1;
00224 }
00225
00226
00227
00228
00229
00230 int XrdSecTLayer::Read(int FD, char *Buff, int rdLen)
00231 {
00232 struct pollfd polltab = {FD, POLLIN|POLLRDNORM|POLLHUP, 0};
00233 int retc, xWt, Tlen = 0;
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 if (Tcur) xWt = (Tcur+10)/10;
00246 else xWt = 1;
00247
00248
00249
00250 do {do {retc = poll(&polltab, 1, xWt);} while(retc < 0 && errno == EINTR);
00251 if (retc <= 0) return (retc ? -errno : Tlen);
00252 do {retc = read(FD, Buff, rdLen);} while(retc < 0 && errno == EINTR);
00253 if (retc <= 0) return (retc ? -errno : (Tlen ? Tlen : -EPIPE));
00254 Tlen += retc; Buff += retc; rdLen -= retc; xWt = 1;
00255 } while(rdLen > 0);
00256
00257 return Tlen;
00258 }
00259
00260
00261
00262
00263
00264 int XrdSecTLayer::secDone()
00265 {
00266
00267
00268
00269 secDrain();
00270
00271
00272
00273 if (!eCode) return 1;
00274
00275
00276
00277 secError((eText ? eText : "?"), eCode, 0);
00278 return 0;
00279 }
00280
00281
00282
00283
00284
00285 void XrdSecTLayer::secDrain()
00286 {
00287 if (myFD >= 0)
00288 {close(myFD); myFD = -1;
00289 mySem.Wait();
00290 }
00291 }
00292
00293
00294
00295
00296
00297 const char *XrdSecTLayer::secErrno(int rc, char *buff)
00298 {
00299 sprintf(buff, "err %d", rc);
00300 return buff;
00301 }
00302
00303
00304
00305
00306
00307 void XrdSecTLayer::secError(const char *Msg, int rc, int iserrno)
00308 {
00309 char buff[32];
00310 const char *tlist[] = {"XrdSecProtocol", Hdr.protName, ": ", Msg, "; ",
00311 (iserrno ? strerror(rc) : secErrno(rc,buff))
00312 };
00313 int i, n = sizeof(tlist)/sizeof(const char *);
00314
00315 if (eDest) eDest->setErrInfo(rc, tlist, n);
00316 else {for (i = 0; i < n; i++) cerr <<tlist[i]; cerr <<endl;}
00317
00318 secDrain();
00319 }
00320
00321
00322
00323
00324
00325 void XrdSecTLayer::secXeq()
00326 {
00327 XrdOucErrInfo einfo;
00328 const char *Msg;
00329
00330
00331
00332 if (Responder == XrdSecTLayer::isClient) secClient(urFD, &einfo);
00333 else secServer(urFD, &einfo);
00334
00335
00336 Msg = einfo.getErrText(eCode);
00337 if (eText) {free(eText); eText = 0;}
00338 if (eCode) eText = strdup(Msg ? Msg : "Authentication failed");
00339
00340
00341
00342 if (urFD>0) close(urFD);
00343 urFD = -1;
00344 mySem.Post();
00345 }