1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <errno.h>
6#include <stdio.h>
7#include <stdlib.h>
8
9#include "base/at_exit.h"
10#include "net/base/dns_util.h"
11#include "net/base/dnssec_chain_verifier.h"
12
13static int usage(const char* argv0) {
14  fprintf(stderr, "Usage: %s [--ignore-timestamps] <target domain> "
15                  "<input file>\n", argv0);
16  return 1;
17}
18
19int main(int argc, char** argv) {
20  base::AtExitManager at_exit_manager;
21
22  if (argc < 3)
23    return usage(argv[0]);
24
25  const char* target = NULL;
26  const char* infilename = NULL;
27  bool ignore_timestamps = false;
28
29  for (int i = 1; i < argc; i++) {
30    if (strcmp(argv[i], "--ignore-timestamps") == 0) {
31      ignore_timestamps = true;
32    } else if (!target) {
33      target = argv[i];
34    } else if (!infilename) {
35      infilename = argv[i];
36    } else {
37      return usage(argv[0]);
38    }
39  }
40
41  if (!target || !infilename)
42    return usage(argv[0]);
43
44  FILE* infile = fopen(infilename, "r");
45  if (!infile) {
46    perror("open");
47    return usage(argv[0]);
48  }
49
50  fseek(infile, 0, SEEK_END);
51  unsigned long inlen = ftell(infile);
52  fseek(infile, 0, SEEK_SET);
53
54  char* const input = (char *) malloc(inlen);
55  if (fread(input, inlen, 1, infile) != 1) {
56    perror("read");
57    return 1;
58  }
59
60  std::string target_dns;
61  if (!net::DNSDomainFromDot(target, &target_dns)) {
62    fprintf(stderr, "Not a valid DNS name: %s\n", target);
63    return usage(argv[0]);
64  }
65
66  net::DNSSECChainVerifier verifier(target_dns,
67                                    base::StringPiece(input, inlen));
68  if (ignore_timestamps)
69    verifier.IgnoreTimestamps();
70  net::DNSSECChainVerifier::Error err = verifier.Verify();
71  const char* err_str;
72  switch (err) {
73    case net::DNSSECChainVerifier::BAD_DATA:
74      err_str = "Bad data";
75      break;
76    case net::DNSSECChainVerifier::UNKNOWN_ROOT_KEY:
77      err_str = "Unknown root key";
78      break;
79    case net::DNSSECChainVerifier::UNKNOWN_DIGEST:
80      err_str = "Unknown digest";
81      break;
82    case net::DNSSECChainVerifier::UNKNOWN_TERMINAL_RRTYPE:
83      err_str = "Unknown terminal RR type";
84      break;
85    case net::DNSSECChainVerifier::BAD_SIGNATURE:
86      err_str = "Bad signature";
87      break;
88    case net::DNSSECChainVerifier::NO_DS_LINK:
89      err_str = "No DS link";
90      break;
91    case net::DNSSECChainVerifier::OFF_COURSE:
92      err_str = "Off course";
93      break;
94    case net::DNSSECChainVerifier::BAD_TARGET:
95      err_str = "Bad target";
96      break;
97    default:
98      err_str = "Unknown";
99      break;
100  }
101
102  if (err != net::DNSSECChainVerifier::OK) {
103    fprintf(stderr, "Chain error: %s (%d)\n", err_str, (int) err);
104    return 1;
105  }
106
107  fprintf(stderr, "Chain good: rrtype:%d\n", verifier.rrtype());
108  return 0;
109}
110