GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/letter.cc Lines: 0 65 0.0 %
Date: 2019-02-03 02:48:13 Branches: 0 30 0.0 %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM File System.
3
 */
4
5
#include "cvmfs_config.h"
6
#include "letter.h"
7
8
#include <inttypes.h>
9
#include <cassert>
10
11
#include <map>
12
13
#include "signature.h"
14
#include "util/string.h"
15
16
using namespace std;  // NOLINT
17
18
namespace letter {
19
20
Letter::Letter(const string &fqrn,
21
               const string &text,
22
               signature::SignatureManager *signature_manager) :
23
  fqrn_(fqrn),
24
  text_(text),
25
  signature_manager_(signature_manager)
26
{
27
}
28
29
30
string Letter::Sign(const shash::Algorithms hash_algorithm) {
31
  unsigned char *cert_buf = NULL;
32
  unsigned cert_buf_size;
33
  bool retval = signature_manager_->WriteCertificateMem(&cert_buf,
34
                                                        &cert_buf_size);
35
  assert(retval);
36
  string cert_base64 = Base64(string(reinterpret_cast<char *>(cert_buf),
37
                                     cert_buf_size));
38
  free(cert_buf);
39
40
  string output = text_;
41
  output += string("\n##\n") +
42
            "V1" + "\n" +
43
            "N" + fqrn_ + "\n" +
44
            "T" + StringifyInt(time(NULL)) + "\n" +
45
            "X" + cert_base64 + "\n";
46
  shash::Any output_hash(hash_algorithm);
47
  shash::HashMem(reinterpret_cast<const unsigned char *>(output.data()),
48
                 output.length(), &output_hash);
49
  output += "--\n" + output_hash.ToString() + "\n";
50
51
  unsigned char *sig;
52
  unsigned sig_size;
53
  retval = signature_manager_->Sign(
54
    reinterpret_cast<const unsigned char *>(output_hash.ToString().data()),
55
    output_hash.GetHexSize(), &sig, &sig_size);
56
  assert(retval);
57
  output.append(reinterpret_cast<char *>(sig), sig_size);
58
  free(sig);
59
60
  return Base64(output);
61
}
62
63
64
Failures Letter::Verify(uint64_t max_age, string *msg, string *cert) {
65
  msg->clear();
66
  cert->clear();
67
  bool retval;
68
69
  string dec;
70
  retval = Debase64(text_, &dec);
71
72
  if (!retval)
73
    return kFailBadBase64;
74
75
  // Cut envelope and signature
76
  unsigned env_pos = 0;
77
  unsigned sig_pos = 0;
78
  unsigned msg_len = 0;
79
  unsigned env_len = 0;
80
  const unsigned char *data_ptr =
81
    reinterpret_cast<const unsigned char *>(dec.data());
82
  signature::SignatureManager::CutLetter(
83
    data_ptr, dec.length(), '#', &msg_len, &env_pos);
84
  if (env_pos >= dec.length())
85
    return kFailMalformed;
86
  // Sign adds a newline
87
  if (msg_len == 0)
88
    return kFailMalformed;
89
  *msg = dec.substr(0, msg_len-1);
90
  signature::SignatureManager::CutLetter(
91
    data_ptr+env_pos, dec.length()-env_pos, '-', &env_len, &sig_pos);
92
  if (sig_pos >= dec.length())
93
    return kFailMalformed;
94
95
  map<char, string> env;
96
  ParseKeyvalMem(data_ptr+env_pos, env_len, &env);
97
  map<char, string>::const_iterator iter;
98
  if ((iter = env.find('T')) == env.end())
99
    return kFailMalformed;
100
  uint64_t timestamp = String2Uint64(iter->second);
101
  if (max_age > 0) {
102
    if (timestamp + max_age < static_cast<uint64_t>(time(NULL)))
103
      return kFailExpired;
104
  }
105
  if ((iter = env.find('N')) == env.end())
106
    return kFailMalformed;
107
  if (iter->second != fqrn_)
108
    return kFailNameMismatch;
109
  if ((iter = env.find('X')) == env.end())
110
    return kFailMalformed;
111
  string cert_b64 = iter->second;
112
  retval = Debase64(cert_b64, cert);
113
  if (!retval)
114
    return kFailMalformed;
115
  retval = signature_manager_->LoadCertificateMem(
116
    reinterpret_cast<const unsigned char *>(cert->data()), cert->length());
117
  if (!retval)
118
    return kFailBadCertificate;
119
120
  retval = signature_manager_->VerifyLetter(
121
    data_ptr, dec.length(), false);
122
  if (!retval)
123
    return kFailBadSignature;
124
125
  return kFailOk;
126
}
127
128
}  // namespace letter