List of usage examples for java.util TreeSet addAll
public boolean addAll(Collection<? extends E> c)
From source file:net.sourceforge.fenixedu.domain.phd.PhdIndividualProgramProcess.java
public PrecedentDegreeInformation getLatestPrecedentDegreeInformation() { TreeSet<PrecedentDegreeInformation> degreeInformations = new TreeSet<PrecedentDegreeInformation>( Collections.reverseOrder(PrecedentDegreeInformation.COMPARATOR_BY_EXECUTION_YEAR)); ExecutionYear currentExecutionYear = ExecutionYear.readCurrentExecutionYear(); for (PrecedentDegreeInformation pdi : getPrecedentDegreeInformationsSet()) { if (!pdi.getExecutionYear().isAfter(currentExecutionYear)) { degreeInformations.add(pdi); }/*from w w w.j a va2 s . co m*/ } degreeInformations.addAll(getPrecedentDegreeInformationsSet()); return (degreeInformations.iterator().hasNext()) ? degreeInformations.iterator().next() : null; }
From source file:org.lockss.devtools.CrawlRuleTester.java
private void checkRules() { outputMessage("\nChecking " + m_baseUrl, TEST_SUMMARY_MESSAGE); outputMessage("crawl depth: " + m_crawlDepth + " crawl delay: " + m_crawlDelay + " ms.", PLAIN_MESSAGE); TreeSet crawlList = new TreeSet(); TreeSet fetched = new TreeSet(); // inialize with the baseUrl crawlList.add(m_baseUrl);//from w w w. j a v a2s . c o m depth_incl = new int[m_crawlDepth]; depth_fetched = new int[m_crawlDepth]; depth_parsed = new int[m_crawlDepth]; long start_time = TimeBase.nowMs(); for (int depth = 1; depth <= m_crawlDepth; depth++) { if (isInterrupted()) { return; } m_curDepth = depth; if (crawlList.isEmpty() && depth <= m_crawlDepth) { outputMessage("\nNothing left to crawl, exiting after depth " + (depth - 1), PLAIN_MESSAGE); break; } String[] urls = (String[]) crawlList.toArray(new String[0]); crawlList.clear(); outputMessage("\nDepth " + depth, PLAIN_MESSAGE); for (int ix = 0; ix < urls.length; ix++) { if (isInterrupted()) { return; } pauseBeforeFetch(); String urlstr = urls[ix]; m_incls.clear(); m_excls.clear(); // crawl the page buildUrlSets(urlstr); fetched.add(urlstr); // output incl/excl results, // add the new_incls to the crawlList for next crawl depth loop crawlList.addAll(outputUrlResults(urlstr, m_incls, m_excls)); } } long elapsed_time = TimeBase.nowMs() - start_time; outputSummary(m_baseUrl, fetched, crawlList, elapsed_time); }
From source file:com.cloud.deploy.DeploymentPlanningManagerImpl.java
protected Pair<Host, Map<Volume, StoragePool>> findPotentialDeploymentResources(List<Host> suitableHosts, Map<Volume, List<StoragePool>> suitableVolumeStoragePools, ExcludeList avoid, DeploymentPlanner.PlannerResourceUsage resourceUsageRequired, List<Volume> readyAndReusedVolumes, List<Long> preferredHosts) { s_logger.debug(//from ww w .ja v a2s.co m "Trying to find a potenial host and associated storage pools from the suitable host/pool lists for this VM"); boolean hostCanAccessPool = false; boolean haveEnoughSpace = false; boolean hostAffinityCheck = false; if (readyAndReusedVolumes == null) { readyAndReusedVolumes = new ArrayList<Volume>(); } Map<Volume, StoragePool> storage = new HashMap<Volume, StoragePool>(); TreeSet<Volume> volumesOrderBySizeDesc = new TreeSet<Volume>(new Comparator<Volume>() { @Override public int compare(Volume v1, Volume v2) { if (v1.getSize() < v2.getSize()) return 1; else return -1; } }); volumesOrderBySizeDesc.addAll(suitableVolumeStoragePools.keySet()); boolean multipleVolume = volumesOrderBySizeDesc.size() > 1; for (Host potentialHost : suitableHosts) { Map<StoragePool, List<Volume>> volumeAllocationMap = new HashMap<StoragePool, List<Volume>>(); for (Volume vol : volumesOrderBySizeDesc) { haveEnoughSpace = false; s_logger.debug("Checking if host: " + potentialHost.getId() + " can access any suitable storage pool for volume: " + vol.getVolumeType()); List<StoragePool> volumePoolList = suitableVolumeStoragePools.get(vol); hostCanAccessPool = false; hostAffinityCheck = checkAffinity(potentialHost, preferredHosts); for (StoragePool potentialSPool : volumePoolList) { if (hostCanAccessSPool(potentialHost, potentialSPool)) { hostCanAccessPool = true; if (multipleVolume && !readyAndReusedVolumes.contains(vol)) { List<Volume> requestVolumes = null; if (volumeAllocationMap.containsKey(potentialSPool)) requestVolumes = volumeAllocationMap.get(potentialSPool); else requestVolumes = new ArrayList<Volume>(); requestVolumes.add(vol); if (!_storageMgr.storagePoolHasEnoughIops(requestVolumes, potentialSPool) || !_storageMgr.storagePoolHasEnoughSpace(requestVolumes, potentialSPool, potentialHost.getClusterId())) continue; volumeAllocationMap.put(potentialSPool, requestVolumes); } storage.put(vol, potentialSPool); haveEnoughSpace = true; break; } } if (!hostCanAccessPool) { break; } if (!haveEnoughSpace) { s_logger.warn("insufficient capacity to allocate all volumes"); break; } if (!hostAffinityCheck) { s_logger.debug("Host affinity check failed"); break; } } if (hostCanAccessPool && haveEnoughSpace && hostAffinityCheck && checkIfHostFitsPlannerUsage(potentialHost.getId(), resourceUsageRequired)) { s_logger.debug("Found a potential host " + "id: " + potentialHost.getId() + " name: " + potentialHost.getName() + " and associated storage pools for this VM"); return new Pair<Host, Map<Volume, StoragePool>>(potentialHost, storage); } else { avoid.addHost(potentialHost.getId()); } } s_logger.debug( "Could not find a potential host that has associated storage pools from the suitable host/pool lists for this VM"); return null; }
From source file:org.languagetool.rules.patterns.MatchState.java
/** * Gets all strings formatted using the match element. *///from w ww.j a va 2s . c om public final String[] toFinalString(Language lang) throws IOException { String[] formattedString = new String[1]; if (formattedToken != null) { int readingCount = formattedToken.getReadingsLength(); formattedString[0] = formattedToken.getToken(); Pattern pRegexMatch = match.getRegexMatch(); String regexReplace = match.getRegexReplace(); if (pRegexMatch != null) { formattedString[0] = pRegexMatch.matcher(formattedString[0]).replaceAll(regexReplace); } String posTag = match.getPosTag(); if (posTag != null) { if (synthesizer == null) { formattedString[0] = formattedToken.getToken(); } else if (match.isPostagRegexp()) { TreeSet<String> wordForms = new TreeSet<>(); boolean oneForm = false; for (int k = 0; k < readingCount; k++) { if (formattedToken.getAnalyzedToken(k).getLemma() == null) { String posUnique = formattedToken.getAnalyzedToken(k).getPOSTag(); if (posUnique == null) { wordForms.add(formattedToken.getToken()); oneForm = true; } else { if (SENTENCE_START_TAGNAME.equals(posUnique) || SENTENCE_END_TAGNAME.equals(posUnique) || PARAGRAPH_END_TAGNAME.equals(posUnique)) { if (!oneForm) { wordForms.add(formattedToken.getToken()); } oneForm = true; } else { oneForm = false; } } } } String targetPosTag = getTargetPosTag(); if (!oneForm) { for (int i = 0; i < readingCount; i++) { String[] possibleWordForms = synthesizer.synthesize(formattedToken.getAnalyzedToken(i), targetPosTag, true); if (possibleWordForms != null && possibleWordForms.length > 0) { wordForms.addAll(Arrays.asList(possibleWordForms)); } } } if (wordForms.isEmpty()) { if (match.checksSpelling()) { formattedString[0] = ""; } else { formattedString[0] = "(" + formattedToken.getToken() + ")"; } } else { formattedString = wordForms.toArray(new String[0]); } } else { TreeSet<String> wordForms = new TreeSet<>(); for (int i = 0; i < readingCount; i++) { String[] possibleWordForms = synthesizer.synthesize(formattedToken.getAnalyzedToken(i), posTag); if (possibleWordForms != null) { wordForms.addAll(Arrays.asList(possibleWordForms)); } } formattedString = wordForms.toArray(new String[0]); } } } String original; if (match.isStaticLemma()) { original = matchedToken != null ? matchedToken.getToken() : ""; } else { original = formattedToken != null ? formattedToken.getToken() : ""; } for (int i = 0; i < formattedString.length; i++) { formattedString[i] = convertCase(formattedString[i], original, lang); } // TODO should case conversion happen before or after including skipped tokens? IncludeRange includeSkipped = match.getIncludeSkipped(); if (includeSkipped != IncludeRange.NONE && skippedTokens != null && !skippedTokens.isEmpty()) { String[] helper = new String[formattedString.length]; for (int i = 0; i < formattedString.length; i++) { if (formattedString[i] == null) { formattedString[i] = ""; } helper[i] = formattedString[i] + skippedTokens; } formattedString = helper; } if (match.checksSpelling() && lang != null) { List<String> formattedStringElements = Arrays.asList(formattedString); // tagger-based speller List<AnalyzedTokenReadings> analyzed = lang.getTagger().tag(formattedStringElements); for (int i = 0; i < formattedString.length; i++) { AnalyzedToken analyzedToken = analyzed.get(i).getAnalyzedToken(0); if (analyzedToken.getLemma() == null && analyzedToken.hasNoTag()) { formattedString[i] = ""; } } } return formattedString; }
From source file:org.slc.sli.api.resources.security.TenantResourceImpl.java
@SuppressWarnings({ "rawtypes", "unchecked" }) protected String createLandingZone(final String tenantId, String edOrgId, String desc, List<String> userNames, boolean isSandbox) throws TenantResourceCreationException { // get the exisint tenant resource EntityService tenantService = store.lookupByResourceName(RESOURCE_NAME).getService(); NeutralQuery query = new NeutralQuery(); query.addCriteria(new NeutralCriteria(TENANT_ID, "=", tenantId)); String ingestionServer = findLeastLoadedIngestionServer(); File inboundDirFile = new File(landingZoneMountPoint); File fullPath = new File(inboundDirFile, tenantId + "/" + DigestUtils.sha256Hex(edOrgId)); String path = fullPath.getAbsolutePath(); // resolve localhost ingestion server to the current server name if (ingestionServer.equals(LZ_INGESTION_SERVER_LOCALHOST)) { try {/* w w w.j a va 2s . c om*/ ingestionServer = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { throw new TenantResourceCreationException(Status.INTERNAL_SERVER_ERROR, "Failed to resolve ingestion server for " + LZ_INGESTION_SERVER_LOCALHOST + ".", e); } } // look up ids of existing tenant entries List<String> existingIds = new ArrayList<String>(); for (String id : tenantService.listIds(query)) { existingIds.add(id); } // If more than exists, something is wrong if (existingIds.size() > 1) { throw new IllegalStateException("Internal error: multiple tenant entry with identical IDs"); } // If no tenant already exists, create one if (existingIds.size() == 0) { EntityBody newTenant = new EntityBody(); newTenant.put(TENANT_ID, tenantId); newTenant.put(DB_NAME, getDatabaseName(tenantId)); Map<String, Object> nlz = buildLandingZone(edOrgId, desc, ingestionServer, path, userNames); List<Map<String, Object>> newLandingZoneList = new ArrayList<Map<String, Object>>(); newLandingZoneList.add(nlz); newTenant.put(LZ, newLandingZoneList); // In sandbox a user doesn't create a realm, so this is the only opportunity to create // the custom roles if (isSandbox) { roleInitializer.dropAndBuildRoles(realmHelper.getSandboxRealmId()); } return tenantService.create(newTenant); } else { String existingTenantId = existingIds.get(0); // combine lzs from existing tenant and new tenant entry, overwriting with values of new // tenant entry if there is conflict. TreeSet allLandingZones = new TreeSet(new Comparator<Object>() { @Override public int compare(Object o1, Object o2) { Map<String, Object> lz1 = (Map<String, Object>) o1; Map<String, Object> lz2 = (Map<String, Object>) o2; if (!lz1.containsKey(LZ_EDUCATION_ORGANIZATION) || !(lz1.get(LZ_EDUCATION_ORGANIZATION) instanceof String)) { throw new IllegalArgumentException("Badly formed tenant entry: " + lz1.toString()); } if (!lz2.containsKey(LZ_EDUCATION_ORGANIZATION) || !(lz2.get(LZ_EDUCATION_ORGANIZATION) instanceof String)) { throw new IllegalArgumentException("Badly formed tenant entry: " + lz2.toString()); } return ((String) lz1.get(LZ_EDUCATION_ORGANIZATION)) .compareTo((String) lz2.get(LZ_EDUCATION_ORGANIZATION)); } }); Set<Map<String, Object>> all = allLandingZones; for (Map<String, Object> lz : all) { if (lz.get(LZ_EDUCATION_ORGANIZATION).equals(edOrgId)) { throw new TenantResourceCreationException(Status.CONFLICT, "This tenant/educational organization combination all ready has a landing zone provisioned."); } } EntityBody existingBody = tenantService.get(existingTenantId); List existingLandingZones = (List) existingBody.get(LZ); allLandingZones.addAll(existingLandingZones); Map<String, Object> nlz = this.buildLandingZone(edOrgId, desc, ingestionServer, path, userNames); allLandingZones.add(nlz); existingBody.put(LZ, new ArrayList(allLandingZones)); tenantService.update(existingTenantId, existingBody, false); return existingTenantId; } }
From source file:org.unitime.timetable.solver.studentsct.StudentSectioningDatabaseLoader.java
private Offering loadOffering(InstructionalOffering io, Hashtable<Long, Course> courseTable, Hashtable<Long, Section> classTable) { if (io.getInstrOfferingConfigs().isEmpty()) { return null; }// ww w .j a va 2 s.c o m String courseName = io.getCourseName(); Offering offering = new Offering(io.getUniqueId().longValue(), courseName); for (Iterator<CourseOffering> i = io.getCourseOfferings().iterator(); i.hasNext();) { CourseOffering co = i.next(); if (!co.isAllowStudentScheduling()) continue; int projected = (co.getProjectedDemand() == null ? 0 : co.getProjectedDemand().intValue()); boolean unlimited = false; int limit = 0; for (Iterator<InstrOfferingConfig> j = io.getInstrOfferingConfigs().iterator(); j.hasNext();) { InstrOfferingConfig ioc = j.next(); if (ioc.isUnlimitedEnrollment()) unlimited = true; limit += ioc.getLimit(); } if (co.getReservation() != null) limit = co.getReservation(); if (limit >= 9999) unlimited = true; if (unlimited) limit = -1; Course course = new Course(co.getUniqueId(), co.getSubjectArea().getSubjectAreaAbbreviation(), co.getCourseNbr(), offering, limit, projected); if (co.getCredit() != null) course.setCredit(co.getCredit().creditAbbv() + "|" + co.getCredit().creditText()); courseTable.put(co.getUniqueId(), course); } Hashtable<Long, Section> class2section = new Hashtable<Long, Section>(); Hashtable<Long, Subpart> ss2subpart = new Hashtable<Long, Subpart>(); DecimalFormat df = new DecimalFormat("000"); for (Iterator<InstrOfferingConfig> i = io.getInstrOfferingConfigs().iterator(); i.hasNext();) { InstrOfferingConfig ioc = i.next(); int configLimit = (ioc.isUnlimitedEnrollment() ? -1 : ioc.getLimit()); if (configLimit >= 9999) configLimit = -1; Config config = new Config(ioc.getUniqueId(), configLimit, courseName + " [" + ioc.getName() + "]", offering); TreeSet<SchedulingSubpart> subparts = new TreeSet<SchedulingSubpart>(new SchedulingSubpartComparator()); subparts.addAll(ioc.getSchedulingSubparts()); for (SchedulingSubpart ss : subparts) { String sufix = ss.getSchedulingSubpartSuffix(); Subpart parentSubpart = (ss.getParentSubpart() == null ? null : (Subpart) ss2subpart.get(ss.getParentSubpart().getUniqueId())); if (ss.getParentSubpart() != null && parentSubpart == null) { iProgress.error("Subpart " + ss.getSchedulingSubpartLabel() + " has parent " + ss.getSchedulingSubpartLabel() + ", but the appropriate parent subpart is not loaded."); } Subpart subpart = new Subpart(ss.getUniqueId().longValue(), df.format(ss.getItype().getItype()) + sufix, ss.getItype().getAbbv().trim() + (ioc.getInstructionalMethod() == null ? "" : " (" + ioc.getInstructionalMethod().getLabel() + ")"), config, parentSubpart); subpart.setAllowOverlap(ss.isStudentAllowOverlap()); if (ss.getCredit() != null) subpart.setCredit(ss.getCredit().creditAbbv() + "|" + ss.getCredit().creditText()); ss2subpart.put(ss.getUniqueId(), subpart); for (Iterator<Class_> j = ss.getClasses().iterator(); j.hasNext();) { Class_ c = j.next(); Section parentSection = (c.getParentClass() == null ? null : (Section) class2section.get(c.getParentClass().getUniqueId())); if (c.getParentClass() != null && parentSection == null) { iProgress.error("Class " + c.getClassLabel() + " has parent " + c.getClassLabel() + ", but the appropriate parent section is not loaded."); } Assignment a = c.getCommittedAssignment(); Placement p = null; if (iMakeupAssignmentsFromRequiredPrefs) { p = makeupPlacement(c); } else if (a != null) { p = a.getPlacement(); } if (p != null && p.getTimeLocation() != null) { p.getTimeLocation().setDatePattern(p.getTimeLocation().getDatePatternId(), datePatternName(a.getDatePattern(), p.getTimeLocation()), p.getTimeLocation().getWeekCode()); } int minLimit = c.getExpectedCapacity(); int maxLimit = c.getMaxExpectedCapacity(); int limit = maxLimit; if (minLimit < maxLimit && p != null) { int roomLimit = (int) Math .floor(p.getRoomSize() / (c.getRoomRatio() == null ? 1.0f : c.getRoomRatio())); // int roomLimit = Math.round((c.getRoomRatio() == null ? 1.0f : c.getRoomRatio()) * p.getRoomSize()); limit = Math.min(Math.max(minLimit, roomLimit), maxLimit); } if (ioc.isUnlimitedEnrollment() || limit >= 9999) limit = -1; if (iCheckEnabledForScheduling && !c.isEnabledForStudentScheduling()) limit = 0; Section section = new Section(c.getUniqueId().longValue(), limit, (c.getExternalUniqueId() == null ? c.getClassSuffix() == null ? c.getSectionNumberString() : c.getClassSuffix() : c.getExternalUniqueId()), subpart, p, getInstructorIds(c), getInstructorNames(c), parentSection); section.setCancelled(c.isCancelled()); class2section.put(c.getUniqueId(), section); classTable.put(c.getUniqueId(), section); } } } for (org.unitime.timetable.model.Reservation reservation : io.getReservations()) { Reservation r = null; if (reservation instanceof OverrideReservation) { List<Long> studentIds = new ArrayList<Long>(); for (org.unitime.timetable.model.Student s : ((org.unitime.timetable.model.IndividualReservation) reservation) .getStudents()) studentIds.add(s.getUniqueId()); r = new ReservationOverride(reservation.getUniqueId(), offering, studentIds); OverrideType type = ((OverrideReservation) reservation).getOverrideType(); ((ReservationOverride) r).setMustBeUsed(type.isMustBeUsed()); ((ReservationOverride) r).setAllowOverlap(type.isAllowTimeConflict()); ((ReservationOverride) r).setCanAssignOverLimit(type.isAllowOverLimit()); } else if (reservation instanceof org.unitime.timetable.model.IndividualReservation) { List<Long> studentIds = new ArrayList<Long>(); for (org.unitime.timetable.model.Student s : ((org.unitime.timetable.model.IndividualReservation) reservation) .getStudents()) studentIds.add(s.getUniqueId()); r = new IndividualReservation(reservation.getUniqueId(), offering, studentIds); r.setPriority(ApplicationProperty.ReservationPriorityIndividual.intValue()); r.setAllowOverlap(ApplicationProperty.ReservationAllowOverlapIndividual.isTrue()); r.setCanAssignOverLimit(ApplicationProperty.ReservationCanOverLimitIndividual.isTrue()); r.setMustBeUsed(ApplicationProperty.ReservationMustBeUsedIndividual.isTrue()); } else if (reservation instanceof StudentGroupReservation) { List<Long> studentIds = new ArrayList<Long>(); for (org.unitime.timetable.model.Student s : ((StudentGroupReservation) reservation).getGroup() .getStudents()) studentIds.add(s.getUniqueId()); r = new GroupReservation(reservation.getUniqueId(), (reservation.getLimit() == null ? iNoUnlimitedGroupReservations ? studentIds.size() : -1.0 : reservation.getLimit()), offering, studentIds); r.setPriority(ApplicationProperty.ReservationPriorityGroup.intValue()); r.setAllowOverlap(ApplicationProperty.ReservationAllowOverlapGroup.isTrue()); r.setCanAssignOverLimit(ApplicationProperty.ReservationCanOverLimitGroup.isTrue()); r.setMustBeUsed(ApplicationProperty.ReservationMustBeUsedGroup.isTrue()); } else if (reservation instanceof org.unitime.timetable.model.CurriculumReservation) { org.unitime.timetable.model.CurriculumReservation cr = (org.unitime.timetable.model.CurriculumReservation) reservation; List<String> classifications = new ArrayList<String>(); for (AcademicClassification clasf : cr.getClassifications()) classifications.add(clasf.getCode()); List<String> majors = new ArrayList<String>(); for (PosMajor major : cr.getMajors()) majors.add(major.getCode()); r = new CurriculumReservation(reservation.getUniqueId(), (reservation.getLimit() == null ? -1.0 : reservation.getLimit()), offering, cr.getArea().getAcademicAreaAbbreviation(), classifications, majors); r.setPriority(ApplicationProperty.ReservationPriorityCurriculum.intValue()); r.setAllowOverlap(ApplicationProperty.ReservationAllowOverlapCurriculum.isTrue()); r.setCanAssignOverLimit(ApplicationProperty.ReservationCanOverLimitCurriculum.isTrue()); r.setMustBeUsed(ApplicationProperty.ReservationMustBeUsedCurriculum.isTrue()); } else if (reservation instanceof org.unitime.timetable.model.CourseReservation) { CourseOffering co = ((org.unitime.timetable.model.CourseReservation) reservation).getCourse(); for (Course course : offering.getCourses()) { if (co.getUniqueId().equals(course.getId())) r = new CourseReservation(reservation.getUniqueId(), course); } r.setPriority(ApplicationProperty.ReservationPriorityCourse.intValue()); r.setAllowOverlap(ApplicationProperty.ReservationAllowOverlapCourse.isTrue()); r.setCanAssignOverLimit(ApplicationProperty.ReservationCanOverLimitCourse.isTrue()); r.setMustBeUsed(ApplicationProperty.ReservationMustBeUsedCourse.isTrue()); } if (r == null) { iProgress.warn("Failed to load reservation " + reservation.getUniqueId() + "."); continue; } r.setExpired(reservation.isExpired()); configs: for (InstrOfferingConfig ioc : reservation.getConfigurations()) { for (Config config : offering.getConfigs()) { if (ioc.getUniqueId().equals(config.getId())) { r.addConfig(config); continue configs; } } } classes: for (Class_ c : reservation.getClasses()) { for (Config config : offering.getConfigs()) { for (Subpart subpart : config.getSubparts()) { for (Section section : subpart.getSections()) { if (c.getUniqueId().equals(section.getId())) { r.addSection(section); continue classes; } } } } } } if (io.isByReservationOnly()) new DummyReservation(offering); return offering; }
From source file:org.dasein.cloud.aws.AWSCloud.java
private String buildEc2AuthString(String method, String serviceUrl, Map<String, String> parameters) throws InternalException { StringBuilder authString = new StringBuilder(); TreeSet<String> sortedKeys; URI endpoint;//from w w w. j a v a 2s .com String tmp; authString.append(method); authString.append("\n"); try { endpoint = new URI(serviceUrl); } catch (URISyntaxException e) { logger.error(e); e.printStackTrace(); throw new InternalException(e); } authString.append(endpoint.getHost().toLowerCase()); authString.append("\n"); tmp = endpoint.getPath(); if (tmp == null || tmp.length() == 0) { tmp = "/"; } authString.append(encode(tmp, true)); authString.append("\n"); sortedKeys = new TreeSet<String>(); sortedKeys.addAll(parameters.keySet()); boolean first = true; for (String key : sortedKeys) { String value = parameters.get(key); if (!first) { authString.append("&"); } else { first = false; } authString.append(encode(key, false)); authString.append("="); if (value == null) { value = ""; } authString.append(encode(value, false)); } return authString.toString(); }
From source file:com.ecyrd.jspwiki.WikiEngine.java
/** * Returns a Collection of WikiPages, sorted in time * order of last change (i.e. first object is the most * recently changed). This method also includes attachments. * * @return Collection of WikiPage objects. In reality, the returned * collection is a Set, but due to API compatibility reasons, * we're not changing the signature soon... *///from ww w . j a v a2 s.c om // FIXME: Should really get a Date object and do proper comparisons. // This is terribly wasteful. @SuppressWarnings("unchecked") public Collection getRecentChanges() { try { Collection<WikiPage> pages = m_pageManager.getAllPages(); Collection<Attachment> atts = m_attachmentManager.getAllAttachments(); TreeSet<WikiPage> sortedPages = new TreeSet<WikiPage>(new PageTimeComparator()); sortedPages.addAll(pages); sortedPages.addAll(atts); return sortedPages; } catch (ProviderException e) { log.error("Unable to fetch all pages: ", e); return null; } }
From source file:org.dbflute.maven.plugin.CreateClientPlugin.java
protected String extractLatestVersion(String enginePrefix, List<String> engineDirNameList) { final TreeSet<String> versionOrderedSet = new TreeSet<String>(new Comparator<String>() { public int compare(String o1, String o2) { final String comp1; final String comp2; if (startsWithDBFlute(o1) && startsWithDBFlute(o2)) { comp1 = filterPriority(extractVersion(o1)); comp2 = filterPriority(extractVersion(o2)); } else { comp1 = (startsWithDBFlute(o1) ? "9" : "0") + o1; comp2 = (startsWithDBFlute(o2) ? "9" : "0") + o2; }/*from w ww .j av a 2 s. c om*/ return -comp1.compareTo(comp2); // ordering bigger } protected String extractVersion(String o1) { return o1.substring(o1.indexOf("-") + "-".length()); } protected boolean startsWithDBFlute(String str) { return str.startsWith(enginePrefix); } protected String filterPriority(String ver) { if (!ver.contains("-")) { // e.g. dbflute-1.1.0 (B. next priority) return ver + "-77"; } // contains hyphen here if (ver.contains("-sp")) { // e.g. 1.1.0-sp1 (A. most priority) return ver.replace("-sp", "-99"); } else if (ver.contains("-RC")) { // e.g. 1.1.0-RC1 (C. middle priority) return ver.replace("-RC", "-55"); } else if (ver.contains("-SNAPSHOT")) { // e.g. 1.1.0-RC1 (D. low priority) return ver.substring(0, ver.indexOf("-")) + "-33" + ver.substring(ver.indexOf("-")); } else { // e.g. 1.1.0-pilot1 (E. low priority) return ver.substring(0, ver.indexOf("-")) + "-11" + ver.substring(ver.indexOf("-")); } } }); versionOrderedSet.addAll(engineDirNameList); final String latestVersionEngineName = versionOrderedSet.iterator().next(); return latestVersionEngineName.substring(latestVersionEngineName.indexOf("-") + "-".length()); }
From source file:org.zaproxy.zap.extension.ascanrulesBeta.SessionFixation.java
/** * scans all GET, Cookie params for Session fields, and looks for SessionFixation * vulnerabilities//ww w.j a v a2s .c o m */ @Override public void scan() { // TODO: scan the POST (form) params for session id fields. try { boolean loginUrl = false; // Are we dealing with a login url in any of the contexts of which this uri is part URI requestUri = getBaseMsg().getRequestHeader().getURI(); ExtensionAuthentication extAuth = (ExtensionAuthentication) Control.getSingleton().getExtensionLoader() .getExtension(ExtensionAuthentication.NAME); // using the session, get the list of contexts for the url List<Context> contextList = extAuth.getModel().getSession().getContextsForUrl(requestUri.getURI()); // now loop, and see if the url is a login url in each of the contexts in turn... for (Context context : contextList) { URI loginUri = extAuth.getLoginRequestURIForContext(context); if (loginUri != null && requestUri.getPath() != null) { if (requestUri.getScheme().equals(loginUri.getScheme()) && requestUri.getHost().equals(loginUri.getHost()) && requestUri.getPort() == loginUri.getPort() && requestUri.getPath().equals(loginUri.getPath())) { // we got this far.. only the method (GET/POST), user details, query params, // fragment, and POST params // are possibly different from the login page. loginUrl = true; break; } } } // For now (from Zap 2.0), the Session Fixation scanner will only run for login pages if (loginUrl == false) { log.debug("For the Session Fixation scanner to actually do anything, a Login Page *must* be set!"); return; } // find all params set in the request (GET/POST/Cookie) // Note: this will be the full set, before we delete anything. TreeSet<HtmlParameter> htmlParams = new TreeSet<>(); htmlParams.addAll(getBaseMsg().getRequestHeader().getCookieParams()); // request cookies only. no response cookies htmlParams.addAll(getBaseMsg().getFormParams()); // add in the POST params htmlParams.addAll(getBaseMsg().getUrlParams()); // add in the GET params // Now add in the pseudo parameters set in the URL itself, such as in the following: // http://www.example.com/someurl;JSESSIONID=abcdefg?x=123&y=456 // as opposed to the url parameters in the following example, which are already picked // up by getUrlParams() // http://www.example.com/someurl?JSESSIONID=abcdefg&x=123&y=456 // convert from org.apache.commons.httpclient.URI to a String String requestUrl = "Unknown URL"; try { requestUrl = new URL(requestUri.getScheme(), requestUri.getHost(), requestUri.getPort(), requestUri.getPath()).toString(); } catch (Exception e) { // no point in continuing. The URL is invalid. This is a peculiarity in the Zap // core, // and can happen when // - the user browsed to http://www.example.com/bodgeit and // - the user did not browse to http://www.example.com or to http://www.example.com/ // so the Zap GUI displays "http://www.example.com" as a node under "Sites", // and under that, it displays the actual urls to which the user browsed // (http://www.example.com/bodgeit, for instance) // When the user selects the node "http://www.example.com", and tries to scan it // with // the session fixation scanner, the URI that is passed is "http://www.example.com", // which is *not* a valid url. // If the user actually browses to "http://www.example.com" (even without the // trailing slash) // the web browser appends the trailing slash, and so Zap records the URI as // "http://www.example.com/", which IS a valid url, and which can (and should) be // scanned. // // In short.. if this happens, we do not want to scan the URL anyway // (because the user never browsed to it), so just do nothing instead. log.error("Cannot convert URI [" + requestUri + "] to a URL: " + e.getMessage()); return; } // suck out any pseudo url parameters from the url Set<HtmlParameter> pseudoUrlParams = getPseudoUrlParameters(requestUrl); htmlParams.addAll(pseudoUrlParams); if (this.debugEnabled) log.debug("Pseudo url params of URL [" + requestUrl + "] : [" + pseudoUrlParams + "]"); //// for each parameter in turn, // int counter = 0; for (Iterator<HtmlParameter> iter = htmlParams.iterator(); iter.hasNext();) { HttpMessage msg1Final; HttpMessage msg1Initial = getNewMsg(); //// debug logic only.. to do first field only // counter ++; // if ( counter > 1 ) // return; HtmlParameter currentHtmlParameter = iter.next(); // Useful for debugging, but I can't find a way to view this data in the GUI, so // leave it out for now. // msg1Initial.setNote("Message 1 for parameter "+ currentHtmlParameter); if (this.debugEnabled) log.debug("Scanning URL [" + msg1Initial.getRequestHeader().getMethod() + "] [" + msg1Initial.getRequestHeader().getURI() + "], [" + currentHtmlParameter.getType() + "] field [" + currentHtmlParameter.getName() + "] with value [" + currentHtmlParameter.getValue() + "] for Session Fixation"); if (currentHtmlParameter.getType().equals(HtmlParameter.Type.cookie)) { // careful to pick up the cookies from the Request, and not to include cookies // set in any earlier response TreeSet<HtmlParameter> cookieRequestParams = msg1Initial.getRequestHeader().getCookieParams(); // delete the original cookie from the parameters cookieRequestParams.remove(currentHtmlParameter); msg1Initial.setCookieParams(cookieRequestParams); // send the message, minus the cookie parameter, and see how it comes back. // Note: do NOT automatically follow redirects.. handle those here instead. sendAndReceive(msg1Initial, false, false); ///////////////////////////// // create a copy of msg1Initial to play with to handle redirects (if any). // we use a copy because if we change msg1Initial itself, it messes the URL and // params displayed on the GUI. msg1Final = msg1Initial; HtmlParameter cookieBack1 = getResponseCookie(msg1Initial, currentHtmlParameter.getName()); long cookieBack1TimeReceived = System.currentTimeMillis(); // in ms. when was the cookie received? // Important if it has a Max-Age directive Date cookieBack1ExpiryDate = null; HttpMessage temp = msg1Initial; int redirectsFollowed1 = 0; while (HttpStatusCode.isRedirection(temp.getResponseHeader().getStatusCode())) { // Note that we need to clone the Request and the Response.. // we seem to need to track the secure flag now to make sure its set later boolean secure1 = temp.getRequestHeader().isSecure(); temp = temp.cloneAll(); // clone the previous message redirectsFollowed1++; if (redirectsFollowed1 > 10) { throw new Exception("Too many redirects were specified in the first message"); } // create a new URI from the absolute location returned, and interpret it as // escaped // note that the standard says that the Location returned should be // absolute, but it ain't always so... URI newLocation = new URI(temp.getResponseHeader().getHeader(HttpHeader.LOCATION), true); // and follow the forward url // need to clear the params (which would come from the initial POST, // otherwise) temp.getRequestHeader().setGetParams(new TreeSet<HtmlParameter>()); temp.setRequestBody(""); temp.setResponseBody(""); // make sure no values accidentally carry from one iteration to // the next try { temp.getRequestHeader().setURI(newLocation); } catch (Exception e) { // the Location field contents may not be standards compliant. Lets // generate a uri to use as a workaround where a relative path was // given instead of an absolute one URI newLocationWorkaround = new URI(temp.getRequestHeader().getURI(), temp.getResponseHeader().getHeader(HttpHeader.LOCATION), true); // try again, except this time, if it fails, don't try to handle it if (this.debugEnabled) log.debug("The Location [" + newLocation + "] specified in a redirect was not valid. Trying workaround url [" + newLocationWorkaround + "]"); temp.getRequestHeader().setURI(newLocationWorkaround); } temp.getRequestHeader().setSecure(secure1); temp.getRequestHeader().setMethod(HttpRequestHeader.GET); temp.getRequestHeader().setContentLength(0); // since we send a GET, the body will be 0 long if (cookieBack1 != null) { // if the previous request sent back a cookie, we need to set that // cookie when following redirects, as a browser would if (this.debugEnabled) log.debug("Adding in cookie [" + cookieBack1 + "] for a redirect"); TreeSet<HtmlParameter> forwardCookieParams = temp.getRequestHeader().getCookieParams(); forwardCookieParams.add(cookieBack1); temp.getRequestHeader().setCookieParams(forwardCookieParams); } if (this.debugEnabled) log.debug("DEBUG: Cookie Message 1 causes us to follow redirect to [" + newLocation + "]"); sendAndReceive(temp, false, false); // do NOT redirect.. handle it here // handle any cookies set from following redirects that override the cookie // set in the redirect itself (if any) // note that this will handle the case where a latter cookie unsets one set // earlier. HtmlParameter cookieBack1Temp = getResponseCookie(temp, currentHtmlParameter.getName()); if (cookieBack1Temp != null) { cookieBack1 = cookieBack1Temp; cookieBack1TimeReceived = System.currentTimeMillis(); // in ms. record when we got the // cookie.. in case it has a // Max-Age directive } // reset the "final" version of message1 to use the final response in the // chain msg1Final = temp; } /////////////////////////// // if non-200 on the final response for message 1, no point in continuing. Bale // out. if (msg1Final.getResponseHeader().getStatusCode() != HttpStatusCode.OK) { if (this.debugEnabled) log.debug( "Got a non-200 response code [" + msg1Final.getResponseHeader().getStatusCode() + "] when sending [" + msg1Initial.getRequestHeader().getURI() + "] with param [" + currentHtmlParameter.getName() + "] = NULL (possibly somewhere in the redirects)"); continue; } // now check that the response set a cookie. if it didn't, then either.. // 1) we are messing with the wrong field // 2) the app doesn't do sessions // either way, there is not much point in continuing to look at this field.. if (cookieBack1 == null || cookieBack1.getValue() == null) { // no cookie was set, or the cookie param was set to a null value if (this.debugEnabled) log.debug("The Cookie parameter was NOT set in the response, when cookie param [" + currentHtmlParameter.getName() + "] was set to NULL: " + cookieBack1); continue; } ////////////////////////////////////////////////////////////////////// // at this point, before continuing to check for Session Fixation, do some other // checks on the session cookie we got back // that might cause us to raise additional alerts (in addition to doing the main // check for Session Fixation) ////////////////////////////////////////////////////////////////////// // Check 1: was the session cookie sent and received securely by the server? // If not, alert this fact if ((!msg1Final.getRequestHeader().isSecure()) || (!cookieBack1.getFlags().contains("secure"))) { // pass the original param value here, not the new value, since we're // displaying the session id exposed in the original message String extraInfo = Constant.messages.getString( "ascanbeta.sessionidsentinsecurely.alert.extrainfo", currentHtmlParameter.getType(), currentHtmlParameter.getName(), currentHtmlParameter.getValue()); if (!cookieBack1.getFlags().contains("secure")) { extraInfo += ("\n" + Constant.messages.getString( "ascanbeta.sessionidsentinsecurely.alert.extrainfo.secureflagnotset")); } // and figure out the risk, depending on whether it is a login page int risk = Alert.RISK_LOW; if (loginUrl) { extraInfo += ("\n" + Constant.messages .getString("ascanbeta.sessionidsentinsecurely.alert.extrainfo.loginpage")); // login page, so higher risk risk = Alert.RISK_MEDIUM; } else { // not a login page.. lower risk risk = Alert.RISK_LOW; } String attack = Constant.messages.getString( "ascanbeta.sessionidsentinsecurely.alert.attack", currentHtmlParameter.getType(), currentHtmlParameter.getName()); String vulnname = Constant.messages.getString("ascanbeta.sessionidsentinsecurely.name"); String vulndesc = Constant.messages.getString("ascanbeta.sessionidsentinsecurely.desc"); String vulnsoln = Constant.messages.getString("ascanbeta.sessionidsentinsecurely.soln"); // call bingo with some extra info, indicating that the alert is // not specific to Session Fixation, but has its own title and description // (etc) // the alert here is "Session id sent insecurely", or words to that effect. bingo(risk, Alert.CONFIDENCE_MEDIUM, vulnname, vulndesc, getBaseMsg().getRequestHeader().getURI().getURI(), currentHtmlParameter.getName(), attack, extraInfo, vulnsoln, getBaseMsg()); if (log.isDebugEnabled()) { String logMessage = MessageFormat.format( "A session identifier in {2} field: [{3}] may be sent " + "via an insecure mechanism at [{0}] URL [{1}]", getBaseMsg().getRequestHeader().getMethod(), getBaseMsg().getRequestHeader().getURI().getURI(), currentHtmlParameter.getType(), currentHtmlParameter.getName()); log.debug(logMessage); } // Note: do NOT continue to the next field at this point.. // since we still need to check for Session Fixation. } ////////////////////////////////////////////////////////////////////// // Check 2: is the session cookie that was set accessible to Javascript? // If so, alert this fact too if (!cookieBack1.getFlags().contains("httponly") && loginUrl) { // pass the original param value here, not the new value, since we're // displaying the session id exposed in the original message String extraInfo = Constant.messages.getString( "ascanbeta.sessionidaccessiblebyjavascript.alert.extrainfo", currentHtmlParameter.getType(), currentHtmlParameter.getName(), currentHtmlParameter.getValue()); String attack = Constant.messages.getString( "ascanbeta.sessionidaccessiblebyjavascript.alert.attack", currentHtmlParameter.getType(), currentHtmlParameter.getName()); String vulnname = Constant.messages .getString("ascanbeta.sessionidaccessiblebyjavascript.name"); String vulndesc = Constant.messages .getString("ascanbeta.sessionidaccessiblebyjavascript.desc"); String vulnsoln = Constant.messages .getString("ascanbeta.sessionidaccessiblebyjavascript.soln"); extraInfo += ("\n" + Constant.messages .getString("ascanbeta.sessionidaccessiblebyjavascript.alert.extrainfo.loginpage")); // call bingo with some extra info, indicating that the alert is // not specific to Session Fixation, but has its own title and description // (etc) // the alert here is "Session id accessible in Javascript", or words to that // effect. bingo(Alert.RISK_LOW, Alert.CONFIDENCE_MEDIUM, vulnname, vulndesc, getBaseMsg().getRequestHeader().getURI().getURI(), currentHtmlParameter.getName(), attack, extraInfo, vulnsoln, getBaseMsg()); if (log.isDebugEnabled()) { String logMessage = MessageFormat.format( "A session identifier in [{0}] URL [{1}] {2} field: " + "[{3}] may be accessible to JavaScript", getBaseMsg().getRequestHeader().getMethod(), getBaseMsg().getRequestHeader().getURI().getURI(), currentHtmlParameter.getType(), currentHtmlParameter.getName()); log.debug(logMessage); } // Note: do NOT continue to the next field at this point.. // since we still need to check for Session Fixation. } ////////////////////////////////////////////////////////////////////// // Check 3: is the session cookie set to expire soon? when the browser session // closes? never? // the longer the session cookie is valid, the greater the risk. alert it // accordingly String cookieBack1Expiry = null; int sessionExpiryRiskLevel; String sessionExpiryDescription = null; // check for the Expires header for (Iterator<String> i = cookieBack1.getFlags().iterator(); i.hasNext();) { String cookieBack1Flag = i.next(); // if ( this.debugEnabled ) log.debug("Cookie back 1 flag (checking for // Expires): "+ cookieBack1Flag); // match in a case insensitive manner. never know what case various web // servers are going to send back. // if (cookieBack1Flag.matches("(?i)expires=.*")) { if (cookieBack1Flag.toLowerCase(Locale.ENGLISH).startsWith("expires=")) { String[] cookieBack1FlagValues = cookieBack1Flag.split("="); if (cookieBack1FlagValues.length > 1) { if (this.debugEnabled) log.debug("Cookie Expiry: " + cookieBack1FlagValues[1]); cookieBack1Expiry = cookieBack1FlagValues[1]; // the Date String sessionExpiryDescription = cookieBack1FlagValues[1]; // the Date String cookieBack1ExpiryDate = DateUtil.parseDate(cookieBack1Expiry); // the actual Date } } } // also check for the Max-Age header, which overrides the Expires header. // WARNING: this Directive is reported to be ignored by IE, so if both Expires // and Max-Age are present // and we report based on the Max-Age value, but the user is using IE, then the // results reported // by us here may be different from those actually experienced by the user! (we // use Max-Age, IE uses Expires) for (Iterator<String> i = cookieBack1.getFlags().iterator(); i.hasNext();) { String cookieBack1Flag = i.next(); // if ( this.debugEnabled ) log.debug("Cookie back 1 flag (checking for // Max-Age): "+ cookieBack1Flag); // match in a case insensitive manner. never know what case various web // servers are going to send back. if (cookieBack1Flag.toLowerCase(Locale.ENGLISH).startsWith("max-age=")) { String[] cookieBack1FlagValues = cookieBack1Flag.split("="); if (cookieBack1FlagValues.length > 1) { // now the Max-Age value is the number of seconds relative to the // time the browser received the cookie // (as stored in cookieBack1TimeReceived) if (this.debugEnabled) log.debug("Cookie Max Age: " + cookieBack1FlagValues[1]); long cookie1DropDeadMS = cookieBack1TimeReceived + (Long.parseLong(cookieBack1FlagValues[1]) * 1000); cookieBack1ExpiryDate = new Date(cookie1DropDeadMS); // the actual Date the cookie // expires (by Max-Age) cookieBack1Expiry = DateUtil.formatDate(cookieBack1ExpiryDate, DateUtil.PATTERN_RFC1123); sessionExpiryDescription = cookieBack1Expiry; // needs to the Date String } } } String sessionExpiryRiskDescription = null; // check the Expiry/Max-Age details garnered (if any) // and figure out the risk, depending on whether it is a login page // and how long the session will live before expiring if (cookieBack1ExpiryDate == null) { // session expires when the browser closes.. rate this as medium risk? sessionExpiryRiskLevel = Alert.RISK_MEDIUM; sessionExpiryRiskDescription = "ascanbeta.sessionidexpiry.browserclose"; sessionExpiryDescription = Constant.messages.getString(sessionExpiryRiskDescription); } else { long datediffSeconds = (cookieBack1ExpiryDate.getTime() - cookieBack1TimeReceived) / 1000; long anHourSeconds = 3600; long aDaySeconds = anHourSeconds * 24; long aWeekSeconds = aDaySeconds * 7; if (datediffSeconds < 0) { if (this.debugEnabled) log.debug("The session cookie has expired already"); sessionExpiryRiskDescription = "ascanbeta.sessionidexpiry.timeexpired"; sessionExpiryRiskLevel = Alert.RISK_INFO; // no risk.. the cookie has expired already } else if (datediffSeconds > aWeekSeconds) { if (this.debugEnabled) log.debug("The session cookie is set to last for more than a week!"); sessionExpiryRiskDescription = "ascanbeta.sessionidexpiry.timemorethanoneweek"; sessionExpiryRiskLevel = Alert.RISK_HIGH; } else if (datediffSeconds > aDaySeconds) { if (this.debugEnabled) log.debug("The session cookie is set to last for more than a day"); sessionExpiryRiskDescription = "ascanbeta.sessionidexpiry.timemorethanoneday"; sessionExpiryRiskLevel = Alert.RISK_MEDIUM; } else if (datediffSeconds > anHourSeconds) { if (this.debugEnabled) log.debug("The session cookie is set to last for more than an hour"); sessionExpiryRiskDescription = "ascanbeta.sessionidexpiry.timemorethanonehour"; sessionExpiryRiskLevel = Alert.RISK_LOW; } else { if (this.debugEnabled) log.debug("The session cookie is set to last for less than an hour!"); sessionExpiryRiskDescription = "ascanbeta.sessionidexpiry.timelessthanonehour"; sessionExpiryRiskLevel = Alert.RISK_INFO; } } if (!loginUrl) { // decrement the risk if it's not a login page sessionExpiryRiskLevel--; } // alert it if the default session expiry risk level is more than informational if (sessionExpiryRiskLevel > Alert.RISK_INFO) { // pass the original param value here, not the new value String cookieReceivedTime = cookieBack1Expiry = DateUtil .formatDate(new Date(cookieBack1TimeReceived), DateUtil.PATTERN_RFC1123); String extraInfo = Constant.messages.getString("ascanbeta.sessionidexpiry.alert.extrainfo", currentHtmlParameter.getType(), currentHtmlParameter.getName(), currentHtmlParameter.getValue(), sessionExpiryDescription, cookieReceivedTime); String attack = Constant.messages.getString("ascanbeta.sessionidexpiry.alert.attack", currentHtmlParameter.getType(), currentHtmlParameter.getName()); String vulnname = Constant.messages.getString("ascanbeta.sessionidexpiry.name"); String vulndesc = Constant.messages.getString("ascanbeta.sessionidexpiry.desc"); String vulnsoln = Constant.messages.getString("ascanbeta.sessionidexpiry.soln"); if (loginUrl) { extraInfo += ("\n" + Constant.messages .getString("ascanbeta.sessionidexpiry.alert.extrainfo.loginpage")); } // call bingo with some extra info, indicating that the alert is // not specific to Session Fixation, but has its own title and description // (etc) // the alert here is "Session Id Expiry Time is excessive", or words to that // effect. bingo(sessionExpiryRiskLevel, Alert.CONFIDENCE_MEDIUM, vulnname, vulndesc, getBaseMsg().getRequestHeader().getURI().getURI(), currentHtmlParameter.getName(), attack, extraInfo, vulnsoln, getBaseMsg()); if (log.isDebugEnabled()) { String logMessage = MessageFormat.format( "A session identifier in [{0}] URL [{1}] {2} field: " + "[{3}] may be accessed until [{4}], unless the session is destroyed.", getBaseMsg().getRequestHeader().getMethod(), getBaseMsg().getRequestHeader().getURI().getURI(), currentHtmlParameter.getType(), currentHtmlParameter.getName(), sessionExpiryDescription); log.debug(logMessage); } // Note: do NOT continue to the next field at this point.. // since we still need to check for Session Fixation. } if (!loginUrl) { // not a login page.. skip continue; } //////////////////////////////////////////////////////////////////////////////////////////// /// Message 2 - processing starts here //////////////////////////////////////////////////////////////////////////////////////////// // so now that we know the URL responds with 200 (OK), and that it sets a // cookie, lets re-issue the original request, // but lets add in the new (valid) session cookie that was just issued. // we will re-send it. the aim is then to see if it accepts the cookie (BAD, in // some circumstances), // or if it issues a new session cookie (GOOD, in most circumstances) if (this.debugEnabled) log.debug("A Cookie was set by the URL for the correct param, when param [" + currentHtmlParameter.getName() + "] was set to NULL: " + cookieBack1); // use a copy of msg2Initial, since it has already had the correct cookie // removed in the request.. // do NOT use msg2Initial itself, as this will cause both requests in the GUI to // show the modified data.. // finally send the second message, and see how it comes back. HttpMessage msg2Initial = msg1Initial.cloneRequest(); TreeSet<HtmlParameter> cookieParams2Set = msg2Initial.getRequestHeader().getCookieParams(); cookieParams2Set.add(cookieBack1); msg2Initial.setCookieParams(cookieParams2Set); // resend the copy of the initial message, but with the valid session cookie // added in, to see if it is accepted // do not automatically follow redirects, as we need to check these for cookies // being set. sendAndReceive(msg2Initial, false, false); // create a copy of msg2Initial to play with to handle redirects (if any). // we use a copy because if we change msg2Initial itself, it messes the URL and // params displayed on the GUI. HttpMessage temp2 = msg2Initial; HttpMessage msg2Final = msg2Initial; HtmlParameter cookieBack2Previous = cookieBack1; HtmlParameter cookieBack2 = getResponseCookie(msg2Initial, currentHtmlParameter.getName()); int redirectsFollowed2 = 0; while (HttpStatusCode.isRedirection(temp2.getResponseHeader().getStatusCode())) { // clone the previous message boolean secure2 = temp2.getRequestHeader().isSecure(); temp2 = temp2.cloneAll(); redirectsFollowed2++; if (redirectsFollowed2 > 10) { throw new Exception("Too many redirects were specified in the second message"); } // create a new URI from the absolute location returned, and interpret it as // escaped // note that the standard says that the Location returned should be // absolute, but it ain't always so... URI newLocation = new URI(temp2.getResponseHeader().getHeader(HttpHeader.LOCATION), true); // and follow the forward url // need to clear the params (which would come from the initial POST, // otherwise) temp2.getRequestHeader().setGetParams(new TreeSet<HtmlParameter>()); temp2.setRequestBody(""); temp2.setResponseBody(""); // make sure no values accidentally carry from one iteration to // the next try { temp2.getRequestHeader().setURI(newLocation); } catch (Exception e) { // the Location field contents may not be standards compliant. Lets // generate a uri to use as a workaround where a relative path was // given instead of an absolute one URI newLocationWorkaround = new URI(temp2.getRequestHeader().getURI(), temp2.getResponseHeader().getHeader(HttpHeader.LOCATION), true); // try again, except this time, if it fails, don't try to handle it if (this.debugEnabled) log.debug("The Location [" + newLocation + "] specified in a redirect was not valid. Trying workaround url [" + newLocationWorkaround + "]"); temp2.getRequestHeader().setURI(newLocationWorkaround); } temp2.getRequestHeader().setSecure(secure2); temp2.getRequestHeader().setMethod(HttpRequestHeader.GET); temp2.getRequestHeader().setContentLength(0); // since we send a GET, the body will be 0 long if (cookieBack2 != null) { // if the previous request sent back a cookie, we need to set that // cookie when following redirects, as a browser would // also make sure to delete the previous value set for the cookie value if (this.debugEnabled) { log.debug("Deleting old cookie [" + cookieBack2Previous + "], and adding in cookie [" + cookieBack2 + "] for a redirect"); } TreeSet<HtmlParameter> forwardCookieParams = temp2.getRequestHeader().getCookieParams(); forwardCookieParams.remove(cookieBack2Previous); forwardCookieParams.add(cookieBack2); temp2.getRequestHeader().setCookieParams(forwardCookieParams); } sendAndReceive(temp2, false, false); // do NOT automatically redirect.. handle redirects here // handle any cookies set from following redirects that override the cookie // set in the redirect itself (if any) // note that this will handle the case where a latter cookie unsets one set // earlier. HtmlParameter cookieBack2Temp = getResponseCookie(temp2, currentHtmlParameter.getName()); if (cookieBack2Temp != null) { cookieBack2Previous = cookieBack2; cookieBack2 = cookieBack2Temp; } // reset the "final" version of message2 to use the final response in the // chain msg2Final = temp2; } if (this.debugEnabled) log.debug("Done following redirects"); // final result was non-200, no point in continuing. Bale out. if (msg2Final.getResponseHeader().getStatusCode() != HttpStatusCode.OK) { if (this.debugEnabled) log.debug( "Got a non-200 response code [" + msg2Final.getResponseHeader().getStatusCode() + "] when sending [" + msg2Initial.getRequestHeader().getURI() + "] with a borrowed cookie (or by following a redirect) for param [" + currentHtmlParameter.getName() + "]"); continue; // to next parameter } // and what we've been waiting for.. do we get a *different* cookie being set in // the response of message 2?? // or do we get a new cookie back at all? // No cookie back => the borrowed cookie was accepted. Not ideal // Cookie back, but same as the one we sent in => the borrowed cookie was // accepted. Not ideal if ((cookieBack2 == null) || cookieBack2.getValue().equals(cookieBack1.getValue())) { // no cookie back, when a borrowed cookie is in use.. suspicious! // use the cookie extrainfo message, which is specific to the case of // cookies // pretty much everything else is generic to all types of Session Fixation // vulnerabilities String extraInfo = Constant.messages.getString( "ascanbeta.sessionfixation.alert.cookie.extrainfo", currentHtmlParameter.getName(), cookieBack1.getValue(), (cookieBack2 == null ? "NULL" : cookieBack2.getValue())); String attack = Constant.messages.getString("ascanbeta.sessionfixation.alert.attack", currentHtmlParameter.getType(), currentHtmlParameter.getName()); if (loginUrl) { extraInfo += ("\n" + Constant.messages .getString("ascanbeta.sessionfixation.alert.cookie.extrainfo.loginpage")); } bingo(Alert.RISK_INFO, Alert.CONFIDENCE_MEDIUM, msg2Initial.getRequestHeader().getURI().getURI(), currentHtmlParameter.getName(), attack, extraInfo, msg2Initial); logSessionFixation(msg2Initial, currentHtmlParameter.getType().toString(), currentHtmlParameter.getName()); } continue; // jump to the next iteration of the loop (ie, the next parameter) } // end of the cookie code. // start of the url parameter code // note that this actually caters for // - actual URL parameters // - pseudo URL parameters, where the sessionid was in the path portion of the URL, // in conjunction with URL re-writing if (currentHtmlParameter.getType().equals(HtmlParameter.Type.url)) { boolean isPseudoUrlParameter = false; // is this "url parameter" actually a url parameter, or was it // path of the path (+url re-writing)? String possibleSessionIdIssuedForUrlParam = null; // remove the named url parameter from the request.. TreeSet<HtmlParameter> urlRequestParams = msg1Initial.getUrlParams(); // get parameters? if (!urlRequestParams.remove(currentHtmlParameter)) { isPseudoUrlParameter = true; // was not removed because it was a pseudo Url parameter, not a real url // parameter.. (so it would not be in the url params) // in this case, we will need to "rewrite" (ie hack) the URL path to remove // the pseudo url parameter portion // ie, we need to remove the ";jsessionid=<sessionid>" bit from the path // (assuming the current field is named 'jsessionid') // and replace it with ";jsessionid=" (ie, we nullify the possible "session" // parameter in the hope that a new session will be issued) // then we continue as usual to see if the URL is vulnerable to a Session // Fixation issue // Side note: quote the string to search for, and the replacement, so that // regex special characters are treated as literals String hackedUrl = requestUrl.replaceAll( Pattern.quote(";" + currentHtmlParameter.getName() + "=" + currentHtmlParameter.getValue()), Matcher.quoteReplacement(";" + currentHtmlParameter.getName() + "=")); if (this.debugEnabled) log.debug("Removing the pseudo URL parameter from [" + requestUrl + "]: [" + hackedUrl + "]"); // Note: the URL is not escaped. Handle it. msg1Initial.getRequestHeader().setURI(new URI(hackedUrl, false)); } msg1Initial.setGetParams(urlRequestParams); // url parameters // send the message, minus the value for the current parameter, and see how it // comes back. // Note: automatically follow redirects.. no need to look at any intermediate // responses. // this was only necessary for cookie-based session implementations sendAndReceive(msg1Initial); // if non-200 on the response for message 1, no point in continuing. Bale out. if (msg1Initial.getResponseHeader().getStatusCode() != HttpStatusCode.OK) { if (this.debugEnabled) log.debug("Got a non-200 response code [" + msg1Initial.getResponseHeader().getStatusCode() + "] when sending [" + msg1Initial.getRequestHeader().getURI() + "] with param [" + currentHtmlParameter.getName() + "] = NULL (possibly somewhere in the redirects)"); continue; } // now parse the HTML response for urls that contain the same parameter name, // and look at the values for that parameter // if no values are found for the parameter, then // 1) we are messing with the wrong field, or // 2) the app doesn't do sessions // either way, there is not much point in continuing to look at this field.. // parse out links in HTML (assume for a moment that all the URLs are in links) // this gives us a map of parameter value for the current parameter, to the // number of times it was encountered in links in the HTML SortedMap<String, Integer> parametersInHTMLURls = getParameterValueCountInHtml( msg1Initial.getResponseBody().toString(), currentHtmlParameter.getName(), isPseudoUrlParameter); if (this.debugEnabled) log.debug("The count of the various values of the [" + currentHtmlParameter.getName() + "] parameters in urls in the result of retrieving the url with a null value for parameter [" + currentHtmlParameter.getName() + "]: " + parametersInHTMLURls); if (parametersInHTMLURls.isEmpty()) { // setting the param to NULL did not cause any new values to be generated // for it in the output.. // so either.. // it is not a session field, or // it is a session field, but a session is only issued on authentication, // and this is not an authentication url // the app doesn't do sessions (etc) // either way, the parameter/url combo is not vulnerable, so continue with // the next parameter if (this.debugEnabled) log.debug("The URL parameter [" + currentHtmlParameter.getName() + "] was NOT set in any links in the response, when " + (isPseudoUrlParameter ? "pseudo/URL rewritten" : "") + " URL param [" + currentHtmlParameter.getName() + "] was set to NULL in the request, so it is likely not a session id field"); continue; // to the next parameter } else if (parametersInHTMLURls.size() == 1) { // the parameter was set to just one value in the output // so it's quite possible it is the session id field that we have been // looking for // caveat 1: check it is longer than 3 chars long, to remove false // positives.. // we assume here that a real session id will always be greater than 3 // characters long // caveat 2: the value we got back for the param must be different from the // value we // over-wrote with NULL (empty) in the first place, otherwise it is very // unlikely to // be a session id field possibleSessionIdIssuedForUrlParam = parametersInHTMLURls.firstKey(); // did we get back the same value we just nulled out in the original // request? // if so, use this to eliminate false positives, and to optimise. if (possibleSessionIdIssuedForUrlParam.equals(currentHtmlParameter.getValue())) { if (this.debugEnabled) log.debug((isPseudoUrlParameter ? "pseudo/URL rewritten" : "") + " URL param [" + currentHtmlParameter.getName() + "], when set to NULL, causes 1 distinct values to be set for it in URLs in the output, but the possible session id value [" + possibleSessionIdIssuedForUrlParam + "] is the same as the value we over-wrote with NULL. 'Sorry, kid. You got the gift, but it looks like you're waiting for something'"); continue; // to the next parameter } if (possibleSessionIdIssuedForUrlParam.length() > 3) { // raise an alert here on an exposed session id, even if it is not // subject to a session fixation vulnerability // log.info("The URL parameter ["+ currentHtmlParameter.getName() + "] // was set ["+ // parametersInHTMLURls.get(possibleSessionIdIssuedForUrlParam)+ "] // times to ["+ possibleSessionIdIssuedForUrlParam + "] in links in the // response, when "+ (isPseudoUrlParameter?"pseudo/URL rewritten":"")+ " // URL param ["+ currentHtmlParameter.getName() + "] was set to NULL in // the request. This likely indicates it is a session id field."); // pass the original param value here, not the new value, since we're // displaying the session id exposed in the original message String extraInfo = Constant.messages.getString( "ascanbeta.sessionidexposedinurl.alert.extrainfo", currentHtmlParameter.getType(), currentHtmlParameter.getName(), currentHtmlParameter.getValue()); String attack = Constant.messages .getString("ascanbeta.sessionidexposedinurl.alert.attack", (isPseudoUrlParameter ? "pseudo/URL rewritten " : "") + currentHtmlParameter.getType(), currentHtmlParameter.getName()); String vulnname = Constant.messages.getString("ascanbeta.sessionidexposedinurl.name"); String vulndesc = Constant.messages.getString("ascanbeta.sessionidexposedinurl.desc"); String vulnsoln = Constant.messages.getString("ascanbeta.sessionidexposedinurl.soln"); if (loginUrl) { extraInfo += ("\n" + Constant.messages .getString("ascanbeta.sessionidexposedinurl.alert.extrainfo.loginpage")); } // call bingo with some extra info, indicating that the alert is // not specific to Session Fixation, but has its own title and // description (etc) // the alert here is "Session id exposed in url", or words to that // effect. bingo(Alert.RISK_MEDIUM, Alert.CONFIDENCE_MEDIUM, vulnname, vulndesc, getBaseMsg().getRequestHeader().getURI().getURI(), currentHtmlParameter.getName(), attack, extraInfo, vulnsoln, getBaseMsg()); if (log.isDebugEnabled()) { String logMessage = MessageFormat.format( "An exposed session identifier has been found at " + "[{0}] URL [{1}] on {2} field: [{3}]", getBaseMsg().getRequestHeader().getMethod(), getBaseMsg().getRequestHeader().getURI().getURI(), (isPseudoUrlParameter ? "pseudo " : "") + currentHtmlParameter.getType(), currentHtmlParameter.getName()); log.debug(logMessage); } // Note: do NOT continue to the next field at this point.. // since we still need to check for Session Fixation. } else { if (this.debugEnabled) log.debug((isPseudoUrlParameter ? "pseudo/URL rewritten" : "") + " URL param [" + currentHtmlParameter.getName() + "], when set to NULL, causes 1 distinct values to be set for it in URLs in the output, but the possible session id value [" + possibleSessionIdIssuedForUrlParam + "] is too short to be a real session id."); continue; // to the next parameter } } else { // strange scenario: setting the param to null causes multiple different // values to be set for it in the output // it could still be a session parameter, but we assume it is *not* a // session id field // log it, but assume it is not a session id if (this.debugEnabled) log.debug((isPseudoUrlParameter ? "pseudo/URL rewritten" : "") + " URL param [" + currentHtmlParameter.getName() + "], when set to NULL, causes [" + parametersInHTMLURls.size() + "] distinct values to be set for it in URLs in the output. Assuming it is NOT a session id as a consequence. This could be a false negative"); continue; // to the next parameter } //////////////////////////////////////////////////////////////////////////////////////////// /// Message 2 - processing starts here //////////////////////////////////////////////////////////////////////////////////////////// // we now have a plausible session id field to play with, so set it to a // borrowed value. // ie: lets re-send the request, but add in the new (valid) session value that // was just issued. // the aim is then to see if it accepts the session without re-issuing the // session id (BAD, in some circumstances), // or if it issues a new session value (GOOD, in most circumstances) // and set the (modified) session for the second message // use a copy of msg2Initial, since it has already had the correct session // removed in the request.. // do NOT use msg2Initial itself, as this will cause both requests in the GUI to // show the modified data.. // finally send the second message, and see how it comes back. HttpMessage msg2Initial = msg1Initial.cloneRequest(); // set the parameter to the new session id value (in different manners, // depending on whether it is a real url param, or a pseudo url param) if (isPseudoUrlParameter) { // we need to "rewrite" (hack) the URL path to remove the pseudo url // parameter portion // id, we need to remove the ";jsessionid=<sessionid>" bit from the path // and replace it with ";jsessionid=" (ie, we nullify the possible "session" // parameter in the hope that a new session will be issued) // then we continue as usual to see if the URL is vulnerable to a Session // Fixation issue // Side note: quote the string to search for, and the replacement, so that // regex special characters are treated as literals String hackedUrl = requestUrl.replaceAll( Pattern.quote(";" + currentHtmlParameter.getName() + "=" + currentHtmlParameter.getValue()), Matcher.quoteReplacement(";" + currentHtmlParameter.getName() + "=" + possibleSessionIdIssuedForUrlParam)); if (this.debugEnabled) log.debug("Changing the pseudo URL parameter from [" + requestUrl + "]: [" + hackedUrl + "]"); // Note: the URL is not escaped msg2Initial.getRequestHeader().setURI(new URI(hackedUrl, false)); msg2Initial.setGetParams(msg1Initial.getUrlParams()); // restore the GET params } else { // do it via the normal url parameters TreeSet<HtmlParameter> urlRequestParams2 = msg2Initial.getUrlParams(); urlRequestParams2.add(new HtmlParameter(Type.url, currentHtmlParameter.getName(), possibleSessionIdIssuedForUrlParam)); msg2Initial.setGetParams(urlRequestParams2); // restore the GET params } // resend a copy of the initial message, but with the new valid session // parameter added in, to see if it is accepted // automatically follow redirects, which are irrelevant for the purposes of // testing URL parameters sendAndReceive(msg2Initial); // final result was non-200, no point in continuing. Bale out. if (msg2Initial.getResponseHeader().getStatusCode() != HttpStatusCode.OK) { if (this.debugEnabled) log.debug("Got a non-200 response code [" + msg2Initial.getResponseHeader().getStatusCode() + "] when sending [" + msg2Initial.getRequestHeader().getURI() + "] with a borrowed session (or by following a redirect) for param [" + currentHtmlParameter.getName() + "]"); continue; // next field! } // do the analysis on the parameters in link urls in the HTML output again to // see if the session id was regenerated SortedMap<String, Integer> parametersInHTMLURls2 = getParameterValueCountInHtml( msg2Initial.getResponseBody().toString(), currentHtmlParameter.getName(), isPseudoUrlParameter); if (this.debugEnabled) log.debug("The count of the various values of the [" + currentHtmlParameter.getName() + "] parameters in urls in the result of retrieving the url with a borrowed session value for parameter [" + currentHtmlParameter.getName() + "]: " + parametersInHTMLURls2); if (parametersInHTMLURls2.size() != 1) { // either no values, or multiple values, but not 1 value. For a session // that was regenerated, we would have expected to see // just 1 new value if (this.debugEnabled) log.debug("The HTML has spoken. [" + currentHtmlParameter.getName() + "] doesn't look like a session id field, because there are " + parametersInHTMLURls2.size() + " distinct values for this parameter in urls in the HTML output"); continue; } // there is but one value for this param in links in the HTML output. But is it // vulnerable to Session Fixation? Ie, is it the same parameter? String possibleSessionIdIssuedForUrlParam2 = parametersInHTMLURls2.firstKey(); if (possibleSessionIdIssuedForUrlParam2.equals(possibleSessionIdIssuedForUrlParam)) { // same sessionid used in the output.. so it is likely that we have a // SessionFixation issue.. // use the url param extrainfo message, which is specific to the case of url // parameters and url re-writing Session Fixation issue // pretty much everything else is generic to all types of Session Fixation // vulnerabilities String extraInfo = Constant.messages.getString( "ascanbeta.sessionfixation.alert.url.extrainfo", currentHtmlParameter.getName(), possibleSessionIdIssuedForUrlParam, possibleSessionIdIssuedForUrlParam2); String attack = Constant.messages.getString("ascanbeta.sessionfixation.alert.attack", (isPseudoUrlParameter ? "pseudo/URL rewritten " : "") + currentHtmlParameter.getType(), currentHtmlParameter.getName()); int risk = Alert.RISK_LOW; if (loginUrl) { extraInfo += ("\n" + Constant.messages .getString("ascanbeta.sessionfixation.alert.url.extrainfo.loginpage")); // login page, so higher risk risk = Alert.RISK_MEDIUM; } else { // not a login page.. lower risk risk = Alert.RISK_LOW; } bingo(risk, Alert.CONFIDENCE_MEDIUM, getBaseMsg().getRequestHeader().getURI().getURI(), currentHtmlParameter.getName(), attack, extraInfo, getBaseMsg()); logSessionFixation(getBaseMsg(), (isPseudoUrlParameter ? "pseudo " : "") + currentHtmlParameter.getType(), currentHtmlParameter.getName()); continue; // jump to the next iteration of the loop (ie, the next parameter) } else { // different sessionid used in the output.. so it is unlikely that we have a // SessionFixation issue.. // more likely that the Session is being re-issued for every single request, // or we have issues a login request, which // normally causes a session to be reissued if (this.debugEnabled) log.debug("The " + (isPseudoUrlParameter ? "pseudo/URL rewritten" : "") + " parameter [" + currentHtmlParameter.getName() + "] in url [" + getBaseMsg().getRequestHeader().getMethod() + "] [" + getBaseMsg().getRequestHeader().getURI() + "] changes with requests, and so it likely not vulnerable to Session Fixation"); } continue; // onto the next parameter } // end of the url parameter code. } // end of the for loop around the parameter list } catch (Exception e) { // Do not try to internationalise this.. we need an error message in any event.. // if it's in English, it's still better than not having it at all. log.error("An error occurred checking a url for Session Fixation issues", e); } }