// GetControlFileFromDsc reads control file from dsc package func GetControlFileFromDsc(dscFile string, verifier utils.Verifier) (Stanza, error) { file, err := os.Open(dscFile) if err != nil { return nil, err } defer file.Close() line, err := bufio.NewReader(file).ReadString('\n') if err != nil { return nil, err } file.Seek(0, 0) var text *os.File if strings.Index(line, "BEGIN PGP SIGN") != -1 { text, err = verifier.ExtractClearsigned(file) if err != nil { return nil, err } defer text.Close() } else { text = file } reader := NewControlFileReader(text) stanza, err := reader.ReadStanza() if err != nil { return nil, err } return stanza, nil }
// GetControlFileFromDsc reads control file from dsc package func GetControlFileFromDsc(dscFile string, verifier utils.Verifier) (Stanza, error) { file, err := os.Open(dscFile) if err != nil { return nil, err } defer file.Close() isClearSigned, err := verifier.IsClearSigned(file) file.Seek(0, 0) if err != nil { return nil, err } var text *os.File if isClearSigned { text, err = verifier.ExtractClearsigned(file) if err != nil { return nil, err } defer text.Close() } else { text = file } reader := NewControlFileReader(text) stanza, err := reader.ReadStanza(false) if err != nil { return nil, err } return stanza, nil }
// VerifyAndParse does optional signature verification and parses changes files func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier utils.Verifier) error { input, err := os.Open(filepath.Join(c.TempDir, c.ChangesName)) if err != nil { return err } defer input.Close() isClearSigned, err := verifier.IsClearSigned(input) if err != nil { return err } input.Seek(0, 0) if !isClearSigned && !acceptUnsigned { return fmt.Errorf(".changes file is not signed and unsigned processing hasn't been enabled") } if isClearSigned && !ignoreSignature { keyInfo, err := verifier.VerifyClearsigned(input, false) if err != nil { return err } input.Seek(0, 0) c.SignatureKeys = keyInfo.GoodKeys } var text *os.File if isClearSigned { text, err = verifier.ExtractClearsigned(input) if err != nil { return err } defer text.Close() } else { text = input } reader := NewControlFileReader(text) c.Stanza, err = reader.ReadStanza() if err != nil { return err } c.Distribution = c.Stanza["Distribution"] c.Changes = c.Stanza["Changes"] c.Source = c.Stanza["Source"] c.Binary = strings.Fields(c.Stanza["Binary"]) c.Architectures = strings.Fields(c.Stanza["Architecture"]) c.Files, err = c.Files.ParseSumFields(c.Stanza) if err != nil { return err } return nil }
// Fetch updates information about repository func (repo *RemoteRepo) Fetch(d aptly.Downloader, verifier utils.Verifier) error { var ( release, inrelease, releasesig *os.File err error ) if verifier == nil { // 0. Just download release file to temporary URL release, err = http.DownloadTemp(d, repo.ReleaseURL("Release").String()) if err != nil { return err } } else { // 1. try InRelease file inrelease, err = http.DownloadTemp(d, repo.ReleaseURL("InRelease").String()) if err != nil { goto splitsignature } defer inrelease.Close() _, err = verifier.VerifyClearsigned(inrelease, true) if err != nil { goto splitsignature } inrelease.Seek(0, 0) release, err = verifier.ExtractClearsigned(inrelease) if err != nil { goto splitsignature } goto ok splitsignature: // 2. try Release + Release.gpg release, err = http.DownloadTemp(d, repo.ReleaseURL("Release").String()) if err != nil { return err } releasesig, err = http.DownloadTemp(d, repo.ReleaseURL("Release.gpg").String()) if err != nil { return err } err = verifier.VerifyDetachedSignature(releasesig, release) if err != nil { return err } _, err = release.Seek(0, 0) if err != nil { return err } } ok: defer release.Close() sreader := NewControlFileReader(release) stanza, err := sreader.ReadStanza() if err != nil { return err } if !repo.IsFlat() { architectures := strings.Split(stanza["Architectures"], " ") sort.Strings(architectures) // "source" architecture is never present, despite Release file claims architectures = utils.StrSlicesSubstract(architectures, []string{"source"}) if len(repo.Architectures) == 0 { repo.Architectures = architectures } else { err = utils.StringsIsSubset(repo.Architectures, architectures, fmt.Sprintf("architecture %%s not available in repo %s", repo)) if err != nil { return err } } components := strings.Split(stanza["Components"], " ") if strings.Contains(repo.Distribution, "/") { distributionLast := path.Base(repo.Distribution) + "/" for i := range components { if strings.HasPrefix(components[i], distributionLast) { components[i] = components[i][len(distributionLast):] } } } if len(repo.Components) == 0 { repo.Components = components } else if !repo.SkipComponentCheck { err = utils.StringsIsSubset(repo.Components, components, fmt.Sprintf("component %%s not available in repo %s, use -force-components to override", repo)) if err != nil { return err } } } repo.ReleaseFiles = make(map[string]utils.ChecksumInfo) parseSums := func(field string, setter func(sum *utils.ChecksumInfo, data string)) error { for _, line := range strings.Split(stanza[field], "\n") { line = strings.TrimSpace(line) if line == "" { continue } parts := strings.Fields(line) if len(parts) != 3 { return fmt.Errorf("unparseable hash sum line: %#v", line) } var size int64 size, err = strconv.ParseInt(parts[1], 10, 64) if err != nil { return fmt.Errorf("unable to parse size: %s", err) } sum := repo.ReleaseFiles[parts[2]] sum.Size = size setter(&sum, parts[0]) repo.ReleaseFiles[parts[2]] = sum } delete(stanza, field) return nil } err = parseSums("MD5Sum", func(sum *utils.ChecksumInfo, data string) { sum.MD5 = data }) if err != nil { return err } err = parseSums("SHA1", func(sum *utils.ChecksumInfo, data string) { sum.SHA1 = data }) if err != nil { return err } err = parseSums("SHA256", func(sum *utils.ChecksumInfo, data string) { sum.SHA256 = data }) if err != nil { return err } delete(stanza, "SHA512") repo.Meta = stanza return nil }
// Fetch updates information about repository func (repo *RemoteRepo) Fetch(d utils.Downloader, verifier utils.Verifier) error { var ( release *os.File err error ) if verifier == nil { // 0. Just download release file to temporary URL release, err = utils.DownloadTemp(d, repo.ReleaseURL("Release").String()) if err != nil { return err } } else { // 1. try InRelease file inrelease, err := utils.DownloadTemp(d, repo.ReleaseURL("InRelease").String()) if err != nil { goto splitsignature } defer inrelease.Close() release, err = verifier.VerifyClearsigned(inrelease) if err != nil { goto splitsignature } goto ok splitsignature: // 2. try Release + Release.gpg release, err = utils.DownloadTemp(d, repo.ReleaseURL("Release").String()) if err != nil { return err } releasesig, err := utils.DownloadTemp(d, repo.ReleaseURL("Release.gpg").String()) if err != nil { return err } err = verifier.VerifyDetachedSignature(releasesig, release) if err != nil { return err } _, err = release.Seek(0, 0) if err != nil { return err } } ok: defer release.Close() sreader := NewControlFileReader(release) stanza, err := sreader.ReadStanza() if err != nil { return err } if !repo.IsFlat() { architectures := strings.Split(stanza["Architectures"], " ") if len(repo.Architectures) == 0 { repo.Architectures = architectures } else { err = utils.StringsIsSubset(repo.Architectures, architectures, fmt.Sprintf("architecture %%s not available in repo %s", repo)) if err != nil { return err } } components := strings.Split(stanza["Components"], " ") if len(repo.Components) == 0 { repo.Components = components } else { err = utils.StringsIsSubset(repo.Components, components, fmt.Sprintf("component %%s not available in repo %s", repo)) if err != nil { return err } } } repo.ReleaseFiles = make(map[string]utils.ChecksumInfo) parseSums := func(field string, setter func(sum *utils.ChecksumInfo, data string)) error { for _, line := range strings.Split(stanza[field], "\n") { line = strings.TrimSpace(line) if line == "" { continue } parts := strings.Fields(line) if len(parts) != 3 { return fmt.Errorf("unparseable hash sum line: %#v", line) } size, err := strconv.ParseInt(parts[1], 10, 64) if err != nil { return fmt.Errorf("unable to parse size: %s", err) } sum := repo.ReleaseFiles[parts[2]] sum.Size = size setter(&sum, parts[0]) repo.ReleaseFiles[parts[2]] = sum } delete(stanza, field) return nil } err = parseSums("MD5Sum", func(sum *utils.ChecksumInfo, data string) { sum.MD5 = data }) if err != nil { return err } err = parseSums("SHA1", func(sum *utils.ChecksumInfo, data string) { sum.SHA1 = data }) if err != nil { return err } err = parseSums("SHA256", func(sum *utils.ChecksumInfo, data string) { sum.SHA256 = data }) if err != nil { return err } repo.Meta = stanza return nil }