SecAccessFlags getPermissions(const char *key,const char *obj,IUserDescriptor *udesc,unsigned auditflags,const char * reqSignature, CDateTime * reqUTCTimestamp) { if (!ldapsecurity||((getLDAPflags()&DLF_ENABLED)==0)) return SecAccess_Full; StringBuffer username; StringBuffer password; if (udesc) { udesc->getUserName(username); udesc->getPassword(password); } else { WARNLOG("NULL UserDescriptor in daldap.cpp getPermissions('%s')",key ? key : "NULL"); } if (0 == username.length()) { username.append(filesdefaultuser); decrypt(password, filesdefaultpassword); } Owned<ISecUser> user = ldapsecurity->createUser(username); user->credentials().setPassword(password); bool authenticated = false; //Check that the digital signature provided by the caller (signature of //caller's "scope;username;timeStamp") matches what we expect it to be if (!isEmptyString(reqSignature)) { if (nullptr == pDSM) pDSM = queryDigitalSignatureManagerInstanceFromEnv(); if (pDSM && pDSM->isDigiVerifierConfigured()) { StringBuffer requestTimestamp; reqUTCTimestamp->getString(requestTimestamp, false);//extract timestamp string from Dali request CDateTime now; now.setNow(); if (now.compare(*reqUTCTimestamp) < 0)//timestamp from the future? { ERRLOG("LDAP: getPermissions(%s) scope=%s user=%s Request digital signature timestamp %s from the future",key?key:"NULL",obj?obj:"NULL",username.str(), requestTimestamp.str()); return SecAccess_None;//deny } CDateTime expiry; expiry.set(now); expiry.adjustTime(requestSignatureExpiryMinutes);//compute expiration timestamp if (expiry.compare(*reqUTCTimestamp) < 0)//timestamp too far in the past? { ERRLOG("LDAP: getPermissions(%s) scope=%s user=%s Expired request digital signature timestamp %s",key?key:"NULL",obj?obj:"NULL",username.str(), requestTimestamp.str()); return SecAccess_None;//deny } VStringBuffer expectedStr("%s;%s;%s", obj, username.str(), requestTimestamp.str()); StringBuffer b64Signature(reqSignature);// signature of scope;user;timestamp if (!pDSM->digiVerify(expectedStr, b64Signature))//does the digital signature match what we expect? { ERRLOG("LDAP: getPermissions(%s) scope=%s user=%s fails digital signature verification",key?key:"NULL",obj?obj:"NULL",username.str()); return SecAccess_None;//deny } authenticated = true;//Digital signature verified } else ERRLOG("LDAP: getPermissions(%s) scope=%s user=%s digital signature support not available",key?key:"NULL",obj?obj:"NULL",username.str()); } if (!authenticated && !ldapsecurity->authenticateUser(*user, NULL)) { ERRLOG("LDAP: getPermissions(%s) scope=%s user=%s fails LDAP authentication",key?key:"NULL",obj?obj:"NULL",username.str()); return SecAccess_None;//deny } bool filescope = stricmp(key,"Scope")==0; bool wuscope = stricmp(key,"workunit")==0; if (filescope || wuscope) { SecAccessFlags perm = SecAccess_None; unsigned start = msTick(); if (filescope) perm=ldapsecurity->authorizeFileScope(*user, obj); else if (wuscope) perm=ldapsecurity->authorizeWorkunitScope(*user, obj); if (perm == SecAccess_Unavailable) perm = SecAccess_None; unsigned taken = msTick()-start; #ifndef _DEBUG if (taken>100) #endif { PROGLOG("LDAP: getPermissions(%s) scope=%s user=%s returns %d in %d ms",key?key:"NULL",obj?obj:"NULL",username.str(),perm,taken); } if (auditflags&DALI_LDAP_AUDIT_REPORT) { StringBuffer auditstr; if ((auditflags&DALI_LDAP_READ_WANTED)&&!HASREADPERMISSION(perm)) auditstr.append("Lookup Access Denied"); else if ((auditflags&DALI_LDAP_WRITE_WANTED)&&!HASWRITEPERMISSION(perm)) auditstr.append("Create Access Denied"); if (auditstr.length()) { auditstr.append(":\n\tProcess:\tdaserver"); auditstr.appendf("\n\tUser:\t%s",username.str()); auditstr.appendf("\n\tScope:\t%s\n",obj?obj:""); SYSLOG(AUDIT_TYPE_ACCESS_FAILURE,auditstr.str()); } } return perm; } return SecAccess_Full; }
bool loadPwds() { try { if (!pwFile.length()) throw MakeStringException(-1, "htpasswd Password file not specified"); Owned<IFile> file = createIFile(pwFile.str()); if (!file->exists()) { userMap.kill(); throw MakeStringException(-1, "htpasswd Password file does not exist"); } bool isDir; offset_t size; CDateTime whenChanged; file->getInfo(isDir,size,whenChanged); if (isDir) { userMap.kill(); throw MakeStringException(-1, "htpasswd Password file specifies a directory"); } if (0 == whenChanged.compare(pwFileLastMod)) return true;//Don't reload if file unchanged userMap.kill(); OwnedIFileIO io = file->open(IFOread); if (!io) throw MakeStringException(-1, "htpasswd Unable to open Password file"); MemoryBuffer mb; size32_t count = read(io, 0, (size32_t)-1, mb); if (0 == count) throw MakeStringException(-1, "htpasswd Password file is empty"); mb.append((char)NULL); char * p = (char*)mb.toByteArray(); char *saveptr; const char * seps = "\f\r\n"; char * next = strtok_r(p, seps, &saveptr); if (next) { do { char * colon = strchr(next,':'); if (NULL == colon) throw MakeStringException(-1, "htpasswd Password file appears malformed"); *colon = (char)NULL; userMap.setValue(next, colon+1);//username, enctypted password } while (next = strtok_r(NULL, seps, &saveptr)); } io->close(); pwFileLastMod = whenChanged;//remember when last changed } catch(IException*) { throw MakeStringException(-1, "htpasswd Exception accessing Password file"); } return true; }
void verifyFile(const char *name,CDateTime *cutoff) { Owned<IDistributedFile> file=queryDistributedFileDirectory().lookup(name,UNKNOWN_USER); if (!file) return; IPropertyTree &fileprops = file->queryAttributes(); bool blocked = false; if (file->isCompressed(&blocked)&&!blocked) return; if (stopped) return; StringBuffer dtstr; if (fileprops.getProp("@verified",dtstr)) { if (!cutoff) return; CDateTime dt; dt.setString(dtstr.str()); if (dt.compare(*cutoff)<=0) return; } list.kill(); unsigned width = file->numParts(); unsigned short port = getDaliServixPort(); try { Owned<IDistributedFilePart> testpart = file->getPart(0); SocketEndpoint ep(testpart->queryNode()->endpoint()); if (!dafilesrvips.verifyDaliFileServer(ep)) { StringBuffer ips; ep.getIpText(ips); PROGLOG("VERIFY: file %s, cannot run DAFILESRV on %s",name,ips.str()); return; } } catch (IException *e) { StringBuffer s; s.appendf("VERIFY: file %s",name); EXCLOG(e, s.str()); e->Release(); return; } for (unsigned idx=0;idx<width;idx++) { Owned<IDistributedFilePart> part = file->getPart(idx); for (unsigned copy = 0; copy < part->numCopies(); copy++) { if (stopped) return; unsigned reqcrc; if (!part->getCrc(reqcrc)) continue; SocketEndpoint ep(part->queryNode()->endpoint()); if (!dafilesrvips.verifyDaliFileServer(ep)) { StringBuffer ips; ep.getIpText(ips); PROGLOG("VERIFY: file %s, cannot run DAFILESRV on %s",name,ips.str()); continue; } RemoteFilename rfn; part->getFilename(rfn,copy); rfn.setPort(port); add(rfn,idx,copy,reqcrc); } } if (list.ordinality()==0) return; PROGLOG("VERIFY: file %s started",name); file.clear(); CriticalSection crit; class casyncfor: public CAsyncFor { CFileCrcList *parent; CriticalSection &crit; public: bool ok; casyncfor(CFileCrcList *_parent, CriticalSection &_crit) : crit(_crit) { parent = _parent; ok = true; } void Do(unsigned i) { CriticalBlock block(crit); if (parent->stopped) return; CFileCrcItem &item = parent->list.item(i); RemoteFilename &rfn = item.filename; Owned<IFile> partfile; StringBuffer eps; try { partfile.setown(createIFile(rfn)); // PROGLOG("VERIFY: part %s on %s",partfile->queryFilename(),rfn.queryEndpoint().getUrlStr(eps).str()); if (partfile) { if (parent->stopped) return; CriticalUnblock unblock(crit); item.crc = partfile->getCRC(); } else ok = false; } catch (IException *e) { StringBuffer s; s.appendf("VERIFY: part %s on %s",partfile->queryFilename(),rfn.queryEndpoint().getUrlStr(eps).str()); EXCLOG(e, s.str()); e->Release(); ok = false; } } } afor(this,crit); afor.For(list.ordinality(),50,false,true); ForEachItemIn(j,list) { CFileCrcItem &item = list.item(j); if (item.crc!=item.requiredcrc) { if (stopped) return; StringBuffer rfs; PROGLOG("VERIFY: FAILED %s (%x,%x) file %s",name,item.crc,item.requiredcrc,item.filename.getRemotePath(rfs).str()); afor.ok = false; } }