#
# patch "ChangeLog"
# from [869e89ee76e4ce7d2873763ffe130ecac53084e3]
# to [71c41c875677789a8a849c815c2d56c79387a069]
#
# patch "netsync.cc"
# from [009a32af8adc1ae0d0a5a22c2eff379b494031c2]
# to [71902ef3677adceaa862dc7c9150cad39ce27c5e]
#
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,7 @@
+2005-07-03 Nathaniel Smith
+
+ * netsync.cc: More updating for pattern stuff; getting there...
+
2005-06-28 Nathaniel Smith
* netsync.cc: Update low-level functions to use include_pattern
--- netsync.cc
+++ netsync.cc
@@ -32,6 +32,7 @@
#include "xdelta.hh"
#include "epoch.hh"
#include "platform.hh"
+#include "globish.hh"
#include "cryptopp/osrng.h"
@@ -152,17 +153,18 @@
//
// The client then responds with either:
//
-// An "auth (source|sink|both)
-// " command, which identifies its RSA key, notes the role it
-// wishes to play in the synchronization, identifies the pattern it
-// wishes to sync with, signs the previous nonce with its own key, and
-// informs the server of the HMAC key it wishes to use for this
-// session (encrypted with the server's public key); or
+// An "auth (source|sink|both)
+// " command, which identifies its RSA key, notes the
+// role it wishes to play in the synchronization, identifies the pattern it
+// wishes to sync with, signs the previous nonce with its own key, and informs
+// the server of the HMAC key it wishes to use for this session (encrypted
+// with the server's public key); or
//
-// An "anonymous (source|sink|both) " command,
-// which identifies the role it wishes to play in the synchronization,
-// the pattern it ishes to sync with, and the HMAC key it wishes to
-// use for this session (also encrypted with the server's public key).
+// An "anonymous (source|sink|both)
+// " command, which identifies the role it wishes to play in the
+// synchronization, the pattern it ishes to sync with, and the HMAC key it
+// wishes to use for this session (also encrypted with the server's public
+// key).
//
// The server then replies with a "confirm" command, which contains no
// other data but will only have the correct HMAC integrity code if
@@ -170,24 +172,6 @@
// the client. This transitions the peers into an authenticated state
// and begins refinement.
//
-// ---- Pre-v5 authentication process notes ----
-//
-// the exchange begins in a non-authenticated state. the server sends a
-// "hello " command, which identifies the server's RSA key and
-// issues a nonce which must be used for a subsequent authentication.
-// the client can then respond with an "auth (source|sink|both)
-// " command which identifies its
-// RSA key, notes the role it wishes to play in the synchronization,
-// identifies the pattern it wishes to sync with, signs the previous
-// nonce with its own key, and issues a nonce of its own for mutual
-// authentication.
-//
-// the server can then respond with a "confirm " command, which is
-// the signature of the second nonce sent by the client. this
-// transitions the peers into an authenticated state and begins refinement.
-//
-// ---- End pre-v5 authentication process ----
-//
// refinement begins with the client sending its root public key and
// manifest certificate merkle nodes to the server. the server then
// compares the root to each slot in *its* root node, and for each slot
@@ -252,7 +236,9 @@
{
protocol_role role;
protocol_voice const voice;
- vector patterns;
+ utf8 const & our_include_pattern;
+ utf8 const & our_exclude_pattern;
+ globish_matcher our_matcher;
app_state & app;
string peer_id;
@@ -266,8 +252,6 @@
bool armed;
bool arm();
- utf8 pattern;
- boost::regex pattern_re;
id remote_peer_key_hash;
rsa_keypair_id remote_peer_key_name;
netsync_session_key session_key;
@@ -306,7 +290,8 @@
session(protocol_role role,
protocol_voice voice,
- vector const & patterns,
+ utf8 const & our_include_pattern,
+ utf8 const & our_exclude_pattern,
app_state & app,
string const & peer,
Netxx::socket_type sock,
@@ -400,11 +385,11 @@
rsa_pub_key const & server_key,
id const & nonce);
bool process_anonymous_cmd(protocol_role role,
- utf8 const & include_pattern,
- utf8 const & exclude_pattern);
+ utf8 const & their_include_pattern,
+ utf8 const & their_exclude_pattern);
bool process_auth_cmd(protocol_role role,
- utf8 const & include_pattern,
- utf8 const & exclude_pattern,
+ utf8 const & their_include_pattern,
+ utf8 const & their_exclude_pattern,
id const & client,
id const & nonce1,
string const & signature);
@@ -469,14 +454,17 @@
session::session(protocol_role role,
protocol_voice voice,
- vector const & patterns,
+ utf8 const & our_include_pattern,
+ utf8 const & our_exclude_pattern,
app_state & app,
string const & peer,
Netxx::socket_type sock,
Netxx::Timeout const & to) :
role(role),
voice(voice),
- patterns(patterns),
+ our_include_pattern(our_include_pattern),
+ our_exclude_pattern(our_exclude_pattern),
+ our_matcher(our_include_pattern, our_exclude_pattern),
app(app),
peer_id(peer),
fd(sock),
@@ -484,8 +472,6 @@
inbuf(""),
outbuf(""),
armed(false),
- pattern(""),
- pattern_re(".*"),
remote_peer_key_hash(""),
remote_peer_key_name(""),
session_key(constants::netsync_key_initializer),
@@ -507,14 +493,6 @@
dbw(app, true),
encountered_error(false)
{
- if (voice == client_voice)
- {
- N(patterns.size() == 1,
- F("client can only sync one pattern at a time"));
- this->pattern = idx(patterns, 0);
- this->pattern_re = boost::regex(this->pattern());
- }
-
dbw.set_on_revision_written(boost::bind(&session::rev_written_callback,
this, _1));
dbw.set_on_cert_written(boost::bind(&session::cert_written_callback,
@@ -1189,7 +1167,7 @@
ok = app.lua.hook_get_netsync_write_permitted(name(),
remote_peer_key_name);
else
- ok = boost::regex_match(name(), pattern_re);
+ ok = our_matcher(name());
if (ok)
{
ok_branches.insert(name());
@@ -1761,14 +1739,13 @@
this->remote_peer_key_hash = their_key_hash_decoded;
}
- utf8 pat(pattern);
vector branchnames;
set ok_branches;
get_branches(app, branchnames);
for (vector::const_iterator i = branchnames.begin();
i != branchnames.end(); i++)
{
- if (boost::regex_match(*i, pattern_re))
+ if (our_matcher(*i))
ok_branches.insert(utf8(*i));
}
rebuild_merkle_trees(app, ok_branches);
@@ -1805,21 +1782,10 @@
return true;
}
-bool
-matches_one(string s, vector r)
-{
- for (vector::const_iterator i = r.begin(); i != r.end(); i++)
- {
- if (boost::regex_match(s, *i))
- return true;
- }
- return false;
-}
-
bool
session::process_anonymous_cmd(protocol_role role,
- utf8 const & include_pattern,
- utf8 const & exclude_pattern)
+ utf8 const & their_include_pattern,
+ utf8 const & their_exclude_pattern)
{
//
// internally netsync thinks in terms of sources and sinks. users like
@@ -1853,35 +1819,27 @@
vector branchnames;
set ok_branches;
get_branches(app, branchnames);
- vector allowed;
- boost::regex reg(pattern);
- for (vector::const_iterator i = patterns.begin();
- i != patterns.end(); ++i)
- {
- allowed.push_back(boost::regex((*i)()));
- }
+ globish_matcher their_matcher(their_include_pattern, their_exclude_pattern);
for (vector::const_iterator i = branchnames.begin();
i != branchnames.end(); i++)
{
- if (boost::regex_match(*i, reg)
- && (allowed.size() == 0 || matches_one(*i, allowed)))
- {
- if (app.lua.hook_get_netsync_anonymous_read_permitted(*i))
- ok_branches.insert(utf8(*i));
- }
+ if (our_matcher(*i) && their_matcher(*i)
+ && app.lua.hook_get_netsync_anonymous_read_permitted(*i))
+ ok_branches.insert(utf8(*i));
}
- if (!ok_branches.size())
+ if (ok_branches.empty())
{
- W(F("denied anonymous read permission for '%s'\n") % pattern);
+ W(F("denied anonymous read permission for '%s' excluding '%s'\n")
+ % their_include_pattern % their_exclude_pattern);
this->saved_nonce = id("");
return false;
}
- P(F("allowed anonymous read permission for '%s'\n") % pattern);
+ P(F("allowed anonymous read permission for '%s' excluding '%s'\n")
+ % their_include_pattern % their_exclude_pattern);
rebuild_merkle_trees(app, ok_branches);
- this->pattern = pattern;
this->remote_peer_key_name = rsa_keypair_id("");
this->authenticated = true;
this->role = source_role;
@@ -1889,9 +1847,9 @@
}
bool
-session::process_auth_cmd(protocol_role role,
- utf8 const & include_pattern,
- utf8 const & exclude_pattern,
+session::process_auth_cmd(protocol_role their_role,
+ utf8 const & their_include_pattern,
+ utf8 const & their_exclude_pattern,
id const & client,
id const & nonce1,
string const & signature)
@@ -1904,13 +1862,7 @@
set ok_branches;
vector branchnames;
get_branches(app, branchnames);
- vector allowed;
- for (vector::const_iterator i = patterns.begin();
- i != patterns.end(); ++i)
- {
- allowed.push_back(boost::regex((*i)()));
- }
- boost::regex reg(pattern);
+ globish_matcher their_matcher(their_include_pattern, their_exclude_pattern);
// check that they replied with the nonce we asked for
if (!(nonce1 == this->saved_nonce))
@@ -1929,7 +1881,7 @@
// if the user asks to run a "read only" service, this means they are
// willing to be a source but not a sink.
//
- // nb: the "role" here is the role the *client* wants to play
+ // nb: the "their_role" here is the role the *client* wants to play
// so we need to check that the opposite role is allowed for us,
// in our this->role field.
//
@@ -1948,11 +1900,11 @@
// client as sink, server as source (reading)
- if (role == sink_role || role == source_and_sink_role)
+ if (their_role == sink_role || their_role == source_and_sink_role)
{
if (this->role != source_role && this->role != source_and_sink_role)
{
- W(F("denied '%s' read permission for '%s' while running as sink\n")
+ W(F("denied '%s' read permission for '%s' while running as pure sink\n")
% their_id % pattern);
this->saved_nonce = id("");
return false;
@@ -1961,18 +1913,16 @@
for (vector::const_iterator i = branchnames.begin();
i != branchnames.end(); i++)
{
- if (boost::regex_match(*i, reg)
- && (allowed.size() == 0 || matches_one(*i, allowed)))
- {
- if (app.lua.hook_get_netsync_read_permitted(*i, their_id))
- ok_branches.insert(utf8(*i));
- }
+ if (our_matcher(*i) && their_matcher(*i)
+ && app.lua.hook_get_netsync_anonymous_read_permitted(*i, their_id))
+ ok_branches.insert(utf8(*i));
}
//if we're source_and_sink_role, continue even with no branches readable
//ex: serve --db=empty.db
- if (!ok_branches.size() && role == sink_role)
+ if (ok_branches.empty() && their_role == sink_role)
{
- W(F("denied '%s' read permission for '%s'\n") % their_id % pattern);
+ W(F("denied '%s' read permission for '%s' excluding '%s'\n")
+ % their_id % their_include_pattern % their_exclude_pattern);
this->saved_nonce = id("");
return false;
}
@@ -1982,18 +1932,18 @@
// client as source, server as sink (writing)
- if (role == source_role || role == source_and_sink_role)
+ if (their_role == source_role || their_role == source_and_sink_role)
{
if (this->role != sink_role && this->role != source_and_sink_role)
{
- W(F("denied '%s' write permission for '%s' while running as source\n")
+ W(F("denied '%s' write permission for '%s' while running as pure source\n")
% their_id % pattern);
this->saved_nonce = id("");
return false;
}
// Write permissions are now checked from analyze_ancestry_graph.
- if (role == source_role)
+ if (their_role == source_role)
{
for (vector::const_iterator i = branchnames.begin();
i != branchnames.end(); i++)
@@ -2017,12 +1967,10 @@
{
// get our private key and sign back
L(F("client signature OK, accepting authentication\n"));
- this->pattern = pattern;
- this->pattern_re = boost::regex(this->pattern());
this->authenticated = true;
this->remote_peer_key_name = their_id;
// assume the (possibly degraded) opposite role
- switch (role)
+ switch (their_role)
{
case source_role:
I(this->role != source_role);
@@ -3018,16 +2966,16 @@
"anonymous netcmd received in source or source/sink role");
{
protocol_role role;
- utf8 include_pattern, exclude_pattern;
+ utf8 their_include_pattern, their_exclude_pattern;
rsa_oaep_sha_data hmac_key_encrypted;
- cmd.read_anonymous_cmd(role, include_pattern, exclude_pattern, hmac_key_encrypted);
+ cmd.read_anonymous_cmd(role, their_include_pattern, their_exclude_pattern, hmac_key_encrypted);
L(F("received 'anonymous' netcmd from client for pattern '%s' excluding '%s' "
"in %s mode\n")
- % include_pattern % exclude_pattern
+ % their_include_pattern % their_exclude_pattern
% (role == source_and_sink_role ? "source and sink" :
(role == source_role ? "source " : "sink")));
- if (!process_anonymous_cmd(role, include_pattern, exclude_pattern))
+ if (!process_anonymous_cmd(role, their_include_pattern, their_exclude_pattern))
return false;
respond_to_auth_cmd(hmac_key_encrypted);
return true;
@@ -3040,11 +2988,11 @@
{
protocol_role role;
string signature;
- utf8 include_pattern, exclude_pattern;
+ utf8 their_include_pattern, their_exclude_pattern;
id client, nonce1, nonce2;
rsa_oaep_sha_data hmac_key_encrypted;
- cmd.read_auth_cmd(role, include_pattern, exclude_pattern, client,
- nonce1, hmac_key_encrypted, signature);
+ cmd.read_auth_cmd(role, their_include_pattern, their_exclude_pattern,
+ client, nonce1, hmac_key_encrypted, signature);
hexenc their_key_hash;
encode_hexenc(client, their_key_hash);
@@ -3053,12 +3001,12 @@
L(F("received 'auth(hmac)' netcmd from client '%s' for pattern '%s' "
"exclude '%s' in %s mode with nonce1 '%s'\n")
- % their_key_hash % include_pattern % exclude_pattern
+ % their_key_hash % their_include_pattern % their_exclude_pattern
% (role == source_and_sink_role ? "source and sink" :
(role == source_role ? "source " : "sink"))
% hnonce1);
- if (!process_auth_cmd(role, include_pattern, exclude_pattern,
+ if (!process_auth_cmd(role, their_include_pattern, their_exclude_pattern,
client, nonce1, signature))
return false;
respond_to_auth_cmd(hmac_key_encrypted);
@@ -3232,7 +3180,8 @@
static void
call_server(protocol_role role,
- vector const & patterns,
+ utf8 const & include_pattern,
+ utf8 const & exclude_pattern,
app_state & app,
utf8 const & address,
Netxx::port_type default_port,
@@ -3245,8 +3194,8 @@
P(F("connecting to %s\n") % address());
Netxx::Stream server(address().c_str(), default_port, timeout);
- session sess(role, client_voice, patterns, app,
- address(), server.get_socketfd(), timeout);
+ session sess(role, client_voice, include_pattern, exclude_pattern,
+ app, address(), server.get_socketfd(), timeout);
while (true)
{
@@ -3375,7 +3324,8 @@
Netxx::StreamServer & server,
Netxx::Timeout & timeout,
protocol_role role,
- vector const & patterns,
+ utf8 const & include_pattern,
+ utf8 const & exclude_pattern,
map > & sessions,
app_state & app)
{
@@ -3390,7 +3340,8 @@
else
{
P(F("accepted new client connection from %s\n") % client);
- shared_ptr sess(new session(role, server_voice, patterns,
+ shared_ptr sess(new session(role, server_voice,
+ include_pattern, exclude_pattern,
app,
lexical_cast(client),
client.get_socketfd(), timeout));
@@ -3505,7 +3456,8 @@
static void
serve_connections(protocol_role role,
- vector const & patterns,
+ utf8 const & include_pattern,
+ utf8 const & exclude_pattern,
app_state & app,
utf8 const & address,
Netxx::port_type default_port,
@@ -3558,7 +3510,7 @@
// we either got a new connection
else if (fd == server)
handle_new_connection(addr, server, timeout, role,
- patterns, sessions, app);
+ include_pattern, exclude_pattern, sessions, app);
// or an existing session woke up
else
@@ -3757,7 +3709,8 @@
run_netsync_protocol(protocol_voice voice,
protocol_role role,
utf8 const & addr,
- vector patterns,
+ utf8 const & include_pattern,
+ utf8 const & exclude_pattern,
app_state & app)
{
try
@@ -3765,7 +3718,7 @@
start_platform_netsync();
if (voice == server_voice)
{
- serve_connections(role, patterns, app,
+ serve_connections(role, include_pattern, exclude_pattern, app,
addr, static_cast(constants::netsync_default_port),
static_cast(constants::netsync_timeout_seconds),
static_cast(constants::netsync_connection_limit));
@@ -3774,7 +3727,7 @@
{
I(voice == client_voice);
transaction_guard guard(app.db);
- call_server(role, patterns, app,
+ call_server(role, include_pattern, exclude_pattern, app,
addr, static_cast(constants::netsync_default_port),
static_cast(constants::netsync_timeout_seconds));
guard.commit();