Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #!/usr/bin/ruby
  2. require 'optparse'
  3. require 'yaml'
  4. require 'fileutils'
  5. require 'pathname'
  6. bold = ["\033[0m", "\033[1m"]
  7. @options = {}
  8. def system!(cmd)
  9. system(cmd) or raise "failed to run #{cmd}"
  10. end
  11. def sanitize(str, where)
  12. raise "unsanitary string in #{where}" if (str =~ /[^\w.-]/)
  13. str
  14. end
  15. def sanitize_path(str, where)
  16. raise "unsanitary string in #{where}" if (str =~ /[^@\w\/.:+-]/)
  17. str
  18. end
  19. def info(str)
  20. puts str if @options[:verbose]
  21. end
  22. ################################
  23. OptionParser.new do |opts|
  24. opts.banner = "Usage: build [options] <build-description>.yml"
  25. opts.on("-v", "--verbose", "be more verbose") do |v|
  26. @options[:verbose] = v
  27. end
  28. @options[:markup] = true
  29. opts.on("-m", "--[no-]markup", "markup the output using ANSI escape codes") do |m|
  30. @options[:markup] = m
  31. end
  32. opts.on("-r REL", "--release REL", "release name") do |v|
  33. @options[:release] = v
  34. end
  35. opts.on("-d DEST", "--destination DEST", "directory to place signature in") do |v|
  36. @options[:destination] = v
  37. end
  38. opts.on("-c SIGNER", "--compare-to SIGNER", "compare other manifests to SIGNER's, if not given pick first") do |v|
  39. @options[:compareto] = v
  40. end
  41. opts.on("-p PROG", "--verify-program PROG", "specify verification program to use (default is gpg)") do |v|
  42. @options[:program] = v
  43. end
  44. end.parse!
  45. base_dir = Pathname.new(__FILE__).expand_path.dirname.parent
  46. build_desc_file = ARGV.shift or raise "must supply YAML build description file"
  47. build_desc = YAML.load_file(build_desc_file)
  48. in_sums = []
  49. result_dir = 'result'
  50. package_name = build_desc["name"] or raise "must supply name"
  51. package_name = sanitize(package_name, "package name")
  52. destination = @options[:destination] || File.join(base_dir, "sigs", package_name)
  53. release = @options[:release] || "current"
  54. release = sanitize(release, "release")
  55. verbose = @options[:verbose]
  56. bold = ['', ''] unless @options[:markup]
  57. program = @options[:program] || "gpg"
  58. release_path = File.join(destination, release)
  59. File.exists?(release_path) or raise "#{release_path} does not exist"
  60. result_file = "#{package_name}-build.assert"
  61. sig_file = "#{result_file}.sig"
  62. current_manifest = nil
  63. if @options[:compareto]
  64. # Load a specific 'golden' manifest to compare to
  65. compareto = @options[:compareto]
  66. result_path = sanitize_path(File.join(release_path, compareto, result_file), "result path")
  67. result = YAML.load_file(result_path)
  68. current_manifest = result['out_manifest']
  69. end
  70. did_fail = false
  71. Dir.foreach(release_path) do |signer_dir|
  72. next if signer_dir == "." or signer_dir == ".."
  73. signer_path = sanitize_path(File.join(release_path, signer_dir), "signer path")
  74. next if !File.directory?(signer_path)
  75. result_path = sanitize_path(File.join(signer_path, result_file), "result path")
  76. sig_path = sanitize_path(File.join(signer_path, sig_file), "result path")
  77. if !File.exist?(result_path)
  78. puts "missing result at #{result_path}"
  79. next
  80. end
  81. if !File.exist?(sig_path)
  82. puts "missing signature at #{sig_path}"
  83. next
  84. end
  85. result = YAML.load_file(result_path)
  86. system("#{program} --keyserver pgp.mit.edu --recv-keys `#{program} --quiet --batch --verify \"#{File.join(signer_path, 'signature.pgp')}\" \"#{result_path}\" 2>&1 | head -n1 | grep \"key ID\" | awk '{ print $15 }'` > /dev/null 2>&1")
  87. out = `#{program} --quiet --batch --verify \"#{sig_path}\" \"#{result_path}\" 2>&1`
  88. if $? != 0
  89. out.each_line do |line|
  90. if line =~ /^gpg: Signature made/
  91. info(line)
  92. else
  93. puts line
  94. end
  95. end
  96. puts "#{bold[1]}#{signer_dir}: BAD SIGNATURE#{bold[0]}"
  97. puts
  98. did_fail = true
  99. elsif current_manifest and (result['out_manifest'] != current_manifest or result['release'] != release or result['name'] != package_name)
  100. out.each_line do |line|
  101. if line =~ /^gpg: Signature made/
  102. info(line)
  103. elsif line =~ /^gpg: Good signature/
  104. info(line)
  105. elsif line =~ /^gpg: aka/
  106. info(line)
  107. else
  108. puts line
  109. end
  110. end
  111. puts "#{bold[1]}#{signer_dir}: MISMATCH#{bold[0]}"
  112. puts
  113. if verbose
  114. lines1 = current_manifest.each_line
  115. lines2 = result['out_manifest'].each_line
  116. lines1.zip(lines2) do |line|
  117. if line[0] != line[1]
  118. puts "- "+line[0]
  119. puts "+ "+line[1]
  120. end
  121. end
  122. end
  123. did_fail = true
  124. else
  125. out.each_line do |line|
  126. if line =~ /^gpg: Signature made/
  127. info(line)
  128. elsif line =~ /^gpg: Good signature/
  129. info(line)
  130. elsif line =~ /^gpg: aka/
  131. info(line)
  132. else
  133. puts line
  134. end
  135. end
  136. puts "#{bold[1]}#{signer_dir}: OK#{bold[0]}"
  137. puts
  138. end
  139. if !current_manifest
  140. # take first manifest as 'current' to compare against
  141. current_manifest = result['out_manifest']
  142. end
  143. end
  144. exit 1 if did_fail