monotone

monotone Mtn Source Tree

Root/cert.cc

1// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include "base.hh"
11#include "cert.hh"
12#include "constants.hh"
13#include "database.hh" // lookup key name for hashing
14#include "netio.hh"
15#include "simplestring_xform.hh"
16#include "transforms.hh"
17
18using std::string;
19
20bool
21cert::operator<(cert const & other) const
22{
23 return (ident < other.ident)
24 || ((ident == other.ident) && name < other.name)
25 || (((ident == other.ident) && name == other.name)
26 && value < other.value)
27 || ((((ident == other.ident) && name == other.name)
28 && value == other.value) && key < other.key)
29 || (((((ident == other.ident) && name == other.name)
30 && value == other.value) && key == other.key) && sig < other.sig);
31}
32
33bool
34cert::operator==(cert const & other) const
35{
36 return
37 (ident == other.ident)
38 && (name == other.name)
39 && (value == other.value)
40 && (key == other.key)
41 && (sig == other.sig);
42}
43
44// netio support
45enum read_cert_version {read_cert_v6, read_cert_current};
46
47static bool
48read_cert(database & db, string const & in, cert & t,
49 read_cert_version ver, key_name & keyname)
50{
51 size_t pos = 0;
52 id hash = id(extract_substring(in, pos,
53 constants::merkle_hash_length_in_bytes,
54 "cert hash"),
55 origin::network);
56 revision_id ident = revision_id(extract_substring(in, pos,
57 constants::merkle_hash_length_in_bytes,
58 "cert ident"),
59 origin::network);
60 string name, val, key, sig;
61 extract_variable_length_string(in, name, pos, "cert name");
62 extract_variable_length_string(in, val, pos, "cert val");
63 extract_variable_length_string(in, key, pos, "cert key");
64 extract_variable_length_string(in, sig, pos, "cert sig");
65 assert_end_of_buffer(in, pos, "cert");
66
67 cert tmp;
68 tmp.ident = ident;
69 tmp.name = cert_name(name, origin::network);
70 tmp.value = cert_value(val, origin::network);
71 tmp.sig = rsa_sha1_signature(sig, origin::network);
72 string signable;
73 tmp.signable_text(signable);
74
75 key_id keyid;
76 switch(ver)
77 {
78 case read_cert_v6:
79 {
80 keyname = key_name(key, origin::network);
81 bool found = false;
82 std::vector<key_id> all_keys;
83 db.get_key_ids(all_keys);
84 for (std::vector<key_id>::const_iterator i = all_keys.begin();
85 i != all_keys.end(); ++i)
86 {
87 key_name i_keyname;
88 rsa_pub_key pub;
89 db.get_pubkey(*i, i_keyname, pub);
90 if (i_keyname() == key)
91 {
92 if(db.check_signature(*i, signable, tmp.sig) == cert_ok)
93 {
94 tmp.key = *i;
95 found = true;
96 break;
97 }
98 }
99 }
100 if (!found)
101 {
102 return false;
103 }
104 }
105 break;
106 case read_cert_current:
107 {
108 rsa_pub_key pub;
109 tmp.key = key_id(key, origin::network);
110 db.get_pubkey(tmp.key, keyname, pub);
111 if (db.check_signature(tmp.key, signable, tmp.sig) != cert_ok)
112 {
113 return false;
114 }
115 }
116 break;
117 default:
118 I(false);
119 }
120
121 rsa_pub_key junk;
122 db.get_pubkey(tmp.key, keyname, junk);
123
124 id check;
125 tmp.hash_code(keyname, check);
126 if (!(check == hash))
127 throw bad_decode(F("calculated cert hash '%s' does not match '%s'")
128 % check % hash);
129 t = tmp;
130 return true;
131}
132
133bool cert::read_cert_v6(database & db, std::string const & s, cert & c,
134 key_name & keyname)
135{
136 return ::read_cert(db, s, c, ::read_cert_v6, keyname);
137}
138
139bool cert::read_cert(database & db, std::string const & s, cert & c,
140 key_name & keyname)
141{
142 return ::read_cert(db, s, c, read_cert_current, keyname);
143}
144
145cert::cert(database & db, std::string const & s, origin::type m)
146 : origin_aware(m)
147{
148 key_name keyname;
149 ::read_cert(db, s, *this, read_cert_current, keyname);
150}
151
152void
153cert::marshal_for_netio(key_name const & keyname, string & out) const
154{
155 id hash;
156 hash_code(keyname, hash);
157
158 out.append(hash());
159 out.append(this->ident.inner()());
160 insert_variable_length_string(this->name(), out);
161 insert_variable_length_string(this->value(), out);
162 insert_variable_length_string(this->key.inner()(), out);
163 insert_variable_length_string(this->sig(), out);
164}
165
166void
167cert::marshal_for_netio_v6(key_name const & keyname, string & out) const
168{
169 id hash;
170 hash_code(keyname, hash);
171
172 out.append(hash());
173 out.append(this->ident.inner()());
174 insert_variable_length_string(this->name(), out);
175 insert_variable_length_string(this->value(), out);
176 insert_variable_length_string(keyname(), out);
177 insert_variable_length_string(this->sig(), out);
178}
179
180void
181cert::signable_text(string & out) const
182{
183 base64<cert_value> val_encoded(encode_base64(this->value));
184 string ident_encoded(encode_hexenc(this->ident.inner()(),
185 this->ident.inner().made_from));
186
187 out.clear();
188 out.reserve(4 + this->name().size() + ident_encoded.size()
189 + val_encoded().size());
190
191 out += '[';
192 out.append(this->name());
193 out += '@';
194 out.append(ident_encoded);
195 out += ':';
196 append_without_ws(out, val_encoded());
197 out += ']';
198
199 L(FL("cert: signable text %s") % out);
200}
201
202void
203cert::hash_code(key_name const & keyname, id & out) const
204{
205 base64<rsa_sha1_signature> sig_encoded(encode_base64(this->sig));
206 base64<cert_value> val_encoded(encode_base64(this->value));
207 string ident_encoded(encode_hexenc(this->ident.inner()(),
208 this->ident.inner().made_from));
209 string tmp;
210 tmp.reserve(4 + ident_encoded.size()
211 + this->name().size() + val_encoded().size()
212 + this->key.inner()().size() + sig_encoded().size());
213
214 tmp.append(ident_encoded);
215 tmp += ':';
216 tmp.append(this->name());
217 tmp += ':';
218 append_without_ws(tmp, val_encoded());
219 tmp += ':';
220 tmp.append(keyname());
221 tmp += ':';
222 append_without_ws(tmp, sig_encoded());
223
224 data tdat(tmp, origin::internal);
225 calculate_ident(tdat, out);
226}
227
228// Local Variables:
229// mode: C++
230// fill-column: 76
231// c-file-style: "gnu"
232// indent-tabs-mode: nil
233// End:
234// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status