Example #1
0
func domainWithNoErrors(config ScanInjectorTestConfigFile, domainDAO dao.DomainDAO) {
	domain := newDomain()

	// Set all nameservers as configured correctly and the last check as now, this domain is
	// unlikely to be selected
	for index, _ := range domain.Nameservers {
		domain.Nameservers[index].LastCheckAt = time.Now()
		domain.Nameservers[index].LastStatus = model.NameserverStatusOK
	}

	// Set all DS records as configured correctly and the last check as now, this domain is
	// unlikely to be selected
	for index, _ := range domain.DSSet {
		domain.DSSet[index].LastCheckAt = time.Now()
		domain.DSSet[index].LastStatus = model.DSStatusOK
	}

	if err := domainDAO.Save(&domain); err != nil {
		utils.Fatalln("Error saving domain for scan scenario", err)
	}

	model.StartNewScan()
	if domains := runScan(config, domainDAO); len(domains) > 0 {
		utils.Fatalln(fmt.Sprintf("Selected a domain configured correctly for the scan. "+
			"Expected 0 got %d", len(domains)), nil)
	}

	currentScan := model.GetCurrentScan()
	if currentScan.Status != model.ScanStatusRunning {
		utils.Fatalln("Not changing the scan info status for domain with no errors", nil)
	}

	if currentScan.DomainsToBeScanned > 0 {
		utils.Fatalln("Not counting the domains to be scanned for domain with no errors", nil)
	}

	if err := domainDAO.RemoveByFQDN(domain.FQDN); err != nil {
		utils.Fatalln("Error removing domain", err)
	}
}
Example #2
0
func domainWithDNSErrors(config ScanInjectorTestConfigFile, domainDAO dao.DomainDAO) {
	domain := newDomain()

	// Set all nameservers with error and the last check equal of the error check interval,
	// this will force the domain to be checked
	for index, _ := range domain.Nameservers {
		maxErrorHours := config.Scan.VerificationIntervals.MaxErrorDays * 24
		lessThreeDays, _ := time.ParseDuration("-" + strconv.Itoa(maxErrorHours) + "h")

		domain.Nameservers[index].LastCheckAt = time.Now().Add(lessThreeDays)
		domain.Nameservers[index].LastStatus = model.NameserverStatusServerFailure
	}

	if err := domainDAO.Save(&domain); err != nil {
		utils.Fatalln("Error saving domain for scan scenario", err)
	}

	model.StartNewScan()
	if domains := runScan(config, domainDAO); len(domains) != 1 {
		utils.Fatalln(fmt.Sprintf("Couldn't load a domain with DNS errors for scan. "+
			"Expected 1 got %d", len(domains)), nil)
	}

	currentScan := model.GetCurrentScan()
	if currentScan.Status != model.ScanStatusRunning {
		utils.Fatalln("Not changing the scan info status with DNS errors", nil)
	}

	if currentScan.DomainsToBeScanned != 1 {
		utils.Fatalln("Not counting the domains to be scanned with DNS errors", nil)
	}

	if err := domainDAO.RemoveByFQDN(domain.FQDN); err != nil {
		utils.Fatalln("Error removing domain", err)
	}
}
Example #3
0
func domainWithErrors(config ScanCollectorTestConfigFile, database *mgo.Database) {
	domainsToSave := make(chan *model.Domain, config.Scan.DomainsBufferSize)
	domainsToSave <- &model.Domain{
		FQDN: "br.",
		Nameservers: []model.Nameserver{
			{
				Host:       "ns1.br",
				IPv4:       net.ParseIP("127.0.0.1"),
				LastStatus: model.NameserverStatusTimeout,
			},
		},
		DSSet: []model.DS{
			{
				Keytag:     1234,
				Algorithm:  model.DSAlgorithmRSASHA1NSEC3,
				DigestType: model.DSDigestTypeSHA1,
				Digest:     "EAA0978F38879DB70A53F9FF1ACF21D046A98B5C",
				LastStatus: model.DSStatusExpiredSignature,
			},
		},
	}
	domainsToSave <- nil

	model.StartNewScan()
	runScan(config, database, domainsToSave)

	domainDAO := dao.DomainDAO{
		Database: database,
	}

	domain, err := domainDAO.FindByFQDN("br.")
	if err != nil {
		utils.Fatalln("Error loading domain with problems", err)
	}

	if len(domain.Nameservers) == 0 {
		utils.Fatalln("Error saving nameservers", nil)
	}

	if domain.Nameservers[0].LastStatus != model.NameserverStatusTimeout {
		utils.Fatalln("Error setting status in the nameserver", nil)
	}

	if len(domain.DSSet) == 0 {
		utils.Fatalln("Error saving the DS set", nil)
	}

	if domain.DSSet[0].LastStatus != model.DSStatusExpiredSignature {
		utils.Fatalln("Error setting status in the DS", nil)
	}

	if err := domainDAO.RemoveByFQDN("br."); err != nil {
		utils.Fatalln("Error removing test domain", err)
	}

	currentScan := model.GetCurrentScan()
	if currentScan.DomainsScanned != 1 || currentScan.DomainsWithDNSSECScanned != 1 {
		utils.Fatalln("Not counting domains for scan progress when there're errors", nil)
	}

	if currentScan.NameserverStatistics[model.NameserverStatusToString(model.NameserverStatusTimeout)] != 1 ||
		currentScan.DSStatistics[model.DSStatusToString(model.DSStatusExpiredSignature)] != 1 {
		utils.Fatalln("Not counting statistics properly when there're errors", nil)
	}
}
Example #4
0
// The HEAD method is identical to GET except that the server MUST NOT return a message-
// body in the response. But now the responsability for don't adding the body is from the
// mux while writing the response
func (h *ScansHandler) retrieveScans(w http.ResponseWriter, r *http.Request) {
	var pagination dao.ScanDAOPagination

	expand := false
	returnCurrent := false

	for key, values := range r.URL.Query() {
		key = strings.TrimSpace(key)
		key = strings.ToLower(key)

		// A key can have multiple values in a query string, we are going to always consider
		// the last one (overwrite strategy)
		for _, value := range values {
			value = strings.TrimSpace(value)
			value = strings.ToLower(value)

			switch key {
			case "orderby":
				// OrderBy parameter will store the fields that the user want to be the keys of the sort
				// algorithm in the result set and the direction that each sort field will have. The format
				// that will be used is:
				//
				// <field1>:<direction1>@<field2>:<direction2>@...@<fieldN>:<directionN>

				orderByParts := strings.Split(value, "@")

				for _, orderByPart := range orderByParts {
					orderByPart = strings.TrimSpace(orderByPart)
					orderByAndDirection := strings.Split(orderByPart, ":")

					var field, direction string

					if len(orderByAndDirection) == 1 {
						field, direction = orderByAndDirection[0], "asc"

					} else if len(orderByAndDirection) == 2 {
						field, direction = orderByAndDirection[0], orderByAndDirection[1]

					} else {
						if err := h.MessageResponse("invalid-query-order-by", ""); err == nil {
							w.WriteHeader(http.StatusBadRequest)

						} else {
							log.Println("Error while writing response. Details:", err)
							w.WriteHeader(http.StatusInternalServerError)
						}

						return
					}

					orderByField, err := dao.ScanDAOOrderByFieldFromString(field)
					if err != nil {
						if err := h.MessageResponse("invalid-query-order-by", ""); err == nil {
							w.WriteHeader(http.StatusBadRequest)

						} else {
							log.Println("Error while writing response. Details:", err)
							w.WriteHeader(http.StatusInternalServerError)
						}

						return
					}

					orderByDirection, err := dao.DAOOrderByDirectionFromString(direction)
					if err != nil {
						if err := h.MessageResponse("invalid-query-order-by", ""); err == nil {
							w.WriteHeader(http.StatusBadRequest)

						} else {
							log.Println("Error while writing response. Details:", err)
							w.WriteHeader(http.StatusInternalServerError)
						}

						return
					}

					pagination.OrderBy = append(pagination.OrderBy, dao.ScanDAOSort{
						Field:     orderByField,
						Direction: orderByDirection,
					})
				}

			case "pagesize":
				var err error
				pagination.PageSize, err = strconv.Atoi(value)
				if err != nil {
					if err := h.MessageResponse("invalid-query-page-size", ""); err == nil {
						w.WriteHeader(http.StatusBadRequest)

					} else {
						log.Println("Error while writing response. Details:", err)
						w.WriteHeader(http.StatusInternalServerError)
					}

					return
				}

			case "page":
				var err error
				pagination.Page, err = strconv.Atoi(value)
				if err != nil {
					if err := h.MessageResponse("invalid-query-page", ""); err == nil {
						w.WriteHeader(http.StatusBadRequest)

					} else {
						log.Println("Error while writing response. Details:", err)
						w.WriteHeader(http.StatusInternalServerError)
					}

					return
				}

			case "expand":
				expand = true

			case "current":
				returnCurrent = true
			}
		}
	}

	scanDAO := dao.ScanDAO{
		Database: h.GetDatabase(),
	}

	// As we need to inform the user about the number of items, we always try to retrieve the scan
	// objects even if is requested only the current object
	scans, err := scanDAO.FindAll(&pagination, expand)
	if err != nil {
		log.Println("Error while searching scans objects. Details:", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	var scansResponse protocol.ScansResponse
	var current model.CurrentScan

	if returnCurrent {
		// The current page will be page zero to avoid misunderstandment
		pagination.Page = 0
		current = model.GetCurrentScan()
		scansResponse = protocol.CurrentScanToScansResponse(current, pagination)

	} else {
		scansResponse = protocol.ScansToScansResponse(scans, pagination)
	}

	h.Response = &scansResponse

	// Last-Modified is going to be the most recent date of the list
	if returnCurrent {
		h.lastModifiedAt = current.LastModifiedAt

	} else {
		for _, scan := range scans {
			if scan.LastModifiedAt.After(h.lastModifiedAt) {
				h.lastModifiedAt = scan.LastModifiedAt
			}
		}
	}

	w.Header().Add("ETag", h.GetETag())
	w.Header().Add("Last-Modified", h.lastModifiedAt.Format(time.RFC1123))
	w.WriteHeader(http.StatusOK)
}